mirror of
https://github.com/typst/typst
synced 2025-05-15 17:45:27 +08:00
Better font family definitions ✒
This commit is contained in:
parent
39f55481ed
commit
98336bfafb
@ -1,5 +1,5 @@
|
|||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
use fontdock::fs::FsIndex;
|
use fontdock::FsIndex;
|
||||||
|
|
||||||
use typst::env::{Env, FsIndexExt, ResourceLoader};
|
use typst::env::{Env, FsIndexExt, ResourceLoader};
|
||||||
use typst::eval::eval;
|
use typst::eval::eval;
|
||||||
|
10
src/env.rs
10
src/env.rs
@ -7,13 +7,13 @@ use std::fs;
|
|||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use fontdock::{ContainsChar, FaceFromVec, FaceId, FontSource};
|
use fontdock::{FaceFromVec, FaceId, FontSource};
|
||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use image::{DynamicImage, GenericImageView, ImageFormat};
|
use image::{DynamicImage, GenericImageView, ImageFormat};
|
||||||
use ttf_parser::Face;
|
use ttf_parser::Face;
|
||||||
|
|
||||||
#[cfg(feature = "fs")]
|
#[cfg(feature = "fs")]
|
||||||
use fontdock::fs::{FsIndex, FsSource};
|
use fontdock::{FsIndex, FsSource};
|
||||||
|
|
||||||
/// Encapsulates all environment dependencies (fonts, resources).
|
/// Encapsulates all environment dependencies (fonts, resources).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -83,12 +83,6 @@ impl FaceFromVec for FaceBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContainsChar for FaceBuf {
|
|
||||||
fn contains_char(&self, c: char) -> bool {
|
|
||||||
self.get().glyph_index(c).is_some()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Simplify font loader construction from an [`FsIndex`].
|
/// Simplify font loader construction from an [`FsIndex`].
|
||||||
#[cfg(feature = "fs")]
|
#[cfg(feature = "fs")]
|
||||||
pub trait FsIndexExt {
|
pub trait FsIndexExt {
|
||||||
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use fontdock::FontStyle;
|
use fontdock::FontStyle;
|
||||||
|
|
||||||
use super::{Exec, State};
|
use super::{Exec, FontFamily, State};
|
||||||
use crate::diag::{Diag, DiagSet, Pass};
|
use crate::diag::{Diag, DiagSet, Pass};
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use crate::eval::TemplateValue;
|
use crate::eval::TemplateValue;
|
||||||
@ -74,8 +74,7 @@ impl<'a> ExecContext<'a> {
|
|||||||
/// Set the font to monospace.
|
/// Set the font to monospace.
|
||||||
pub fn set_monospace(&mut self) {
|
pub fn set_monospace(&mut self) {
|
||||||
let families = self.state.font.families_mut();
|
let families = self.state.font.families_mut();
|
||||||
families.list.insert(0, "monospace".to_string());
|
families.list.insert(0, FontFamily::Monospace);
|
||||||
families.flatten();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a layout node into the active paragraph.
|
/// Push a layout node into the active paragraph.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight};
|
use fontdock::{FontStretch, FontStyle, FontVariant, FontWeight};
|
||||||
|
|
||||||
use crate::color::{Color, RgbaColor};
|
use crate::color::{Color, RgbaColor};
|
||||||
use crate::geom::*;
|
use crate::geom::*;
|
||||||
@ -98,8 +99,8 @@ impl Default for ParState {
|
|||||||
/// Defines font properties.
|
/// Defines font properties.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FontState {
|
pub struct FontState {
|
||||||
/// A tree of font family names and generic class names.
|
/// A list of font families with generic class definitions.
|
||||||
pub families: Rc<FallbackTree>,
|
pub families: Rc<FamilyMap>,
|
||||||
/// The selected font variant.
|
/// The selected font variant.
|
||||||
pub variant: FontVariant,
|
pub variant: FontVariant,
|
||||||
/// The font size.
|
/// The font size.
|
||||||
@ -122,7 +123,7 @@ pub struct FontState {
|
|||||||
|
|
||||||
impl FontState {
|
impl FontState {
|
||||||
/// Access the `families` mutably.
|
/// Access the `families` mutably.
|
||||||
pub fn families_mut(&mut self) -> &mut FallbackTree {
|
pub fn families_mut(&mut self) -> &mut FamilyMap {
|
||||||
Rc::make_mut(&mut self.families)
|
Rc::make_mut(&mut self.families)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,12 +136,7 @@ impl FontState {
|
|||||||
impl Default for FontState {
|
impl Default for FontState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
// The default tree of font fallbacks.
|
families: Rc::new(FamilyMap::default()),
|
||||||
families: Rc::new(fallback! {
|
|
||||||
list: [],
|
|
||||||
classes: { "monospace" => ["inconsolata"] },
|
|
||||||
base: ["eb garamond", "twitter color emoji"],
|
|
||||||
}),
|
|
||||||
variant: FontVariant {
|
variant: FontVariant {
|
||||||
style: FontStyle::Normal,
|
style: FontStyle::Normal,
|
||||||
weight: FontWeight::REGULAR,
|
weight: FontWeight::REGULAR,
|
||||||
@ -156,3 +152,68 @@ impl Default for FontState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Font family definitions.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub struct FamilyMap {
|
||||||
|
/// The user-defined list of font families.
|
||||||
|
pub list: Vec<FontFamily>,
|
||||||
|
/// Definition of serif font families.
|
||||||
|
pub serif: Vec<String>,
|
||||||
|
/// Definition of sans-serif font families.
|
||||||
|
pub sans_serif: Vec<String>,
|
||||||
|
/// Definition of monospace font families used for raw text.
|
||||||
|
pub monospace: Vec<String>,
|
||||||
|
/// Base fonts that are tried if the list has no match.
|
||||||
|
pub base: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FamilyMap {
|
||||||
|
/// Flat iterator over this map's family names.
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.list
|
||||||
|
.iter()
|
||||||
|
.flat_map(move |family: &FontFamily| {
|
||||||
|
match family {
|
||||||
|
FontFamily::Named(name) => std::slice::from_ref(name),
|
||||||
|
FontFamily::Serif => &self.serif,
|
||||||
|
FontFamily::SansSerif => &self.sans_serif,
|
||||||
|
FontFamily::Monospace => &self.monospace,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.chain(&self.base)
|
||||||
|
.map(String::as_str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FamilyMap {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
list: vec![FontFamily::Serif],
|
||||||
|
serif: vec!["eb garamond".into()],
|
||||||
|
sans_serif: vec![/* TODO */],
|
||||||
|
monospace: vec!["inconsolata".into()],
|
||||||
|
base: vec!["twitter color emoji".into()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic or named font family.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum FontFamily {
|
||||||
|
Serif,
|
||||||
|
SansSerif,
|
||||||
|
Monospace,
|
||||||
|
Named(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for FontFamily {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
f.pad(match self {
|
||||||
|
Self::Serif => "serif",
|
||||||
|
Self::SansSerif => "sans-serif",
|
||||||
|
Self::Monospace => "monospace",
|
||||||
|
Self::Named(s) => s,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
|
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
|
||||||
use fontdock::{FaceId, FaceQuery, FallbackTree, FontVariant};
|
use fontdock::{FaceId, FontVariant};
|
||||||
use ttf_parser::{Face, GlyphId};
|
use ttf_parser::{Face, GlyphId};
|
||||||
|
|
||||||
use crate::env::FontLoader;
|
use crate::env::FontLoader;
|
||||||
|
use crate::exec::FamilyMap;
|
||||||
use crate::geom::{Dir, Length, Point, Size};
|
use crate::geom::{Dir, Length, Point, Size};
|
||||||
use crate::layout::{Element, Fill, Frame};
|
use crate::layout::{Element, Fill, Frame};
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ impl Shaped {
|
|||||||
glyphs: vec![],
|
glyphs: vec![],
|
||||||
offsets: vec![],
|
offsets: vec![],
|
||||||
font_size,
|
font_size,
|
||||||
color: color,
|
color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ impl Display for VerticalFontMetric {
|
|||||||
pub fn shape(
|
pub fn shape(
|
||||||
text: &str,
|
text: &str,
|
||||||
dir: Dir,
|
dir: Dir,
|
||||||
fallback: &FallbackTree,
|
families: &FamilyMap,
|
||||||
variant: FontVariant,
|
variant: FontVariant,
|
||||||
font_size: Length,
|
font_size: Length,
|
||||||
top_edge: VerticalFontMetric,
|
top_edge: VerticalFontMetric,
|
||||||
@ -122,31 +123,33 @@ pub fn shape(
|
|||||||
};
|
};
|
||||||
|
|
||||||
for c in chars {
|
for c in chars {
|
||||||
let query = FaceQuery { fallback: fallback.iter(), variant, c };
|
for family in families.iter() {
|
||||||
if let Some(id) = loader.query(query) {
|
if let Some(id) = loader.query(family, variant) {
|
||||||
let face = loader.face(id).get();
|
let face = loader.face(id).get();
|
||||||
let (glyph, glyph_width) = match lookup_glyph(face, c) {
|
let (glyph, glyph_width) = match lookup_glyph(face, c) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let units_per_em = f64::from(face.units_per_em().unwrap_or(1000));
|
let units_per_em = f64::from(face.units_per_em().unwrap_or(1000));
|
||||||
let convert = |units| units / units_per_em * font_size;
|
let convert = |units| units / units_per_em * font_size;
|
||||||
|
|
||||||
// Flush the buffer and reset the metrics if we use a new font face.
|
// Flush the buffer and reset the metrics if we use a new font face.
|
||||||
if shaped.face != id {
|
if shaped.face != id {
|
||||||
place(&mut frame, shaped, width, top, bottom);
|
place(&mut frame, shaped, width, top, bottom);
|
||||||
|
|
||||||
shaped = Shaped::new(id, font_size, color);
|
shaped = Shaped::new(id, font_size, color);
|
||||||
width = Length::ZERO;
|
width = Length::ZERO;
|
||||||
top = convert(f64::from(lookup_metric(face, top_edge)));
|
top = convert(f64::from(lookup_metric(face, top_edge)));
|
||||||
bottom = convert(f64::from(lookup_metric(face, bottom_edge)));
|
bottom = convert(f64::from(lookup_metric(face, bottom_edge)));
|
||||||
|
}
|
||||||
|
|
||||||
|
shaped.text.push(c);
|
||||||
|
shaped.glyphs.push(glyph);
|
||||||
|
shaped.offsets.push(width);
|
||||||
|
width += convert(f64::from(glyph_width));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
shaped.text.push(c);
|
|
||||||
shaped.glyphs.push(glyph);
|
|
||||||
shaped.offsets.push(width);
|
|
||||||
width += convert(f64::from(glyph_width));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use fontdock::{FallbackTree, FontVariant};
|
use fontdock::FontVariant;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::exec::FamilyMap;
|
||||||
|
|
||||||
/// A consecutive, styled run of text.
|
/// A consecutive, styled run of text.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
@ -14,8 +15,8 @@ pub struct TextNode {
|
|||||||
pub dir: Dir,
|
pub dir: Dir,
|
||||||
/// How to align this text node in its parent.
|
/// How to align this text node in its parent.
|
||||||
pub aligns: LayoutAligns,
|
pub aligns: LayoutAligns,
|
||||||
/// The families used for font fallback.
|
/// The list of font families for shaping.
|
||||||
pub families: Rc<FallbackTree>,
|
pub families: Rc<FamilyMap>,
|
||||||
/// The font variant,
|
/// The font variant,
|
||||||
pub variant: FontVariant,
|
pub variant: FontVariant,
|
||||||
/// The font size.
|
/// The font size.
|
||||||
|
@ -17,9 +17,9 @@ use super::*;
|
|||||||
/// - Top edge of the font: `top-edge`, of type `vertical-font-metric`.
|
/// - Top edge of the font: `top-edge`, of type `vertical-font-metric`.
|
||||||
/// - Bottom edge of the font: `bottom-edge`, of type `vertical-font-metric`.
|
/// - Bottom edge of the font: `bottom-edge`, of type `vertical-font-metric`.
|
||||||
/// - Color the glyphs: `color`, of type `color`.
|
/// - Color the glyphs: `color`, of type `color`.
|
||||||
/// - Serif family definition: `serif`, of type `font-familiy-list`.
|
/// - Serif family definition: `serif`, of type `font-family-definition`.
|
||||||
/// - Sans-serif family definition: `sans-serif`, of type `font-familiy-list`.
|
/// - Sans-serif family definition: `sans-serif`, of type `font-family-definition`.
|
||||||
/// - Monospace family definition: `monospace`, of type `font-familiy-list`.
|
/// - Monospace family definition: `monospace`, of type `font-family-definition`.
|
||||||
///
|
///
|
||||||
/// # Return value
|
/// # Return value
|
||||||
/// A template that configures font properties. The effect is scoped to the body
|
/// A template that configures font properties. The effect is scoped to the body
|
||||||
@ -31,10 +31,9 @@ use super::*;
|
|||||||
/// - `sans-serif`
|
/// - `sans-serif`
|
||||||
/// - `monospace`
|
/// - `monospace`
|
||||||
/// - coerces from `string`
|
/// - coerces from `string`
|
||||||
/// - Type `font-family-list`
|
/// - Type `font-family-definition`
|
||||||
/// - coerces from `string`
|
/// - coerces from `string`
|
||||||
/// - coerces from `array`
|
/// - coerces from `array`
|
||||||
/// - coerces from `font-family`
|
|
||||||
/// - Type `font-style`
|
/// - Type `font-style`
|
||||||
/// - `normal`
|
/// - `normal`
|
||||||
/// - `italic`
|
/// - `italic`
|
||||||
@ -58,7 +57,7 @@ use super::*;
|
|||||||
/// - `descender`
|
/// - `descender`
|
||||||
pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
||||||
let size = args.find::<Linear>(ctx);
|
let size = args.find::<Linear>(ctx);
|
||||||
let list: Vec<_> = args.filter::<FontFamily>(ctx).map(|f| f.to_string()).collect();
|
let list: Vec<_> = args.filter::<FontFamily>(ctx).collect();
|
||||||
let style = args.get(ctx, "style");
|
let style = args.get(ctx, "style");
|
||||||
let weight = args.get(ctx, "weight");
|
let weight = args.get(ctx, "weight");
|
||||||
let stretch = args.get(ctx, "stretch");
|
let stretch = args.get(ctx, "stretch");
|
||||||
@ -83,9 +82,7 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !list.is_empty() {
|
if !list.is_empty() {
|
||||||
let families = ctx.state.font.families_mut();
|
ctx.state.font.families_mut().list = list.clone();
|
||||||
families.list = list.clone();
|
|
||||||
families.flatten();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(style) = style {
|
if let Some(style) = style {
|
||||||
@ -112,17 +109,16 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
|||||||
ctx.state.font.color = Fill::Color(color);
|
ctx.state.font.color = Fill::Color(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (variant, arg) in &[
|
if let Some(FontFamilies(serif)) = &serif {
|
||||||
(FontFamily::Serif, &serif),
|
ctx.state.font.families_mut().serif = serif.clone();
|
||||||
(FontFamily::SansSerif, &sans_serif),
|
}
|
||||||
(FontFamily::Monospace, &monospace),
|
|
||||||
] {
|
if let Some(FontFamilies(sans_serif)) = &sans_serif {
|
||||||
if let Some(FontFamilies(list)) = arg {
|
ctx.state.font.families_mut().sans_serif = sans_serif.clone();
|
||||||
let strings = list.into_iter().map(|f| f.to_string()).collect();
|
}
|
||||||
let families = ctx.state.font.families_mut();
|
|
||||||
families.update_class_list(variant.to_string(), strings);
|
if let Some(FontFamilies(monospace)) = &monospace {
|
||||||
families.flatten();
|
ctx.state.font.families_mut().monospace = monospace.clone();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(body) = &body {
|
if let Some(body) = &body {
|
||||||
@ -132,45 +128,19 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A list of font families.
|
/// A list of font family names.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct FontFamilies(Vec<FontFamily>);
|
struct FontFamilies(Vec<String>);
|
||||||
|
|
||||||
/// A single font family.
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
|
||||||
pub(super) enum FontFamily {
|
|
||||||
Serif,
|
|
||||||
SansSerif,
|
|
||||||
Monospace,
|
|
||||||
Named(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FontFamily {
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Self::Serif => "serif",
|
|
||||||
Self::SansSerif => "sans-serif",
|
|
||||||
Self::Monospace => "monospace",
|
|
||||||
Self::Named(s) => s,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for FontFamily {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
f.pad(self.as_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typify! {
|
typify! {
|
||||||
FontFamilies: "font family or array of font families",
|
FontFamilies: "string or array of strings",
|
||||||
Value::Str(string) => Self(vec![FontFamily::Named(string.to_lowercase())]),
|
Value::Str(string) => Self(vec![string.to_lowercase()]),
|
||||||
Value::Array(values) => Self(values
|
Value::Array(values) => Self(values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|v| v.cast().ok())
|
.filter_map(|v| v.cast().ok())
|
||||||
|
.map(|string: String| string.to_lowercase())
|
||||||
.collect()
|
.collect()
|
||||||
),
|
),
|
||||||
#(family: FontFamily) => Self(vec![family]),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typify! {
|
typify! {
|
||||||
|
@ -31,7 +31,7 @@ use fontdock::{FontStyle, FontWeight};
|
|||||||
|
|
||||||
use crate::eval::{AnyValue, FuncValue, Scope};
|
use crate::eval::{AnyValue, FuncValue, Scope};
|
||||||
use crate::eval::{EvalContext, FuncArgs, TemplateValue, Value};
|
use crate::eval::{EvalContext, FuncArgs, TemplateValue, Value};
|
||||||
use crate::exec::{Exec, ExecContext};
|
use crate::exec::{Exec, ExecContext, FontFamily};
|
||||||
use crate::geom::*;
|
use crate::geom::*;
|
||||||
use crate::layout::VerticalFontMetric;
|
use crate::layout::VerticalFontMetric;
|
||||||
use crate::syntax::{Node, Spanned};
|
use crate::syntax::{Node, Spanned};
|
||||||
|
@ -2,7 +2,7 @@ use std::fs;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
use fontdock::fs::FsIndex;
|
use fontdock::FsIndex;
|
||||||
|
|
||||||
use typst::diag::Pass;
|
use typst::diag::Pass;
|
||||||
use typst::env::{Env, FsIndexExt, ResourceLoader};
|
use typst::env::{Env, FsIndexExt, ResourceLoader};
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 12 KiB |
@ -48,6 +48,13 @@ Emoji: 🐪, 🌋, 🏞
|
|||||||
#try(cap-height, baseline)
|
#try(cap-height, baseline)
|
||||||
#try(x-height, baseline)
|
#try(x-height, baseline)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test class definitions.
|
||||||
|
#font(sans-serif: "PT Sans")
|
||||||
|
#font(sans-serif)[Sans-serif.] \
|
||||||
|
#font(monospace)[Monospace.] \
|
||||||
|
#font(monospace, monospace: ("Nope", "Latin Modern Math"))[Math.] \
|
||||||
|
|
||||||
---
|
---
|
||||||
// Ref: false
|
// Ref: false
|
||||||
|
|
||||||
@ -56,7 +63,7 @@ Emoji: 🐪, 🌋, 🏞
|
|||||||
|
|
||||||
// Error: 3:14-3:18 expected font style, found font weight
|
// Error: 3:14-3:18 expected font style, found font weight
|
||||||
// Error: 2:28-2:34 expected font weight, found string
|
// Error: 2:28-2:34 expected font weight, found string
|
||||||
// Error: 1:43-1:44 expected font family or array of font families, found integer
|
// Error: 1:43-1:44 expected string or array of strings, found integer
|
||||||
#font(style: bold, weight: "thin", serif: 0)
|
#font(style: bold, weight: "thin", serif: 0)
|
||||||
|
|
||||||
// Warning: 15-19 should be between 100 and 900
|
// Warning: 15-19 should be between 100 and 900
|
||||||
|
@ -5,7 +5,7 @@ use std::fs;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use fontdock::fs::FsIndex;
|
use fontdock::FsIndex;
|
||||||
use image::{GenericImageView, Rgba};
|
use image::{GenericImageView, Rgba};
|
||||||
use tiny_skia::{
|
use tiny_skia::{
|
||||||
Canvas, Color, ColorU8, FillRule, FilterQuality, Paint, Pattern, Pixmap, Rect,
|
Canvas, Color, ColorU8, FillRule, FilterQuality, Paint, Pattern, Pixmap, Rect,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user