25 */ |
25 */ |
26 |
26 |
27 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH |
27 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH |
28 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH |
28 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH |
29 |
29 |
30 #include "hb-private.hh" |
30 #include "hb.hh" |
31 |
31 |
32 #include "hb-ot-shape-private.hh" |
32 #include "hb-ot-shape.hh" |
33 #include "hb-ot-layout-gsub-table.hh" |
33 #include "hb-ot-layout-gsub-table.hh" |
34 |
34 |
35 |
35 |
36 /* Features ordered the same as the entries in shaping_table rows, |
36 /* Features ordered the same as the entries in shaping_table rows, |
37 * followed by rlig. Don't change. */ |
37 * followed by rlig. Don't change. */ |
77 |
77 |
78 /* Bubble-sort or something equally good! |
78 /* Bubble-sort or something equally good! |
79 * May not be good-enough for presidential candidate interviews, but good-enough for us... */ |
79 * May not be good-enough for presidential candidate interviews, but good-enough for us... */ |
80 hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]); |
80 hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]); |
81 |
81 |
82 OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs); |
|
83 OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs); |
|
84 |
82 |
85 /* Each glyph takes four bytes max, and there's some overhead. */ |
83 /* Each glyph takes four bytes max, and there's some overhead. */ |
86 char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128]; |
84 char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128]; |
87 OT::hb_serialize_context_t c (buf, sizeof (buf)); |
85 hb_serialize_context_t c (buf, sizeof (buf)); |
88 OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> (); |
86 OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> (); |
89 bool ret = lookup->serialize_single (&c, |
87 bool ret = lookup->serialize_single (&c, |
90 OT::LookupFlag::IgnoreMarks, |
88 OT::LookupFlag::IgnoreMarks, |
91 glyphs_supplier, |
89 hb_array (glyphs, num_glyphs), |
92 substitutes_supplier, |
90 hb_array (substitutes, num_glyphs)); |
93 num_glyphs); |
|
94 c.end_serialize (); |
91 c.end_serialize (); |
95 /* TODO sanitize the results? */ |
92 /* TODO sanitize the results? */ |
96 |
93 |
97 return ret ? c.copy<OT::SubstLookup> () : nullptr; |
94 return ret ? c.copy<OT::SubstLookup> () : nullptr; |
98 } |
95 } |
153 } |
150 } |
154 |
151 |
155 if (!num_ligatures) |
152 if (!num_ligatures) |
156 return nullptr; |
153 return nullptr; |
157 |
154 |
158 OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs); |
|
159 OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs); |
|
160 OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures); |
|
161 OT::Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures); |
|
162 OT::Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures); |
|
163 |
155 |
164 /* 16 bytes per ligature ought to be enough... */ |
156 /* 16 bytes per ligature ought to be enough... */ |
165 char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128]; |
157 char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128]; |
166 OT::hb_serialize_context_t c (buf, sizeof (buf)); |
158 hb_serialize_context_t c (buf, sizeof (buf)); |
167 OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> (); |
159 OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> (); |
168 bool ret = lookup->serialize_ligature (&c, |
160 bool ret = lookup->serialize_ligature (&c, |
169 OT::LookupFlag::IgnoreMarks, |
161 OT::LookupFlag::IgnoreMarks, |
170 first_glyphs_supplier, |
162 hb_array (first_glyphs, num_first_glyphs), |
171 ligature_per_first_glyph_count_supplier, |
163 hb_array (ligature_per_first_glyph_count_list, num_first_glyphs), |
172 num_first_glyphs, |
164 hb_array (ligature_list, num_ligatures), |
173 ligatures_supplier, |
165 hb_array (component_count_list, num_ligatures), |
174 component_count_supplier, |
166 hb_array (component_list, num_ligatures)); |
175 component_supplier); |
|
176 |
|
177 c.end_serialize (); |
167 c.end_serialize (); |
178 /* TODO sanitize the results? */ |
168 /* TODO sanitize the results? */ |
179 |
169 |
180 return ret ? c.copy<OT::SubstLookup> () : nullptr; |
170 return ret ? c.copy<OT::SubstLookup> () : nullptr; |
181 } |
171 } |
193 |
183 |
194 #define ARABIC_FALLBACK_MAX_LOOKUPS 5 |
184 #define ARABIC_FALLBACK_MAX_LOOKUPS 5 |
195 |
185 |
196 struct arabic_fallback_plan_t |
186 struct arabic_fallback_plan_t |
197 { |
187 { |
198 ASSERT_POD (); |
|
199 |
|
200 unsigned int num_lookups; |
188 unsigned int num_lookups; |
201 bool free_lookups; |
189 bool free_lookups; |
202 |
190 |
203 hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
191 hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
204 OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
192 OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
205 hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
193 OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; |
206 }; |
194 }; |
207 |
195 |
208 static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; |
196 #if defined(_WIN32) && !defined(HB_NO_WIN1256) |
209 |
|
210 #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) |
|
211 #define HB_WITH_WIN1256 |
197 #define HB_WITH_WIN1256 |
212 #endif |
198 #endif |
213 |
199 |
214 #ifdef HB_WITH_WIN1256 |
200 #ifdef HB_WITH_WIN1256 |
215 #include "hb-ot-shape-complex-arabic-win1256.hh" |
201 #include "hb-ot-shape-complex-arabic-win1256.hh" |
216 #endif |
202 #endif |
217 |
203 |
218 struct ManifestLookup { |
204 struct ManifestLookup |
|
205 { |
|
206 public: |
219 OT::Tag tag; |
207 OT::Tag tag; |
220 OT::OffsetTo<OT::SubstLookup> lookupOffset; |
208 OT::OffsetTo<OT::SubstLookup> lookupOffset; |
|
209 public: |
|
210 DEFINE_SIZE_STATIC (6); |
221 }; |
211 }; |
222 typedef OT::ArrayOf<ManifestLookup> Manifest; |
212 typedef OT::ArrayOf<ManifestLookup> Manifest; |
223 |
213 |
224 static bool |
214 static bool |
225 arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, |
215 arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED, |
226 const hb_ot_shape_plan_t *plan, |
216 const hb_ot_shape_plan_t *plan HB_UNUSED, |
227 hb_font_t *font) |
217 hb_font_t *font HB_UNUSED) |
228 { |
218 { |
229 #ifdef HB_WITH_WIN1256 |
219 #ifdef HB_WITH_WIN1256 |
230 /* Does this font look like it's Windows-1256-encoded? */ |
220 /* Does this font look like it's Windows-1256-encoded? */ |
231 hb_codepoint_t g; |
221 hb_codepoint_t g; |
232 if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ && |
222 if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ && |
297 arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, |
287 arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, |
298 hb_font_t *font) |
288 hb_font_t *font) |
299 { |
289 { |
300 arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t)); |
290 arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t)); |
301 if (unlikely (!fallback_plan)) |
291 if (unlikely (!fallback_plan)) |
302 return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil); |
292 return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t)); |
303 |
293 |
304 fallback_plan->num_lookups = 0; |
294 fallback_plan->num_lookups = 0; |
305 fallback_plan->free_lookups = false; |
295 fallback_plan->free_lookups = false; |
306 |
296 |
307 /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms, |
297 /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms, |
312 /* See if this looks like a Windows-1256-encoded font. If it does, use a |
302 /* See if this looks like a Windows-1256-encoded font. If it does, use a |
313 * hand-coded GSUB table. */ |
303 * hand-coded GSUB table. */ |
314 if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) |
304 if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) |
315 return fallback_plan; |
305 return fallback_plan; |
316 |
306 |
|
307 assert (fallback_plan->num_lookups == 0); |
317 free (fallback_plan); |
308 free (fallback_plan); |
318 return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil); |
309 return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t)); |
319 } |
310 } |
320 |
311 |
321 static void |
312 static void |
322 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) |
313 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) |
323 { |
314 { |
324 if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) |
315 if (!fallback_plan || fallback_plan->num_lookups == 0) |
325 return; |
316 return; |
326 |
317 |
327 for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) |
318 for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) |
328 if (fallback_plan->lookup_array[i]) |
319 if (fallback_plan->lookup_array[i]) |
329 { |
320 { |