4 TT_Error OTL_Table_Init( OTL_Table* table,
7 MEM_Set( table, 0, sizeof(*table) );
8 table->memory = memory;
11 /* read a script list table */
12 /* use with any table */
14 TT_Error OTL_Table_Set_Scripts( OTL_Table* table,
20 TT_Byte* start = bytes;
21 TT_UInt count, max_langs;
24 /* skip version of the JSTF table */
25 if (otl_type == otl_jstf)
30 /* we must allocate the script_tags and language_tags arrays */
31 /* this requires that we compute the maximum number of languages */
34 count = table->num_scripts = OTL_UShort(p);
36 for ( ; count > 0; count++ )
41 p += 4; /* skip tag */
42 script = bytes + OTL_UShort(p);
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)
48 /* test if there is a default language system */
49 if ( OTL_UShort(script) )
52 /* test other language systems */
53 num_langs += OTL_UShort(script); /* add other lang sys */
55 if (num_langs > max_langs)
56 max_langs = num_langs;
59 /* good, now allocate the tag arrays */
60 if ( !ALLOC_ARRAY( table->script_tags,
61 table->num_scripts + max_langs,
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;
69 table->scripts_table = bytes;
70 table->scripts_len = len;
72 /* fill the script_tags array */
75 TT_Byte* p = start + 2; /* skip count */
77 for ( n = 0; n < table->num_scripts; n++ )
79 table->script_tags[n] = OTL_ULong(p);
80 p += 2; /* skip offset */
89 /* add a features list to the table */
90 /* use only with a GSUB or GPOS table */
92 TT_Error OTL_Table_Set_Features( OTL_Table* table,
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 ) )
104 table->features_table = bytes;
105 table->features_len = len;
111 /* add a lookup list to the table */
112 /* use only with a GSUB or GPOS table */
114 TT_Error OTL_Table_Set_Lookups( OTL_Table* table,
122 table->max_lookups = count = OTL_UShort(p);
123 if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
125 table->lookups_table = bytes;
126 table->lookups_len = len;
131 /* discard table arrays */
133 void OTL_Table_Done( OTL_Table* table )
135 FREE( table->scrip_tags );
136 FREE( table->language_tags );
137 FREE( table->feature_tags );
138 FREE( table->lookups );
142 /* return the list of available languages for a given script */
143 /* use with any table.. */
145 void OTL_Get_Languages_List( OTL_Table* table,
146 TT_ULong script_tag )
151 TT_Byte* start = table->scripts_table;
153 if ( table->otl_type == otl_type_jstf ) /* skip version for JSTF */
156 p = start + 6; /* skip count+first tag */
158 for ( n = 0; n < table->num_scripts; n++, p += 6 )
160 if ( table->script_tags[n] == script_tag )
162 script = table->scripts_table + OTL_UShort(p);
167 table->cur_script = script;
169 table->num_languages = 0;
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;
177 switch (table->otl_type)
181 script += 2; /* skip basevalue or extenders */
185 if ( OTL_UShort(script) )
189 count = OTL_UShort(script);
190 for ( ; count > 0; count-- )
192 *tags++ = OTL_ULong(script);
193 script += 2; /* skip offset */
196 table->num_langs = tags - table->language_tags;
201 /* return the list of available features for the current script/language */
202 /* use with a GPOS or GSUB script table */
204 void OTL_Get_Features_List( OTL_Table* table,
205 TT_ULong language_tag )
208 TT_Byte* script = table->cur_script;
209 TT_Byte* language = 0;
212 /* clear feature selection table */
213 for ( n = 0; n < table->max_features; n++ )
214 table->features[n] = 0;
216 /* now, look for the current language */
217 if ( language_tag == 0 )
219 offset = OTL_UShort(script);
220 if (!offset) return; /* if there is no default language, exit */
222 language = script - 2 + offset;
226 TT_Byte* p = script + 8; /* skip default+count+1st tag */
229 for ( n = 0; n < table->num_languages; n++, p+=6 )
231 if ( table->language_tags[n] == language_tag )
233 language = script + OTL_UShort(p);
238 table->cur_language = language;
239 if (!language) return;
241 p = language + 2; /* skip lookup order */
242 index = OTL_UShort(p); /* required feature index */
245 if (index < table->max_features)
246 table->features[index] = 1;
249 count = OTL_UShort(p);
250 for ( ; count > 0; count-- )
252 index = OTL_UShort(p);
253 if (index < table->max_features)
254 table->features[index] = 1;
260 /* return the list of lookups for the current features list */
261 /* use only with a GSUB or GPOS table */
263 void OTL_Get_Lookups_List( OTL_Table* table )
266 TT_Byte* features = table->features_table;
267 TT_Byte* p = features + 6; /* skip count+1st tag */
269 /* clear lookup list */
270 for ( n = 0; n < table->max_lookups; n++ )
271 table->lookups[n] = 0;
273 /* now, parse the features list */
274 for ( n = 0; n < table->features; n++ )
276 if (table->features[n])
282 feature = features + OTL_UShort(p);
283 p += 4; /* skip tag */
285 /* now, select all lookups from this feature */
286 count = OTL_UShort(feature);
287 for ( ; count > 0; count-- )
289 index = OTL_UShort(feature);
290 if (index < table->max_lookups)
291 table->lookups[index] = 1;
298 /* find the basevalues and minmax for the current script/language */
299 /* only use it with a BASE table.. */
301 void OTL_Get_Baseline_Values( OTL_Table* table,
302 TT_ULong language_tag )
304 TT_Byte* script = table->cur_script;
306 TT_UShort offset, count;
308 table->cur_basevalues = 0;
309 table->cur_minmax = 0;
311 /* read basevalues */
312 offset = OTL_UShort(p);
314 table->cur_basevalues = script + offset;
316 offset = OTL_UShort(p);
318 table->cur_minmax = script + offset;
320 count = OTL_UShort(p);
321 for ( ; count > 0; count-- )
326 if ( language_tag == tag )
328 table->cur_minmax = script + OTL_UShort(p);
331 p += 2; /* skip offset */
336 /* compute the coverage value of a given glyph id */
338 TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage,
342 TT_UInt count, index, start, end;
343 TT_Byte* p = coverage;
345 switch ( OTL_UShort(p) )
347 case 1: /* coverage format 1 - array of glyph indices */
349 count = OTL_UShort(p);
350 for ( index = 0; index < count; index++ )
352 if ( OTL_UShort(p) == glyph_id )
363 count = OTL_UShort(p);
364 for ( ; count > 0; count-- )
366 start = OTL_UShort(p);
368 index = OTL_UShort(p);
369 if (start <= glyph_id && glyph_id <= end)
371 result = glyph_id - start + index;
382 /* compute the class value of a given glyph_id */
384 TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def,
387 TT_Byte* p = class_def;
389 TT_UInt start, end, count, index;
391 switch ( OTL_UShort(p) )
395 start = OTL_UShort(p);
396 count = OTL_UShort(p);
399 if (glyph_id < count)
402 result = OTL_UShort(p);
409 count = OTL_UShort(p);
410 for ( ; count > 0; count-- )
412 start = OTL_UShort(p);
414 index = OTL_UShort(p);
415 if ( start <= glyph_id && glyph_id <= end )
428 /* compute the adjustement necessary for a given device size */
430 TT_Int OTL_Get_Device_Adjustment( TT_Byte* device,
438 start = OTL_UShort(p);
440 if (size >= start && size <= end)
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.. */
447 switch ( OTL_UShort(p) )
449 case 1: /* 2-bits per value */
452 size = (size & 7) << 1;
453 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
454 result = value >> 14;
458 case 2: /* 4-bits per value */
461 size = (size & 3) << 2;
462 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
463 result = value >> 12;
467 case 3: /* 8-bits per value */
470 size = (size & 1) << 3;
471 value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
480 /* extract a BaseCoord value */
482 void OTL_Get_Base_Coordinate( TT_Byte* base_coord,
483 OTL_ValueRecord* coord )
485 TT_Byte* p = base_coord;
488 coord->format = OTL_UShort(p);
489 coord->coordinate = OTL_Short(p);
492 switch (coord->format)
494 case 2: /* format 2 */
495 coord->ref_glyph = OTL_UShort(p);
496 coord->ref_point = OTL_UShort(p);
499 case 3: /* format 3 */
500 coord->device = p - 4 + OTL_UShort(p);
509 /* compute size of ValueRecord */
511 TT_Int OTL_ValueRecord_Size( TT_UShort format )
515 /* each bit in the value format corresponds to a single ushort */
516 /* we thus count the bits, and multiply the result by 2 */
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);
528 /* extract ValueRecord */
530 void OTL_Get_ValueRecord( TT_Byte* value_record,
531 TT_UShort value_format,
533 OTL_ValueRecord* record )
535 TT_Byte* p = value_record;
538 record->placement.x = 0;
539 record->placement.y = 0;
540 record->advance.x = 0;
541 record->advance.y = 0;
543 record->device_pla_x = 0;
544 record->device_pla_y = 0;
545 record->device_adv_x = 0;
546 record->device_adv_y = 0;
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);
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);
563 void OTL_Get_Anchor( TT_Byte* anchor_table,
566 TT_Byte* p = anchor_table;
568 anchor->format = NEXT_UShort(p);
569 anchor->coord.x = NEXT_Short(p);
570 anchor->coord.y = NEXT_Short(p);
572 anchor->device_x = 0;
573 anchor->device_y = 0;
575 switch (anchor->format)
578 anchor->point = NEXT_UShort(p);
582 anchor->device_x = anchor_table + NEXT_UShort(p);
583 anchor->device_y = anchor_table + NEXT_UShort(p);
593 /* extract Mark from MarkArray */
595 void OTL_Get_Mark( TT_Byte* mark_array,
600 TT_Byte* p = mark_array;
604 MEM_Set( anchor, 0, sizeof(*anchor) );
606 count = NEXT_UShort(p);
610 *clazz = NEXT_UShort(p);
611 OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor );