Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 368 lines (295 sloc) 11.037 kb
fd92a3dd » behdad
2008-01-24 Starting public interface
1 /*
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2006 Behdad Esfahbod
fd92a3dd » behdad
2008-01-24 Starting public interface
4 * Copyright (C) 2007,2008 Red Hat, Inc.
5 *
6 * This is part of HarfBuzz, an OpenType Layout engine library.
7 *
8 * Permission is hereby granted, without written agreement and without
9 * license or royalty fees, to use, copy, modify, and distribute this
10 * software and its documentation for any purpose, provided that the
11 * above copyright notice and the following two paragraphs appear in
12 * all copies of this software.
13 *
14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * DAMAGE.
19 *
20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 *
26 * Red Hat Author(s): Behdad Esfahbod
27 */
28
29 #define HB_OT_LAYOUT_CC
30
31 #include "hb-ot-layout.h"
32 #include "hb-ot-layout-private.h"
33
34 #include "hb-ot-layout-open-private.h"
35 #include "hb-ot-layout-gdef-private.h"
36 #include "hb-ot-layout-gsub-private.h"
37
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
38
fd92a3dd » behdad
2008-01-24 Starting public interface
39 #include <stdlib.h>
aff831ed » behdad
2008-01-24 Implement glyph properties
40 #include <string.h>
41
fd92a3dd » behdad
2008-01-24 Starting public interface
42
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
43 struct _hb_ot_layout_t {
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
44 const GDEF *gdef;
45 const GSUB *gsub;
706ab25a » behdad
2008-01-28 Add script and language public getter API
46 const /*XXX*/GSUBGPOS *gpos;
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
47
48 struct {
49 unsigned char *klasses;
50 unsigned int len;
51 } new_gdef;
52
53 };
54
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
55 hb_ot_layout_t *
dfa81196 » behdad
2008-01-28 Rename hb_ot_layout_create() to hb_ot_layout_create_for_data()
56 hb_ot_layout_create_for_data (const char *font_data,
57 int face_index)
fd92a3dd » behdad
2008-01-24 Starting public interface
58 {
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
59 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
fd92a3dd » behdad
2008-01-24 Starting public interface
60
ead428d7 » behdad
2008-01-24 More public api
61 const OpenTypeFontFile &font = OpenTypeFontFile::get_for_data (font_data);
62 const OpenTypeFontFace &face = font.get_face (face_index);
fd92a3dd » behdad
2008-01-24 Starting public interface
63
54e5aac5 » behdad
2008-01-27 GDEF completely working now
64 layout->gdef = &GDEF::get_for_data (font.get_table_data (face.get_table_by_tag (GDEF::Tag)));
65 layout->gsub = &GSUB::get_for_data (font.get_table_data (face.get_table_by_tag (GSUB::Tag)));
706ab25a » behdad
2008-01-28 Add script and language public getter API
66 layout->gpos = &/*XXX*/GSUBGPOS::get_for_data (font.get_table_data (face.get_table_by_tag (/*XXX*/GSUBGPOS::GPOSTag)));
fd92a3dd » behdad
2008-01-24 Starting public interface
67
68 return layout;
69 }
70
71 void
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
72 hb_ot_layout_destroy (hb_ot_layout_t *layout)
fd92a3dd » behdad
2008-01-24 Starting public interface
73 {
74 free (layout);
75 }
76
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
77 /*
78 * GDEF
79 */
80
81 hb_bool_t
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
82 hb_ot_layout_has_font_glyph_classes (hb_ot_layout_t *layout)
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
83 {
84 return layout->gdef->has_glyph_classes ();
85 }
86
54e5aac5 » behdad
2008-01-27 GDEF completely working now
87 HB_OT_LAYOUT_INTERNAL hb_bool_t
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
88 _hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout)
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
89 {
90 return layout->new_gdef.len > 0;
91 }
92
54e5aac5 » behdad
2008-01-27 GDEF completely working now
93 HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
94 _hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout,
95 hb_glyph_t glyph)
ead428d7 » behdad
2008-01-24 More public api
96 {
aff831ed » behdad
2008-01-24 Implement glyph properties
97 hb_ot_layout_class_t klass;
98
99 /* TODO old harfbuzz doesn't always parse mark attachments as it says it was
100 * introduced without a version bump, so it may not be safe */
101 klass = layout->gdef->get_mark_attachment_type (glyph);
102 if (klass)
103 return klass << 8;
104
105 klass = layout->gdef->get_glyph_class (glyph);
ead428d7 » behdad
2008-01-24 More public api
106
aff831ed » behdad
2008-01-24 Implement glyph properties
107 if (!klass && glyph < layout->new_gdef.len)
108 klass = layout->new_gdef.klasses[glyph];
109
110 switch (klass) {
111 default:
112 case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
113 case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
114 case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
115 case GDEF::MarkGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_MARK;
116 case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
117 }
ead428d7 » behdad
2008-01-24 More public api
118 }
fd92a3dd » behdad
2008-01-24 Starting public interface
119
54e5aac5 » behdad
2008-01-27 GDEF completely working now
120 HB_OT_LAYOUT_INTERNAL hb_bool_t
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
121 _hb_ot_layout_check_glyph_properties (hb_ot_layout_t *layout,
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
122 HB_GlyphItem gitem,
123 hb_ot_layout_lookup_flags_t lookup_flags,
124 hb_ot_layout_glyph_properties_t *property)
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
125 {
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
126 hb_ot_layout_glyph_class_t basic_glyph_class;
127 hb_ot_layout_glyph_properties_t desired_attachment_class;
128
54e5aac5 » behdad
2008-01-27 GDEF completely working now
129 if (gitem->gproperties == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
130 {
54e5aac5 » behdad
2008-01-27 GDEF completely working now
131 gitem->gproperties = *property = _hb_ot_layout_get_glyph_properties (layout, gitem->gindex);
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
132 if (gitem->gproperties == HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED)
133 return false;
134 }
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
135
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
136 *property = gitem->gproperties;
137
138 /* If the glyph was found in the MarkAttachmentClass table,
139 * then that class value is the high byte of the result,
140 * otherwise the low byte contains the basic type of the glyph
141 * as defined by the GlyphClassDef table.
142 */
143 if (*property & LookupFlag::MarkAttachmentType)
144 basic_glyph_class = HB_OT_LAYOUT_GLYPH_CLASS_MARK;
145 else
146 basic_glyph_class = (hb_ot_layout_glyph_class_t) *property;
147
148 /* Not covered, if, for example, basic_glyph_class
149 * is HB_GDEF_LIGATURE and lookup_flags includes LookupFlags::IgnoreLigatures
150 */
151 if (lookup_flags & basic_glyph_class)
152 return false;
153
154 /* The high byte of lookup_flags has the meaning
155 * "ignore marks of attachment type different than
156 * the attachment type specified."
157 */
158 desired_attachment_class = lookup_flags & LookupFlag::MarkAttachmentType;
159 if (desired_attachment_class)
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
160 {
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
161 if (basic_glyph_class == HB_OT_LAYOUT_GLYPH_CLASS_MARK &&
162 *property != desired_attachment_class )
163 return false;
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
164 }
165
6f425b11 » behdad
2008-01-24 [GDEF] Finish internal API
166 return true;
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
167 }
168
169
aff831ed » behdad
2008-01-24 Implement glyph properties
170 hb_ot_layout_glyph_class_t
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
171 hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
172 hb_glyph_t glyph)
ead428d7 » behdad
2008-01-24 More public api
173 {
aff831ed » behdad
2008-01-24 Implement glyph properties
174 hb_ot_layout_glyph_properties_t properties;
175 hb_ot_layout_class_t klass;
ead428d7 » behdad
2008-01-24 More public api
176
aff831ed » behdad
2008-01-24 Implement glyph properties
177 properties = _hb_ot_layout_get_glyph_properties (layout, glyph);
178
54e5aac5 » behdad
2008-01-27 GDEF completely working now
179 if (properties & 0xFF00)
aff831ed » behdad
2008-01-24 Implement glyph properties
180 return HB_OT_LAYOUT_GLYPH_CLASS_MARK;
181
182 return (hb_ot_layout_glyph_class_t) properties;
ead428d7 » behdad
2008-01-24 More public api
183 }
184
aff831ed » behdad
2008-01-24 Implement glyph properties
185 void
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
186 hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout,
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
187 hb_glyph_t glyph,
aff831ed » behdad
2008-01-24 Implement glyph properties
188 hb_ot_layout_glyph_class_t klass)
189 {
190 /* TODO optimize this, similar to old harfbuzz code for example */
191
192 hb_ot_layout_class_t gdef_klass;
193 int len = layout->new_gdef.len;
194
195 if (glyph >= len) {
196 int new_len;
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
197 unsigned char *new_klasses;
aff831ed » behdad
2008-01-24 Implement glyph properties
198
199 new_len = len == 0 ? 120 : 2 * len;
200 if (new_len > 65535)
201 new_len = 65535;
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
202 new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char));
aff831ed » behdad
2008-01-24 Implement glyph properties
203
204 if (G_UNLIKELY (!new_klasses))
205 return;
206
207 memset (new_klasses + len, 0, new_len - len);
208
209 layout->new_gdef.klasses = new_klasses;
210 layout->new_gdef.len = new_len;
211 }
212
213 switch (klass) {
214 default:
215 case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break;
216 case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break;
217 case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break;
218 case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break;
219 case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break;
220 }
221
222 layout->new_gdef.klasses[glyph] = gdef_klass;
223 return;
224 }
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
225
226 void
e50c3978 » behdad
2008-01-28 Rename HB_OT_Layout to hb_ot_layout_t
227 hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout,
228 uint16_t num_total_glyphs,
229 hb_glyph_t *glyphs,
230 unsigned char *klasses,
231 uint16_t count)
590d55cb » behdad
2008-01-24 [GDEF] Finish public API
232 {
233 int i;
234
235 if (G_UNLIKELY (!count || !glyphs || !klasses))
236 return;
237
238 if (layout->new_gdef.len == 0) {
239 layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char));
240 layout->new_gdef.len = count;
241 }
242
243 for (i = 0; i < count; i++)
244 hb_ot_layout_set_glyph_class (layout, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]);
245 }
706ab25a » behdad
2008-01-28 Add script and language public getter API
246
247 /*
248 * GSUB/GPOS
249 */
250
251 static const GSUBGPOS&
252 get_gsubgpos_table (hb_ot_layout_t *layout,
253 hb_ot_layout_table_type_t table_type)
254 {
255 switch (table_type) {
256 case HB_OT_LAYOUT_TABLE_TYPE_GSUB: return *(layout->gsub);
257 case HB_OT_LAYOUT_TABLE_TYPE_GPOS: return *(layout->gpos);
258 default: return NullGSUBGPOS;
259 }
260 }
261
262
263 unsigned int
264 hb_ot_layout_get_script_count (hb_ot_layout_t *layout,
265 hb_ot_layout_table_type_t table_type)
266 {
267 const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
268
269 return g.get_script_count ();
270 }
271
272 hb_tag_t
273 hb_ot_layout_get_script_tag (hb_ot_layout_t *layout,
274 hb_ot_layout_table_type_t table_type,
275 unsigned int script_index)
276 {
277 const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
278
279 return g.get_script_tag (script_index);
280 }
281
282 hb_bool_t
283 hb_ot_layout_find_script (hb_ot_layout_t *layout,
284 hb_ot_layout_table_type_t table_type,
285 hb_tag_t script_tag,
286 unsigned int *script_index)
287 {
288 unsigned int i;
289 const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
290
291 if (g.find_script_index (script_tag, script_index))
292 return TRUE;
293
294 /* try finding 'DFLT' */
295 if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT, script_index))
296 return FALSE;
297
298 /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
299 if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, script_index))
300 return FALSE;
301
302 if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
303 return FALSE;
304 }
305
306
307 unsigned int
308 hb_ot_layout_get_language_count (hb_ot_layout_t *layout,
309 hb_ot_layout_table_type_t table_type,
310 unsigned int script_index)
311 {
312 const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
313
314 return s.get_lang_sys_count ();
315 }
316
317 hb_tag_t
318 hb_ot_layout_get_language_tag (hb_ot_layout_t *layout,
319 hb_ot_layout_table_type_t table_type,
320 unsigned int script_index,
321 unsigned int language_index)
322 {
323 const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
324
325 return s.get_lang_sys_tag (language_index);
326 }
327
328 hb_bool_t
329 hb_ot_layout_find_language (hb_ot_layout_t *layout,
330 hb_ot_layout_table_type_t table_type,
331 unsigned int script_index,
332 hb_tag_t language_tag,
333 unsigned int *language_index,
334 unsigned int *required_features_index)
335 {
336 unsigned int i;
337 const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
338
339 #if 0
340 if (s.find_script_index (script_tag, script_index))
341 return TRUE;
342
343 /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
344 if (s.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, script_index))
345 return FALSE;
346
347 ////////////////////////
348 if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
349 return FALSE;
350
351 if (language_index)
352 *language_index = PANGO_OT_DEFAULT_LANGUAGE;
353 if (required_feature_index)
354 *required_feature_index = PANGO_OT_NO_FEATURE;
355
356 if (script_index == PANGO_OT_NO_SCRIPT)
357 return FALSE;
358
359
360 /* DefaultLangSys */
361 if (language_index)
362 *language_index = PANGO_OT_DEFAULT_LANGUAGE;
363 if (required_feature_index)
364 *required_feature_index = script->DefaultLangSys.ReqFeatureIndex;
365 #endif
366
367 return FALSE;
368 }
Something went wrong with that request. Please try again.