Line data Source code
1 : /*
2 : * Copyright © 2010,2011,2012 Google, Inc.
3 : *
4 : * This is part of HarfBuzz, a text shaping library.
5 : *
6 : * Permission is hereby granted, without written agreement and without
7 : * license or royalty fees, to use, copy, modify, and distribute this
8 : * software and its documentation for any purpose, provided that the
9 : * above copyright notice and the following two paragraphs appear in
10 : * all copies of this software.
11 : *
12 : * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 : * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 : * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 : * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 : * DAMAGE.
17 : *
18 : * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 : * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 : * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 : * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 : * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 : *
24 : * Google Author(s): Behdad Esfahbod
25 : */
26 :
27 : #ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
28 : #define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
29 :
30 : #include "hb-private.hh"
31 :
32 : #include "hb-ot-shape-private.hh"
33 : #include "hb-ot-shape-normalize-private.hh"
34 :
35 :
36 :
37 : /* buffer var allocations, used by complex shapers */
38 : #define complex_var_u8_0() var2.u8[2]
39 : #define complex_var_u8_1() var2.u8[3]
40 :
41 :
42 : enum hb_ot_shape_zero_width_marks_type_t {
43 : HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
44 : HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
45 : HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
46 : };
47 :
48 :
49 : /* Master OT shaper list */
50 : #define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
51 : HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
52 : HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
53 : HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
54 : HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
55 : HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
56 : HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
57 : HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
58 : HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
59 : HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
60 : HB_COMPLEX_SHAPER_IMPLEMENT (use) \
61 : /* ^--- Add new shapers here */
62 :
63 :
64 : struct hb_ot_complex_shaper_t
65 : {
66 : char name[8];
67 :
68 : /* collect_features()
69 : * Called during shape_plan().
70 : * Shapers should use plan->map to add their features and callbacks.
71 : * May be NULL.
72 : */
73 : void (*collect_features) (hb_ot_shape_planner_t *plan);
74 :
75 : /* override_features()
76 : * Called during shape_plan().
77 : * Shapers should use plan->map to override features and add callbacks after
78 : * common features are added.
79 : * May be NULL.
80 : */
81 : void (*override_features) (hb_ot_shape_planner_t *plan);
82 :
83 :
84 : /* data_create()
85 : * Called at the end of shape_plan().
86 : * Whatever shapers return will be accessible through plan->data later.
87 : * If NULL is returned, means a plan failure.
88 : */
89 : void *(*data_create) (const hb_ot_shape_plan_t *plan);
90 :
91 : /* data_destroy()
92 : * Called when the shape_plan is being destroyed.
93 : * plan->data is passed here for destruction.
94 : * If NULL is returned, means a plan failure.
95 : * May be NULL.
96 : */
97 : void (*data_destroy) (void *data);
98 :
99 :
100 : /* preprocess_text()
101 : * Called during shape().
102 : * Shapers can use to modify text before shaping starts.
103 : * May be NULL.
104 : */
105 : void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
106 : hb_buffer_t *buffer,
107 : hb_font_t *font);
108 :
109 : /* postprocess_glyphs()
110 : * Called during shape().
111 : * Shapers can use to modify glyphs after shaping ends.
112 : * May be NULL.
113 : */
114 : void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
115 : hb_buffer_t *buffer,
116 : hb_font_t *font);
117 :
118 :
119 : hb_ot_shape_normalization_mode_t normalization_preference;
120 :
121 : /* decompose()
122 : * Called during shape()'s normalization.
123 : * May be NULL.
124 : */
125 : bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
126 : hb_codepoint_t ab,
127 : hb_codepoint_t *a,
128 : hb_codepoint_t *b);
129 :
130 : /* compose()
131 : * Called during shape()'s normalization.
132 : * May be NULL.
133 : */
134 : bool (*compose) (const hb_ot_shape_normalize_context_t *c,
135 : hb_codepoint_t a,
136 : hb_codepoint_t b,
137 : hb_codepoint_t *ab);
138 :
139 : /* setup_masks()
140 : * Called during shape().
141 : * Shapers should use map to get feature masks and set on buffer.
142 : * Shapers may NOT modify characters.
143 : * May be NULL.
144 : */
145 : void (*setup_masks) (const hb_ot_shape_plan_t *plan,
146 : hb_buffer_t *buffer,
147 : hb_font_t *font);
148 :
149 : /* disable_otl()
150 : * Called during shape().
151 : * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
152 : * and fallback operations used.
153 : * May be NULL.
154 : */
155 : bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
156 :
157 : hb_ot_shape_zero_width_marks_type_t zero_width_marks;
158 :
159 : bool fallback_position;
160 : };
161 :
162 : #define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
163 : HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
164 : #undef HB_COMPLEX_SHAPER_IMPLEMENT
165 :
166 :
167 : static inline const hb_ot_complex_shaper_t *
168 2 : hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
169 : {
170 2 : switch ((hb_tag_t) planner->props.script)
171 : {
172 : default:
173 2 : return &_hb_ot_complex_shaper_default;
174 :
175 :
176 : /* Unicode-1.1 additions */
177 : case HB_SCRIPT_ARABIC:
178 :
179 : /* Unicode-3.0 additions */
180 : case HB_SCRIPT_MONGOLIAN:
181 : case HB_SCRIPT_SYRIAC:
182 :
183 : /* Unicode-5.0 additions */
184 : case HB_SCRIPT_NKO:
185 : case HB_SCRIPT_PHAGS_PA:
186 :
187 : /* Unicode-6.0 additions */
188 : case HB_SCRIPT_MANDAIC:
189 :
190 : /* Unicode-7.0 additions */
191 : case HB_SCRIPT_MANICHAEAN:
192 : case HB_SCRIPT_PSALTER_PAHLAVI:
193 :
194 : /* Unicode-9.0 additions */
195 : case HB_SCRIPT_ADLAM:
196 :
197 : /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
198 : * This is because we do fallback shaping for Arabic script (and not others).
199 : * But note that Arabic shaping is applicable only to horizontal layout; for
200 : * vertical text, just use the generic shaper instead. */
201 0 : if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
202 0 : planner->props.script == HB_SCRIPT_ARABIC) &&
203 0 : HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
204 0 : return &_hb_ot_complex_shaper_arabic;
205 : else
206 0 : return &_hb_ot_complex_shaper_default;
207 :
208 :
209 : /* Unicode-1.1 additions */
210 : case HB_SCRIPT_THAI:
211 : case HB_SCRIPT_LAO:
212 :
213 0 : return &_hb_ot_complex_shaper_thai;
214 :
215 :
216 : /* Unicode-1.1 additions */
217 : case HB_SCRIPT_HANGUL:
218 :
219 0 : return &_hb_ot_complex_shaper_hangul;
220 :
221 :
222 : /* Unicode-2.0 additions */
223 : case HB_SCRIPT_TIBETAN:
224 :
225 0 : return &_hb_ot_complex_shaper_tibetan;
226 :
227 :
228 : /* Unicode-1.1 additions */
229 : case HB_SCRIPT_HEBREW:
230 :
231 0 : return &_hb_ot_complex_shaper_hebrew;
232 :
233 :
234 : /* ^--- Add new shapers here */
235 :
236 : #if 0
237 : /* Unicode-4.1 additions */
238 : case HB_SCRIPT_NEW_TAI_LUE:
239 : #endif
240 :
241 : /* Unicode-1.1 additions */
242 : case HB_SCRIPT_BENGALI:
243 : case HB_SCRIPT_DEVANAGARI:
244 : case HB_SCRIPT_GUJARATI:
245 : case HB_SCRIPT_GURMUKHI:
246 : case HB_SCRIPT_KANNADA:
247 : case HB_SCRIPT_MALAYALAM:
248 : case HB_SCRIPT_ORIYA:
249 : case HB_SCRIPT_TAMIL:
250 : case HB_SCRIPT_TELUGU:
251 :
252 : /* Unicode-3.0 additions */
253 : case HB_SCRIPT_SINHALA:
254 :
255 : /* If the designer designed the font for the 'DFLT' script,
256 : * use the default shaper. Otherwise, use the specific shaper.
257 : * Note that for some simple scripts, there may not be *any*
258 : * GSUB/GPOS needed, so there may be no scripts found! */
259 0 : if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
260 0 : return &_hb_ot_complex_shaper_default;
261 : else
262 0 : return &_hb_ot_complex_shaper_indic;
263 :
264 : case HB_SCRIPT_KHMER:
265 : /* A number of Khmer fonts in the wild don't have a 'pref' feature,
266 : * and as such won't shape properly via the Indic shaper;
267 : * however, they typically have 'liga' / 'clig' features that implement
268 : * the necessary "reordering" by means of ligature substitutions.
269 : * So we send such pref-less fonts through the generic shaper instead. */
270 0 : if (planner->map.found_script[0] &&
271 0 : hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
272 0 : planner->map.script_index[0],
273 0 : planner->map.language_index[0],
274 : HB_TAG ('p','r','e','f'),
275 : NULL))
276 0 : return &_hb_ot_complex_shaper_indic;
277 : else
278 0 : return &_hb_ot_complex_shaper_default;
279 :
280 : case HB_SCRIPT_MYANMAR:
281 0 : if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
282 0 : return &_hb_ot_complex_shaper_myanmar;
283 0 : else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
284 0 : return &_hb_ot_complex_shaper_myanmar_old;
285 : else
286 0 : return &_hb_ot_complex_shaper_default;
287 :
288 :
289 : /* Unicode-2.0 additions */
290 : //case HB_SCRIPT_TIBETAN:
291 :
292 : /* Unicode-3.0 additions */
293 : //case HB_SCRIPT_MONGOLIAN:
294 : //case HB_SCRIPT_SINHALA:
295 :
296 : /* Unicode-3.2 additions */
297 : case HB_SCRIPT_BUHID:
298 : case HB_SCRIPT_HANUNOO:
299 : case HB_SCRIPT_TAGALOG:
300 : case HB_SCRIPT_TAGBANWA:
301 :
302 : /* Unicode-4.0 additions */
303 : case HB_SCRIPT_LIMBU:
304 : case HB_SCRIPT_TAI_LE:
305 :
306 : /* Unicode-4.1 additions */
307 : case HB_SCRIPT_BUGINESE:
308 : case HB_SCRIPT_KHAROSHTHI:
309 : case HB_SCRIPT_SYLOTI_NAGRI:
310 : case HB_SCRIPT_TIFINAGH:
311 :
312 : /* Unicode-5.0 additions */
313 : case HB_SCRIPT_BALINESE:
314 : //case HB_SCRIPT_NKO:
315 : //case HB_SCRIPT_PHAGS_PA:
316 :
317 : /* Unicode-5.1 additions */
318 : case HB_SCRIPT_CHAM:
319 : case HB_SCRIPT_KAYAH_LI:
320 : case HB_SCRIPT_LEPCHA:
321 : case HB_SCRIPT_REJANG:
322 : case HB_SCRIPT_SAURASHTRA:
323 : case HB_SCRIPT_SUNDANESE:
324 :
325 : /* Unicode-5.2 additions */
326 : case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
327 : case HB_SCRIPT_JAVANESE:
328 : case HB_SCRIPT_KAITHI:
329 : case HB_SCRIPT_MEETEI_MAYEK:
330 : case HB_SCRIPT_TAI_THAM:
331 : case HB_SCRIPT_TAI_VIET:
332 :
333 : /* Unicode-6.0 additions */
334 : case HB_SCRIPT_BATAK:
335 : case HB_SCRIPT_BRAHMI:
336 : //case HB_SCRIPT_MANDAIC:
337 :
338 : /* Unicode-6.1 additions */
339 : case HB_SCRIPT_CHAKMA:
340 : case HB_SCRIPT_SHARADA:
341 : case HB_SCRIPT_TAKRI:
342 :
343 : /* Unicode-7.0 additions */
344 : case HB_SCRIPT_DUPLOYAN:
345 : case HB_SCRIPT_GRANTHA:
346 : case HB_SCRIPT_KHOJKI:
347 : case HB_SCRIPT_KHUDAWADI:
348 : case HB_SCRIPT_MAHAJANI:
349 : //case HB_SCRIPT_MANICHAEAN:
350 : case HB_SCRIPT_MODI:
351 : case HB_SCRIPT_PAHAWH_HMONG:
352 : //case HB_SCRIPT_PSALTER_PAHLAVI:
353 : case HB_SCRIPT_SIDDHAM:
354 : case HB_SCRIPT_TIRHUTA:
355 :
356 : /* Unicode-8.0 additions */
357 : case HB_SCRIPT_AHOM:
358 : //case HB_SCRIPT_MULTANI:
359 :
360 : /* Unicode-9.0 additions */
361 : case HB_SCRIPT_BHAIKSUKI:
362 : case HB_SCRIPT_MARCHEN:
363 : case HB_SCRIPT_NEWA:
364 :
365 : /* If the designer designed the font for the 'DFLT' script,
366 : * use the default shaper. Otherwise, use the specific shaper.
367 : * Note that for some simple scripts, there may not be *any*
368 : * GSUB/GPOS needed, so there may be no scripts found! */
369 0 : if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
370 0 : return &_hb_ot_complex_shaper_default;
371 : else
372 0 : return &_hb_ot_complex_shaper_use;
373 : }
374 : }
375 :
376 :
377 : #endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
|