Source code

Revision control

Copy as Markdown

Other Tools

commit 362a59be47f9e187eec43df0938def661be6c972
Author: Jonathan Kew <jkew@mozilla.com>
Date: Wed Aug 30 12:55:02 2023 +0000
Bug 1850314 - Don't do glyph bounding-box fixup for "tricky" fonts, because it may disrupt glyph rendering on macOS. r=gfx-reviewers,lsalzman
diff --git a/src/glyf.cc b/src/glyf.cc
index 0ed9515ef16d6..31487957bf99b 100644
--- a/src/glyf.cc
+++ b/src/glyf.cc
@@ -10,6 +10,7 @@
#include "head.h"
#include "loca.h"
#include "maxp.h"
+#include "name.h"
// glyf - Glyph Data
@@ -97,7 +98,8 @@ bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
int16_t& xmin,
int16_t& ymin,
int16_t& xmax,
- int16_t& ymax) {
+ int16_t& ymax,
+ bool is_tricky_font) {
// read the end-points array
uint16_t num_flags = 0;
for (int i = 0; i < num_contours; ++i) {
@@ -219,27 +221,32 @@ bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
}
if (adjusted_bbox) {
- Warning("Glyph bbox was incorrect; adjusting (glyph %u)", gid);
- // copy the numberOfContours field
- this->iov.push_back(std::make_pair(glyph.buffer(), 2));
- // output a fixed-up version of the bounding box
- uint8_t* fixed_bbox = new uint8_t[8];
- fixed_bboxes.push_back(fixed_bbox);
- xmin = ots_htons(xmin);
- std::memcpy(fixed_bbox, &xmin, 2);
- ymin = ots_htons(ymin);
- std::memcpy(fixed_bbox + 2, &ymin, 2);
- xmax = ots_htons(xmax);
- std::memcpy(fixed_bbox + 4, &xmax, 2);
- ymax = ots_htons(ymax);
- std::memcpy(fixed_bbox + 6, &ymax, 2);
- this->iov.push_back(std::make_pair(fixed_bbox, 8));
- // copy the remainder of the glyph data
- this->iov.push_back(std::make_pair(glyph.buffer() + 10, glyph.offset() - 10));
- } else {
- this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
+ if (is_tricky_font) {
+ Warning("Glyph bbox was incorrect; NOT adjusting tricky font (glyph %u)", gid);
+ } else {
+ Warning("Glyph bbox was incorrect; adjusting (glyph %u)", gid);
+ // copy the numberOfContours field
+ this->iov.push_back(std::make_pair(glyph.buffer(), 2));
+ // output a fixed-up version of the bounding box
+ uint8_t* fixed_bbox = new uint8_t[8];
+ fixed_bboxes.push_back(fixed_bbox);
+ xmin = ots_htons(xmin);
+ std::memcpy(fixed_bbox, &xmin, 2);
+ ymin = ots_htons(ymin);
+ std::memcpy(fixed_bbox + 2, &ymin, 2);
+ xmax = ots_htons(xmax);
+ std::memcpy(fixed_bbox + 4, &xmax, 2);
+ ymax = ots_htons(ymax);
+ std::memcpy(fixed_bbox + 6, &ymax, 2);
+ this->iov.push_back(std::make_pair(fixed_bbox, 8));
+ // copy the remainder of the glyph data
+ this->iov.push_back(std::make_pair(glyph.buffer() + 10, glyph.offset() - 10));
+ return true;
+ }
}
+ this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
+
return true;
}
@@ -342,6 +349,10 @@ bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
return Error("Missing maxp or loca or head table needed by glyf table");
}
+ OpenTypeNAME *name = static_cast<OpenTypeNAME*>(
+ GetFont()->GetTypedTable(OTS_TAG_NAME));
+ bool is_tricky = name->IsTrickyFont();
+
this->maxp = maxp;
const unsigned num_glyphs = maxp->num_glyphs;
@@ -397,7 +408,7 @@ bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
// does we will simply ignore it.
glyph.set_offset(0);
} else if (num_contours > 0) {
- if (!ParseSimpleGlyph(glyph, i, num_contours, xmin, ymin, xmax, ymax)) {
+ if (!ParseSimpleGlyph(glyph, i, num_contours, xmin, ymin, xmax, ymax, is_tricky)) {
return Error("Failed to parse glyph %d", i);
}
} else {
diff --git a/src/glyf.h b/src/glyf.h
index 05e846f1cb6e8..f85fdc4652fcf 100644
--- a/src/glyf.h
+++ b/src/glyf.h
@@ -51,7 +51,8 @@ class OpenTypeGLYF : public Table {
int16_t& xmin,
int16_t& ymin,
int16_t& xmax,
- int16_t& ymax);
+ int16_t& ymax,
+ bool is_tricky_font);
bool ParseCompositeGlyph(
Buffer &glyph,
ComponentPointCount* component_point_count);
diff --git a/src/name.cc b/src/name.cc
index fc5074b0587a3..7526e1f72b9ea 100644
--- a/src/name.cc
+++ b/src/name.cc
@@ -366,4 +366,44 @@ bool OpenTypeNAME::IsValidNameId(uint16_t nameID, bool addIfMissing) {
return this->name_ids.count(nameID);
}
+// List of font names considered "tricky" (dependent on applying original TrueType instructions) by FreeType, see
+static const char* tricky_font_names[] = {
+ "cpop",
+ "DFGirl-W6-WIN-BF",
+ "DFGothic-EB",
+ "DFGyoSho-Lt",
+ "DFHei",
+ "DFHSGothic-W5",
+ "DFHSMincho-W3",
+ "DFHSMincho-W7",
+ "DFKaiSho-SB",
+ "DFKaiShu",
+ "DFKai-SB",
+ "DFMing",
+ "DLC",
+ "HuaTianKaiTi?",
+ "HuaTianSongTi?",
+ "Ming(for ISO10646)",
+ "MingLiU",
+ "MingMedium",
+ "PMingLiU",
+ "MingLi43"
+};
+
+bool OpenTypeNAME::IsTrickyFont() const {
+ for (const auto& name : this->names) {
+ const uint16_t id = name.name_id;
+ if (id != 1) {
+ continue;
+ }
+ for (const auto* p : tricky_font_names) {
+ if (name.text.find(p) != std::string::npos) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
} // namespace
diff --git a/src/name.h b/src/name.h
index 68c7ac096d3f8..a241e77ee26bb 100644
--- a/src/name.h
+++ b/src/name.h
@@ -52,6 +52,7 @@ class OpenTypeNAME : public Table {
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
bool IsValidNameId(uint16_t nameID, bool addIfMissing = false);
+ bool IsTrickyFont() const;
private:
std::vector<NameRecord> names;