Test [font] 🧣

This commit is contained in:
Laurenz 2020-12-17 15:43:30 +01:00
parent 7e91c8dc87
commit 6f111f9410
13 changed files with 66 additions and 28 deletions

BIN
fonts/PTSans-Bold.ttf Normal file

Binary file not shown.

BIN
fonts/PTSans-BoldItalic.ttf Normal file

Binary file not shown.

BIN
fonts/PTSans-Italic.ttf Normal file

Binary file not shown.

View File

@ -60,7 +60,7 @@ impl ResourceLoader {
}
};
Some((id, self.get_loaded(id)))
Some((id, self.loaded(id)))
}
/// Retrieve a previously loaded resource by its id.
@ -68,7 +68,7 @@ impl ResourceLoader {
/// # Panics
/// This panics if no resource with this id was loaded.
#[track_caller]
pub fn get_loaded<R: 'static>(&self, id: ResourceId) -> &R {
pub fn loaded<R: 'static>(&self, id: ResourceId) -> &R {
self.entries[id.0].downcast_ref().expect("bad resource type")
}
}

View File

@ -51,7 +51,7 @@ impl<'a> PdfExporter<'a> {
match element {
LayoutElement::Text(shaped) => fonts.insert(shaped.face),
LayoutElement::Image(image) => {
let img = env.resources.get_loaded::<ImageResource>(image.res);
let img = env.resources.loaded::<ImageResource>(image.res);
if img.buf.color().has_alpha() {
alpha_masks += 1;
}
@ -181,7 +181,7 @@ impl<'a> PdfExporter<'a> {
fn write_fonts(&mut self) {
for (refs, face_id) in self.refs.fonts().zip(self.fonts.layout_indices()) {
let owned_face = self.env.fonts.get_loaded(face_id);
let owned_face = self.env.fonts.face(face_id);
let face = owned_face.get();
let name = face
@ -292,7 +292,7 @@ impl<'a> PdfExporter<'a> {
let mut masks_seen = 0;
for (id, resource) in self.refs.images().zip(self.images.layout_indices()) {
let img = self.env.resources.get_loaded::<ImageResource>(resource);
let img = self.env.resources.loaded::<ImageResource>(resource);
let (width, height) = img.buf.dimensions();
// Add the primary image.

View File

@ -21,10 +21,10 @@ use crate::prelude::*;
pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
let snapshot = ctx.state.clone();
let body = args.find::<SynTree>();
let first = args.get::<_, Spanned<AlignArg>>(ctx, 0);
let second = args.get::<_, Spanned<AlignArg>>(ctx, 1);
let hor = args.get::<_, Spanned<AlignArg>>(ctx, "horizontal");
let ver = args.get::<_, Spanned<AlignArg>>(ctx, "vertical");
let first = args.get::<_, Spanned<SpecAlign>>(ctx, 0);
let second = args.get::<_, Spanned<SpecAlign>>(ctx, 1);
let hor = args.get::<_, Spanned<SpecAlign>>(ctx, "horizontal");
let ver = args.get::<_, Spanned<SpecAlign>>(ctx, "vertical");
args.done(ctx);
let prev_main = ctx.state.align.main;
@ -58,7 +58,7 @@ pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
} else {
// We don't know the axis: This has to be a `center` alignment for a
// positional argument.
debug_assert_eq!(arg, AlignArg::Center);
debug_assert_eq!(arg, SpecAlign::Center);
if had.main && had.cross {
ctx.diag(error!(span, "duplicate alignment"));
@ -108,7 +108,7 @@ pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
/// An argument to `[align]`.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
enum AlignArg {
enum SpecAlign {
Left,
Right,
Top,
@ -116,7 +116,7 @@ enum AlignArg {
Center,
}
convert_ident!(AlignArg, "alignment", |v| match v {
convert_ident!(SpecAlign, "alignment", |v| match v {
"left" => Some(Self::Left),
"right" => Some(Self::Right),
"top" => Some(Self::Top),
@ -125,7 +125,7 @@ convert_ident!(AlignArg, "alignment", |v| match v {
_ => None,
});
impl AlignArg {
impl SpecAlign {
/// The specific axis this alignment refers to.
///
/// Returns `None` if this is `Center` since the axis is unknown.
@ -140,7 +140,7 @@ impl AlignArg {
}
}
impl Switch for AlignArg {
impl Switch for SpecAlign {
type Other = Align;
fn switch(self, flow: Flow) -> Self::Other {
@ -163,7 +163,7 @@ impl Switch for AlignArg {
}
}
impl Display for AlignArg {
impl Display for SpecAlign {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad(match self {
Self::Left => "left",

View File

@ -71,13 +71,6 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
}
}
let mut needs_flattening = false;
let list: Vec<_> = args.find_all::<StringLike>().map(|s| s.to_lowercase()).collect();
if !list.is_empty() {
Rc::make_mut(&mut ctx.state.font.families).list = list;
needs_flattening = true;
}
if let Some(style) = args.get::<_, FontStyle>(ctx, "style") {
ctx.state.font.variant.style = style;
}
@ -90,6 +83,13 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
ctx.state.font.variant.stretch = stretch;
}
let mut needs_flattening = false;
let list: Vec<_> = args.find_all::<StringLike>().map(|s| s.to_lowercase()).collect();
if !list.is_empty() {
Rc::make_mut(&mut ctx.state.font.families).list = list;
needs_flattening = true;
}
for (class, dict) in args.find_all_str::<Spanned<ValueDict>>() {
let fallback = Args(dict)
.find_all::<StringLike>()
@ -100,12 +100,12 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
needs_flattening = true;
}
args.done(ctx);
if needs_flattening {
Rc::make_mut(&mut ctx.state.font.families).flatten();
}
args.done(ctx);
if let Some(body) = body {
body.eval(ctx);
ctx.state = snapshot;

View File

@ -82,8 +82,8 @@ pub fn shape(
for c in chars {
let query = FaceQuery { fallback: fallback.iter(), variant, c };
if let Some((id, owned_face)) = loader.query(query) {
let face = owned_face.get();
if let Some(id) = loader.query(query) {
let face = loader.face(id).get();
let (glyph, width) = match lookup_glyph(face, c, font_size) {
Some(v) => v,
None => continue,

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,18 @@
// Test font fallback.
// Source Sans Pro + Segoe UI Emoji.
Emoji: 🏀
// CMU Serif + Noto Emoji.
[font: "CMU Serif", "Noto Emoji"][Emoji: 🏀]
// Class definitions.
[font: math=("CMU Serif", "Latin Modern Math", "Noto Emoji")]
[font: math][Math: α + β 3]
// Class redefinition.
[font: sans-serif=("Noto Emoji",)]
[font: sans-serif=("Archivo", sans-serif)]
New sans-serif. 🚀
// TODO: Add tests for other scripts.

View File

@ -0,0 +1,20 @@
// Test configuring font properties.
[font: "PT Sans", 10pt]
// Set same font size in three different ways.
[font: 20pt][A]
[font: 200%][A]
[font: 15pt + 50%][A]
// Do nothing.
[font][Normal]
// Set style (is available).
[font: style=italic][Italic]
// Set weight (is available).
[font: weight=bold][Bold]
// Set stretch (not available, matching closest).
[font: stretch=ultra-condensed][Condensed]

View File

@ -278,7 +278,7 @@ fn draw(layouts: &[BoxLayout], env: &Env, pixel_per_pt: f32) -> Canvas {
}
fn draw_text(canvas: &mut Canvas, pos: Point, env: &Env, shaped: &Shaped) {
let face = env.fonts.get_loaded(shaped.face).get();
let face = env.fonts.face(shaped.face).get();
for (&glyph, &offset) in shaped.glyphs.iter().zip(&shaped.offsets) {
let units_per_em = face.units_per_em().unwrap_or(1000);
@ -304,7 +304,7 @@ fn draw_text(canvas: &mut Canvas, pos: Point, env: &Env, shaped: &Shaped) {
}
fn draw_image(canvas: &mut Canvas, pos: Point, env: &Env, img: &ImageElement) {
let buf = &env.resources.get_loaded::<ImageResource>(img.res).buf;
let buf = &env.resources.loaded::<ImageResource>(img.res).buf;
let mut pixmap = Pixmap::new(buf.width(), buf.height()).unwrap();
for ((_, _, src), dest) in buf.pixels().zip(pixmap.pixels_mut()) {