`font.outline()` renders a glyph in reversed shape
kmoon2437 opened this issue · 0 comments
kmoon2437 commented
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?