11dcaa1ca0cf44131097f38d509334989c67a403
[framework/uifw/harfbuzz.git] / src / hb-ot-shape.cc
1 /*
2  * Copyright (C) 2009,2010  Red Hat, Inc.
3  * Copyright (C) 2010  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28
29 #include "hb-ot-shape-private.h"
30
31 #include "hb-open-type-private.hh"
32
33 #include "hb-ot-layout.h"
34
35 HB_BEGIN_DECLS
36
37
38 /* XXX vertical */
39 hb_tag_t default_features[] = {
40   HB_TAG('c','a','l','t'),
41   HB_TAG('c','c','m','p'),
42   HB_TAG('c','l','i','g'),
43   HB_TAG('c','s','w','h'),
44   HB_TAG('c','u','r','s'),
45   HB_TAG('k','e','r','n'),
46   HB_TAG('l','i','g','a'),
47   HB_TAG('l','o','c','l'),
48   HB_TAG('m','a','r','k'),
49   HB_TAG('m','k','m','k'),
50   HB_TAG('r','l','i','g')
51 };
52
53 #define MAX_FEATURES 100 /* FIXME */
54 #define MAX_LOOKUPS 1000 /* FIXME */
55
56 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
57
58
59 struct hb_mask_allocator_t {
60
61   struct feature_info_t {
62     hb_tag_t tag;
63     unsigned int value;
64     unsigned int seq;
65     bool global;
66
67     static int
68     cmp (const void *p1, const void *p2)
69     {
70       const feature_info_t *a = reinterpret_cast<const feature_info_t *>(p1);
71       const feature_info_t *b = reinterpret_cast<const feature_info_t *>(p2);
72
73       if (a->tag != b->tag)
74         return a->tag < b->tag ? -1 : 1;
75
76       return a->seq < b->seq ? -1 : 1;
77     }
78   };
79
80   struct feature_map_t {
81     hb_tag_t tag; /* should be first for our bsearch to work */
82     unsigned int index[2]; /* GSUB, GPOS */
83     unsigned int shift;
84     hb_mask_t mask;
85
86     static int
87     cmp (const void *p1, const void *p2)
88     {
89       const feature_map_t *a = reinterpret_cast<const feature_map_t *>(p1);
90       const feature_map_t *b = reinterpret_cast<const feature_map_t *>(p2);
91
92       return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
93     }
94   };
95
96   struct lookup_map_t {
97     unsigned int index;
98     hb_mask_t mask;
99
100     static int
101     cmp (const void *p1, const void *p2)
102     {
103       const lookup_map_t *a = reinterpret_cast<const lookup_map_t *>(p1);
104       const lookup_map_t *b = reinterpret_cast<const lookup_map_t *>(p2);
105
106       return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
107     }
108   };
109
110
111   void
112   add_lookups (hb_ot_shape_context_t *c,
113                unsigned int  table_index,
114                unsigned int  feature_index,
115                hb_mask_t     mask)
116   {
117     unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
118     lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
119
120     unsigned int *lookup_indices = (unsigned int *) lookups;
121
122     hb_ot_layout_feature_get_lookup_indexes (c->face,
123                                              table_tags[table_index],
124                                              feature_index,
125                                              0, &i,
126                                              lookup_indices);
127
128     lookup_count[table_index] += i;
129
130     while (i--) {
131       lookups[i].mask = mask;
132       lookups[i].index = lookup_indices[i];
133     }
134   }
135
136
137
138
139   hb_mask_allocator_t (void) : feature_count (0) {}
140
141   void add_feature (hb_tag_t tag,
142                     unsigned int value,
143                     bool global)
144   {
145     feature_info_t *info = &feature_infos[feature_count++];
146     info->tag = tag;
147     info->value = value;
148     info->seq = feature_count;
149     info->global = global;
150   }
151
152   void compile (hb_ot_shape_context_t *c)
153   {
154    global_mask = 0;
155    lookup_count[0] = lookup_count[1] = 0;
156
157     if (!feature_count)
158       return;
159
160
161     /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
162      * features not available in either table and not waste precious bits for them. */
163
164     const hb_tag_t *script_tags;
165     hb_tag_t language_tag;
166
167     script_tags = hb_ot_tags_from_script (c->buffer->props.script);
168     language_tag = hb_ot_tag_from_language (c->buffer->props.language);
169
170     unsigned int script_index[2], language_index[2];
171     for (unsigned int table_index = 0; table_index < 2; table_index++) {
172       hb_tag_t table_tag = table_tags[table_index];
173       hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
174       hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
175     }
176
177
178     /* Sort the features so we can bsearch later */
179     qsort (feature_infos, feature_count, sizeof (feature_infos[0]), feature_info_t::cmp);
180
181     /* Remove dups, let later-occurring features override earlier ones. */
182     unsigned int j = 0;
183     for (unsigned int i = 1; i < feature_count; i++)
184       if (feature_infos[i].tag != feature_infos[j].tag)
185         feature_infos[++j] = feature_infos[i];
186       else {
187         if (feature_infos[i].global)
188           feature_infos[j] = feature_infos[i];
189         else {
190           feature_infos[j].global = feature_infos[j].global && (feature_infos[j].value == feature_infos[i].value);
191           feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
192         }
193       }
194     feature_count = j + 1;
195
196
197     /* Allocate bits now */
198     unsigned int next_bit = 1;
199     j = 0;
200     for (unsigned int i = 0; i < feature_count; i++) {
201       const feature_info_t *info = &feature_infos[i];
202
203       unsigned int bits_needed;
204
205       if (info->global && info->value == 1)
206         /* Uses the global bit */
207         bits_needed = 0;
208       else
209         bits_needed = _hb_bit_storage (info->value);
210
211       if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
212         continue; /* Feature disabled, or not enough bits. */
213
214
215       bool found = false;
216       unsigned int feature_index[2];
217       for (unsigned int table_index = 0; table_index < 2; table_index++)
218         found |= hb_ot_layout_language_find_feature (c->face,
219                                                      table_tags[table_index],
220                                                      script_index[table_index],
221                                                      language_index[table_index],
222                                                      info->tag,
223                                                      &feature_index[table_index]);
224       if (!found)
225         continue;
226
227
228       feature_map_t *map = &feature_maps[j++];
229
230       map->tag = info->tag;
231       map->index[0] = feature_index[0];
232       map->index[1] = feature_index[1];
233       if (info->global && info->value == 1) {
234         /* Uses the global bit */
235         map->shift = 0;
236         map->mask = 1;
237       } else {
238         map->shift = next_bit;
239         map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
240         next_bit += bits_needed;
241         if (info->global)
242           global_mask |= map->mask;
243       }
244
245     }
246     feature_count = j;
247
248
249     for (unsigned int table_index = 0; table_index < 2; table_index++) {
250       hb_tag_t table_tag = table_tags[table_index];
251
252       /* Collect lookup indices for features */
253
254       unsigned int required_feature_index;
255       if (hb_ot_layout_language_get_required_feature_index (c->face,
256                                                             table_tag,
257                                                             script_index[table_index],
258                                                             language_index[table_index],
259                                                             &required_feature_index))
260         add_lookups (c, table_index, required_feature_index, 1);
261
262       for (unsigned i = 0; i < feature_count; i++)
263         add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
264
265       /* Sort lookups and merge duplicates */
266
267       qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), lookup_map_t::cmp);
268
269       if (lookup_count[table_index])
270       {
271         unsigned int j = 0;
272         for (unsigned int i = 1; i < lookup_count[table_index]; i++)
273           if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
274             lookup_maps[table_index][++j] = lookup_maps[table_index][i];
275           else
276             lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
277         j++;
278         lookup_count[table_index] = j;
279       }
280     }
281   }
282
283   hb_mask_t get_global_mask (void) { return global_mask; }
284
285   const feature_map_t *find_feature (hb_tag_t tag) const {
286     static const feature_map_t off_map = { HB_TAG_NONE, {Index::NOT_FOUND_INDEX,Index::NOT_FOUND_INDEX}, 0, 0 };
287     const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), feature_map_t::cmp);
288     return map ? map : &off_map;
289   }
290
291   void substitute (hb_ot_shape_context_t *c) const {
292     for (unsigned int i = 0; i < lookup_count[0]; i++)
293       hb_ot_layout_substitute_lookup (c->face, c->buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
294   }
295
296   void position (hb_ot_shape_context_t *c) const {
297     for (unsigned int i = 0; i < lookup_count[1]; i++)
298       hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
299   }
300
301   private:
302
303   hb_mask_t global_mask;
304
305   unsigned int feature_count;
306   feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
307   feature_map_t feature_maps[MAX_FEATURES];
308
309   lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
310   unsigned int lookup_count[2];
311 };
312
313 static void
314 hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
315                               hb_mask_allocator_t   *allocator)
316 {
317   switch (c->original_direction) {
318     case HB_DIRECTION_LTR:
319       allocator->add_feature (HB_TAG ('l','t','r','a'), 1, true);
320       allocator->add_feature (HB_TAG ('l','t','r','m'), 1, true);
321       break;
322     case HB_DIRECTION_RTL:
323       allocator->add_feature (HB_TAG ('r','t','l','a'), 1, true);
324       allocator->add_feature (HB_TAG ('r','t','l','m'), 1, false);
325       break;
326     case HB_DIRECTION_TTB:
327     case HB_DIRECTION_BTT:
328     default:
329       break;
330   }
331
332   for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
333     allocator->add_feature (default_features[i], 1, true);
334
335   /* complex */
336
337   for (unsigned int i = 0; i < c->num_features; i++) {
338     const hb_feature_t *feature = &c->features[i];
339     allocator->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
340   }
341 }
342
343
344 static void
345 hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
346                            hb_mask_allocator_t   *allocator)
347 {
348   hb_ot_shape_collect_features (c, allocator);
349
350   /* Compile features */
351   allocator->compile (c);
352
353   /* Set masks in buffer */
354
355   hb_mask_t global_mask = allocator->get_global_mask ();
356   if (global_mask)
357     c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
358
359   for (unsigned int i = 0; i < c->num_features; i++)
360   {
361     hb_feature_t *feature = &c->features[i];
362     const hb_mask_allocator_t::feature_map_t *map = allocator->find_feature (feature->tag);
363     if (!(feature->start == 0 && feature->end == (unsigned int)-1))
364       c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
365   }
366
367   /* complex */
368 }
369
370
371 static void
372 hb_ot_substitute_complex (hb_ot_shape_context_t *c,
373                           const hb_mask_allocator_t *allocator)
374 {
375   if (!hb_ot_layout_has_substitution (c->face))
376     return;
377
378   allocator->substitute (c);
379
380   c->applied_substitute_complex = TRUE;
381   return;
382 }
383
384 static void
385 hb_ot_position_complex (hb_ot_shape_context_t *c,
386                         const hb_mask_allocator_t *allocator)
387 {
388
389   if (!hb_ot_layout_has_positioning (c->face))
390     return;
391
392   allocator->position (c);
393
394   hb_ot_layout_position_finish (c->font, c->face, c->buffer);
395
396   c->applied_position_complex = TRUE;
397   return;
398 }
399
400
401 /* Main shaper */
402
403 /* Prepare */
404
405 static inline hb_bool_t
406 is_variation_selector (hb_codepoint_t unicode)
407 {
408   return unlikely ((unicode >=  0x180B && unicode <=  0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
409                    (unicode >=  0xFE00 && unicode <=  0xFE0F) || /* VARIATION SELECTOR-1..16 */
410                    (unicode >= 0xE0100 && unicode <= 0xE01EF));  /* VARIATION SELECTOR-17..256 */
411 }
412
413 static void
414 hb_form_clusters (hb_buffer_t *buffer)
415 {
416   unsigned int count = buffer->len;
417   for (unsigned int i = 1; i < count; i++)
418     if (buffer->unicode->v.get_general_category (buffer->info[i].codepoint) == HB_CATEGORY_NON_SPACING_MARK)
419       buffer->info[i].cluster = buffer->info[i - 1].cluster;
420 }
421
422 static void
423 hb_ensure_native_direction (hb_buffer_t *buffer)
424 {
425   hb_direction_t direction = buffer->props.direction;
426
427   /* TODO vertical */
428   if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
429       direction != _hb_script_get_horizontal_direction (buffer->props.script))
430   {
431     hb_buffer_reverse_clusters (buffer);
432     buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
433   }
434 }
435
436
437 /* Substitute */
438
439 static void
440 hb_mirror_chars (hb_buffer_t *buffer)
441 {
442   hb_unicode_get_mirroring_func_t get_mirroring = buffer->unicode->v.get_mirroring;
443
444   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
445     return;
446
447 //  map = allocator.find_feature (HB_TAG ('r','t','l','m'));
448
449   unsigned int count = buffer->len;
450   for (unsigned int i = 0; i < count; i++) {
451     hb_codepoint_t codepoint = get_mirroring (buffer->info[i].codepoint);
452     if (likely (codepoint == buffer->info[i].codepoint))
453 ;//      buffer->info[i].mask |= map->mask;
454     else
455       buffer->info[i].codepoint = codepoint;
456   }
457 }
458
459 static void
460 hb_map_glyphs (hb_font_t    *font,
461                hb_face_t    *face,
462                hb_buffer_t  *buffer)
463 {
464   if (unlikely (!buffer->len))
465     return;
466
467   buffer->clear_output ();
468   unsigned int count = buffer->len - 1;
469   for (buffer->i = 0; buffer->i < count;) {
470     if (unlikely (is_variation_selector (buffer->info[buffer->i + 1].codepoint))) {
471       buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, buffer->info[buffer->i + 1].codepoint));
472       buffer->i++;
473     } else {
474       buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
475     }
476   }
477   if (likely (buffer->i < buffer->len))
478     buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
479   buffer->swap ();
480 }
481
482 static void
483 hb_substitute_default (hb_ot_shape_context_t *c)
484 {
485   hb_map_glyphs (c->font, c->face, c->buffer);
486 }
487
488 static void
489 hb_substitute_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
490 {
491   /* TODO Arabic */
492 }
493
494
495 /* Position */
496
497 static void
498 hb_position_default (hb_ot_shape_context_t *c)
499 {
500   hb_buffer_clear_positions (c->buffer);
501
502   unsigned int count = c->buffer->len;
503   for (unsigned int i = 0; i < count; i++) {
504     hb_glyph_metrics_t metrics;
505     hb_font_get_glyph_metrics (c->font, c->face, c->buffer->info[i].codepoint, &metrics);
506     c->buffer->pos[i].x_advance = metrics.x_advance;
507     c->buffer->pos[i].y_advance = metrics.y_advance;
508   }
509 }
510
511 static void
512 hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
513 {
514   /* TODO Mark pos */
515 }
516
517 static void
518 hb_truetype_kern (hb_ot_shape_context_t *c)
519 {
520   /* TODO Check for kern=0 */
521   unsigned int count = c->buffer->len;
522   for (unsigned int i = 1; i < count; i++) {
523     hb_position_t kern, kern1, kern2;
524     kern = hb_font_get_kerning (c->font, c->face, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint);
525     kern1 = kern >> 1;
526     kern2 = kern - kern1;
527     c->buffer->pos[i - 1].x_advance += kern1;
528     c->buffer->pos[i].x_advance += kern2;
529     c->buffer->pos[i].x_offset += kern2;
530   }
531 }
532
533 static void
534 hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
535 {
536   hb_truetype_kern (c);
537 }
538
539
540 /* Do it! */
541
542 static void
543 hb_ot_shape_internal (hb_ot_shape_context_t *c)
544 {
545   hb_mask_allocator_t allocator;
546
547   hb_ot_shape_setup_lookups (c, &allocator);
548
549
550   hb_form_clusters (c->buffer);
551
552   /* SUBSTITUTE */
553   {
554     c->buffer->clear_masks ();
555
556     /* Mirroring needs to see the original direction */
557     hb_mirror_chars (c->buffer);
558
559     hb_ensure_native_direction (c->buffer);
560
561     hb_substitute_default (c);
562
563     hb_ot_substitute_complex (c, &allocator);
564
565     if (!c->applied_substitute_complex)
566       hb_substitute_complex_fallback (c);
567   }
568
569   /* POSITION */
570   {
571     c->buffer->clear_masks ();
572
573     hb_position_default (c);
574
575     hb_ot_position_complex (c, &allocator);
576
577     hb_bool_t position_fallback = !c->applied_position_complex;
578     if (position_fallback)
579       hb_position_complex_fallback (c);
580
581     if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
582       hb_buffer_reverse (c->buffer);
583
584     if (position_fallback)
585       hb_position_complex_fallback_visual (c);
586   }
587
588   c->buffer->props.direction = c->original_direction;
589 }
590
591 void
592 hb_ot_shape (hb_font_t    *font,
593              hb_face_t    *face,
594              hb_buffer_t  *buffer,
595              hb_feature_t *features,
596              unsigned int  num_features)
597 {
598   hb_ot_shape_context_t c = {font, face, buffer, features, num_features};
599
600   /* Setup transient context members */
601   c.original_direction = buffer->props.direction;
602
603   hb_ot_shape_internal (&c);
604 }
605
606
607 HB_END_DECLS