Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: third_party/harfbuzz/src/harfbuzz-gdef.c

Issue 384503008: Delete third_party/harfbuzz (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove public header Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2006 Behdad Esfahbod
4 *
5 * This is part of HarfBuzz, an OpenType Layout engine library.
6 *
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.
12 *
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
17 * DAMAGE.
18 *
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.
24 */
25
26 #include "harfbuzz-impl.h"
27 #include "harfbuzz-gdef-private.h"
28 #include "harfbuzz-open-private.h"
29
30 static HB_Error Load_AttachList( HB_AttachList* al,
31 HB_Stream stream );
32 static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,
33 HB_Stream stream );
34
35 static void Free_AttachList( HB_AttachList* al);
36 static void Free_LigCaretList( HB_LigCaretList* lcl);
37
38 static void Free_NewGlyphClasses( HB_GDEFHeader* gdef);
39
40
41
42 /* GDEF glyph classes */
43
44 #define UNCLASSIFIED_GLYPH 0
45 #define SIMPLE_GLYPH 1
46 #define LIGATURE_GLYPH 2
47 #define MARK_GLYPH 3
48 #define COMPONENT_GLYPH 4
49
50
51
52
53
54
55 HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr )
56 {
57 HB_Error error;
58
59 HB_GDEFHeader* gdef;
60
61 if ( !retptr )
62 return ERR(HB_Err_Invalid_Argument);
63
64 if ( ALLOC( gdef, sizeof( *gdef ) ) )
65 return error;
66
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;
72
73 gdef->LastGlyph = 0;
74 gdef->NewGlyphClasses = NULL;
75
76 *retptr = gdef;
77
78 return HB_Err_Ok;
79 }
80
81
82 HB_Error HB_Load_GDEF_Table( HB_Stream stream,
83 HB_GDEFHeader** retptr )
84 {
85 HB_Error error;
86 HB_UInt cur_offset, new_offset, base_offset;
87
88 HB_GDEFHeader* gdef;
89
90
91 if ( !retptr )
92 return ERR(HB_Err_Invalid_Argument);
93
94 if ( GOTO_Table( TTAG_GDEF ) )
95 return error;
96
97 if (( error = HB_New_GDEF_Table ( &gdef ) ))
98 return error;
99
100 base_offset = FILE_Pos();
101
102 /* skip version */
103
104 if ( FILE_Seek( base_offset + 4L ) ||
105 ACCESS_Frame( 2L ) )
106 goto Fail0;
107
108 new_offset = GET_UShort();
109
110 FORGET_Frame();
111
112 /* all GDEF subtables are optional */
113
114 if ( new_offset )
115 {
116 new_offset += base_offset;
117
118 /* only classes 1-4 are allowed here */
119
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 )
124 goto Fail0;
125 (void)FILE_Seek( cur_offset );
126 }
127
128 if ( ACCESS_Frame( 2L ) )
129 goto Fail1;
130
131 new_offset = GET_UShort();
132
133 FORGET_Frame();
134
135 if ( new_offset )
136 {
137 new_offset += base_offset;
138
139 cur_offset = FILE_Pos();
140 if ( FILE_Seek( new_offset ) ||
141 ( error = Load_AttachList( &gdef->AttachList,
142 stream ) ) != HB_Err_Ok )
143 goto Fail1;
144 (void)FILE_Seek( cur_offset );
145 }
146
147 if ( ACCESS_Frame( 2L ) )
148 goto Fail2;
149
150 new_offset = GET_UShort();
151
152 FORGET_Frame();
153
154 if ( new_offset )
155 {
156 new_offset += base_offset;
157
158 cur_offset = FILE_Pos();
159 if ( FILE_Seek( new_offset ) ||
160 ( error = Load_LigCaretList( &gdef->LigCaretList,
161 stream ) ) != HB_Err_Ok )
162 goto Fail2;
163 (void)FILE_Seek( cur_offset );
164 }
165
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. */
169
170 if ( ACCESS_Frame( 2L ) )
171 goto Fail3;
172
173 new_offset = GET_UShort();
174
175 FORGET_Frame();
176
177 if ( new_offset )
178 gdef->MarkAttachClassDef_offset = new_offset + base_offset;
179 else
180 gdef->MarkAttachClassDef_offset = 0;
181
182 *retptr = gdef;
183
184 return HB_Err_Ok;
185
186 Fail3:
187 Free_LigCaretList( &gdef->LigCaretList );
188
189 Fail2:
190 Free_AttachList( &gdef->AttachList );
191
192 Fail1:
193 _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );
194
195 Fail0:
196 FREE( gdef );
197
198 return error;
199 }
200
201
202 HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef )
203 {
204 Free_LigCaretList( &gdef->LigCaretList );
205 Free_AttachList( &gdef->AttachList );
206 _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );
207 _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef );
208
209 Free_NewGlyphClasses( gdef );
210
211 FREE( gdef );
212
213 return HB_Err_Ok;
214 }
215
216
217
218
219 /*******************************
220 * AttachList related functions
221 *******************************/
222
223
224 /* AttachPoint */
225
226 static HB_Error Load_AttachPoint( HB_AttachPoint* ap,
227 HB_Stream stream )
228 {
229 HB_Error error;
230
231 HB_UShort n, count;
232 HB_UShort* pi;
233
234
235 if ( ACCESS_Frame( 2L ) )
236 return error;
237
238 count = ap->PointCount = GET_UShort();
239
240 FORGET_Frame();
241
242 ap->PointIndex = NULL;
243
244 if ( count )
245 {
246 if ( ALLOC_ARRAY( ap->PointIndex, count, HB_UShort ) )
247 return error;
248
249 pi = ap->PointIndex;
250
251 if ( ACCESS_Frame( count * 2L ) )
252 {
253 FREE( pi );
254 return error;
255 }
256
257 for ( n = 0; n < count; n++ )
258 pi[n] = GET_UShort();
259
260 FORGET_Frame();
261 }
262
263 return HB_Err_Ok;
264 }
265
266
267 static void Free_AttachPoint( HB_AttachPoint* ap )
268 {
269 FREE( ap->PointIndex );
270 }
271
272
273 /* AttachList */
274
275 static HB_Error Load_AttachList( HB_AttachList* al,
276 HB_Stream stream )
277 {
278 HB_Error error;
279
280 HB_UShort n, m, count;
281 HB_UInt cur_offset, new_offset, base_offset;
282
283 HB_AttachPoint* ap;
284
285
286 base_offset = FILE_Pos();
287
288 if ( ACCESS_Frame( 2L ) )
289 return error;
290
291 new_offset = GET_UShort() + base_offset;
292
293 FORGET_Frame();
294
295 cur_offset = FILE_Pos();
296 if ( FILE_Seek( new_offset ) ||
297 ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != HB_Err_Ok )
298 return error;
299 (void)FILE_Seek( cur_offset );
300
301 if ( ACCESS_Frame( 2L ) )
302 goto Fail2;
303
304 count = al->GlyphCount = GET_UShort();
305
306 FORGET_Frame();
307
308 al->AttachPoint = NULL;
309
310 if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
311 goto Fail2;
312
313 ap = al->AttachPoint;
314
315 for ( n = 0; n < count; n++ )
316 {
317 if ( ACCESS_Frame( 2L ) )
318 goto Fail1;
319
320 new_offset = GET_UShort() + base_offset;
321
322 FORGET_Frame();
323
324 cur_offset = FILE_Pos();
325 if ( FILE_Seek( new_offset ) ||
326 ( error = Load_AttachPoint( &ap[n], stream ) ) != HB_Err_Ok )
327 goto Fail1;
328 (void)FILE_Seek( cur_offset );
329 }
330
331 al->loaded = TRUE;
332
333 return HB_Err_Ok;
334
335 Fail1:
336 for ( m = 0; m < n; m++ )
337 Free_AttachPoint( &ap[m] );
338
339 FREE( ap );
340
341 Fail2:
342 _HB_OPEN_Free_Coverage( &al->Coverage );
343 return error;
344 }
345
346
347 static void Free_AttachList( HB_AttachList* al)
348 {
349 HB_UShort n, count;
350
351 HB_AttachPoint* ap;
352
353
354 if ( !al->loaded )
355 return;
356
357 if ( al->AttachPoint )
358 {
359 count = al->GlyphCount;
360 ap = al->AttachPoint;
361
362 for ( n = 0; n < count; n++ )
363 Free_AttachPoint( &ap[n] );
364
365 FREE( ap );
366 }
367
368 _HB_OPEN_Free_Coverage( &al->Coverage );
369 }
370
371
372
373 /*********************************
374 * LigCaretList related functions
375 *********************************/
376
377
378 /* CaretValueFormat1 */
379 /* CaretValueFormat2 */
380 /* CaretValueFormat3 */
381 /* CaretValueFormat4 */
382
383 static HB_Error Load_CaretValue( HB_CaretValue* cv,
384 HB_Stream stream )
385 {
386 HB_Error error;
387
388 HB_UInt cur_offset, new_offset, base_offset;
389
390
391 base_offset = FILE_Pos();
392
393 if ( ACCESS_Frame( 2L ) )
394 return error;
395
396 cv->CaretValueFormat = GET_UShort();
397
398 FORGET_Frame();
399
400 switch ( cv->CaretValueFormat )
401 {
402 case 1:
403 if ( ACCESS_Frame( 2L ) )
404 return error;
405
406 cv->cvf.cvf1.Coordinate = GET_Short();
407
408 FORGET_Frame();
409
410 break;
411
412 case 2:
413 if ( ACCESS_Frame( 2L ) )
414 return error;
415
416 cv->cvf.cvf2.CaretValuePoint = GET_UShort();
417
418 FORGET_Frame();
419
420 break;
421
422 case 3:
423 if ( ACCESS_Frame( 4L ) )
424 return error;
425
426 cv->cvf.cvf3.Coordinate = GET_Short();
427
428 new_offset = GET_UShort() + base_offset;
429
430 FORGET_Frame();
431
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 )
436 return error;
437 (void)FILE_Seek( cur_offset );
438
439 break;
440
441 case 4:
442 if ( ACCESS_Frame( 2L ) )
443 return error;
444
445 cv->cvf.cvf4.IdCaretValue = GET_UShort();
446
447 FORGET_Frame();
448 break;
449
450 default:
451 return ERR(HB_Err_Invalid_SubTable_Format);
452 }
453
454 return HB_Err_Ok;
455 }
456
457
458 static void Free_CaretValue( HB_CaretValue* cv)
459 {
460 if ( cv->CaretValueFormat == 3 )
461 _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device );
462 }
463
464
465 /* LigGlyph */
466
467 static HB_Error Load_LigGlyph( HB_LigGlyph* lg,
468 HB_Stream stream )
469 {
470 HB_Error error;
471
472 HB_UShort n, m, count;
473 HB_UInt cur_offset, new_offset, base_offset;
474
475 HB_CaretValue* cv;
476
477
478 base_offset = FILE_Pos();
479
480 if ( ACCESS_Frame( 2L ) )
481 return error;
482
483 count = lg->CaretCount = GET_UShort();
484
485 FORGET_Frame();
486
487 lg->CaretValue = NULL;
488
489 if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
490 return error;
491
492 cv = lg->CaretValue;
493
494 for ( n = 0; n < count; n++ )
495 {
496 if ( ACCESS_Frame( 2L ) )
497 goto Fail;
498
499 new_offset = GET_UShort() + base_offset;
500
501 FORGET_Frame();
502
503 cur_offset = FILE_Pos();
504 if ( FILE_Seek( new_offset ) ||
505 ( error = Load_CaretValue( &cv[n], stream ) ) != HB_Err_Ok )
506 goto Fail;
507 (void)FILE_Seek( cur_offset );
508 }
509
510 return HB_Err_Ok;
511
512 Fail:
513 for ( m = 0; m < n; m++ )
514 Free_CaretValue( &cv[m] );
515
516 FREE( cv );
517 return error;
518 }
519
520
521 static void Free_LigGlyph( HB_LigGlyph* lg)
522 {
523 HB_UShort n, count;
524
525 HB_CaretValue* cv;
526
527
528 if ( lg->CaretValue )
529 {
530 count = lg->CaretCount;
531 cv = lg->CaretValue;
532
533 for ( n = 0; n < count; n++ )
534 Free_CaretValue( &cv[n] );
535
536 FREE( cv );
537 }
538 }
539
540
541 /* LigCaretList */
542
543 static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,
544 HB_Stream stream )
545 {
546 HB_Error error;
547
548 HB_UShort m, n, count;
549 HB_UInt cur_offset, new_offset, base_offset;
550
551 HB_LigGlyph* lg;
552
553
554 base_offset = FILE_Pos();
555
556 if ( ACCESS_Frame( 2L ) )
557 return error;
558
559 new_offset = GET_UShort() + base_offset;
560
561 FORGET_Frame();
562
563 cur_offset = FILE_Pos();
564 if ( FILE_Seek( new_offset ) ||
565 ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != HB_Err_Ok )
566 return error;
567 (void)FILE_Seek( cur_offset );
568
569 if ( ACCESS_Frame( 2L ) )
570 goto Fail2;
571
572 count = lcl->LigGlyphCount = GET_UShort();
573
574 FORGET_Frame();
575
576 lcl->LigGlyph = NULL;
577
578 if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
579 goto Fail2;
580
581 lg = lcl->LigGlyph;
582
583 for ( n = 0; n < count; n++ )
584 {
585 if ( ACCESS_Frame( 2L ) )
586 goto Fail1;
587
588 new_offset = GET_UShort() + base_offset;
589
590 FORGET_Frame();
591
592 cur_offset = FILE_Pos();
593 if ( FILE_Seek( new_offset ) ||
594 ( error = Load_LigGlyph( &lg[n], stream ) ) != HB_Err_Ok )
595 goto Fail1;
596 (void)FILE_Seek( cur_offset );
597 }
598
599 lcl->loaded = TRUE;
600
601 return HB_Err_Ok;
602
603 Fail1:
604 for ( m = 0; m < n; m++ )
605 Free_LigGlyph( &lg[m] );
606
607 FREE( lg );
608
609 Fail2:
610 _HB_OPEN_Free_Coverage( &lcl->Coverage );
611 return error;
612 }
613
614
615 static void Free_LigCaretList( HB_LigCaretList* lcl )
616 {
617 HB_UShort n, count;
618
619 HB_LigGlyph* lg;
620
621
622 if ( !lcl->loaded )
623 return;
624
625 if ( lcl->LigGlyph )
626 {
627 count = lcl->LigGlyphCount;
628 lg = lcl->LigGlyph;
629
630 for ( n = 0; n < count; n++ )
631 Free_LigGlyph( &lg[n] );
632
633 FREE( lg );
634 }
635
636 _HB_OPEN_Free_Coverage( &lcl->Coverage );
637 }
638
639
640
641 /***********
642 * GDEF API
643 ***********/
644
645
646 static HB_UShort Get_New_Class( HB_GDEFHeader* gdef,
647 HB_UShort glyphID,
648 HB_UShort index )
649 {
650 HB_UShort glyph_index, array_index, count;
651 HB_UShort byte, bits;
652
653 HB_ClassRangeRecord* gcrr;
654 HB_UShort** ngc;
655
656
657 if ( glyphID >= gdef->LastGlyph )
658 return 0;
659
660 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
661 gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
662 ngc = gdef->NewGlyphClasses;
663
664 if ( index < count && glyphID < gcrr[index].Start )
665 {
666 array_index = index;
667 if ( index == 0 )
668 glyph_index = glyphID;
669 else
670 glyph_index = glyphID - gcrr[index - 1].End - 1;
671 }
672 else
673 {
674 array_index = index + 1;
675 glyph_index = glyphID - gcrr[index].End - 1;
676 }
677
678 byte = ngc[array_index][glyph_index / 4];
679 bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
680
681 return bits & 0x000F;
682 }
683
684
685
686 HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
687 HB_UShort glyphID,
688 HB_UShort* property )
689 {
690 HB_UShort class = 0, index = 0; /* shut compiler up */
691
692 HB_Error error;
693
694
695 if ( !gdef || !property )
696 return ERR(HB_Err_Invalid_Argument);
697
698 /* first, we check for mark attach classes */
699
700 if ( gdef->MarkAttachClassDef.loaded )
701 {
702 error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &ind ex );
703 if ( error && error != HB_Err_Not_Covered )
704 return error;
705 if ( !error )
706 {
707 *property = class << 8;
708 return HB_Err_Ok;
709 }
710 }
711
712 error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
713 if ( error && error != HB_Err_Not_Covered )
714 return error;
715
716 /* if we have a constructed class table, check whether additional
717 values have been assigned */
718
719 if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )
720 class = Get_New_Class( gdef, glyphID, index );
721
722 switch ( class )
723 {
724 default:
725 case UNCLASSIFIED_GLYPH:
726 *property = 0;
727 break;
728
729 case SIMPLE_GLYPH:
730 *property = HB_GDEF_BASE_GLYPH;
731 break;
732
733 case LIGATURE_GLYPH:
734 *property = HB_GDEF_LIGATURE;
735 break;
736
737 case MARK_GLYPH:
738 *property = HB_GDEF_MARK;
739 break;
740
741 case COMPONENT_GLYPH:
742 *property = HB_GDEF_COMPONENT;
743 break;
744 }
745
746 return HB_Err_Ok;
747 }
748
749
750 static HB_Error Make_ClassRange( HB_ClassDefinition* cd,
751 HB_UShort start,
752 HB_UShort end,
753 HB_UShort class )
754 {
755 HB_Error error;
756 HB_UShort index;
757
758 HB_ClassDefFormat2* cdf2;
759 HB_ClassRangeRecord* crr;
760
761
762 cdf2 = &cd->cd.cd2;
763
764 if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
765 cdf2->ClassRangeCount + 1 ,
766 HB_ClassRangeRecord ) )
767 return error;
768
769 cdf2->ClassRangeCount++;
770
771 crr = cdf2->ClassRangeRecord;
772 index = cdf2->ClassRangeCount - 1;
773
774 crr[index].Start = start;
775 crr[index].End = end;
776 crr[index].Class = class;
777
778 return HB_Err_Ok;
779 }
780
781
782
783 HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
784 HB_UShort num_glyphs,
785 HB_UShort glyph_count,
786 HB_UShort* glyph_array,
787 HB_UShort* class_array )
788 {
789 HB_UShort start, curr_glyph, curr_class;
790 HB_UShort n, m, count;
791 HB_Error error;
792
793 HB_ClassDefinition* gcd;
794 HB_ClassRangeRecord* gcrr;
795 HB_UShort** ngc;
796
797
798 if ( !gdef || !glyph_array || !class_array )
799 return ERR(HB_Err_Invalid_Argument);
800
801 gcd = &gdef->GlyphClassDef;
802
803 /* We build a format 2 table */
804
805 gcd->ClassFormat = 2;
806
807 gcd->cd.cd2.ClassRangeCount = 0;
808 gcd->cd.cd2.ClassRangeRecord = NULL;
809
810 start = glyph_array[0];
811 curr_class = class_array[0];
812 curr_glyph = start;
813
814 if ( curr_class >= 5 )
815 {
816 error = ERR(HB_Err_Invalid_Argument);
817 goto Fail4;
818 }
819
820 glyph_count--;
821
822 for ( n = 0; n < glyph_count + 1; n++ )
823 {
824 if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
825 {
826 if ( n == glyph_count )
827 {
828 if ( ( error = Make_ClassRange( gcd, start,
829 curr_glyph,
830 curr_class) ) != HB_Err_Ok )
831 goto Fail3;
832 }
833 else
834 {
835 if ( curr_glyph == 0xFFFF )
836 {
837 error = ERR(HB_Err_Invalid_Argument);
838 goto Fail3;
839 }
840 else
841 curr_glyph++;
842 }
843 }
844 else
845 {
846 if ( ( error = Make_ClassRange( gcd, start,
847 curr_glyph - 1,
848 curr_class) ) != HB_Err_Ok )
849 goto Fail3;
850
851 if ( curr_glyph > glyph_array[n] )
852 {
853 error = ERR(HB_Err_Invalid_Argument);
854 goto Fail3;
855 }
856
857 start = glyph_array[n];
858 curr_class = class_array[n];
859 curr_glyph = start;
860
861 if ( curr_class >= 5 )
862 {
863 error = ERR(HB_Err_Invalid_Argument);
864 goto Fail3;
865 }
866
867 if ( n == glyph_count )
868 {
869 if ( ( error = Make_ClassRange( gcd, start,
870 curr_glyph,
871 curr_class) ) != HB_Err_Ok )
872 goto Fail3;
873 }
874 else
875 {
876 if ( curr_glyph == 0xFFFF )
877 {
878 error = ERR(HB_Err_Invalid_Argument);
879 goto Fail3;
880 }
881 else
882 curr_glyph++;
883 }
884 }
885 }
886
887 /* now prepare the arrays for class values assigned during the lookup
888 process */
889
890 if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
891 gcd->cd.cd2.ClassRangeCount + 1, HB_UShort* ) )
892 goto Fail3;
893
894 count = gcd->cd.cd2.ClassRangeCount;
895 gcrr = gcd->cd.cd2.ClassRangeRecord;
896 ngc = gdef->NewGlyphClasses;
897
898 /* We allocate arrays for all glyphs not covered by the class range
899 records. Each element holds four class values. */
900
901 if ( count > 0 )
902 {
903 if ( gcrr[0].Start )
904 {
905 if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) )
906 goto Fail2;
907 }
908
909 for ( n = 1; n < count; n++ )
910 {
911 if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
912 if ( ALLOC_ARRAY( ngc[n],
913 ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
914 HB_UShort ) )
915 goto Fail1;
916 }
917
918 if ( gcrr[count - 1].End != num_glyphs - 1 )
919 {
920 if ( ALLOC_ARRAY( ngc[count],
921 ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
922 HB_UShort ) )
923 goto Fail1;
924 }
925 }
926 else if ( num_glyphs > 0 )
927 {
928 if ( ALLOC_ARRAY( ngc[count],
929 ( num_glyphs + 3 ) / 4,
930 HB_UShort ) )
931 goto Fail2;
932 }
933
934 gdef->LastGlyph = num_glyphs - 1;
935
936 gdef->MarkAttachClassDef_offset = 0L;
937 gdef->MarkAttachClassDef.loaded = FALSE;
938
939 gcd->loaded = TRUE;
940
941 return HB_Err_Ok;
942
943 Fail1:
944 for ( m = 0; m < n; m++ )
945 FREE( ngc[m] );
946
947 Fail2:
948 FREE( gdef->NewGlyphClasses );
949
950 Fail3:
951 FREE( gcd->cd.cd2.ClassRangeRecord );
952
953 Fail4:
954 return error;
955 }
956
957
958 static void Free_NewGlyphClasses( HB_GDEFHeader* gdef )
959 {
960 HB_UShort** ngc;
961 HB_UShort n, count;
962
963
964 if ( gdef->NewGlyphClasses )
965 {
966 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
967 ngc = gdef->NewGlyphClasses;
968
969 for ( n = 0; n < count; n++ )
970 FREE( ngc[n] );
971
972 FREE( ngc );
973 }
974 }
975
976
977 HB_INTERNAL HB_Error
978 _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
979 HB_UShort glyphID,
980 HB_UShort property )
981 {
982 HB_Error error;
983 HB_UShort class, new_class, index = 0; /* shut compiler up */
984 HB_UShort byte, bits, mask;
985 HB_UShort array_index, glyph_index, count;
986
987 HB_ClassRangeRecord* gcrr;
988 HB_UShort** ngc;
989
990
991 error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
992 if ( error && error != HB_Err_Not_Covered )
993 return error;
994
995 /* we don't accept glyphs covered in `GlyphClassDef' */
996
997 if ( !error )
998 return HB_Err_Not_Covered;
999
1000 switch ( property )
1001 {
1002 case 0:
1003 new_class = UNCLASSIFIED_GLYPH;
1004 break;
1005
1006 case HB_GDEF_BASE_GLYPH:
1007 new_class = SIMPLE_GLYPH;
1008 break;
1009
1010 case HB_GDEF_LIGATURE:
1011 new_class = LIGATURE_GLYPH;
1012 break;
1013
1014 case HB_GDEF_MARK:
1015 new_class = MARK_GLYPH;
1016 break;
1017
1018 case HB_GDEF_COMPONENT:
1019 new_class = COMPONENT_GLYPH;
1020 break;
1021
1022 default:
1023 return ERR(HB_Err_Invalid_Argument);
1024 }
1025
1026 count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
1027 gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
1028 ngc = gdef->NewGlyphClasses;
1029
1030 if ( index < count && glyphID < gcrr[index].Start )
1031 {
1032 array_index = index;
1033 if ( index == 0 )
1034 glyph_index = glyphID;
1035 else
1036 glyph_index = glyphID - gcrr[index - 1].End - 1;
1037 }
1038 else
1039 {
1040 array_index = index + 1;
1041 glyph_index = glyphID - gcrr[index].End - 1;
1042 }
1043
1044 byte = ngc[array_index][glyph_index / 4];
1045 bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
1046 class = bits & 0x000F;
1047
1048 /* we don't overwrite existing entries */
1049
1050 if ( !class )
1051 {
1052 bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
1053 mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );
1054
1055 ngc[array_index][glyph_index / 4] &= mask;
1056 ngc[array_index][glyph_index / 4] |= bits;
1057 }
1058
1059 return HB_Err_Ok;
1060 }
1061
1062
1063 HB_INTERNAL HB_Error
1064 _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
1065 HB_GlyphItem gitem,
1066 HB_UShort flags,
1067 HB_UShort* property )
1068 {
1069 HB_Error error;
1070
1071 if ( gdef )
1072 {
1073 HB_UShort basic_glyph_class;
1074 HB_UShort desired_attachment_class;
1075
1076 if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
1077 {
1078 error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperti es );
1079 if ( error )
1080 return error;
1081 }
1082
1083 *property = gitem->gproperties;
1084
1085 /* If the glyph was found in the MarkAttachmentClass table,
1086 * then that class value is the high byte of the result,
1087 * otherwise the low byte contains the basic type of the glyph
1088 * as defined by the GlyphClassDef table.
1089 */
1090 if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
1091 basic_glyph_class = HB_GDEF_MARK;
1092 else
1093 basic_glyph_class = *property;
1094
1095 /* Return Not_Covered, if, for example, basic_glyph_class
1096 * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURE S
1097 */
1098 if ( flags & basic_glyph_class )
1099 return HB_Err_Not_Covered;
1100
1101 /* The high byte of LookupFlags has the meaning
1102 * "ignore marks of attachment type different than
1103 * the attachment type specified."
1104 */
1105 desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
1106 if ( desired_attachment_class )
1107 {
1108 if ( basic_glyph_class == HB_GDEF_MARK &&
1109 *property != desired_attachment_class )
1110 return HB_Err_Not_Covered;
1111 }
1112 } else {
1113 *property = 0;
1114 }
1115
1116 return HB_Err_Ok;
1117 }
1118
1119 HB_INTERNAL HB_Error
1120 _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
1121 HB_Stream stream,
1122 HB_Lookup* lo,
1123 HB_UShort num_lookups)
1124 {
1125 HB_Error error = HB_Err_Ok;
1126 HB_UShort i;
1127
1128 /* We now check the LookupFlags for values larger than 0xFF to find
1129 out whether we need to load the `MarkAttachClassDef' field of the
1130 GDEF table -- this hack is necessary for OpenType 1.2 tables since
1131 the version field of the GDEF table hasn't been incremented.
1132
1133 For constructed GDEF tables, we only load it if
1134 `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
1135 a constructed mark attach table is not supported currently). */
1136
1137 if ( gdef &&
1138 gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
1139 {
1140 for ( i = 0; i < num_lookups; i++ )
1141 {
1142
1143 if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
1144 {
1145 if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
1146 ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
1147 256, stream ) ) != HB_Err_Ok )
1148 goto Done;
1149
1150 break;
1151 }
1152 }
1153 }
1154
1155 Done:
1156 return error;
1157 }
1158
1159 /* END */
OLDNEW
« no previous file with comments | « third_party/harfbuzz/src/harfbuzz-gdef.h ('k') | third_party/harfbuzz/src/harfbuzz-gdef-private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698