:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / freetype / src / 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