Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / gfx / ots / ots-1850314.patch
blob88088f5064d5e7bee2fbceb6ec6758239e923a91
1 commit 362a59be47f9e187eec43df0938def661be6c972
2 Author: Jonathan Kew <jkew@mozilla.com>
3 Date: Wed Aug 30 12:55:02 2023 +0000
5 Bug 1850314 - Don't do glyph bounding-box fixup for "tricky" fonts, because it may disrupt glyph rendering on macOS. r=gfx-reviewers,lsalzman
7 Differential Revision: https://phabricator.services.mozilla.com/D187096
9 diff --git a/src/glyf.cc b/src/glyf.cc
10 index 0ed9515ef16d6..31487957bf99b 100644
11 --- a/src/glyf.cc
12 +++ b/src/glyf.cc
13 @@ -10,6 +10,7 @@
14 #include "head.h"
15 #include "loca.h"
16 #include "maxp.h"
17 +#include "name.h"
19 // glyf - Glyph Data
20 // http://www.microsoft.com/typography/otspec/glyf.htm
21 @@ -97,7 +98,8 @@ bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
22 int16_t& xmin,
23 int16_t& ymin,
24 int16_t& xmax,
25 - int16_t& ymax) {
26 + int16_t& ymax,
27 + bool is_tricky_font) {
28 // read the end-points array
29 uint16_t num_flags = 0;
30 for (int i = 0; i < num_contours; ++i) {
31 @@ -219,27 +221,32 @@ bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
34 if (adjusted_bbox) {
35 - Warning("Glyph bbox was incorrect; adjusting (glyph %u)", gid);
36 - // copy the numberOfContours field
37 - this->iov.push_back(std::make_pair(glyph.buffer(), 2));
38 - // output a fixed-up version of the bounding box
39 - uint8_t* fixed_bbox = new uint8_t[8];
40 - fixed_bboxes.push_back(fixed_bbox);
41 - xmin = ots_htons(xmin);
42 - std::memcpy(fixed_bbox, &xmin, 2);
43 - ymin = ots_htons(ymin);
44 - std::memcpy(fixed_bbox + 2, &ymin, 2);
45 - xmax = ots_htons(xmax);
46 - std::memcpy(fixed_bbox + 4, &xmax, 2);
47 - ymax = ots_htons(ymax);
48 - std::memcpy(fixed_bbox + 6, &ymax, 2);
49 - this->iov.push_back(std::make_pair(fixed_bbox, 8));
50 - // copy the remainder of the glyph data
51 - this->iov.push_back(std::make_pair(glyph.buffer() + 10, glyph.offset() - 10));
52 - } else {
53 - this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
54 + if (is_tricky_font) {
55 + Warning("Glyph bbox was incorrect; NOT adjusting tricky font (glyph %u)", gid);
56 + } else {
57 + Warning("Glyph bbox was incorrect; adjusting (glyph %u)", gid);
58 + // copy the numberOfContours field
59 + this->iov.push_back(std::make_pair(glyph.buffer(), 2));
60 + // output a fixed-up version of the bounding box
61 + uint8_t* fixed_bbox = new uint8_t[8];
62 + fixed_bboxes.push_back(fixed_bbox);
63 + xmin = ots_htons(xmin);
64 + std::memcpy(fixed_bbox, &xmin, 2);
65 + ymin = ots_htons(ymin);
66 + std::memcpy(fixed_bbox + 2, &ymin, 2);
67 + xmax = ots_htons(xmax);
68 + std::memcpy(fixed_bbox + 4, &xmax, 2);
69 + ymax = ots_htons(ymax);
70 + std::memcpy(fixed_bbox + 6, &ymax, 2);
71 + this->iov.push_back(std::make_pair(fixed_bbox, 8));
72 + // copy the remainder of the glyph data
73 + this->iov.push_back(std::make_pair(glyph.buffer() + 10, glyph.offset() - 10));
74 + return true;
75 + }
78 + this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
80 return true;
83 @@ -342,6 +349,10 @@ bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
84 return Error("Missing maxp or loca or head table needed by glyf table");
87 + OpenTypeNAME *name = static_cast<OpenTypeNAME*>(
88 + GetFont()->GetTypedTable(OTS_TAG_NAME));
89 + bool is_tricky = name->IsTrickyFont();
91 this->maxp = maxp;
93 const unsigned num_glyphs = maxp->num_glyphs;
94 @@ -397,7 +408,7 @@ bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
95 // does we will simply ignore it.
96 glyph.set_offset(0);
97 } else if (num_contours > 0) {
98 - if (!ParseSimpleGlyph(glyph, i, num_contours, xmin, ymin, xmax, ymax)) {
99 + if (!ParseSimpleGlyph(glyph, i, num_contours, xmin, ymin, xmax, ymax, is_tricky)) {
100 return Error("Failed to parse glyph %d", i);
102 } else {
103 diff --git a/src/glyf.h b/src/glyf.h
104 index 05e846f1cb6e8..f85fdc4652fcf 100644
105 --- a/src/glyf.h
106 +++ b/src/glyf.h
107 @@ -51,7 +51,8 @@ class OpenTypeGLYF : public Table {
108 int16_t& xmin,
109 int16_t& ymin,
110 int16_t& xmax,
111 - int16_t& ymax);
112 + int16_t& ymax,
113 + bool is_tricky_font);
114 bool ParseCompositeGlyph(
115 Buffer &glyph,
116 ComponentPointCount* component_point_count);
117 diff --git a/src/name.cc b/src/name.cc
118 index fc5074b0587a3..7526e1f72b9ea 100644
119 --- a/src/name.cc
120 +++ b/src/name.cc
121 @@ -366,4 +366,44 @@ bool OpenTypeNAME::IsValidNameId(uint16_t nameID, bool addIfMissing) {
122 return this->name_ids.count(nameID);
125 +// List of font names considered "tricky" (dependent on applying original TrueType instructions) by FreeType, see
126 +// https://gitlab.freedesktop.org/freetype/freetype/-/blob/2d9fce53d4ce89f36075168282fcdd7289e082f9/src/truetype/ttobjs.c#L170-241
127 +static const char* tricky_font_names[] = {
128 + "cpop",
129 + "DFGirl-W6-WIN-BF",
130 + "DFGothic-EB",
131 + "DFGyoSho-Lt",
132 + "DFHei",
133 + "DFHSGothic-W5",
134 + "DFHSMincho-W3",
135 + "DFHSMincho-W7",
136 + "DFKaiSho-SB",
137 + "DFKaiShu",
138 + "DFKai-SB",
139 + "DFMing",
140 + "DLC",
141 + "HuaTianKaiTi?",
142 + "HuaTianSongTi?",
143 + "Ming(for ISO10646)",
144 + "MingLiU",
145 + "MingMedium",
146 + "PMingLiU",
147 + "MingLi43"
150 +bool OpenTypeNAME::IsTrickyFont() const {
151 + for (const auto& name : this->names) {
152 + const uint16_t id = name.name_id;
153 + if (id != 1) {
154 + continue;
156 + for (const auto* p : tricky_font_names) {
157 + if (name.text.find(p) != std::string::npos) {
158 + return true;
162 + return false;
165 } // namespace
166 diff --git a/src/name.h b/src/name.h
167 index 68c7ac096d3f8..a241e77ee26bb 100644
168 --- a/src/name.h
169 +++ b/src/name.h
170 @@ -52,6 +52,7 @@ class OpenTypeNAME : public Table {
171 bool Parse(const uint8_t *data, size_t length);
172 bool Serialize(OTSStream *out);
173 bool IsValidNameId(uint16_t nameID, bool addIfMissing = false);
174 + bool IsTrickyFont() const;
176 private:
177 std::vector<NameRecord> names;