summaryrefslogtreecommitdiffstats
path: root/gfx/ots/ots-1850314.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/ots/ots-1850314.patch')
-rw-r--r--gfx/ots/ots-1850314.patch177
1 files changed, 177 insertions, 0 deletions
diff --git a/gfx/ots/ots-1850314.patch b/gfx/ots/ots-1850314.patch
new file mode 100644
index 0000000000..88088f5064
--- /dev/null
+++ b/gfx/ots/ots-1850314.patch
@@ -0,0 +1,177 @@
+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
+
+ Differential Revision: https://phabricator.services.mozilla.com/D187096
+
+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
+ // http://www.microsoft.com/typography/otspec/glyf.htm
+@@ -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
++// https://gitlab.freedesktop.org/freetype/freetype/-/blob/2d9fce53d4ce89f36075168282fcdd7289e082f9/src/truetype/ttobjs.c#L170-241
++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;