2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2006 Behdad Esfahbod
5 * This is part of HarfBuzz, an OpenType Layout engine library.
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
26 #include "harfbuzz-impl.h"
27 #include "harfbuzz-gdef-private.h"
28 #include "harfbuzz-open-private.h"
30 static HB_Error Load_AttachList( HB_AttachList* al,
32 static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,
35 static void Free_AttachList( HB_AttachList* al);
36 static void Free_LigCaretList( HB_LigCaretList* lcl);
38 static void Free_NewGlyphClasses( HB_GDEFHeader* gdef);
42 /* GDEF glyph classes */
44 #define UNCLASSIFIED_GLYPH 0
45 #define SIMPLE_GLYPH 1
46 #define LIGATURE_GLYPH 2
48 #define COMPONENT_GLYPH 4
55 HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr )
62 return ERR(HB_Err_Invalid_Argument);
64 if ( ALLOC( gdef, sizeof( *gdef ) ) )
67 gdef->GlyphClassDef.loaded = FALSE;
68 gdef->AttachList.loaded = FALSE;
69 gdef->LigCaretList.loaded = FALSE;
70 gdef->MarkAttachClassDef_offset = 0;
71 gdef->MarkAttachClassDef.loaded = FALSE;
74 gdef->NewGlyphClasses = NULL;
82 HB_Error HB_Load_GDEF_Table( HB_Stream stream,
83 HB_GDEFHeader** retptr )
86 HB_UInt cur_offset, new_offset, base_offset;
92 return ERR(HB_Err_Invalid_Argument);
94 if ( GOTO_Table( TTAG_GDEF ) )
97 if (( error = HB_New_GDEF_Table ( &gdef ) ))
100 base_offset = FILE_Pos();
104 if ( FILE_Seek( base_offset + 4L ) ||
108 new_offset = GET_UShort();
112 /* all GDEF subtables are optional */
116 new_offset += base_offset;
118 /* only classes 1-4 are allowed here */
120 cur_offset = FILE_Pos();
121 if ( FILE_Seek( new_offset ) ||
122 ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,
123 stream ) ) != HB_Err_Ok )
125 (void)FILE_Seek( cur_offset );
128 if ( ACCESS_Frame( 2L ) )
131 new_offset = GET_UShort();
137 new_offset += base_offset;
139 cur_offset = FILE_Pos();
140 if ( FILE_Seek( new_offset ) ||
141 ( error = Load_AttachList( &gdef->AttachList,
142 stream ) ) != HB_Err_Ok )
144 (void)FILE_Seek( cur_offset );
147 if ( ACCESS_Frame( 2L ) )
150 new_offset = GET_UShort();
156 new_offset += base_offset;
158 cur_offset = FILE_Pos();
159 if ( FILE_Seek( new_offset ) ||
160 ( error = Load_LigCaretList( &gdef->LigCaretList,
161 stream ) ) != HB_Err_Ok )
163 (void)FILE_Seek( cur_offset );
166 /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We
167 first have to scan the LookupFlag values to find out whether we
168 must load it or not. Here we only store the offset of the table. */
170 if ( ACCESS_Frame( 2L ) )
173 new_offset = GET_UShort();
178 gdef->MarkAttachClassDef_offset = new_offset + base_offset;
180 gdef->MarkAttachClassDef_offset = 0;
187 Free_LigCaretList( &gdef->LigCaretList );
190 Free_AttachList( &gdef->AttachList );
193 _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );
202 HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef )
204 Free_LigCaretList( &gdef->LigCaretList );
205 Free_AttachList( &gdef->AttachList );
206 _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );
207 _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef );
209 Free_NewGlyphClasses( gdef );
219 /*******************************
220 * AttachList related functions
221 *******************************/
226 static HB_Error Load_AttachPoint( HB_AttachPoint* ap,
235 if ( ACCESS_Frame( 2L ) )
238 count = ap->PointCount = GET_UShort();
242 ap->PointIndex = NULL;
246 if ( ALLOC_ARRAY( ap->PointIndex, count, HB_UShort ) )
251 if ( ACCESS_Frame( count * 2L ) )
257 for ( n = 0; n < count; n++ )
258 pi[n] = GET_UShort();
267 static void Free_AttachPoint( HB_AttachPoint* ap )
269 FREE( ap->PointIndex );
275 static HB_Error Load_AttachList( HB_AttachList* al,
280 HB_UShort n, m, count;
281 HB_UInt cur_offset, new_offset, base_offset;
286 base_offset = FILE_Pos();
288 if ( ACCESS_Frame( 2L ) )
291 new_offset = GET_UShort() + base_offset;
295 cur_offset = FILE_Pos();
296 if ( FILE_Seek( new_offset ) ||
297 ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != HB_Err_Ok )
299 (void)FILE_Seek( cur_offset );
301 if ( ACCESS_Frame( 2L ) )
304 count = al->GlyphCount = GET_UShort();
308 al->AttachPoint = NULL;
310 if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
313 ap = al->AttachPoint;
315 for ( n = 0; n < count; n++ )
317 if ( ACCESS_Frame( 2L ) )
320 new_offset = GET_UShort() + base_offset;
324 cur_offset = FILE_Pos();
325 if ( FILE_Seek( new_offset ) ||
326 ( error = Load_AttachPoint( &ap[n], stream ) ) != HB_Err_Ok )
328 (void)FILE_Seek( cur_offset );
336 for ( m = 0; m < n; m++ )
337 Free_AttachPoint( &ap[m] );
342 _HB_OPEN_Free_Coverage( &al->Coverage );
347 static void Free_AttachList( HB_AttachList* al)
357 if ( al->AttachPoint )
359 count = al->GlyphCount;
360 ap = al->AttachPoint;
362 for ( n = 0; n < count; n++ )
363 Free_AttachPoint( &ap[n] );
368 _HB_OPEN_Free_Coverage( &al->Coverage );
373 /*********************************
374 * LigCaretList related functions
375 *********************************/
378 /* CaretValueFormat1 */
379 /* CaretValueFormat2 */
380 /* CaretValueFormat3 */
381 /* CaretValueFormat4 */
383 static HB_Error Load_CaretValue( HB_CaretValue* cv,
388 HB_UInt cur_offset, new_offset, base_offset;
391 base_offset = FILE_Pos();
393 if ( ACCESS_Frame( 2L ) )
396 cv->CaretValueFormat = GET_UShort();
400 switch ( cv->CaretValueFormat )
403 if ( ACCESS_Frame( 2L ) )
406 cv->cvf.cvf1.Coordinate = GET_Short();
413 if ( ACCESS_Frame( 2L ) )
416 cv->cvf.cvf2.CaretValuePoint = GET_UShort();
423 if ( ACCESS_Frame( 4L ) )
426 cv->cvf.cvf3.Coordinate = GET_Short();
428 new_offset = GET_UShort() + base_offset;
432 cur_offset = FILE_Pos();
433 if ( FILE_Seek( new_offset ) ||
434 ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
435 stream ) ) != HB_Err_Ok )
437 (void)FILE_Seek( cur_offset );
442 if ( ACCESS_Frame( 2L ) )
445 #ifdef HB_SUPPORT_MULTIPLE_MASTER
446 cv->cvf.cvf4.IdCaretValue = GET_UShort();
455 return ERR(HB_Err_Invalid_SubTable_Format);
462 static void Free_CaretValue( HB_CaretValue* cv)
464 if ( cv->CaretValueFormat == 3 )
465 _HB_OPEN_Free_Device( cv->cvf.cvf3.Device );
471 static HB_Error Load_LigGlyph( HB_LigGlyph* lg,
476 HB_UShort n, m, count;
477 HB_UInt cur_offset, new_offset, base_offset;
482 base_offset = FILE_Pos();
484 if ( ACCESS_Frame( 2L ) )
487 count = lg->CaretCount = GET_UShort();
491 lg->CaretValue = NULL;
493 if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
498 for ( n = 0; n < count; n++ )
500 if ( ACCESS_Frame( 2L ) )
503 new_offset = GET_UShort() + base_offset;
507 cur_offset = FILE_Pos();
508 if ( FILE_Seek( new_offset ) ||
509 ( error = Load_CaretValue( &cv[n], stream ) ) != HB_Err_Ok )
511 (void)FILE_Seek( cur_offset );
517 for ( m = 0; m < n; m++ )
518 Free_CaretValue( &cv[m] );
525 static void Free_LigGlyph( HB_LigGlyph* lg)
532 if ( lg->CaretValue )
534 count = lg->CaretCount;
537 for ( n = 0; n < count; n++ )
538 Free_CaretValue( &cv[n] );
547 static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,
552 HB_UShort m, n, count;
553 HB_UInt cur_offset, new_offset, base_offset;
558 base_offset = FILE_Pos();
560 if ( ACCESS_Frame( 2L ) )
563 new_offset = GET_UShort() + base_offset;
567 cur_offset = FILE_Pos();
568 if ( FILE_Seek( new_offset ) ||
569 ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != HB_Err_Ok )
571 (void)FILE_Seek( cur_offset );
573 if ( ACCESS_Frame( 2L ) )
576 count = lcl->LigGlyphCount = GET_UShort();
580 lcl->LigGlyph = NULL;
582 if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
587 for ( n = 0; n < count; n++ )
589 if ( ACCESS_Frame( 2L ) )
592 new_offset = GET_UShort() + base_offset;
596 cur_offset = FILE_Pos();
597 if ( FILE_Seek( new_offset ) ||
598 ( error = Load_LigGlyph( &lg[n], stream ) ) != HB_Err_Ok )
600 (void)FILE_Seek( cur_offset );
608 for ( m = 0; m < n; m++ )
609 Free_LigGlyph( &lg[m] );
614 _HB_OPEN_Free_Coverage( &lcl->Coverage );
619 static void Free_LigCaretList( HB_LigCaretList* lcl )
631 count = lcl->LigGlyphCount;
634 for ( n = 0; n < count; n++ )
635 Free_LigGlyph( &lg[n] );
640 _HB_OPEN_Free_Coverage( &lcl->Coverage );
650 static HB_UShort Get_New_Class( HB_GDEFHeader* gdef,
654 HB_UShort glyph_index, array_index, count;
655 HB_UShort byte, bits;
657 HB_ClassRangeRecord* gcrr;
661 if ( glyphID >= gdef->LastGlyph )
664 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
665 gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
666 ngc = gdef->NewGlyphClasses;
668 if ( index < count && glyphID < gcrr[index].Start )
672 glyph_index = glyphID;
674 glyph_index = glyphID - gcrr[index - 1].End - 1;
678 array_index = index + 1;
679 glyph_index = glyphID - gcrr[index].End - 1;
682 byte = ngc[array_index][glyph_index / 4];
683 bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
685 return bits & 0x000F;
690 HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
692 HB_UShort* property )
694 HB_UShort class = 0, index = 0; /* shut compiler up */
699 if ( !gdef || !property )
700 return ERR(HB_Err_Invalid_Argument);
702 /* first, we check for mark attach classes */
704 if ( gdef->MarkAttachClassDef.loaded )
706 error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index );
707 if ( error && error != HB_Err_Not_Covered )
711 *property = class << 8;
716 error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
717 if ( error && error != HB_Err_Not_Covered )
720 /* if we have a constructed class table, check whether additional
721 values have been assigned */
723 if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )
724 class = Get_New_Class( gdef, glyphID, index );
729 case UNCLASSIFIED_GLYPH:
734 *property = HB_GDEF_BASE_GLYPH;
738 *property = HB_GDEF_LIGATURE;
742 *property = HB_GDEF_MARK;
745 case COMPONENT_GLYPH:
746 *property = HB_GDEF_COMPONENT;
754 static HB_Error Make_ClassRange( HB_ClassDefinition* cd,
762 HB_ClassDefFormat2* cdf2;
763 HB_ClassRangeRecord* crr;
768 if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
769 cdf2->ClassRangeCount + 1 ,
770 HB_ClassRangeRecord ) )
773 cdf2->ClassRangeCount++;
775 crr = cdf2->ClassRangeRecord;
776 index = cdf2->ClassRangeCount - 1;
778 crr[index].Start = start;
779 crr[index].End = end;
780 crr[index].Class = class;
787 HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
788 HB_UShort num_glyphs,
789 HB_UShort glyph_count,
790 HB_UShort* glyph_array,
791 HB_UShort* class_array )
793 HB_UShort start, curr_glyph, curr_class;
794 HB_UShort n, m, count;
797 HB_ClassDefinition* gcd;
798 HB_ClassRangeRecord* gcrr;
802 if ( !gdef || !glyph_array || !class_array )
803 return ERR(HB_Err_Invalid_Argument);
805 gcd = &gdef->GlyphClassDef;
807 /* We build a format 2 table */
809 gcd->ClassFormat = 2;
811 gcd->cd.cd2.ClassRangeCount = 0;
812 gcd->cd.cd2.ClassRangeRecord = NULL;
814 start = glyph_array[0];
815 curr_class = class_array[0];
818 if ( curr_class >= 5 )
820 error = ERR(HB_Err_Invalid_Argument);
826 for ( n = 0; n < glyph_count + 1; n++ )
828 if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
830 if ( n == glyph_count )
832 if ( ( error = Make_ClassRange( gcd, start,
834 curr_class) ) != HB_Err_Ok )
839 if ( curr_glyph == 0xFFFF )
841 error = ERR(HB_Err_Invalid_Argument);
850 if ( ( error = Make_ClassRange( gcd, start,
852 curr_class) ) != HB_Err_Ok )
855 if ( curr_glyph > glyph_array[n] )
857 error = ERR(HB_Err_Invalid_Argument);
861 start = glyph_array[n];
862 curr_class = class_array[n];
865 if ( curr_class >= 5 )
867 error = ERR(HB_Err_Invalid_Argument);
871 if ( n == glyph_count )
873 if ( ( error = Make_ClassRange( gcd, start,
875 curr_class) ) != HB_Err_Ok )
880 if ( curr_glyph == 0xFFFF )
882 error = ERR(HB_Err_Invalid_Argument);
891 /* now prepare the arrays for class values assigned during the lookup
894 if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
895 gcd->cd.cd2.ClassRangeCount + 1, HB_UShort* ) )
898 count = gcd->cd.cd2.ClassRangeCount;
899 gcrr = gcd->cd.cd2.ClassRangeRecord;
900 ngc = gdef->NewGlyphClasses;
902 /* We allocate arrays for all glyphs not covered by the class range
903 records. Each element holds four class values. */
909 if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) )
913 for ( n = 1; n < count; n++ )
915 if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
916 if ( ALLOC_ARRAY( ngc[n],
917 ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
922 if ( gcrr[count - 1].End != num_glyphs - 1 )
924 if ( ALLOC_ARRAY( ngc[count],
925 ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
930 else if ( num_glyphs > 0 )
932 if ( ALLOC_ARRAY( ngc[count],
933 ( num_glyphs + 3 ) / 4,
938 gdef->LastGlyph = num_glyphs - 1;
940 gdef->MarkAttachClassDef_offset = 0L;
941 gdef->MarkAttachClassDef.loaded = FALSE;
948 for ( m = 0; m < n; m++ )
952 FREE( gdef->NewGlyphClasses );
955 FREE( gcd->cd.cd2.ClassRangeRecord );
962 static void Free_NewGlyphClasses( HB_GDEFHeader* gdef )
968 if ( gdef->NewGlyphClasses )
970 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
971 ngc = gdef->NewGlyphClasses;
973 for ( n = 0; n < count; n++ )
982 _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
987 HB_UShort class, new_class, index = 0; /* shut compiler up */
988 HB_UShort byte, bits, mask;
989 HB_UShort array_index, glyph_index, count;
991 HB_ClassRangeRecord* gcrr;
995 error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
996 if ( error && error != HB_Err_Not_Covered )
999 /* we don't accept glyphs covered in `GlyphClassDef' */
1002 return HB_Err_Not_Covered;
1007 new_class = UNCLASSIFIED_GLYPH;
1010 case HB_GDEF_BASE_GLYPH:
1011 new_class = SIMPLE_GLYPH;
1014 case HB_GDEF_LIGATURE:
1015 new_class = LIGATURE_GLYPH;
1019 new_class = MARK_GLYPH;
1022 case HB_GDEF_COMPONENT:
1023 new_class = COMPONENT_GLYPH;
1027 return ERR(HB_Err_Invalid_Argument);
1030 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
1031 gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
1032 ngc = gdef->NewGlyphClasses;
1034 if ( index < count && glyphID < gcrr[index].Start )
1036 array_index = index;
1038 glyph_index = glyphID;
1040 glyph_index = glyphID - gcrr[index - 1].End - 1;
1044 array_index = index + 1;
1045 glyph_index = glyphID - gcrr[index].End - 1;
1048 byte = ngc[array_index][glyph_index / 4];
1049 bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
1050 class = bits & 0x000F;
1052 /* we don't overwrite existing entries */
1056 bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
1057 mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );
1059 ngc[array_index][glyph_index / 4] &= mask;
1060 ngc[array_index][glyph_index / 4] |= bits;
1067 HB_INTERNAL HB_Error
1068 _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
1071 HB_UShort* property )
1077 HB_UShort basic_glyph_class;
1078 HB_UShort desired_attachment_class;
1080 if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
1082 error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
1087 *property = gitem->gproperties;
1089 /* If the glyph was found in the MarkAttachmentClass table,
1090 * then that class value is the high byte of the result,
1091 * otherwise the low byte contains the basic type of the glyph
1092 * as defined by the GlyphClassDef table.
1094 if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
1095 basic_glyph_class = HB_GDEF_MARK;
1097 basic_glyph_class = *property;
1099 /* Return Not_Covered, if, for example, basic_glyph_class
1100 * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES
1102 if ( flags & basic_glyph_class )
1103 return HB_Err_Not_Covered;
1105 /* The high byte of LookupFlags has the meaning
1106 * "ignore marks of attachment type different than
1107 * the attachment type specified."
1109 desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
1110 if ( desired_attachment_class )
1112 if ( basic_glyph_class == HB_GDEF_MARK &&
1113 *property != desired_attachment_class )
1114 return HB_Err_Not_Covered;
1123 HB_INTERNAL HB_Error
1124 _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
1127 HB_UShort num_lookups)
1129 HB_Error error = HB_Err_Ok;
1132 /* We now check the LookupFlags for values larger than 0xFF to find
1133 out whether we need to load the `MarkAttachClassDef' field of the
1134 GDEF table -- this hack is necessary for OpenType 1.2 tables since
1135 the version field of the GDEF table hasn't been incremented.
1137 For constructed GDEF tables, we only load it if
1138 `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
1139 a constructed mark attach table is not supported currently). */
1142 gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
1144 for ( i = 0; i < num_lookups; i++ )
1147 if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
1149 if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
1150 ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
1151 256, stream ) ) != HB_Err_Ok )