1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 04:27:45 +00:00

LibPDF/CFF: Compute per-glyph glyph width in CID-keyed fonts

Make TopDict's defaultWidthX and nominalWidthX Optional<>s so that
we can check if they're set per fdselect-selected font dict, and
if so use the value from there in CID-keyed fonts. Otherwise, keep
using the value in the top dict.
This commit is contained in:
Nico Weber 2024-02-15 07:44:22 -05:00 committed by Tim Flynn
parent 4348b484c6
commit 5c8778a161
2 changed files with 19 additions and 9 deletions

View file

@ -214,24 +214,34 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
}
// CFF spec, "18 CID-keyed Fonts"
Vector<TopDict> font_dicts;
if (top_dict.fdarray_offset != 0) {
Reader fdarray_reader { cff_bytes.slice(top_dict.fdarray_offset) };
auto font_dicts = TRY(parse_top_dicts(fdarray_reader, cff_bytes));
font_dicts = TRY(parse_top_dicts(fdarray_reader, cff_bytes));
dbgln_if(CFF_DEBUG, "CFF has {} FDArray entries", font_dicts.size());
}
// CFF spec, "19 FDSelect"
Vector<u8> fdselect;
if (top_dict.fdselect_offset != 0) {
auto fdselect = TRY(parse_fdselect(Reader { cff_bytes.slice(top_dict.fdselect_offset) }, glyphs.size()));
fdselect = TRY(parse_fdselect(Reader { cff_bytes.slice(top_dict.fdselect_offset) }, glyphs.size()));
dbgln_if(CFF_DEBUG, "CFF has {} FDSelect entries", fdselect.size());
}
// Adjust glyphs' widths as they are deltas from nominalWidthX
for (auto& glyph : glyphs) {
if (!glyph.has_width())
glyph.set_width(top_dict.defaultWidthX);
else
glyph.set_width(glyph.width() + top_dict.nominalWidthX);
for (size_t glyph_id = 0; glyph_id < glyphs.size(); glyph_id++) {
auto& glyph = glyphs[glyph_id];
if (!glyph.has_width()) {
auto default_width = top_dict.defaultWidthX.value_or(0.0f);
if (top_dict.is_cid_keyed)
default_width = font_dicts[fdselect[glyph_id]].defaultWidthX.value_or(default_width);
glyph.set_width(default_width);
} else {
auto nominal_width = top_dict.nominalWidthX.value_or(0.0f);
if (top_dict.is_cid_keyed)
nominal_width = font_dicts[fdselect[glyph_id]].nominalWidthX.value_or(nominal_width);
glyph.set_width(glyph.width() + nominal_width);
}
}
for (size_t i = 0; i < glyphs.size(); i++) {

View file

@ -124,8 +124,8 @@ public:
int encoding_offset = 0;
int charstrings_offset = 0;
Vector<ByteBuffer> local_subroutines;
float defaultWidthX = 0;
float nominalWidthX = 0;
Optional<float> defaultWidthX;
Optional<float> nominalWidthX;
bool is_cid_keyed = false;
int fdselect_offset = 0;
int fdarray_offset = 0;