`font.outline()` renders a glyph in reversed shape
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 840
- Forks
- 137
- Avg merge
- 4h 56m
- Merged PRs (30d)
- 1
Description
I'm using this library with raqote for text rendering. I wrote the code below:
use std::fs::File;
use font_kit::font::Font;
use font_kit::hinting::HintingOptions;
use font_kit::outline::OutlineSink;
use raqote::{
Path, PathBuilder,
Point, Source, SolidSource,
StrokeStyle, LineCap, LineJoin,
DrawTarget, DrawOptions
};
use pathfinder_geometry::vector::Vector2F;
use pathfinder_geometry::line_segment::LineSegment2F;
pub struct TextPathBuilder {
pb: PathBuilder,
font_scale: f32,
start: Point
}
impl TextPathBuilder {
pub fn new(font_size: f32, start: Point, units_per_em: u32) -> Self {
return Self {
pb: PathBuilder::new(),
font_scale: font_size / units_per_em as f32,
start
};
}
fn calc_point(&self, point: f32) -> f32 {
return point * self.font_scale;
}
fn calc_x(&self, point: f32) -> f32 {
return self.calc_point(point) + self.start.x;
}
fn calc_y(&self, point: f32) -> f32 {
return self.calc_point(point) + self.start.y;
}
pub fn finish(self) -> Path {
return self.pb.finish();
}
}
impl OutlineSink for TextPathBuilder {
fn move_to(&mut self, to: Vector2F) {
self.pb.move_to(self.calc_x(to.x()), self.calc_y(to.y()));
}
fn line_to(&mut self, to: Vector2F) {
self.pb.line_to(self.calc_x(to.x()), self.calc_y(to.y()));
}
fn quadratic_curve_to(&mut self, ctrl: Vector2F, to: Vector2F) {
self.pb.quad_to(self.calc_x(ctrl.x()), self.calc_y(ctrl.y()), self.calc_x(to.x()), self.calc_y(to.y()));
}
fn cubic_curve_to(&mut self, ctrl: LineSegment2F, to: Vector2F) {
self.pb.cubic_to(self.calc_x(ctrl.from().x()), self.calc_y(ctrl.from().y()), self.calc_x(ctrl.to().x()), self.calc_y(ctrl.to().y()), self.calc_x(to.x()), self.calc_y(to.y()));
}
fn close(&mut self) {
self.pb.close();
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("tmp/NotoSansCJK-Medium.otf")?;
let font = Font::from_file(&mut file, 0)?;
let mut tpb = TextPathBuilder::new(70.0, Point::new(10.0, 10.0), font.metrics().units_per_em);
font.outline(font.glyph_for_char('9').unwrap(), HintingOptions::None, &mut tpb)?;
let path = tpb.finish();
let mut dt = DrawTarget::new(100, 100);
let color1 = Source::Solid(SolidSource::from_unpremultiplied_argb(255, 255, 255, 255));
let color2 = Source::Solid(SolidSource::from_unpremultiplied_argb(255, 0x2a, 0xbd, 0x71));
let stroke = StrokeStyle {
cap: LineCap::Butt,
join: LineJoin::Round,
width: 10.0,
miter_limit: 10.0,
..Default::default()
};
let draw_options = DrawOptions {
..Default::default()
};
dt.stroke(&path, &color1, &stroke, &draw_options);
dt.fill(&path, &color2, &draw_options);
dt.write_png("example.png")?;
return Ok(());
}
However, the output is reversed "9".
I fixed TextPathBuilder like this:
pub struct TextPathBuilder {
pb: PathBuilder,
font_scale: f32,
font_size: f32,
start: Point
}
impl TextPathBuilder {
pub fn new(font_size: f32, start: Point, units_per_em: u32) -> Self {
return Self {
pb: PathBuilder::new(),
font_scale: font_size / units_per_em as f32,
font_size,
start
};
}
fn calc_point(&self, point: f32) -> f32 {
return point * self.font_scale;
}
fn calc_x(&self, point: f32) -> f32 {
return self.calc_point(point) + self.start.x;
}
fn calc_y(&self, point: f32) -> f32 {
return -self.calc_point(point) + self.font_size + self.start.y;
}
pub fn finish(self) -> Path {
return self.pb.finish();
}
}
and the image is generated correctly.
Did I fix the problem correctly?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the provided font.outline call and the TextPathBuilder coordinate conversions, especially calc_y, then compare the resulting path with raqote's coordinate expectations. Verify the example using the NotoSansCJK-Medium.otf glyph for '9'; done means determining whether the inverted y transformation is the correct fix and documenting or correcting the behavior as needed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100