summaryrefslogtreecommitdiffstats
path: root/third_party/harfbuzz/chromium.patch
blob: 371c6e6bb2c181e77d9e244dfe3a1db0ded9f8ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
diff --git a/contrib/harfbuzz-unicode.c b/contrib/harfbuzz-unicode.c
index 72c5cf2..49e47b0 100644
--- a/contrib/harfbuzz-unicode.c
+++ b/contrib/harfbuzz-unicode.c
@@ -120,7 +120,6 @@ hb_utf16_script_run_next(unsigned *num_code_points, HB_ScriptItem *output,
         current_script = script;
         continue;
       } else if (script == HB_Script_Inherited) {
-        current_script = script;
         continue;
       } else {
         *iter = prev_iter;
@@ -171,7 +170,10 @@ hb_utf16_script_run_prev(unsigned *num_code_points, HB_ScriptItem *output,
         current_script = script;
         continue;
       } else if (script == HB_Script_Inherited) {
-        current_script = script;
+        // Just assume that whatever follows this combining character is within
+        // the same script.  This is incorrect if you had language1 + combining
+        // char + language 2, but that is rare and this code is suspicious
+        // anyway.
         continue;
       } else {
         *iter = prev_iter;
diff --git a/src/harfbuzz-arabic.c b/src/harfbuzz-arabic.c
index 51f839a..af40bf8 100644
--- a/src/harfbuzz-arabic.c
+++ b/src/harfbuzz-arabic.c
@@ -1107,6 +1107,7 @@ HB_Bool HB_ArabicShape(HB_ShaperItem *item)
     assert(item->item.script == HB_Script_Arabic || item->item.script == HB_Script_Syriac
            || item->item.script == HB_Script_Nko);

+    item->shaperFlags |= HB_ShaperFlag_ForceMarksToZeroWidth;
 #ifndef NO_OPENTYPE

     if (HB_SelectScript(item, item->item.script == HB_Script_Arabic ? arabic_features : syriac_features)) {
diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp
index 7fd04a9..66f0ea6 100644
--- a/src/harfbuzz-shaper.cpp
+++ b/src/harfbuzz-shaper.cpp
@@ -430,8 +430,6 @@ void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item)

     // ### zeroWidth and justification are missing here!!!!!

-    assert(item->num_glyphs <= length);
-
 //     qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs);
     HB_GlyphAttributes *attributes = item->attributes;
     unsigned short *logClusters = item->log_clusters;
@@ -448,7 +446,6 @@ void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item)
         }
         ++glyph_pos;
     }
-    assert(glyph_pos == item->num_glyphs);

     // first char in a run is never (treated as) a mark
     int cStart = 0;
@@ -1151,10 +1148,12 @@ HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)
         return false;
     face->tmpLogClusters = tmpLogClusters;

+    const int itemLength = item->item.length;
+    assert(itemLength > 0);
     for (int i = 0; i < face->length; ++i) {
         hb_buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i);
         face->tmpAttributes[i] = item->attributes[i];
-        face->tmpLogClusters[i] = item->log_clusters[i];
+        face->tmpLogClusters[i] = i < itemLength ? item->log_clusters[i] : item->log_clusters[itemLength - 1];
     }

 #ifdef OT_DEBUG
@@ -1190,6 +1189,24 @@ HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)
     return true;
 }

+/* See comments near the definition of HB_ShaperFlag_ForceMarksToZeroWidth for a description
+   of why this function exists. */
+void HB_FixupZeroWidth(HB_ShaperItem *item)
+{
+    HB_UShort property;
+
+    if (!item->face->gdef)
+        return;
+
+    for (unsigned int i = 0; i < item->num_glyphs; ++i) {
+        /* If the glyph is a mark, force its advance to zero. */
+        if (HB_GDEF_Get_Glyph_Property (item->face->gdef, item->glyphs[i], &property) == HB_Err_Ok &&
+            property == HB_GDEF_MARK) {
+            item->advances[i] = 0;
+        }
+    }
+}
+
 HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters)
 {
     HB_Face face = item->face;
@@ -1204,6 +1221,8 @@ HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool do

     if (!face->glyphs_substituted && !glyphs_positioned) {
         HB_GetGlyphAdvances(item);
+        if (item->face->current_flags & HB_ShaperFlag_ForceMarksToZeroWidth)
+            HB_FixupZeroWidth(item);
         return true; // nothing to do for us
     }

diff --git a/src/harfbuzz-shaper.h b/src/harfbuzz-shaper.h
index ab5c07a..72c9aa3 100644
--- a/src/harfbuzz-shaper.h
+++ b/src/harfbuzz-shaper.h
@@ -170,7 +170,11 @@ typedef enum {
 typedef enum {
     HB_ShaperFlag_Default = 0,
     HB_ShaperFlag_NoKerning = 1,
-    HB_ShaperFlag_UseDesignMetrics = 2
+    HB_ShaperFlag_UseDesignMetrics = 1 << 1,
+    /* Arabic vowels in some fonts (Times New Roman, at least) have
+       non-zero advances, when they should be zero.  Setting this shaper
+       flag causes us to zero out the advances for mark glyphs. */
+    HB_ShaperFlag_ForceMarksToZeroWidth = 1 << 2
 } HB_ShaperFlag;

 /*

diff --git a/third_party/harfbuzz/contrib/harfbuzz-freetype.c b/third_party/harfbuzz
index a2962df..f6a1e1a 100644
--- a/third_party/harfbuzz/contrib/harfbuzz-freetype.c
+++ b/third_party/harfbuzz/contrib/harfbuzz-freetype.c
@@ -21,7 +21,8 @@ hb_freetype_string_to_glyphs(HB_Font font,
   if (len > *numGlyphs)
     return 0;

-  size_t i = 0, j = 0;
+  ssize_t i = 0;
+  hb_uint32 j = 0;
   while (i < len) {
     const uint32_t cp = utf16_to_code_point(chars, len, &i);
     glyphs[j++] = FT_Get_Char_Index(face, cp);
@@ -53,7 +54,7 @@ static HB_Bool
 hb_freetype_can_render(HB_Font font, const HB_UChar16 *chars, hb_uint32 len) {
   FT_Face face = (FT_Face)font->userData;

-  size_t i = 0;
+  ssize_t i = 0;
   while (i < len) {
     const uint32_t cp = utf16_to_code_point(chars, len, &i);
     if (FT_Get_Char_Index(face, cp) == 0)