]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/otlayout/oltypes.c
A fix for attribrute sorting, but it's still broken if there are
[wxWidgets.git] / src / freetype / otlayout / oltypes.c
1 #include <oltypes.h>
2
3 LOCAL_FUNC
4 TT_Error OTL_Table_Init( OTL_Table* table,
5 FT_Memory memory )
6 {
7 MEM_Set( table, 0, sizeof(*table) );
8 table->memory = memory;
9 }
10
11 /* read a script list table */
12 /* use with any table */
13 LOCAL_FUNC
14 TT_Error OTL_Table_Set_Scripts( OTL_Table* table,
15 TT_Byte* bytes,
16 TT_Long len,
17 OTL_Type otl_type )
18 {
19 TT_Byte* p;
20 TT_Byte* start = bytes;
21 TT_UInt count, max_langs;
22 TT_Error error;
23
24 /* skip version of the JSTF table */
25 if (otl_type == otl_jstf)
26 start += 4;
27
28 p = start;
29
30 /* we must allocate the script_tags and language_tags arrays */
31 /* this requires that we compute the maximum number of languages */
32 /* per script.. */
33
34 count = table->num_scripts = OTL_UShort(p);
35 max_langs = 0;
36 for ( ; count > 0; count++ )
37 {
38 TT_Byte* script;
39 TT_UInt num_langs;
40
41 p += 4; /* skip tag */
42 script = bytes + OTL_UShort(p);
43
44 /* skip the baseValues or extenders field of the BASE and JSTF table */
45 if (otl_type == otl_type_base || otl_type == otl_type_jstf)
46 script += 2;
47
48 /* test if there is a default language system */
49 if ( OTL_UShort(script) )
50 num_langs++;
51
52 /* test other language systems */
53 num_langs += OTL_UShort(script); /* add other lang sys */
54
55 if (num_langs > max_langs)
56 max_langs = num_langs;
57 }
58
59 /* good, now allocate the tag arrays */
60 if ( !ALLOC_ARRAY( table->script_tags,
61 table->num_scripts + max_langs,
62 TT_ULong ) )
63 {
64 table->language_tags = table->script_tags + table->num_scripts;
65 table->max_languages = max_langs;
66 table->num_languages = 0;
67 table->otl_type = otl_type;
68
69 table->scripts_table = bytes;
70 table->scripts_len = len;
71
72 /* fill the script_tags array */
73 {
74 TT_UInt n;
75 TT_Byte* p = start + 2; /* skip count */
76
77 for ( n = 0; n < table->num_scripts; n++ )
78 {
79 table->script_tags[n] = OTL_ULong(p);
80 p += 2; /* skip offset */
81 }
82 }
83 }
84 return error;
85 }
86
87
88
89 /* add a features list to the table */
90 /* use only with a GSUB or GPOS table */
91 LOCAL_FUNC
92 TT_Error OTL_Table_Set_Features( OTL_Table* table,
93 TT_Byte* bytes,
94 TT_Long len )
95 {
96 TT_Error error;
97 TT_Byte* p = bytes;
98 TT_UInt count;
99
100 table->max_features = count = OTL_UShort(p);
101 if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) &&
102 !ALLOC_ARRAY( table->features, count, TT_Bool ) )
103 {
104 table->features_table = bytes;
105 table->features_len = len;
106 }
107 return error;
108 }
109
110
111 /* add a lookup list to the table */
112 /* use only with a GSUB or GPOS table */
113 LOCAL_FUNC
114 TT_Error OTL_Table_Set_Lookups( OTL_Table* table,
115 TT_Byte* bytes,
116 TT_Long len )
117 {
118 TT_Error error;
119 TT_Byte* p = bytes;
120 TT_UInt count;
121
122 table->max_lookups = count = OTL_UShort(p);
123 if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
124 {
125 table->lookups_table = bytes;
126 table->lookups_len = len;
127 }
128 return error;
129 }
130
131 /* discard table arrays */
132 LOCAL_FUNC
133 void OTL_Table_Done( OTL_Table* table )
134 {
135 FREE( table->scrip_tags );
136 FREE( table->language_tags );
137 FREE( table->feature_tags );
138 FREE( table->lookups );
139 }
140
141
142 /* return the list of available languages for a given script */
143 /* use with any table.. */
144 LOCAL_FUNC
145 void OTL_Get_Languages_List( OTL_Table* table,
146 TT_ULong script_tag )
147 {
148 TT_UInt n;
149 TT_Byte* p;
150 TT_Byte* script = 0;
151 TT_Byte* start = table->scripts_table;
152
153 if ( table->otl_type == otl_type_jstf ) /* skip version for JSTF */
154 start += 4;
155
156 p = start + 6; /* skip count+first tag */
157
158 for ( n = 0; n < table->num_scripts; n++, p += 6 )
159 {
160 if ( table->script_tags[n] == script_tag )
161 {
162 script = table->scripts_table + OTL_UShort(p);
163 break;
164 }
165 }
166
167 table->cur_script = script;
168 if (!script)
169 table->num_languages = 0;
170 else
171 {
172 /* now fill the language_tags array with the appropriate values */
173 /* not that we put a '0' tag in front of the list to indicate that */
174 /* there is a default language for this script.. */
175 TT_ULong* tags = table->language_tags;
176
177 switch (table->otl_type)
178 {
179 case otl_type_base:
180 case otl_type_jstf:
181 script += 2; /* skip basevalue or extenders */
182 /* fall-through */
183
184 default:
185 if ( OTL_UShort(script) )
186 *tags++ = 0;
187 }
188
189 count = OTL_UShort(script);
190 for ( ; count > 0; count-- )
191 {
192 *tags++ = OTL_ULong(script);
193 script += 2; /* skip offset */
194 }
195
196 table->num_langs = tags - table->language_tags;
197 }
198 }
199
200
201 /* return the list of available features for the current script/language */
202 /* use with a GPOS or GSUB script table */
203 LOCAL_FUNC
204 void OTL_Get_Features_List( OTL_Table* table,
205 TT_ULong language_tag )
206 {
207 TT_UInt n;
208 TT_Byte* script = table->cur_script;
209 TT_Byte* language = 0;
210 TT_UShort offset;
211
212 /* clear feature selection table */
213 for ( n = 0; n < table->max_features; n++ )
214 table->features[n] = 0;
215
216 /* now, look for the current language */
217 if ( language_tag == 0 )
218 {
219 offset = OTL_UShort(script);
220 if (!offset) return; /* if there is no default language, exit */
221
222 language = script - 2 + offset;
223 }
224 else
225 {
226 TT_Byte* p = script + 8; /* skip default+count+1st tag */
227 TT_UShort index;
228
229 for ( n = 0; n < table->num_languages; n++, p+=6 )
230 {
231 if ( table->language_tags[n] == language_tag )
232 {
233 language = script + OTL_UShort(p);
234 break;
235 }
236 }
237
238 table->cur_language = language;
239 if (!language) return;
240
241 p = language + 2; /* skip lookup order */
242 index = OTL_UShort(p); /* required feature index */
243 if (index != 0xFFFF)
244 {
245 if (index < table->max_features)
246 table->features[index] = 1;
247 }
248
249 count = OTL_UShort(p);
250 for ( ; count > 0; count-- )
251 {
252 index = OTL_UShort(p);
253 if (index < table->max_features)
254 table->features[index] = 1;
255 }
256 }
257 }
258
259
260 /* return the list of lookups for the current features list */
261 /* use only with a GSUB or GPOS table */
262 LOCAL_FUNC
263 void OTL_Get_Lookups_List( OTL_Table* table )
264 {
265 TT_UInt n;
266 TT_Byte* features = table->features_table;
267 TT_Byte* p = features + 6; /* skip count+1st tag */
268
269 /* clear lookup list */
270 for ( n = 0; n < table->max_lookups; n++ )
271 table->lookups[n] = 0;
272
273 /* now, parse the features list */
274 for ( n = 0; n < table->features; n++ )
275 {
276 if (table->features[n])
277 {
278 TT_UInt count;
279 TT_UShort index;
280 TT_Byte* feature;
281
282 feature = features + OTL_UShort(p);
283 p += 4; /* skip tag */
284
285 /* now, select all lookups from this feature */
286 count = OTL_UShort(feature);
287 for ( ; count > 0; count-- )
288 {
289 index = OTL_UShort(feature);
290 if (index < table->max_lookups)
291 table->lookups[index] = 1;
292 }
293 }
294 }
295 }
296
297
298 /* find the basevalues and minmax for the current script/language */
299 /* only use it with a BASE table.. */
300 LOCAL_FUNC
301 void OTL_Get_Baseline_Values( OTL_Table* table,
302 TT_ULong language_tag )
303 {
304 TT_Byte* script = table->cur_script;
305 TT_Byte* p = script;
306 TT_UShort offset, count;
307
308 table->cur_basevalues = 0;
309 table->cur_minmax = 0;
310
311 /* read basevalues */
312 offset = OTL_UShort(p);
313 if (offset)
314 table->cur_basevalues = script + offset;
315
316 offset = OTL_UShort(p);
317 if (offset)
318 table->cur_minmax = script + offset;
319
320 count = OTL_UShort(p);
321 for ( ; count > 0; count-- )
322 {
323 TT_ULong tag;
324
325 tag = OTL_ULong(p);
326 if ( language_tag == tag )
327 {
328 table->cur_minmax = script + OTL_UShort(p);
329 break;
330 }
331 p += 2; /* skip offset */
332 }
333 }
334
335
336 /* compute the coverage value of a given glyph id */
337 LOCAL_FUNC
338 TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage,
339 TT_UInt glyph_id )
340 {
341 TT_Long result = -1;
342 TT_UInt count, index, start, end;
343 TT_Byte* p = coverage;
344
345 switch ( OTL_UShort(p) )
346 {
347 case 1: /* coverage format 1 - array of glyph indices */
348 {
349 count = OTL_UShort(p);
350 for ( index = 0; index < count; index++ )
351 {
352 if ( OTL_UShort(p) == glyph_id )
353 {
354 result = index;
355 break;
356 }
357 }
358 }
359 break;
360
361 case 2:
362 {
363 count = OTL_UShort(p);
364 for ( ; count > 0; count-- )
365 {
366 start = OTL_UShort(p);
367 end = OTL_UShort(p);
368 index = OTL_UShort(p);
369 if (start <= glyph_id && glyph_id <= end)
370 {
371 result = glyph_id - start + index;
372 break;
373 }
374 }
375 }
376 break;
377 }
378 return result;
379 }
380
381
382 /* compute the class value of a given glyph_id */
383 LOCAL_FUNC
384 TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def,
385 TT_UInt glyph_id )
386 {
387 TT_Byte* p = class_def;
388 TT_UInt result = 0;
389 TT_UInt start, end, count, index;
390
391 switch ( OTL_UShort(p) )
392 {
393 case 1:
394 {
395 start = OTL_UShort(p);
396 count = OTL_UShort(p);
397
398 glyph_id -= start;
399 if (glyph_id < count)
400 {
401 p += 2*glyph_id;
402 result = OTL_UShort(p);
403 }
404 }
405 break;
406
407 case 2:
408 {
409 count = OTL_UShort(p);
410 for ( ; count > 0; count-- )
411 {
412 start = OTL_UShort(p);
413 end = OTL_UShort(p);
414 index = OTL_UShort(p);
415 if ( start <= glyph_id && glyph_id <= end )
416 {
417 result = index;
418 break;
419 }
420 }
421 }
422 break;
423 }
424 return result;
425 }
426
427
428 /* compute the adjustement necessary for a given device size */
429 LOCAL_FUNC
430 TT_Int OTL_Get_Device_Adjustment( TT_Byte* device,
431 TT_UInt size )
432 {
433 TT_Byte* p = device;
434 TT_Int result = 0;
435 TT_UInt start, end;
436 TT_Short value;
437
438 start = OTL_UShort(p);
439 end = OTL_UShort(p);
440 if (size >= start && size <= end)
441 {
442 /* I know we could do all of this without a switch, with */
443 /* clever shifts and everything, but it makes the code */
444 /* really difficult to understand.. */
445
446 size -= start;
447 switch ( OTL_UShort(p) )
448 {
449 case 1: /* 2-bits per value */
450 {
451 p += 2*(size >> 3);
452 size = (size & 7) << 1;
453 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
454 result = value >> 14;
455 }
456 break;
457
458 case 2: /* 4-bits per value */
459 {
460 p += 2*(size >> 2);
461 size = (size & 3) << 2;
462 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
463 result = value >> 12;
464 }
465 break;
466
467 case 3: /* 8-bits per value */
468 {
469 p += 2*(size >> 1);
470 size = (size & 1) << 3;
471 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
472 result = value >> 8;
473 }
474 break;
475 }
476 }
477 return result;
478 }
479
480 /* extract a BaseCoord value */
481 LOCAL_FUNC
482 void OTL_Get_Base_Coordinate( TT_Byte* base_coord,
483 OTL_ValueRecord* coord )
484 {
485 TT_Byte* p = base_coord;
486 TT_Int result = 0;
487
488 coord->format = OTL_UShort(p);
489 coord->coordinate = OTL_Short(p);
490 coord->device = 0;
491
492 switch (coord->format)
493 {
494 case 2: /* format 2 */
495 coord->ref_glyph = OTL_UShort(p);
496 coord->ref_point = OTL_UShort(p);
497 break;
498
499 case 3: /* format 3 */
500 coord->device = p - 4 + OTL_UShort(p);
501 break;
502
503 default:
504 ;
505 }
506 }
507
508
509 /* compute size of ValueRecord */
510 LOCAL_FUNC
511 TT_Int OTL_ValueRecord_Size( TT_UShort format )
512 {
513 TT_Int count;
514
515 /* each bit in the value format corresponds to a single ushort */
516 /* we thus count the bits, and multiply the result by 2 */
517
518 count = (TT_Int)(format & 0xFF);
519 count = ((count & 0xAA) >> 1) + (count & 0x55);
520 count = ((count & 0xCC) >> 2) + (count & 0x33);
521 count = ((count & 0xF0) >> 4) + (count & 0x0F);
522
523 return count*2;
524 }
525
526
527
528 /* extract ValueRecord */
529 LOCAL_FUNC
530 void OTL_Get_ValueRecord( TT_Byte* value_record,
531 TT_UShort value_format,
532 TT_Byte* pos_table,
533 OTL_ValueRecord* record )
534 {
535 TT_Byte* p = value_record;
536
537 /* clear vectors */
538 record->placement.x = 0;
539 record->placement.y = 0;
540 record->advance.x = 0;
541 record->advance.y = 0;
542
543 record->device_pla_x = 0;
544 record->device_pla_y = 0;
545 record->device_adv_x = 0;
546 record->device_adv_y = 0;
547
548 if (value_format & 1) record->placement.x = NEXT_Short(p);
549 if (value_format & 2) record->placement.y = NEXT_Short(p);
550 if (value_format & 4) record->advance.x = NEXT_Short(p);
551 if (value_format & 8) record->advance.y = NEXT_Short(p);
552
553 if (value_format & 16) record->device_pla_x = pos_table + NEXT_UShort(p);
554 if (value_format & 32) record->device_pla_y = pos_table + NEXT_UShort(p);
555 if (value_format & 64) record->device_adv_x = pos_table + NEXT_UShort(p);
556 if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p);
557 }
558
559
560
561 /* extract Anchor */
562 LOCAL_FUNC
563 void OTL_Get_Anchor( TT_Byte* anchor_table,
564 OTL_Anchor* anchor )
565 {
566 TT_Byte* p = anchor_table;
567
568 anchor->format = NEXT_UShort(p);
569 anchor->coord.x = NEXT_Short(p);
570 anchor->coord.y = NEXT_Short(p);
571 anchor->point = 0;
572 anchor->device_x = 0;
573 anchor->device_y = 0;
574
575 switch (anchor->format)
576 {
577 case 2:
578 anchor->point = NEXT_UShort(p);
579 break;
580
581 case 3:
582 anchor->device_x = anchor_table + NEXT_UShort(p);
583 anchor->device_y = anchor_table + NEXT_UShort(p);
584 break;
585
586 default:
587 ;
588 }
589 }
590
591
592
593 /* extract Mark from MarkArray */
594 LOCAL_FUNC
595 void OTL_Get_Mark( TT_Byte* mark_array,
596 TT_UInt index,
597 TT_UShort* clazz,
598 OTL_Anchor* anchor )
599 {
600 TT_Byte* p = mark_array;
601 TT_UInt count;
602
603 *clazz = 0;
604 MEM_Set( anchor, 0, sizeof(*anchor) );
605
606 count = NEXT_UShort(p);
607 if (index < count)
608 {
609 p += 4*index;
610 *clazz = NEXT_UShort(p);
611 OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor );
612 }
613 }
614