LibPDF: Make truetype fonts marked as symbol fonts actually work

Turns out the spec didn't mean that the whole range is populated,
but that one of these ranges is populated. So take the argmax.

As fallout, explicitly mark the Liberation fonts as nonsymbolic
when we use them for the 14 standard fonts. Else, we'd regress
"PostScrõpt", since the Liberation fonts would otherwise go down
the "is symbolic or doesn't have explicit encoding" codepath,
since the standard fonts usually don't have an explicit encoding.

As a fallout from _that_, since the 14 standard fonts now go down
the regular truetype rendering path, and since we don't implement
lookup by postscript name yet, glyphs not present in Liberation
now cause text to stop rendering with a diag, instead of rendering
a "glyph not found" symbol. That isn't super common, only an
additional 4 files appear for the "'post' table not yet implemented"
diag. Since we'll implement that soon, this seems fine until then.
This commit is contained in:
Nico Weber 2024-03-06 18:40:19 -05:00 committed by Tim Flynn
parent 2e2cae26c6
commit 3a39939995
Notes: sideshowbarker 2024-07-16 21:42:29 +09:00
3 changed files with 32 additions and 15 deletions

View File

@ -39,10 +39,15 @@ public:
// TABLE 5.20 Font flags
bool is_fixed_pitch() const { return m_flags & (1 << (1 - 1)); }
bool is_serif() const { return m_flags & (1 << (2 - 1)); }
bool is_symbolic() const { return m_flags & (1 << (3 - 1)); }
static constexpr unsigned Symbolic = 1 << (3 - 1);
bool is_symbolic() const { return m_flags & Symbolic; }
bool is_script() const { return m_flags & (1 << (4 - 1)); }
// Note: No bit position 5.
bool is_nonsymbolic() const { return m_flags & (1 << (6 - 1)); }
static constexpr unsigned NonSymbolic = 1 << (6 - 1);
bool is_nonsymbolic() const { return m_flags & NonSymbolic; }
bool is_italic() const { return m_flags & (1 << (7 - 1)); }
// Note: Big jump in bit positions.
bool is_all_cap() const { return m_flags & (1 << (17 - 1)); }

View File

@ -37,23 +37,26 @@ NonnullOwnPtr<TrueTypePainter> TrueTypePainter::create(Document* document, Nonnu
}
}
// See long spec comment in TrueTypeFont::draw_glyp().
// See long spec comment in TrueTypeFont::draw_glyph().
Optional<u8> high_byte;
if (!dict->contains(CommonNames::Encoding) || containing_pdf_font.is_symbolic()) {
// FIXME: Looks like this is never hit in the test set (?).
for (u8 prefix : { 0x00, 0xF0, 0xF1, 0xF2 }) {
bool has_all = true;
Array<u8, 4> prefixes { 0x00, 0xF0, 0xF1, 0xF2 };
Array<size_t, prefixes.size()> counts { 0, 0, 0, 0 };
for (size_t i = 0; i < prefixes.size(); ++i) {
for (unsigned suffix = 0x00; suffix <= 0xFF; ++suffix) {
if (!font->contains_glyph((prefix << 8) | suffix)) {
has_all = false;
break;
}
}
if (has_all) {
high_byte = prefix;
break;
if (font->contains_glyph((prefixes[i] << 8) | suffix))
counts[i] += 1;
}
}
size_t max = 0, max_index = -1;
for (size_t i = 0; i < counts.size(); ++i) {
if (counts[i] > max) {
max = counts[i];
max_index = i;
}
}
if (max > 0)
high_byte = max_index;
}
return adopt_own(*new TrueTypePainter { move(font), move(encoding), encoding_is_mac_roman_or_win_ansi, containing_pdf_font.is_nonsymbolic(), high_byte, is_zapf_dingbats });

View File

@ -54,6 +54,10 @@ PDFErrorOr<void> Type1Font::initialize(Document* document, NonnullRefPtr<DictObj
auto font = TRY(replacement_for(base_font_name().to_lowercase(), font_size));
auto effective_encoding = encoding();
bool is_standard_14_font = base_font_name() == "Helvetica" || base_font_name() == "Helvetica-Bold" || base_font_name() == "Helvetica-Oblique" || base_font_name() == "Helvetica-BoldOblique"
|| base_font_name() == "Times-Roman" || base_font_name() == "Times-Bold" || base_font_name() == "Times-Italic" || base_font_name() == "Times-BoldItalic"
|| base_font_name() == "Courier" || base_font_name() == "Courier-Bold" || base_font_name() == "Courier-Oblique" || base_font_name() == "Courier-BoldOblique"
|| base_font_name() == "Symbol" || base_font_name() == "ZapfDingbats";
if (!effective_encoding) {
// PDF 1.7 spec, APPENDIX D Character Sets and Encodings
// "Sections D.4, “Symbol Set and Encoding,” and D.5, “ZapfDingbats Set and Encoding,”
@ -73,7 +77,12 @@ PDFErrorOr<void> Type1Font::initialize(Document* document, NonnullRefPtr<DictObj
effective_encoding = Encoding::standard_encoding();
}
// FIXME: For the standard 14 fonts, set some m_flags bits (symbolic/nonsymbolic, italic, bold, fixed pitch, serif).
if (is_standard_14_font) {
// We use the Liberation fonts as a replacement for the standard 14 fonts, and they're all non-symbolic.
m_flags = (m_flags | NonSymbolic) & ~Symbolic;
// FIXME: Set more m_flags bits (symbolic/nonsymbolic, italic, bold, fixed pitch, serif).
}
m_fallback_font_painter = TrueTypePainter::create(document, dict, *this, *font, *effective_encoding, base_font_name() == "ZapfDingbats"sv);
}