diff --git a/src/font.rs b/src/font.rs index ba3341ef..d23a46f7 100644 --- a/src/font.rs +++ b/src/font.rs @@ -458,15 +458,15 @@ impl Font { pub fn metrics_indexed(&self, index: u16, px: f32) -> Metrics { let glyph = &self.glyphs[index as usize]; let scale = self.scale_factor(px); - let (metrics, _, _) = self.metrics_raw(scale, glyph, 0.0); + let (metrics, _, _) = self.metrics_raw(scale, glyph, (0.0, 0.0)); metrics } /// Internal function to generate the metrics, offset_x, and offset_y of the glyph. - fn metrics_raw(&self, scale: f32, glyph: &Glyph, offset: f32) -> (Metrics, f32, f32) { + fn metrics_raw(&self, scale: f32, glyph: &Glyph, offset: (f32, f32)) -> (Metrics, f32, f32) { let bounds = glyph.bounds.scale(scale); - let mut offset_x = fract(bounds.xmin + offset); - let mut offset_y = fract(1.0 - fract(bounds.height) - fract(bounds.ymin)); + let mut offset_x = fract(bounds.xmin + offset.0); + let mut offset_y = fract(1.0 - fract(bounds.height) - fract(bounds.ymin + offset.1)); if is_negative(offset_x) { offset_x += 1.0; } @@ -577,12 +577,51 @@ impl Font { /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at /// the top left corner of the glyph. pub fn rasterize_indexed(&self, index: u16, px: f32) -> (Metrics, Vec) { + self.rasterize_indexed_offset(index, px, (0.0, 0.0)) + } + + /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to + /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed. + /// + /// This will perform the operation with the width multiplied by 3, as to simulate subpixels. + /// Taking these as RGB values will perform subpixel anti aliasing. + /// # Arguments + /// + /// * `index` - The glyph index in the font to rasterize. + /// * `px` - The size to render the character at. Cannot be negative. The units of the scale + /// are pixels per Em unit. + /// # Returns + /// + /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph. + /// * `Vec` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0 + /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The + /// vec starts at the top left corner of the glyph. + pub fn rasterize_indexed_subpixel(&self, index: u16, px: f32) -> (Metrics, Vec) { + self.rasterize_indexed_subpixel_offset(index, px, (0.0, 0.0)) + } + + /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to + /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed. + /// # Arguments + /// + /// * `index` - The glyph index in the font to rasterize. + /// * `px` - The size to render the character at. Cannot be negative. The units of the scale + /// are pixels per Em unit. + /// * `offset` - Additional horizontal and vertical (in that order) offset to apply while + /// rendering for more control over hinting. + /// # Returns + /// + /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph. + /// * `Vec` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents + /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at + /// the top left corner of the glyph. + pub fn rasterize_indexed_offset(&self, index: u16, px: f32, offset: (f32, f32)) -> (Metrics, Vec) { if px <= 0.0 { return (Metrics::default(), Vec::new()); } let glyph = &self.glyphs[index as usize]; let scale = self.scale_factor(px); - let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0); + let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, offset); let mut canvas = Raster::new(metrics.width, metrics.height); canvas.draw(&glyph, scale, scale, offset_x, offset_y); (metrics, canvas.get_bitmap()) @@ -598,19 +637,26 @@ impl Font { /// * `index` - The glyph index in the font to rasterize. /// * `px` - The size to render the character at. Cannot be negative. The units of the scale /// are pixels per Em unit. + /// * `offset` - Additional horizontal and vertical (in that order) offset to apply while + /// rendering for more control over hinting. /// # Returns /// /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph. /// * `Vec` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The /// vec starts at the top left corner of the glyph. - pub fn rasterize_indexed_subpixel(&self, index: u16, px: f32) -> (Metrics, Vec) { + pub fn rasterize_indexed_subpixel_offset( + &self, + index: u16, + px: f32, + offset: (f32, f32), + ) -> (Metrics, Vec) { if px <= 0.0 { return (Metrics::default(), Vec::new()); } let glyph = &self.glyphs[index as usize]; let scale = self.scale_factor(px); - let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0); + let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, (offset.0 * 3.0, offset.1)); let mut canvas = Raster::new(metrics.width * 3, metrics.height); canvas.draw(&glyph, scale * 3.0, scale, offset_x, offset_y); (metrics, canvas.get_bitmap())