mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Test [font] 🧣
This commit is contained in:
parent
7e91c8dc87
commit
6f111f9410
BIN
fonts/PTSans-Bold.ttf
Normal file
BIN
fonts/PTSans-Bold.ttf
Normal file
Binary file not shown.
BIN
fonts/PTSans-BoldItalic.ttf
Normal file
BIN
fonts/PTSans-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
fonts/PTSans-Italic.ttf
Normal file
BIN
fonts/PTSans-Italic.ttf
Normal file
Binary file not shown.
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
BIN
tests/ref/func-font-fallback.png
Normal file
BIN
tests/ref/func-font-fallback.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
tests/ref/func-font-properties.png
Normal file
BIN
tests/ref/func-font-properties.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
18
tests/typ/func-font-fallback.typ
Normal file
18
tests/typ/func-font-fallback.typ
Normal 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.
|
20
tests/typ/func-font-properties.typ
Normal file
20
tests/typ/func-font-properties.typ
Normal 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]
|
@ -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()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user