More refactoring
[apps/core/preloaded/video-player.git] / src / hb-ot-map.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-map-private.hh"
30
31 #include "hb-ot-shape-private.hh"
32
33 HB_BEGIN_DECLS
34
35
36 void
37 hb_ot_map_t::add_lookups (hb_ot_shape_plan_context_t *c,
38                           unsigned int  table_index,
39                           unsigned int  feature_index,
40                           hb_mask_t     mask)
41 {
42   unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
43   lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
44
45   unsigned int *lookup_indices = (unsigned int *) lookups;
46
47   hb_ot_layout_feature_get_lookup_indexes (c->face,
48                                            table_tags[table_index],
49                                            feature_index,
50                                            0, &i,
51                                            lookup_indices);
52
53   lookup_count[table_index] += i;
54
55   while (i--) {
56     lookups[i].mask = mask;
57     lookups[i].index = lookup_indices[i];
58   }
59 }
60
61
62 void
63 hb_ot_map_t::compile (hb_ot_shape_plan_context_t *c)
64 {
65  global_mask = 0;
66  lookup_count[0] = lookup_count[1] = 0;
67
68   if (!feature_count)
69     return;
70
71
72   /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
73    * features not available in either table and not waste precious bits for them. */
74
75   const hb_tag_t *script_tags;
76   hb_tag_t language_tag;
77
78   script_tags = hb_ot_tags_from_script (c->props->script);
79   language_tag = hb_ot_tag_from_language (c->props->language);
80
81   unsigned int script_index[2], language_index[2];
82   for (unsigned int table_index = 0; table_index < 2; table_index++) {
83     hb_tag_t table_tag = table_tags[table_index];
84     hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
85     hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
86   }
87
88
89   /* Sort features and merge duplicates */
90   qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
91   unsigned int j = 0;
92   for (unsigned int i = 1; i < feature_count; i++)
93     if (feature_infos[i].tag != feature_infos[j].tag)
94       feature_infos[++j] = feature_infos[i];
95     else {
96       if (feature_infos[i].global)
97         feature_infos[j] = feature_infos[i];
98       else {
99         feature_infos[j].global = false;
100         feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
101       }
102     }
103   feature_count = j + 1;
104
105
106   /* Allocate bits now */
107   unsigned int next_bit = 1;
108   j = 0;
109   for (unsigned int i = 0; i < feature_count; i++) {
110     const feature_info_t *info = &feature_infos[i];
111
112     unsigned int bits_needed;
113
114     if (info->global && info->value == 1)
115       /* Uses the global bit */
116       bits_needed = 0;
117     else
118       bits_needed = _hb_bit_storage (info->value);
119
120     if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
121       continue; /* Feature disabled, or not enough bits. */
122
123
124     bool found = false;
125     unsigned int feature_index[2];
126     for (unsigned int table_index = 0; table_index < 2; table_index++)
127       found |= hb_ot_layout_language_find_feature (c->face,
128                                                    table_tags[table_index],
129                                                    script_index[table_index],
130                                                    language_index[table_index],
131                                                    info->tag,
132                                                    &feature_index[table_index]);
133     if (!found)
134       continue;
135
136
137     feature_map_t *map = &feature_maps[j++];
138
139     map->tag = info->tag;
140     map->index[0] = feature_index[0];
141     map->index[1] = feature_index[1];
142     if (info->global && info->value == 1) {
143       /* Uses the global bit */
144       map->shift = 0;
145       map->mask = 1;
146     } else {
147       map->shift = next_bit;
148       map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
149       next_bit += bits_needed;
150       if (info->global)
151         global_mask |= map->mask;
152     }
153
154   }
155   feature_count = j;
156
157
158   for (unsigned int table_index = 0; table_index < 2; table_index++) {
159     hb_tag_t table_tag = table_tags[table_index];
160
161     /* Collect lookup indices for features */
162
163     unsigned int required_feature_index;
164     if (hb_ot_layout_language_get_required_feature_index (c->face,
165                                                           table_tag,
166                                                           script_index[table_index],
167                                                           language_index[table_index],
168                                                           &required_feature_index))
169       add_lookups (c, table_index, required_feature_index, 1);
170
171     for (unsigned i = 0; i < feature_count; i++)
172       add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
173
174     /* Sort lookups and merge duplicates */
175     qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
176     if (lookup_count[table_index])
177     {
178       unsigned int j = 0;
179       for (unsigned int i = 1; i < lookup_count[table_index]; i++)
180         if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
181           lookup_maps[table_index][++j] = lookup_maps[table_index][i];
182         else
183           lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
184       j++;
185       lookup_count[table_index] = j;
186     }
187   }
188 }
189
190
191 HB_END_DECLS