Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose offset when rasterizing #148

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 53 additions & 7 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<u8>) {
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<u8>` - 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<u8>) {
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<u8>` - 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<u8>) {
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())
Expand All @@ -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<u8>` - 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<u8>) {
pub fn rasterize_indexed_subpixel_offset(
&self,
index: u16,
px: f32,
offset: (f32, f32),
) -> (Metrics, Vec<u8>) {
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())
Expand Down
Loading