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

Side by Side Diff: third_party/harfbuzz/src/harfbuzz-open.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-open-private.h"
28
29
30 /***************************
31 * Script related functions
32 ***************************/
33
34
35 /* LangSys */
36
37 static HB_Error Load_LangSys( HB_LangSys* ls,
38 HB_Stream stream )
39 {
40 HB_Error error;
41 HB_UShort n, count;
42 HB_UShort* fi;
43
44
45 if ( ACCESS_Frame( 6L ) )
46 return error;
47
48 ls->LookupOrderOffset = GET_UShort(); /* should be 0 */
49 ls->ReqFeatureIndex = GET_UShort();
50 count = ls->FeatureCount = GET_UShort();
51
52 FORGET_Frame();
53
54 ls->FeatureIndex = NULL;
55
56 if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) )
57 return error;
58
59 if ( ACCESS_Frame( count * 2L ) )
60 {
61 FREE( ls->FeatureIndex );
62 return error;
63 }
64
65 fi = ls->FeatureIndex;
66
67 for ( n = 0; n < count; n++ )
68 fi[n] = GET_UShort();
69
70 FORGET_Frame();
71
72 return HB_Err_Ok;
73 }
74
75
76 static void Free_LangSys( HB_LangSys* ls )
77 {
78 FREE( ls->FeatureIndex );
79 }
80
81
82 /* Script */
83
84 static HB_Error Load_Script( HB_ScriptTable* s,
85 HB_Stream stream )
86 {
87 HB_Error error;
88 HB_UShort n, m, count;
89 HB_UInt cur_offset, new_offset, base_offset;
90
91 HB_LangSysRecord* lsr;
92
93
94 base_offset = FILE_Pos();
95
96 if ( ACCESS_Frame( 2L ) )
97 return error;
98
99 new_offset = GET_UShort() + base_offset;
100
101 FORGET_Frame();
102
103 if ( new_offset != base_offset ) /* not a NULL offset */
104 {
105 cur_offset = FILE_Pos();
106 if ( FILE_Seek( new_offset ) ||
107 ( error = Load_LangSys( &s->DefaultLangSys,
108 stream ) ) != HB_Err_Ok )
109 return error;
110 (void)FILE_Seek( cur_offset );
111 }
112 else
113 {
114 /* we create a DefaultLangSys table with no entries */
115
116 s->DefaultLangSys.LookupOrderOffset = 0;
117 s->DefaultLangSys.ReqFeatureIndex = 0xFFFF;
118 s->DefaultLangSys.FeatureCount = 0;
119 s->DefaultLangSys.FeatureIndex = NULL;
120 }
121
122 if ( ACCESS_Frame( 2L ) )
123 goto Fail2;
124
125 count = s->LangSysCount = GET_UShort();
126
127 /* safety check; otherwise the official handling of TrueType Open
128 fonts won't work */
129
130 if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
131 {
132 error = HB_Err_Not_Covered;
133 goto Fail2;
134 }
135
136 FORGET_Frame();
137
138 s->LangSysRecord = NULL;
139
140 if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )
141 goto Fail2;
142
143 lsr = s->LangSysRecord;
144
145 for ( n = 0; n < count; n++ )
146 {
147 if ( ACCESS_Frame( 6L ) )
148 goto Fail1;
149
150 lsr[n].LangSysTag = GET_ULong();
151 new_offset = GET_UShort() + base_offset;
152
153 FORGET_Frame();
154
155 cur_offset = FILE_Pos();
156 if ( FILE_Seek( new_offset ) ||
157 ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok )
158 goto Fail1;
159 (void)FILE_Seek( cur_offset );
160 }
161
162 return HB_Err_Ok;
163
164 Fail1:
165 for ( m = 0; m < n; m++ )
166 Free_LangSys( &lsr[m].LangSys );
167
168 FREE( s->LangSysRecord );
169
170 Fail2:
171 Free_LangSys( &s->DefaultLangSys );
172 return error;
173 }
174
175
176 static void Free_Script( HB_ScriptTable* s )
177 {
178 HB_UShort n, count;
179
180 HB_LangSysRecord* lsr;
181
182
183 Free_LangSys( &s->DefaultLangSys );
184
185 if ( s->LangSysRecord )
186 {
187 count = s->LangSysCount;
188 lsr = s->LangSysRecord;
189
190 for ( n = 0; n < count; n++ )
191 Free_LangSys( &lsr[n].LangSys );
192
193 FREE( lsr );
194 }
195 }
196
197
198 /* ScriptList */
199
200 HB_INTERNAL HB_Error
201 _HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
202 HB_Stream stream )
203 {
204 HB_Error error;
205
206 HB_UShort n, script_count;
207 HB_UInt cur_offset, new_offset, base_offset;
208
209 HB_ScriptRecord* sr;
210
211
212 base_offset = FILE_Pos();
213
214 if ( ACCESS_Frame( 2L ) )
215 return error;
216
217 script_count = GET_UShort();
218
219 FORGET_Frame();
220
221 sl->ScriptRecord = NULL;
222
223 if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )
224 return error;
225
226 sr = sl->ScriptRecord;
227
228 sl->ScriptCount= 0;
229 for ( n = 0; n < script_count; n++ )
230 {
231 if ( ACCESS_Frame( 6L ) )
232 goto Fail;
233
234 sr[sl->ScriptCount].ScriptTag = GET_ULong();
235 new_offset = GET_UShort() + base_offset;
236
237 FORGET_Frame();
238
239 cur_offset = FILE_Pos();
240
241 if ( FILE_Seek( new_offset ) )
242 goto Fail;
243
244 error = Load_Script( &sr[sl->ScriptCount].Script, stream );
245 if ( error == HB_Err_Ok )
246 sl->ScriptCount += 1;
247 else if ( error != HB_Err_Not_Covered )
248 goto Fail;
249
250 (void)FILE_Seek( cur_offset );
251 }
252
253 /* Empty tables are harmless and generated by fontforge.
254 * See http://bugzilla.gnome.org/show_bug.cgi?id=347073
255 */
256 #if 0
257 if ( sl->ScriptCount == 0 )
258 {
259 error = ERR(HB_Err_Invalid_SubTable);
260 goto Fail;
261 }
262 #endif
263
264 return HB_Err_Ok;
265
266 Fail:
267 for ( n = 0; n < sl->ScriptCount; n++ )
268 Free_Script( &sr[n].Script );
269
270 FREE( sl->ScriptRecord );
271 return error;
272 }
273
274
275 HB_INTERNAL void
276 _HB_OPEN_Free_ScriptList( HB_ScriptList* sl )
277 {
278 HB_UShort n, count;
279
280 HB_ScriptRecord* sr;
281
282
283 if ( sl->ScriptRecord )
284 {
285 count = sl->ScriptCount;
286 sr = sl->ScriptRecord;
287
288 for ( n = 0; n < count; n++ )
289 Free_Script( &sr[n].Script );
290
291 FREE( sr );
292 }
293 }
294
295
296
297 /*********************************
298 * Feature List related functions
299 *********************************/
300
301
302 /* Feature */
303
304 static HB_Error Load_Feature( HB_Feature* f,
305 HB_Stream stream )
306 {
307 HB_Error error;
308
309 HB_UShort n, count;
310
311 HB_UShort* lli;
312
313
314 if ( ACCESS_Frame( 4L ) )
315 return error;
316
317 f->FeatureParams = GET_UShort(); /* should be 0 */
318 count = f->LookupListCount = GET_UShort();
319
320 FORGET_Frame();
321
322 f->LookupListIndex = NULL;
323
324 if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) )
325 return error;
326
327 lli = f->LookupListIndex;
328
329 if ( ACCESS_Frame( count * 2L ) )
330 {
331 FREE( f->LookupListIndex );
332 return error;
333 }
334
335 for ( n = 0; n < count; n++ )
336 lli[n] = GET_UShort();
337
338 FORGET_Frame();
339
340 return HB_Err_Ok;
341 }
342
343
344 static void Free_Feature( HB_Feature* f )
345 {
346 FREE( f->LookupListIndex );
347 }
348
349
350 /* FeatureList */
351
352 HB_INTERNAL HB_Error
353 _HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
354 HB_Stream stream )
355 {
356 HB_Error error;
357
358 HB_UShort n, m, count;
359 HB_UInt cur_offset, new_offset, base_offset;
360
361 HB_FeatureRecord* fr;
362
363
364 base_offset = FILE_Pos();
365
366 if ( ACCESS_Frame( 2L ) )
367 return error;
368
369 count = fl->FeatureCount = GET_UShort();
370
371 FORGET_Frame();
372
373 fl->FeatureRecord = NULL;
374
375 if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )
376 return error;
377 if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) )
378 goto Fail2;
379
380 fl->ApplyCount = 0;
381
382 fr = fl->FeatureRecord;
383
384 for ( n = 0; n < count; n++ )
385 {
386 if ( ACCESS_Frame( 6L ) )
387 goto Fail1;
388
389 fr[n].FeatureTag = GET_ULong();
390 new_offset = GET_UShort() + base_offset;
391
392 FORGET_Frame();
393
394 cur_offset = FILE_Pos();
395 if ( FILE_Seek( new_offset ) ||
396 ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok )
397 goto Fail1;
398 (void)FILE_Seek( cur_offset );
399 }
400
401 return HB_Err_Ok;
402
403 Fail1:
404 for ( m = 0; m < n; m++ )
405 Free_Feature( &fr[m].Feature );
406
407 FREE( fl->ApplyOrder );
408
409 Fail2:
410 FREE( fl->FeatureRecord );
411
412 return error;
413 }
414
415
416 HB_INTERNAL void
417 _HB_OPEN_Free_FeatureList( HB_FeatureList* fl )
418 {
419 HB_UShort n, count;
420
421 HB_FeatureRecord* fr;
422
423
424 if ( fl->FeatureRecord )
425 {
426 count = fl->FeatureCount;
427 fr = fl->FeatureRecord;
428
429 for ( n = 0; n < count; n++ )
430 Free_Feature( &fr[n].Feature );
431
432 FREE( fr );
433 }
434
435 FREE( fl->ApplyOrder );
436 }
437
438
439
440 /********************************
441 * Lookup List related functions
442 ********************************/
443
444 /* the subroutines of the following two functions are defined in
445 ftxgsub.c and ftxgpos.c respectively */
446
447
448 /* SubTable */
449
450 static HB_Error Load_SubTable( HB_SubTable* st,
451 HB_Stream stream,
452 HB_Type table_type,
453 HB_UShort lookup_type )
454 {
455 if ( table_type == HB_Type_GSUB )
456 return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );
457 else
458 return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );
459 }
460
461
462 static void Free_SubTable( HB_SubTable* st,
463 HB_Type table_type,
464 HB_UShort lookup_type )
465 {
466 if ( table_type == HB_Type_GSUB )
467 _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type );
468 else
469 _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type );
470 }
471
472
473 /* Lookup */
474
475 static HB_Error Load_Lookup( HB_Lookup* l,
476 HB_Stream stream,
477 HB_Type type )
478 {
479 HB_Error error;
480
481 HB_UShort n, m, count;
482 HB_UInt cur_offset, new_offset, base_offset;
483
484 HB_SubTable* st;
485
486 HB_Bool is_extension = FALSE;
487
488
489 base_offset = FILE_Pos();
490
491 if ( ACCESS_Frame( 6L ) )
492 return error;
493
494 l->LookupType = GET_UShort();
495 l->LookupFlag = GET_UShort();
496 count = l->SubTableCount = GET_UShort();
497
498 FORGET_Frame();
499
500 l->SubTable = NULL;
501
502 if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )
503 return error;
504
505 st = l->SubTable;
506
507 if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||
508 ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )
509 is_extension = TRUE;
510
511 for ( n = 0; n < count; n++ )
512 {
513 if ( ACCESS_Frame( 2L ) )
514 goto Fail;
515
516 new_offset = GET_UShort() + base_offset;
517
518 FORGET_Frame();
519
520 cur_offset = FILE_Pos();
521
522 if ( is_extension )
523 {
524 if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
525 goto Fail;
526
527 if (GET_UShort() != 1) /* format should be 1 */
528 goto Fail;
529
530 l->LookupType = GET_UShort();
531 new_offset += GET_ULong();
532
533 FORGET_Frame();
534 }
535
536 if ( FILE_Seek( new_offset ) ||
537 ( error = Load_SubTable( &st[n], stream,
538 type, l->LookupType ) ) != HB_Err_Ok )
539 goto Fail;
540 (void)FILE_Seek( cur_offset );
541 }
542
543 return HB_Err_Ok;
544
545 Fail:
546 for ( m = 0; m < n; m++ )
547 Free_SubTable( &st[m], type, l->LookupType );
548
549 FREE( l->SubTable );
550 return error;
551 }
552
553
554 static void Free_Lookup( HB_Lookup* l,
555 HB_Type type)
556 {
557 HB_UShort n, count;
558
559 HB_SubTable* st;
560
561
562 if ( l->SubTable )
563 {
564 count = l->SubTableCount;
565 st = l->SubTable;
566
567 for ( n = 0; n < count; n++ )
568 Free_SubTable( &st[n], type, l->LookupType );
569
570 FREE( st );
571 }
572 }
573
574
575 /* LookupList */
576
577 HB_INTERNAL HB_Error
578 _HB_OPEN_Load_LookupList( HB_LookupList* ll,
579 HB_Stream stream,
580 HB_Type type )
581 {
582 HB_Error error;
583
584 HB_UShort n, m, count;
585 HB_UInt cur_offset, new_offset, base_offset;
586
587 HB_Lookup* l;
588
589
590 base_offset = FILE_Pos();
591
592 if ( ACCESS_Frame( 2L ) )
593 return error;
594
595 count = ll->LookupCount = GET_UShort();
596
597 FORGET_Frame();
598
599 ll->Lookup = NULL;
600
601 if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )
602 return error;
603 if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) )
604 goto Fail2;
605
606 l = ll->Lookup;
607
608 for ( n = 0; n < count; n++ )
609 {
610 if ( ACCESS_Frame( 2L ) )
611 goto Fail1;
612
613 new_offset = GET_UShort() + base_offset;
614
615 FORGET_Frame();
616
617 cur_offset = FILE_Pos();
618 if ( FILE_Seek( new_offset ) ||
619 ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok )
620 goto Fail1;
621 (void)FILE_Seek( cur_offset );
622 }
623
624 return HB_Err_Ok;
625
626 Fail1:
627 FREE( ll->Properties );
628
629 for ( m = 0; m < n; m++ )
630 Free_Lookup( &l[m], type );
631
632 Fail2:
633 FREE( ll->Lookup );
634 return error;
635 }
636
637
638 HB_INTERNAL void
639 _HB_OPEN_Free_LookupList( HB_LookupList* ll,
640 HB_Type type )
641 {
642 HB_UShort n, count;
643
644 HB_Lookup* l;
645
646
647 FREE( ll->Properties );
648
649 if ( ll->Lookup )
650 {
651 count = ll->LookupCount;
652 l = ll->Lookup;
653
654 for ( n = 0; n < count; n++ )
655 Free_Lookup( &l[n], type );
656
657 FREE( l );
658 }
659 }
660
661
662
663 /*****************************
664 * Coverage related functions
665 *****************************/
666
667
668 /* CoverageFormat1 */
669
670 static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1,
671 HB_Stream stream )
672 {
673 HB_Error error;
674
675 HB_UShort n, count;
676
677 HB_UShort* ga;
678
679
680 if ( ACCESS_Frame( 2L ) )
681 return error;
682
683 count = cf1->GlyphCount = GET_UShort();
684
685 FORGET_Frame();
686
687 cf1->GlyphArray = NULL;
688
689 if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) )
690 return error;
691
692 ga = cf1->GlyphArray;
693
694 if ( ACCESS_Frame( count * 2L ) )
695 {
696 FREE( cf1->GlyphArray );
697 return error;
698 }
699
700 for ( n = 0; n < count; n++ )
701 ga[n] = GET_UShort();
702
703 FORGET_Frame();
704
705 return HB_Err_Ok;
706 }
707
708
709 static void Free_Coverage1( HB_CoverageFormat1* cf1)
710 {
711 FREE( cf1->GlyphArray );
712 }
713
714
715 /* CoverageFormat2 */
716
717 static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2,
718 HB_Stream stream )
719 {
720 HB_Error error;
721
722 HB_UShort n, count;
723
724 HB_RangeRecord* rr;
725
726
727 if ( ACCESS_Frame( 2L ) )
728 return error;
729
730 count = cf2->RangeCount = GET_UShort();
731
732 FORGET_Frame();
733
734 cf2->RangeRecord = NULL;
735
736 if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )
737 return error;
738
739 rr = cf2->RangeRecord;
740
741 if ( ACCESS_Frame( count * 6L ) )
742 goto Fail;
743
744 for ( n = 0; n < count; n++ )
745 {
746 rr[n].Start = GET_UShort();
747 rr[n].End = GET_UShort();
748 rr[n].StartCoverageIndex = GET_UShort();
749
750 /* sanity check; we are limited to 16bit integers */
751 if ( rr[n].Start > rr[n].End ||
752 ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
753 0x10000L )
754 {
755 error = ERR(HB_Err_Invalid_SubTable);
756 goto Fail;
757 }
758 }
759
760 FORGET_Frame();
761
762 return HB_Err_Ok;
763
764 Fail:
765 FREE( cf2->RangeRecord );
766 return error;
767 }
768
769
770 static void Free_Coverage2( HB_CoverageFormat2* cf2 )
771 {
772 FREE( cf2->RangeRecord );
773 }
774
775
776 HB_INTERNAL HB_Error
777 _HB_OPEN_Load_Coverage( HB_Coverage* c,
778 HB_Stream stream )
779 {
780 HB_Error error;
781
782 if ( ACCESS_Frame( 2L ) )
783 return error;
784
785 c->CoverageFormat = GET_UShort();
786
787 FORGET_Frame();
788
789 switch ( c->CoverageFormat )
790 {
791 case 1: return Load_Coverage1( &c->cf.cf1, stream );
792 case 2: return Load_Coverage2( &c->cf.cf2, stream );
793 default: return ERR(HB_Err_Invalid_SubTable_Format);
794 }
795
796 return HB_Err_Ok; /* never reached */
797 }
798
799
800 HB_INTERNAL void
801 _HB_OPEN_Free_Coverage( HB_Coverage* c )
802 {
803 switch ( c->CoverageFormat )
804 {
805 case 1: Free_Coverage1( &c->cf.cf1 ); break;
806 case 2: Free_Coverage2( &c->cf.cf2 ); break;
807 default: break;
808 }
809 }
810
811
812 static HB_Error Coverage_Index1( HB_CoverageFormat1* cf1,
813 HB_UShort glyphID,
814 HB_UShort* index )
815 {
816 HB_UShort min, max, new_min, new_max, middle;
817
818 HB_UShort* array = cf1->GlyphArray;
819
820
821 /* binary search */
822
823 if ( cf1->GlyphCount == 0 )
824 return HB_Err_Not_Covered;
825
826 new_min = 0;
827 new_max = cf1->GlyphCount - 1;
828
829 do
830 {
831 min = new_min;
832 max = new_max;
833
834 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
835 overflow and rounding errors */
836
837 middle = max - ( ( max - min ) >> 1 );
838
839 if ( glyphID == array[middle] )
840 {
841 *index = middle;
842 return HB_Err_Ok;
843 }
844 else if ( glyphID < array[middle] )
845 {
846 if ( middle == min )
847 break;
848 new_max = middle - 1;
849 }
850 else
851 {
852 if ( middle == max )
853 break;
854 new_min = middle + 1;
855 }
856 } while ( min < max );
857
858 return HB_Err_Not_Covered;
859 }
860
861
862 static HB_Error Coverage_Index2( HB_CoverageFormat2* cf2,
863 HB_UShort glyphID,
864 HB_UShort* index )
865 {
866 HB_UShort min, max, new_min, new_max, middle;
867
868 HB_RangeRecord* rr = cf2->RangeRecord;
869
870
871 /* binary search */
872
873 if ( cf2->RangeCount == 0 )
874 return HB_Err_Not_Covered;
875
876 new_min = 0;
877 new_max = cf2->RangeCount - 1;
878
879 do
880 {
881 min = new_min;
882 max = new_max;
883
884 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
885 overflow and rounding errors */
886
887 middle = max - ( ( max - min ) >> 1 );
888
889 if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
890 {
891 *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
892 return HB_Err_Ok;
893 }
894 else if ( glyphID < rr[middle].Start )
895 {
896 if ( middle == min )
897 break;
898 new_max = middle - 1;
899 }
900 else
901 {
902 if ( middle == max )
903 break;
904 new_min = middle + 1;
905 }
906 } while ( min < max );
907
908 return HB_Err_Not_Covered;
909 }
910
911
912 HB_INTERNAL HB_Error
913 _HB_OPEN_Coverage_Index( HB_Coverage* c,
914 HB_UShort glyphID,
915 HB_UShort* index )
916 {
917 switch ( c->CoverageFormat )
918 {
919 case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index );
920 case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index );
921 default: return ERR(HB_Err_Invalid_SubTable_Format);
922 }
923
924 return HB_Err_Ok; /* never reached */
925 }
926
927
928
929 /*************************************
930 * Class Definition related functions
931 *************************************/
932
933
934 /* ClassDefFormat1 */
935
936 static HB_Error Load_ClassDef1( HB_ClassDefinition* cd,
937 HB_UShort limit,
938 HB_Stream stream )
939 {
940 HB_Error error;
941
942 HB_UShort n, count;
943
944 HB_UShort* cva;
945
946 HB_ClassDefFormat1* cdf1;
947
948
949 cdf1 = &cd->cd.cd1;
950
951 if ( ACCESS_Frame( 4L ) )
952 return error;
953
954 cdf1->StartGlyph = GET_UShort();
955 count = cdf1->GlyphCount = GET_UShort();
956
957 FORGET_Frame();
958
959 /* sanity check; we are limited to 16bit integers */
960
961 if ( cdf1->StartGlyph + (long)count >= 0x10000L )
962 return ERR(HB_Err_Invalid_SubTable);
963
964 cdf1->ClassValueArray = NULL;
965
966 if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) )
967 return error;
968
969 cva = cdf1->ClassValueArray;
970
971 if ( ACCESS_Frame( count * 2L ) )
972 goto Fail;
973
974 for ( n = 0; n < count; n++ )
975 {
976 cva[n] = GET_UShort();
977 if ( cva[n] >= limit )
978 {
979 error = ERR(HB_Err_Invalid_SubTable);
980 goto Fail;
981 }
982 }
983
984 FORGET_Frame();
985
986 return HB_Err_Ok;
987
988 Fail:
989 FREE( cva );
990
991 return error;
992 }
993
994
995 static void Free_ClassDef1( HB_ClassDefFormat1* cdf1 )
996 {
997 FREE( cdf1->ClassValueArray );
998 }
999
1000
1001 /* ClassDefFormat2 */
1002
1003 static HB_Error Load_ClassDef2( HB_ClassDefinition* cd,
1004 HB_UShort limit,
1005 HB_Stream stream )
1006 {
1007 HB_Error error;
1008
1009 HB_UShort n, count;
1010
1011 HB_ClassRangeRecord* crr;
1012
1013 HB_ClassDefFormat2* cdf2;
1014
1015
1016 cdf2 = &cd->cd.cd2;
1017
1018 if ( ACCESS_Frame( 2L ) )
1019 return error;
1020
1021 count = GET_UShort();
1022 cdf2->ClassRangeCount = 0; /* zero for now. we fill with the number of good e ntries later */
1023
1024 FORGET_Frame();
1025
1026 cdf2->ClassRangeRecord = NULL;
1027
1028 if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )
1029 return error;
1030
1031 crr = cdf2->ClassRangeRecord;
1032
1033 if ( ACCESS_Frame( count * 6L ) )
1034 goto Fail;
1035
1036 for ( n = 0; n < count; n++ )
1037 {
1038 crr[n].Start = GET_UShort();
1039 crr[n].End = GET_UShort();
1040 crr[n].Class = GET_UShort();
1041
1042 /* sanity check */
1043
1044 if ( crr[n].Start > crr[n].End ||
1045 crr[n].Class >= limit )
1046 {
1047 /* XXX
1048 * Corrupt entry. Skip it.
1049 * This is hit by Nafees Nastaliq font for example
1050 */
1051 n--;
1052 count--;
1053 }
1054 }
1055
1056 FORGET_Frame();
1057
1058 cdf2->ClassRangeCount = count;
1059
1060 return HB_Err_Ok;
1061
1062 Fail:
1063 FREE( crr );
1064
1065 return error;
1066 }
1067
1068
1069 static void Free_ClassDef2( HB_ClassDefFormat2* cdf2 )
1070 {
1071 FREE( cdf2->ClassRangeRecord );
1072 }
1073
1074
1075 /* ClassDefinition */
1076
1077 HB_INTERNAL HB_Error
1078 _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
1079 HB_UShort limit,
1080 HB_Stream stream )
1081 {
1082 HB_Error error;
1083
1084 if ( ACCESS_Frame( 2L ) )
1085 return error;
1086
1087 cd->ClassFormat = GET_UShort();
1088
1089 FORGET_Frame();
1090
1091 switch ( cd->ClassFormat )
1092 {
1093 case 1: error = Load_ClassDef1( cd, limit, stream ); break;
1094 case 2: error = Load_ClassDef2( cd, limit, stream ); break;
1095 default: error = ERR(HB_Err_Invalid_SubTable_Format); break;
1096 }
1097
1098 if ( error )
1099 return error;
1100
1101 cd->loaded = TRUE;
1102
1103 return HB_Err_Ok;
1104 }
1105
1106
1107 static HB_Error
1108 _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd )
1109 {
1110 HB_Error error;
1111
1112 cd->ClassFormat = 1; /* Meaningless */
1113
1114 if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) )
1115 return error;
1116
1117 cd->loaded = TRUE;
1118
1119 return HB_Err_Ok;
1120 }
1121
1122 HB_INTERNAL HB_Error
1123 _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
1124 HB_UShort limit,
1125 HB_UInt class_offset ,
1126 HB_UInt base_offset,
1127 HB_Stream stream )
1128 {
1129 HB_Error error;
1130 HB_UInt cur_offset;
1131
1132 cur_offset = FILE_Pos();
1133
1134 if ( class_offset )
1135 {
1136 if ( !FILE_Seek( class_offset + base_offset ) )
1137 error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
1138 }
1139 else
1140 error = _HB_OPEN_Load_EmptyClassDefinition ( cd );
1141
1142 if (error == HB_Err_Ok)
1143 (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
1144
1145 return error;
1146 }
1147
1148 HB_INTERNAL void
1149 _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd )
1150 {
1151 if ( !cd->loaded )
1152 return;
1153
1154 switch ( cd->ClassFormat )
1155 {
1156 case 1: Free_ClassDef1( &cd->cd.cd1 ); break;
1157 case 2: Free_ClassDef2( &cd->cd.cd2 ); break;
1158 default: break;
1159 }
1160 }
1161
1162
1163 static HB_Error Get_Class1( HB_ClassDefFormat1* cdf1,
1164 HB_UShort glyphID,
1165 HB_UShort* klass,
1166 HB_UShort* index )
1167 {
1168 HB_UShort* cva = cdf1->ClassValueArray;
1169
1170
1171 if ( index )
1172 *index = 0;
1173
1174 if ( glyphID >= cdf1->StartGlyph &&
1175 glyphID < cdf1->StartGlyph + cdf1->GlyphCount )
1176 {
1177 *klass = cva[glyphID - cdf1->StartGlyph];
1178 return HB_Err_Ok;
1179 }
1180 else
1181 {
1182 *klass = 0;
1183 return HB_Err_Not_Covered;
1184 }
1185 }
1186
1187
1188 /* we need the index value of the last searched class range record
1189 in case of failure for constructed GDEF tables */
1190
1191 static HB_Error Get_Class2( HB_ClassDefFormat2* cdf2,
1192 HB_UShort glyphID,
1193 HB_UShort* klass,
1194 HB_UShort* index )
1195 {
1196 HB_Error error = HB_Err_Ok;
1197 HB_UShort min, max, new_min, new_max, middle;
1198
1199 HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord;
1200
1201
1202 /* binary search */
1203
1204 if ( cdf2->ClassRangeCount == 0 )
1205 {
1206 *klass = 0;
1207 if ( index )
1208 *index = 0;
1209
1210 return HB_Err_Not_Covered;
1211 }
1212
1213 new_min = 0;
1214 new_max = cdf2->ClassRangeCount - 1;
1215
1216 do
1217 {
1218 min = new_min;
1219 max = new_max;
1220
1221 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
1222 overflow and rounding errors */
1223
1224 middle = max - ( ( max - min ) >> 1 );
1225
1226 if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
1227 {
1228 *klass = crr[middle].Class;
1229 error = HB_Err_Ok;
1230 break;
1231 }
1232 else if ( glyphID < crr[middle].Start )
1233 {
1234 if ( middle == min )
1235 {
1236 *klass = 0;
1237 error = HB_Err_Not_Covered;
1238 break;
1239 }
1240 new_max = middle - 1;
1241 }
1242 else
1243 {
1244 if ( middle == max )
1245 {
1246 *klass = 0;
1247 error = HB_Err_Not_Covered;
1248 break;
1249 }
1250 new_min = middle + 1;
1251 }
1252 } while ( min < max );
1253
1254 if ( index )
1255 *index = middle;
1256
1257 return error;
1258 }
1259
1260
1261 HB_INTERNAL HB_Error
1262 _HB_OPEN_Get_Class( HB_ClassDefinition* cd,
1263 HB_UShort glyphID,
1264 HB_UShort* klass,
1265 HB_UShort* index )
1266 {
1267 switch ( cd->ClassFormat )
1268 {
1269 case 1: return Get_Class1( &cd->cd.cd1, glyphID, klass, index );
1270 case 2: return Get_Class2( &cd->cd.cd2, glyphID, klass, index );
1271 default: return ERR(HB_Err_Invalid_SubTable_Format);
1272 }
1273
1274 return HB_Err_Ok; /* never reached */
1275 }
1276
1277
1278
1279 /***************************
1280 * Device related functions
1281 ***************************/
1282
1283
1284 HB_INTERNAL HB_Error
1285 _HB_OPEN_Load_Device( HB_Device* d,
1286 HB_Stream stream )
1287 {
1288 HB_Error error;
1289
1290 HB_UShort n, count;
1291
1292 HB_UShort* dv;
1293
1294
1295 if ( ACCESS_Frame( 6L ) )
1296 return error;
1297
1298 d->StartSize = GET_UShort();
1299 d->EndSize = GET_UShort();
1300 d->DeltaFormat = GET_UShort();
1301
1302 FORGET_Frame();
1303
1304 d->DeltaValue = NULL;
1305
1306 if ( d->StartSize > d->EndSize ||
1307 d->DeltaFormat == 0 || d->DeltaFormat > 3 )
1308 {
1309 /* XXX
1310 * I've seen fontforge generate DeltaFormat == 0.
1311 * Just return Ok and let the NULL DeltaValue disable
1312 * this table.
1313 */
1314 return HB_Err_Ok;
1315 }
1316
1317 count = ( ( d->EndSize - d->StartSize + 1 ) >>
1318 ( 4 - d->DeltaFormat ) ) + 1;
1319
1320 if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) )
1321 return error;
1322
1323 if ( ACCESS_Frame( count * 2L ) )
1324 {
1325 FREE( d->DeltaValue );
1326 return error;
1327 }
1328
1329 dv = d->DeltaValue;
1330
1331 for ( n = 0; n < count; n++ )
1332 dv[n] = GET_UShort();
1333
1334 FORGET_Frame();
1335
1336 return HB_Err_Ok;
1337 }
1338
1339
1340 HB_INTERNAL void
1341 _HB_OPEN_Free_Device( HB_Device* d )
1342 {
1343 FREE( d->DeltaValue );
1344 }
1345
1346
1347 /* Since we have the delta values stored in compressed form, we must
1348 uncompress it now. To simplify the interface, the function always
1349 returns a meaningful value in `value'; the error is just for
1350 information.
1351 | |
1352 format = 1: 0011223344556677|8899101112131415|...
1353 | |
1354 byte 1 byte 2
1355
1356 00: (byte >> 14) & mask
1357 11: (byte >> 12) & mask
1358 ...
1359
1360 mask = 0x0003
1361 | |
1362 format = 2: 0000111122223333|4444555566667777|...
1363 | |
1364 byte 1 byte 2
1365
1366 0000: (byte >> 12) & mask
1367 1111: (byte >> 8) & mask
1368 ...
1369
1370 mask = 0x000F
1371 | |
1372 format = 3: 0000000011111111|2222222233333333|...
1373 | |
1374 byte 1 byte 2
1375
1376 00000000: (byte >> 8) & mask
1377 11111111: (byte >> 0) & mask
1378 ....
1379
1380 mask = 0x00FF */
1381
1382 HB_INTERNAL HB_Error
1383 _HB_OPEN_Get_Device( HB_Device* d,
1384 HB_UShort size,
1385 HB_Short* value )
1386 {
1387 HB_UShort byte, bits, mask, f, s;
1388
1389
1390 f = d->DeltaFormat;
1391
1392 if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
1393 {
1394 s = size - d->StartSize;
1395 byte = d->DeltaValue[s >> ( 4 - f )];
1396 bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
1397 mask = 0xFFFF >> ( 16 - ( 1 << f ) );
1398
1399 *value = (HB_Short)( bits & mask );
1400
1401 /* conversion to a signed value */
1402
1403 if ( *value >= ( ( mask + 1 ) >> 1 ) )
1404 *value -= mask + 1;
1405
1406 return HB_Err_Ok;
1407 }
1408 else
1409 {
1410 *value = 0;
1411 return HB_Err_Not_Covered;
1412 }
1413 }
1414
1415
1416 /* END */
OLDNEW
« no previous file with comments | « third_party/harfbuzz/src/harfbuzz-open.h ('k') | third_party/harfbuzz/src/harfbuzz-open-private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698