Skip to content

Commit

Permalink
Allow disabling using color tables for fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurenzV committed Nov 30, 2024
1 parent 97d9f48 commit adbcf69
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 53 deletions.
4 changes: 2 additions & 2 deletions crates/krilla/src/font/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ mod tests {
#[visreg(document, pdfium, mupdf, pdfbox, ghostscript, poppler, quartz)]
fn noto_color_emoji_cbdt(document: &mut Document) {
let font_data = NOTO_COLOR_EMOJI_CBDT.clone();
all_glyphs_to_pdf(font_data, None, false, document);
all_glyphs_to_pdf(font_data, None, false, true, document);
}

#[cfg(target_os = "macos")]
Expand All @@ -461,6 +461,6 @@ mod tests {

let font_data =
Arc::new(std::fs::read("/System/Library/Fonts/Apple Color Emoji.ttc").unwrap());
all_glyphs_to_pdf(font_data, None, false, document);
all_glyphs_to_pdf(font_data, None, false, true, document);
}
}
6 changes: 3 additions & 3 deletions crates/krilla/src/font/colr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,13 @@ mod tests {
.map(|n| (GlyphId::new(n), "".to_string()))
.collect::<Vec<_>>();

all_glyphs_to_pdf(font_data, Some(glyphs), false, document);
all_glyphs_to_pdf(font_data, Some(glyphs), false, true, document);
}

#[visreg]
fn colr_context_color(surface: &mut Surface) {
let font_data = COLR_TEST_GLYPHS.clone();
let font = Font::new(font_data, 0).unwrap();
let font = Font::new(font_data, 0, true).unwrap();

let text = [
0xf0b00, 0xf0b01, 0xf0b02, 0xf0b03, 0xf0b04, 0xf0b05, 0xf0b06, 0xf0b07,
Expand Down Expand Up @@ -570,6 +570,6 @@ mod tests {
#[visreg(document, pdfium, mupdf, pdfbox, ghostscript, poppler, quartz)]
fn noto_color_emoji_colr(document: &mut Document) {
let font_data = NOTO_COLOR_EMOJI_COLR.clone();
all_glyphs_to_pdf(font_data, None, false, document);
all_glyphs_to_pdf(font_data, None, false, true, document);
}
}
24 changes: 20 additions & 4 deletions crates/krilla/src/font/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,24 @@ pub use skrifa::GlyphId;
pub struct Font(Arc<Prehashed<Repr>>);

impl Font {
/// Create a new font from some data. The `index` indicates the index that should be
/// Create a new font from some data.
///
/// The `index` indicates the index that should be
/// associated with this font for TrueType collections, otherwise this value should be
/// set to 0. The location indicates the variation axes that should be associated with
/// the font.
///
/// The `allow_color` property allows you to specify whether krilla should render the font
/// as a color font. When setting this property to false, krilla will always only use the
/// `glyf`/`CFF` tables of the font. If you don't know what this means, just set it to `true`.
///
/// Returns `None` if the index is invalid or the font couldn't be read.
pub fn new(data: Arc<dyn AsRef<[u8]> + Send + Sync>, index: u32) -> Option<Self> {
let font_info = FontInfo::new(data.as_ref().as_ref(), index)?;
pub fn new(
data: Arc<dyn AsRef<[u8]> + Send + Sync>,
index: u32,
allow_color: bool,
) -> Option<Self> {
let font_info = FontInfo::new(data.as_ref().as_ref(), index, allow_color)?;

Font::new_with_info(data, Arc::new(font_info))
}
Expand Down Expand Up @@ -108,6 +118,10 @@ impl Font {
self.0.font_info.ascent.get()
}

pub(crate) fn allow_color(&self) -> bool {
self.0.font_info.allow_color
}

pub(crate) fn weight(&self) -> f32 {
self.0.font_info.weight.get()
}
Expand Down Expand Up @@ -182,6 +196,7 @@ pub(crate) struct FontInfo {
global_bbox: RectWrapper,
postscript_name: Option<String>,
ascent: FiniteF32,
allow_color: bool,
descent: FiniteF32,
cap_height: Option<FiniteF32>,
is_monospaced: bool,
Expand All @@ -208,7 +223,7 @@ impl Hash for Repr {
}

impl FontInfo {
pub(crate) fn new(data: &[u8], index: u32) -> Option<Self> {
pub(crate) fn new(data: &[u8], index: u32, allow_color: bool) -> Option<Self> {
let font_ref = FontRef::from_index(data, index).ok()?;
let checksum = font_ref.head().ok()?.checksum_adjustment();

Expand Down Expand Up @@ -252,6 +267,7 @@ impl FontInfo {
index,
checksum,
location,
allow_color,
units_per_em,
postscript_name,
ascent,
Expand Down
10 changes: 8 additions & 2 deletions crates/krilla/src/font/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,19 @@ mod tests {
#[visreg(document, all)]
fn twitter_color_emoji(document: &mut Document) {
let font_data = TWITTER_COLOR_EMOJI.clone();
all_glyphs_to_pdf(font_data, None, false, document);
all_glyphs_to_pdf(font_data, None, false, true, document);
}

#[visreg(document)]
fn twitter_color_emoji_no_color(document: &mut Document) {
let font_data = TWITTER_COLOR_EMOJI.clone();
all_glyphs_to_pdf(font_data, None, false, false, document);
}

#[visreg]
fn svg_extra(surface: &mut Surface) {
let font_data = SVG_EXTRA.clone();
let font = Font::new(font_data, 0).unwrap();
let font = Font::new(font_data, 0, true).unwrap();

surface.fill_text(
Point::from_xy(0., 30.0),
Expand Down
16 changes: 8 additions & 8 deletions crates/krilla/src/object/font/cid_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ mod tests {

#[snapshot]
fn cid_font_noto_sans_two_glyphs(sc: &mut SerializerContext) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
let container = sc.create_or_get_font_container(font.clone());
let mut font_container = container.borrow_mut();

Expand All @@ -374,7 +374,7 @@ mod tests {

#[visreg(all)]
fn cid_font_noto_sans_simple_text(surface: &mut Surface) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -389,7 +389,7 @@ mod tests {

#[visreg(all)]
fn cid_font_latin_modern_simple_text(surface: &mut Surface) {
let font = Font::new(LATIN_MODERN_ROMAN.clone(), 0).unwrap();
let font = Font::new(LATIN_MODERN_ROMAN.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -404,7 +404,7 @@ mod tests {

#[visreg(all)]
fn cid_font_noto_arabic_simple_text(surface: &mut Surface) {
let font = Font::new(NOTO_SANS_ARABIC.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS_ARABIC.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -419,7 +419,7 @@ mod tests {

#[snapshot]
fn cid_font_latin_modern_four_glyphs(sc: &mut SerializerContext) {
let font = Font::new(LATIN_MODERN_ROMAN.clone(), 0).unwrap();
let font = Font::new(LATIN_MODERN_ROMAN.clone(), 0, true).unwrap();
let container = sc.create_or_get_font_container(font.clone());
let mut font_container = container.borrow_mut();

Expand All @@ -445,9 +445,9 @@ mod tests {

let font_data =
Arc::new(std::fs::read("/System/Library/Fonts/Supplemental/Songti.ttc").unwrap());
let font_1 = Font::new(font_data.clone(), 0).unwrap();
let font_2 = Font::new(font_data.clone(), 3).unwrap();
let font_3 = Font::new(font_data, 6).unwrap();
let font_1 = Font::new(font_data.clone(), 0, true).unwrap();
let font_2 = Font::new(font_data.clone(), 3, true).unwrap();
let font_3 = Font::new(font_data, 6, true).unwrap();

surface.fill_text(
Point::from_xy(0.0, 75.0),
Expand Down
6 changes: 3 additions & 3 deletions crates/krilla/src/object/font/type3_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ mod tests {
#[test]
fn type3_more_than_256_glyphs() {
let mut sc = SerializerContext::new(SerializeSettings::settings_1());
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0).unwrap();
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0, true).unwrap();
let container = sc.create_or_get_font_container(font.clone());
let mut font_container = container.borrow_mut();

Expand Down Expand Up @@ -586,7 +586,7 @@ mod tests {

#[snapshot(single_page, settings_1)]
fn type3_color_glyphs(page: &mut Page) {
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0).unwrap();
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0, true).unwrap();
let mut surface = page.surface();

surface.fill_text(
Expand All @@ -603,7 +603,7 @@ mod tests {

#[snapshot(single_page, settings_17)]
fn type3_pdf_14(page: &mut Page) {
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0).unwrap();
let font = Font::new(TWITTER_COLOR_EMOJI.clone(), 0, true).unwrap();
let mut surface = page.surface();

surface.fill_text(
Expand Down
16 changes: 10 additions & 6 deletions crates/krilla/src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,15 @@ impl SerializerContext {
// For now, we make the simplifying assumption that a font is either mapped
// to a series of Type3 fonts or to a single CID font, but not a mix of both.
let font_ref = font.font_ref();
let use_type3 = font_ref.svg().is_ok()
|| font_ref.colr().is_ok()
|| font_ref.sbix().is_ok()
|| font_ref.cbdt().is_ok()
|| font_ref.ebdt().is_ok();
let use_type3 = if !font.allow_color() {
false
} else {
font_ref.svg().is_ok()
|| font_ref.colr().is_ok()
|| font_ref.sbix().is_ok()
|| font_ref.cbdt().is_ok()
|| font_ref.ebdt().is_ok()
};

if use_type3 {
Rc::new(RefCell::new(FontContainer::Type3(Type3FontMapper::new(
Expand Down Expand Up @@ -487,7 +491,7 @@ impl SerializerContext {
// cheaper, and then check whether we already have a corresponding font object in the cache.
// If not, we still need to construct it.
if let Some((font_data, index)) = unsafe { db.make_shared_face_data(id) } {
if let Some(font_info) = FontInfo::new(font_data.as_ref().as_ref(), index) {
if let Some(font_info) = FontInfo::new(font_data.as_ref().as_ref(), index, true) {
let font_info = Arc::new(font_info);
let font = self
.font_cache
Expand Down
32 changes: 16 additions & 16 deletions crates/krilla/src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ mod tests {

#[visreg]
fn text_direction_ltr(surface: &mut Surface) {
let font = Font::new(NOTO_SANS_CJK.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS_CJK.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -673,7 +673,7 @@ mod tests {

#[visreg]
fn text_direction_rtl(surface: &mut Surface) {
let font = Font::new(NOTO_SANS_CJK.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS_CJK.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -688,7 +688,7 @@ mod tests {

#[visreg]
fn text_direction_ttb(surface: &mut Surface) {
let font = Font::new(NOTO_SANS_CJK.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS_CJK.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(100.0, 0.0),
Fill::default(),
Expand All @@ -703,7 +703,7 @@ mod tests {

#[visreg]
fn text_direction_btt(surface: &mut Surface) {
let font = Font::new(NOTO_SANS_CJK.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS_CJK.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(100.0, 0.0),
Fill::default(),
Expand Down Expand Up @@ -783,7 +783,7 @@ mod tests {
surface.fill_text(
Point::from_xy(0.0, 50.0),
Fill::default(),
Font::new(NOTO_SANS.clone(), 0).unwrap(),
Font::new(NOTO_SANS.clone(), 0, true).unwrap(),
16.0,
&[],
"hi there",
Expand All @@ -797,7 +797,7 @@ mod tests {
surface.stroke_text(
Point::from_xy(0.0, 50.0),
Stroke::default(),
Font::new(NOTO_SANS.clone(), 0).unwrap(),
Font::new(NOTO_SANS.clone(), 0, true).unwrap(),
16.0,
&[],
"hi there",
Expand All @@ -811,7 +811,7 @@ mod tests {
surface.fill_text(
Point::from_xy(0.0, 50.0),
Fill::default(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0).unwrap(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0, true).unwrap(),
16.0,
&[],
"यह कुछ जटिल पाठ है.",
Expand All @@ -825,7 +825,7 @@ mod tests {
surface.fill_text(
Point::from_xy(0.0, 50.0),
Fill::default(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0).unwrap(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0, true).unwrap(),
16.0,
&[],
"यु॒धा नर॑ ऋ॒ष्वा ",
Expand All @@ -839,7 +839,7 @@ mod tests {
surface.fill_text(
Point::from_xy(0.0, 50.0),
Fill::default(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0).unwrap(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0, true).unwrap(),
16.0,
&[],
"आ रु॒क्मैरा यु॒धा नर॑ ऋ॒ष्वा ऋ॒ष्टीर॑सृक्षत ।",
Expand All @@ -853,7 +853,7 @@ mod tests {
surface.fill_text(
Point::from_xy(0.0, 50.0),
Fill::default(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0).unwrap(),
Font::new(NOTO_SANS_DEVANAGARI.clone(), 0, true).unwrap(),
16.0,
&[],
"अन्वे॑नाँ॒ अह॑ वि॒द्युतो॑ म॒रुतो॒ जज्झ॑तीरव भनर॑र्त॒ त्मना॑ दि॒वः ॥",
Expand Down Expand Up @@ -956,7 +956,7 @@ mod tests {
}

fn text_with_fill_impl(surface: &mut Surface, outlined: bool) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 80.0),
red_fill(0.5),
Expand Down Expand Up @@ -995,7 +995,7 @@ mod tests {
TextDirection::Auto,
);

let noto_font = Font::new(NOTO_COLOR_EMOJI_COLR.clone(), 0).unwrap();
let noto_font = Font::new(NOTO_COLOR_EMOJI_COLR.clone(), 0, true).unwrap();

surface.fill_text(
Point::from_xy(0.0, 140.0),
Expand Down Expand Up @@ -1031,7 +1031,7 @@ mod tests {
}

fn text_with_stroke_impl(surface: &mut Surface, outlined: bool) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
surface.stroke_text(
Point::from_xy(0.0, 80.0),
red_stroke(0.5, 1.0),
Expand Down Expand Up @@ -1070,7 +1070,7 @@ mod tests {
TextDirection::Auto,
);

let font = Font::new(NOTO_COLOR_EMOJI_COLR.clone(), 0).unwrap();
let font = Font::new(NOTO_COLOR_EMOJI_COLR.clone(), 0, true).unwrap();

surface.stroke_text(
Point::from_xy(0.0, 140.0),
Expand All @@ -1091,7 +1091,7 @@ mod tests {

#[visreg]
fn text_zalgo(surface: &mut Surface) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand All @@ -1106,7 +1106,7 @@ mod tests {

#[visreg]
fn text_zalgo_outlined(surface: &mut Surface) {
let font = Font::new(NOTO_SANS.clone(), 0).unwrap();
let font = Font::new(NOTO_SANS.clone(), 0, true).unwrap();
surface.fill_text(
Point::from_xy(0.0, 100.0),
Fill::default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/krilla/src/tagging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ mod tests {
impl SurfaceExt for Surface<'_> {
fn fill_text_(&mut self, y: f32, content: &str) {
let font_data = NOTO_SANS.clone();
let font = Font::new(font_data, 0).unwrap();
let font = Font::new(font_data, 0, true).unwrap();

self.fill_text(
tiny_skia_path::Point::from_xy(0.0, y),
Expand Down
Loading

0 comments on commit adbcf69

Please sign in to comment.