OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2009,2010 Red Hat, Inc. | 2 * Copyright © 2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2011 Google, Inc. | 3 * Copyright © 2010,2011,2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
11 * all copies of this software. | 11 * all copies of this software. |
12 * | 12 * |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
(...skipping 10 matching lines...) Expand all Loading... |
24 * | 24 * |
25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #ifndef HB_OT_MAP_PRIVATE_HH | 29 #ifndef HB_OT_MAP_PRIVATE_HH |
30 #define HB_OT_MAP_PRIVATE_HH | 30 #define HB_OT_MAP_PRIVATE_HH |
31 | 31 |
32 #include "hb-buffer-private.hh" | 32 #include "hb-buffer-private.hh" |
33 | 33 |
34 #include "hb-ot-layout.h" | 34 #include "hb-ot-layout-private.hh" |
35 | |
36 | 35 |
37 | 36 |
38 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}; | 37 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}; |
39 | 38 |
40 struct hb_ot_map_t | 39 struct hb_ot_map_t |
41 { | 40 { |
42 friend struct hb_ot_map_builder_t; | 41 friend struct hb_ot_map_builder_t; |
43 | 42 |
44 public: | 43 public: |
45 | 44 |
46 hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); } | |
47 | |
48 typedef void (*gsub_pause_func_t) (const hb_ot_map_t *map, hb_face_t *face, hb
_buffer_t *buffer, void *user_data); | |
49 typedef void (*gpos_pause_func_t) (const hb_ot_map_t *map, hb_font_t *font, hb
_buffer_t *buffer, void *user_data); | |
50 | |
51 inline hb_mask_t get_global_mask (void) const { return global_mask; } | |
52 | |
53 inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const { | |
54 const feature_map_t *map = features.bsearch (&tag); | |
55 if (shift) *shift = map ? map->shift : 0; | |
56 return map ? map->mask : 0; | |
57 } | |
58 | |
59 inline hb_mask_t get_1_mask (hb_tag_t tag) const { | |
60 const feature_map_t *map = features.bsearch (&tag); | |
61 return map ? map->_1_mask : 0; | |
62 } | |
63 | |
64 inline hb_tag_t get_chosen_script (unsigned int table_index) const | |
65 { return chosen_script[table_index]; } | |
66 | |
67 inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const | |
68 { apply (0, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_substitute_lookup,
face, buffer); } | |
69 inline void position (hb_font_t *font, hb_buffer_t *buffer) const | |
70 { apply (1, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_position_lookup, f
ont, buffer); } | |
71 | |
72 HB_INTERNAL void substitute_closure (hb_face_t *face, | |
73 hb_set_t *glyphs) const; | |
74 | |
75 | |
76 inline void finish (void) { | |
77 features.finish (); | |
78 lookups[0].finish (); | |
79 lookups[1].finish (); | |
80 pauses[0].finish (); | |
81 pauses[1].finish (); | |
82 } | |
83 | |
84 private: | |
85 | |
86 struct feature_map_t { | 45 struct feature_map_t { |
87 hb_tag_t tag; /* should be first for our bsearch to work */ | 46 hb_tag_t tag; /* should be first for our bsearch to work */ |
88 unsigned int index[2]; /* GSUB/GPOS */ | 47 unsigned int index[2]; /* GSUB/GPOS */ |
89 unsigned int stage[2]; /* GSUB/GPOS */ | 48 unsigned int stage[2]; /* GSUB/GPOS */ |
90 unsigned int shift; | 49 unsigned int shift; |
91 hb_mask_t mask; | 50 hb_mask_t mask; |
92 hb_mask_t _1_mask; /* mask for value=1, for quick access */ | 51 hb_mask_t _1_mask; /* mask for value=1, for quick access */ |
| 52 hb_bool_t needs_fallback; |
93 | 53 |
94 static int cmp (const feature_map_t *a, const feature_map_t *b) | 54 static int cmp (const feature_map_t *a, const feature_map_t *b) |
95 { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } | 55 { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } |
96 }; | 56 }; |
97 | 57 |
98 struct lookup_map_t { | 58 struct lookup_map_t { |
99 unsigned int index; | 59 unsigned int index; |
100 hb_mask_t mask; | 60 hb_mask_t mask; |
101 | 61 |
102 static int cmp (const lookup_map_t *a, const lookup_map_t *b) | 62 static int cmp (const lookup_map_t *a, const lookup_map_t *b) |
103 { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; } | 63 { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; } |
104 }; | 64 }; |
105 | 65 |
106 typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, hb_b
uffer_t *buffer, void *user_data); | 66 typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t
*font, hb_buffer_t *buffer); |
107 typedef struct { | |
108 pause_func_t func; | |
109 void *user_data; | |
110 } pause_callback_t; | |
111 | 67 |
112 struct pause_map_t { | 68 struct pause_map_t { |
113 unsigned int num_lookups; /* Cumulative */ | 69 unsigned int num_lookups; /* Cumulative */ |
114 pause_callback_t callback; | 70 pause_func_t callback; |
115 }; | 71 }; |
116 | 72 |
117 typedef hb_bool_t (*apply_lookup_func_t) (void *face_or_font, | 73 |
118 » » » » » hb_buffer_t *buffer, | 74 hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); } |
119 » » » » » unsigned int lookup_index, | 75 |
120 » » » » » hb_mask_t mask); | 76 inline hb_mask_t get_global_mask (void) const { return global_mask; } |
| 77 |
| 78 inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) c
onst { |
| 79 const feature_map_t *map = features.bsearch (&feature_tag); |
| 80 if (shift) *shift = map ? map->shift : 0; |
| 81 return map ? map->mask : 0; |
| 82 } |
| 83 |
| 84 inline bool needs_fallback (hb_tag_t feature_tag) const { |
| 85 const feature_map_t *map = features.bsearch (&feature_tag); |
| 86 return map ? map->needs_fallback : false; |
| 87 } |
| 88 |
| 89 inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const { |
| 90 const feature_map_t *map = features.bsearch (&feature_tag); |
| 91 return map ? map->_1_mask : 0; |
| 92 } |
| 93 |
| 94 inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feat
ure_tag) const { |
| 95 const feature_map_t *map = features.bsearch (&feature_tag); |
| 96 return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX; |
| 97 } |
| 98 |
| 99 inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feat
ure_tag) const { |
| 100 const feature_map_t *map = features.bsearch (&feature_tag); |
| 101 return map ? map->stage[table_index] : (unsigned int) -1; |
| 102 } |
| 103 |
| 104 inline void get_stage_lookups (unsigned int table_index, unsigned int stage, |
| 105 » » » » const struct lookup_map_t **plookups, unsigned
int *lookup_count) const { |
| 106 if (unlikely (stage == (unsigned int) -1)) { |
| 107 *plookups = NULL; |
| 108 *lookup_count = 0; |
| 109 return; |
| 110 } |
| 111 assert (stage <= pauses[table_index].len); |
| 112 unsigned int start = stage ? pauses[table_index][stage - 1].num_lookups : 0; |
| 113 unsigned int end = stage < pauses[table_index].len ? pauses[table_index][s
tage].num_lookups : lookups[table_index].len; |
| 114 *plookups = &lookups[table_index][start]; |
| 115 *lookup_count = end - start; |
| 116 } |
| 117 |
| 118 inline hb_tag_t get_chosen_script (unsigned int table_index) const |
| 119 { return chosen_script[table_index]; } |
| 120 |
| 121 HB_INTERNAL void substitute_closure (const struct hb_ot_shape_plan_t *plan, hb
_face_t *face, hb_set_t *glyphs) const; |
| 122 HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t
*font, hb_buffer_t *buffer) const; |
| 123 HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *f
ont, hb_buffer_t *buffer) const; |
| 124 |
| 125 inline void finish (void) { |
| 126 features.finish (); |
| 127 lookups[0].finish (); |
| 128 lookups[1].finish (); |
| 129 pauses[0].finish (); |
| 130 pauses[1].finish (); |
| 131 } |
| 132 |
| 133 |
| 134 private: |
121 | 135 |
122 HB_INTERNAL void add_lookups (hb_face_t *face, | 136 HB_INTERNAL void add_lookups (hb_face_t *face, |
123 unsigned int table_index, | 137 unsigned int table_index, |
124 unsigned int feature_index, | 138 unsigned int feature_index, |
125 hb_mask_t mask); | 139 hb_mask_t mask); |
126 | 140 |
127 HB_INTERNAL void apply (unsigned int table_index, | |
128 hb_ot_map_t::apply_lookup_func_t apply_lookup_func, | |
129 void *face_or_font, | |
130 hb_buffer_t *buffer) const; | |
131 | |
132 hb_mask_t global_mask; | 141 hb_mask_t global_mask; |
133 | 142 |
134 hb_tag_t chosen_script[2]; | 143 hb_tag_t chosen_script[2]; |
135 hb_prealloced_array_t<feature_map_t, 8> features; | 144 hb_prealloced_array_t<feature_map_t, 8> features; |
136 hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ | 145 hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ |
137 hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */ | 146 hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */ |
138 }; | 147 }; |
139 | 148 |
140 | 149 |
141 struct hb_ot_map_builder_t | 150 struct hb_ot_map_builder_t |
142 { | 151 { |
143 public: | 152 public: |
144 | 153 |
145 hb_ot_map_builder_t (void) { memset (this, 0, sizeof (*this)); } | 154 hb_ot_map_builder_t (void) { memset (this, 0, sizeof (*this)); } |
146 | 155 |
147 HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global); | 156 HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global, b
ool has_fallback = false); |
148 | 157 |
149 inline void add_bool_feature (hb_tag_t tag, bool global = true) | 158 inline void add_bool_feature (hb_tag_t tag, bool global = true, bool has_fallb
ack = false) |
150 { add_feature (tag, 1, global); } | 159 { add_feature (tag, 1, global, has_fallback); } |
151 | 160 |
152 inline void add_gsub_pause (hb_ot_map_t::gsub_pause_func_t pause_func, void *u
ser_data) | 161 inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func) |
153 { add_pause (0, (hb_ot_map_t::pause_func_t) pause_func, user_data); } | 162 { add_pause (0, pause_func); } |
154 inline void add_gpos_pause (hb_ot_map_t::gpos_pause_func_t pause_func, void *u
ser_data) | 163 inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) |
155 { add_pause (1, (hb_ot_map_t::pause_func_t) pause_func, user_data); } | 164 { add_pause (1, pause_func); } |
156 | 165 |
157 HB_INTERNAL void compile (hb_face_t *face, | 166 HB_INTERNAL void compile (hb_face_t *face, |
158 const hb_segment_properties_t *props, | 167 const hb_segment_properties_t *props, |
159 struct hb_ot_map_t &m); | 168 struct hb_ot_map_t &m); |
160 | 169 |
161 inline void finish (void) { | 170 inline void finish (void) { |
162 feature_infos.finish (); | 171 feature_infos.finish (); |
163 pauses[0].finish (); | 172 pauses[0].finish (); |
164 pauses[1].finish (); | 173 pauses[1].finish (); |
165 } | 174 } |
166 | 175 |
167 private: | 176 private: |
168 | 177 |
169 struct feature_info_t { | 178 struct feature_info_t { |
170 hb_tag_t tag; | 179 hb_tag_t tag; |
171 unsigned int seq; /* sequence#, used for stable sorting only */ | 180 unsigned int seq; /* sequence#, used for stable sorting only */ |
172 unsigned int max_value; | 181 unsigned int max_value; |
173 bool global; /* whether the feature applies value to every glyph in the buff
er */ | 182 bool global; /* whether the feature applies value to every glyph in the buff
er */ |
| 183 bool has_fallback; /* whether to allocate bits even if feature not found */ |
174 unsigned int default_value; /* for non-global features, what should the unse
t glyphs take */ | 184 unsigned int default_value; /* for non-global features, what should the unse
t glyphs take */ |
175 unsigned int stage[2]; /* GSUB/GPOS */ | 185 unsigned int stage[2]; /* GSUB/GPOS */ |
176 | 186 |
177 static int cmp (const feature_info_t *a, const feature_info_t *b) | 187 static int cmp (const feature_info_t *a, const feature_info_t *b) |
178 { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq
? -1 : 1); } | 188 { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq
? -1 : 1); } |
179 }; | 189 }; |
180 | 190 |
181 struct pause_info_t { | 191 struct pause_info_t { |
182 unsigned int stage; | 192 unsigned int stage; |
183 hb_ot_map_t::pause_callback_t callback; | 193 hb_ot_map_t::pause_func_t callback; |
184 }; | 194 }; |
185 | 195 |
186 HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_
t pause_func, void *user_data); | 196 HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_
t pause_func); |
187 | 197 |
188 unsigned int current_stage[2]; /* GSUB/GPOS */ | 198 unsigned int current_stage[2]; /* GSUB/GPOS */ |
189 hb_prealloced_array_t<feature_info_t,16> feature_infos; | 199 hb_prealloced_array_t<feature_info_t,16> feature_infos; |
190 hb_prealloced_array_t<pause_info_t, 1> pauses[2]; /* GSUB/GPOS */ | 200 hb_prealloced_array_t<pause_info_t, 1> pauses[2]; /* GSUB/GPOS */ |
191 }; | 201 }; |
192 | 202 |
193 | 203 |
194 | 204 |
195 #endif /* HB_OT_MAP_PRIVATE_HH */ | 205 #endif /* HB_OT_MAP_PRIVATE_HH */ |
OLD | NEW |