Skip to content

Commit

Permalink
Merge pull request #637 from googlefonts/bitmaps
Browse files Browse the repository at this point in the history
[read-fonts] parse embedded bitmap tables
  • Loading branch information
dfrg authored Oct 10, 2023
2 parents a08ca98 + 05d977f commit ca4fea8
Show file tree
Hide file tree
Showing 23 changed files with 3,062 additions and 11 deletions.
31 changes: 22 additions & 9 deletions font-codegen/src/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use quote::{quote, ToTokens};
use syn::spanned::Spanned;

use super::parsing::{
logged_syn_error, Attr, Count, CustomCompile, Field, FieldReadArgs, FieldType, FieldValidation,
Fields, NeededWhen, OffsetTarget, Phase, Record, ReferencedFields,
logged_syn_error, Attr, Count, CountArg, CustomCompile, Field, FieldReadArgs, FieldType,
FieldValidation, Fields, NeededWhen, OffsetTarget, Phase, Record, ReferencedFields,
};

impl Fields {
Expand Down Expand Up @@ -401,8 +401,9 @@ fn traversal_arm_for_field(
let data = fld.offset_getter_data_src();
quote!(Field::new(#name_str, traversal::FieldType::var_array(#typ_str, self.#name()#maybe_unwrap, #data)))
}
// HACK: who wouldn't want to hard-code ValueRecord handling
FieldType::Struct { typ } if typ == "ValueRecord" => {
// See if there are better ways to handle these hardcoded types
// <https://github.com/googlefonts/fontations/issues/659>
FieldType::Struct { typ } if typ == "ValueRecord" || typ == "SbitLineMetrics" => {
let offset_data = pass_data
.cloned()
.unwrap_or_else(|| fld.offset_getter_data_src());
Expand Down Expand Up @@ -475,10 +476,16 @@ impl Field {
}

pub(crate) fn is_zerocopy_compatible(&self) -> bool {
matches!(
self.typ,
FieldType::Scalar { .. } | FieldType::Offset { .. }
)
// hack: we want to add `FieldType::Struct` here but don't want to
// catch `ValueRecord` so use this attribute to ignore it.
// Fields that require args for reading can't be read "zerocopy"
// anyway.
// <https://github.com/googlefonts/fontations/issues/659>
self.attrs.read_with_args.is_none()
&& matches!(
self.typ,
FieldType::Scalar { .. } | FieldType::Offset { .. } | FieldType::Struct { .. }
)
}

pub(crate) fn is_array(&self) -> bool {
Expand Down Expand Up @@ -1012,7 +1019,13 @@ impl Field {
}
_ => unreachable!("count not valid here"),
};
quote!( #count_expr * #size_expr )
match other {
Count::SingleArg(CountArg::Literal(lit)) if lit.base10_digits() == "1" => {
// Prevent identity-op clippy error with `1 * size`
size_expr
}
_ => quote!( #count_expr * #size_expr ),
}
}
None => quote!(compile_error!("missing count attribute?")),
};
Expand Down
11 changes: 9 additions & 2 deletions font-codegen/src/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,17 @@ pub(crate) fn generate(item: &Record, all_items: &Items) -> syn::Result<TokenStr
}
});
let maybe_impl_read_with_args = (has_read_args).then(|| generate_read_with_args(item));
let maybe_extra_traits = item
let mut maybe_extra_traits = item
.gets_extra_traits(all_items)
.then(|| quote!(PartialEq, Eq, PartialOrd, Ord, Hash));

// Just make all records Copy?
// <https://github.com/googlefonts/fontations/issues/659>
if item.name == "SbitLineMetrics" {
use quote::TokenStreamExt;
let mut copy_trait = quote!(Copy,);
copy_trait.append_all(maybe_extra_traits.unwrap_or_default());
maybe_extra_traits = Some(copy_trait);
}
Ok(quote! {
#( #docs )*
#[derive(Clone, Debug, #maybe_extra_traits)]
Expand Down
2 changes: 2 additions & 0 deletions font-test-data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub static CANTARELL_VF_TRIMMED_GLYPHS: &str =

pub static CHARSTRING_PATH_OPS: &[u8] = include_bytes!("../test_data/ttf/charstring_path_ops.ttf");

pub static EMBEDDED_BITMAPS: &[u8] = include_bytes!("../test_data/ttf/embedded_bitmaps.ttf");

pub mod post {

#[rustfmt::skip]
Expand Down
Binary file added font-test-data/test_data/ttf/embedded_bitmaps.ttf
Binary file not shown.
246 changes: 246 additions & 0 deletions font-test-data/test_data/ttx/embedded_bitmaps.ttx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.37">
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xe34c4a3"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1024"/>
<created value="Sat Nov 5 18:46:15 2022"/>
<modified value="Sat Nov 5 18:46:15 2022"/>
<xMin value="51"/>
<yMin value="-250"/>
<xMax value="998"/>
<yMax value="950"/>
<macStyle value="00000000 00000011"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>

<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="eblc_3_ebdt_2"/>
<GlyphID id="2" name="eblc_3_ebdt_2_glyph2"/>
<GlyphID id="3" name="eblc_2_ebdt_5"/>
<GlyphID id="4" name="noto_emoji_style_ebdt"/>
</GlyphOrder>

<maxp>
<tableVersion value="0x5000"/>
<numGlyphs value="4"/>
</maxp>

<EBDT>
<header version="2.0"/>
<strikedata index="0">
<ebdt_bitmap_format_2 name="eblc_3_ebdt_2">
<SmallGlyphMetrics>
<height value="8"/>
<width value="3"/>
<BearingX value="1"/>
<BearingY value="6"/>
<Advance value="4"/>
</SmallGlyphMetrics>
<rawimagedata>
eeaeea
</rawimagedata>
</ebdt_bitmap_format_2>
<ebdt_bitmap_format_2 name="eblc_3_ebdt_2_glyph2">
<SmallGlyphMetrics>
<height value="8"/>
<width value="4"/>
<BearingX value="0"/>
<BearingY value="6"/>
<Advance value="4"/>
</SmallGlyphMetrics>
<rawimagedata>
f0f0f0f0
</rawimagedata>
</ebdt_bitmap_format_2>
</strikedata>
<strikedata index="1">
<ebdt_bitmap_format_5 name="eblc_2_ebdt_5">
<rawimagedata>
aabbccdd 00112233 ffee1234 424242aa
88990011
</rawimagedata>
</ebdt_bitmap_format_5>
</strikedata>
</EBDT>

<EBLC>
<header version="2.0"/>
<strike index="0">
<bitmapSizeTable>
<sbitLineMetrics direction="hori">
<ascender value="6"/>
<descender value="2"/>
<widthMax value="4"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="6"/>
<minAfterBL value="-2"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<sbitLineMetrics direction="vert">
<ascender value="6"/>
<descender value="2"/>
<widthMax value="0"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="0"/>
<minAfterBL value="0"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<colorRef value="0"/>
<startGlyphIndex value="1"/>
<endGlyphIndex value="2"/>
<ppemX value="7"/>
<ppemY value="7"/>
<bitDepth value="1"/>
<flags value="1"/>
</bitmapSizeTable>
<!-- GlyphIds are written but not read. The firstGlyphIndex and
lastGlyphIndex values will be recalculated by the compiler. -->
<eblc_index_sub_table_3 imageFormat="2" firstGlyphIndex="1" lastGlyphIndex="2">
<glyphLoc id="1" name="eblc_3_ebdt_2"/>
<glyphLoc id="2" name="eblc_3_ebdt_2_glyph2"/>
</eblc_index_sub_table_3>
</strike>
<strike index="1">
<bitmapSizeTable>
<sbitLineMetrics direction="hori">
<ascender value="12"/>
<descender value="5"/>
<widthMax value="9"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="12"/>
<minAfterBL value="-5"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<sbitLineMetrics direction="vert">
<ascender value="12"/>
<descender value="5"/>
<widthMax value="0"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="0"/>
<minAfterBL value="0"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<colorRef value="0"/>
<startGlyphIndex value="3"/>
<endGlyphIndex value="3"/>
<ppemX value="15"/>
<ppemY value="15"/>
<bitDepth value="1"/>
<flags value="1"/>
</bitmapSizeTable>
<!-- GlyphIds are written but not read. The firstGlyphIndex and
lastGlyphIndex values will be recalculated by the compiler. -->
<eblc_index_sub_table_2 imageFormat="5" firstGlyphIndex="3" lastGlyphIndex="3">
<imageSize value="20"/>
<BigGlyphMetrics>
<height value="17"/>
<width value="9"/>
<horiBearingX value="0"/>
<horiBearingY value="12"/>
<horiAdvance value="9"/>
<vertBearingX value="-4"/>
<vertBearingY value="-9"/>
<vertAdvance value="0"/>
</BigGlyphMetrics>
<glyphLoc id="3" name="eblc_2_ebdt_5"/>
</eblc_index_sub_table_2>
</strike>
</EBLC>

<CBDT>
<header version="3.0"/>
<strikedata index="0">
<cbdt_bitmap_format_17 name="noto_emoji_style_ebdt">
<SmallGlyphMetrics>
<height value="128"/>
<width value="136"/>
<BearingX value="0"/>
<BearingY value="101"/>
<Advance value="136"/>
</SmallGlyphMetrics>
<rawimagedata>
89504e47 0d0a1a0a
</rawimagedata>
</cbdt_bitmap_format_17>
</strikedata>
</CBDT>

<CBLC>
<header version="3.0"/>
<strike index="0">
<bitmapSizeTable>
<sbitLineMetrics direction="hori">
<ascender value="101"/>
<descender value="-27"/>
<widthMax value="136"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="0"/>
<minAfterBL value="0"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<sbitLineMetrics direction="vert">
<ascender value="101"/>
<descender value="-27"/>
<widthMax value="136"/>
<caretSlopeNumerator value="0"/>
<caretSlopeDenominator value="0"/>
<caretOffset value="0"/>
<minOriginSB value="0"/>
<minAdvanceSB value="0"/>
<maxBeforeBL value="0"/>
<minAfterBL value="0"/>
<pad1 value="0"/>
<pad2 value="0"/>
</sbitLineMetrics>
<colorRef value="0"/>
<startGlyphIndex value="4"/>
<endGlyphIndex value="4"/>
<ppemX value="109"/>
<ppemY value="109"/>
<bitDepth value="32"/>
<flags value="1"/>
</bitmapSizeTable>
<!-- GlyphIds are written but not read. The firstGlyphIndex and
lastGlyphIndex values will be recalculated by the compiler. -->
<eblc_index_sub_table_1 imageFormat="17" firstGlyphIndex="4" lastGlyphIndex="4">
<glyphLoc id="4" name="noto_emoji_style_ebdt"/>
</eblc_index_sub_table_1>
</strike>
</CBLC>

</ttFont>
Loading

0 comments on commit ca4fea8

Please sign in to comment.