... |
... |
@@ -498,6 +498,14 @@ |
498
|
498
|
}
|
499
|
499
|
|
500
|
500
|
|
|
501
|
+ FT_COMPARE_DEF( int )
|
|
502
|
+ compare_ppem( const void* a,
|
|
503
|
+ const void* b )
|
|
504
|
+ {
|
|
505
|
+ return **(FT_Byte**)a - **(FT_Byte**)b;
|
|
506
|
+ }
|
|
507
|
+
|
|
508
|
+
|
501
|
509
|
/**************************************************************************
|
502
|
510
|
*
|
503
|
511
|
* @Function:
|
... |
... |
@@ -574,20 +582,21 @@ |
574
|
582
|
goto Fail;
|
575
|
583
|
}
|
576
|
584
|
|
577
|
|
- if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) )
|
|
585
|
+ if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) )
|
578
|
586
|
goto Fail;
|
579
|
587
|
|
580
|
|
- /* XXX: We do not check if the records are sorted by ppem */
|
581
|
|
- /* and cannot use binary search later. */
|
582
|
588
|
for ( nn = 0; nn < num_records; nn++ )
|
583
|
589
|
{
|
584
|
590
|
if ( p + record_size > limit )
|
585
|
591
|
break;
|
586
|
|
-
|
587
|
|
- face->hdmx_record_sizes[nn] = p[0];
|
588
|
|
- p += record_size;
|
|
592
|
+ face->hdmx_records[nn] = p;
|
|
593
|
+ p += record_size;
|
589
|
594
|
}
|
590
|
595
|
|
|
596
|
+ /* The records must be already sorted by ppem but it does not */
|
|
597
|
+ /* hurt to make sure so that the binary search works later. */
|
|
598
|
+ ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem );
|
|
599
|
+
|
591
|
600
|
face->hdmx_record_count = nn;
|
592
|
601
|
face->hdmx_table_size = table_size;
|
593
|
602
|
face->hdmx_record_size = record_size;
|
... |
... |
@@ -611,7 +620,7 @@ |
611
|
620
|
FT_Memory memory = stream->memory;
|
612
|
621
|
|
613
|
622
|
|
614
|
|
- FT_FREE( face->hdmx_record_sizes );
|
|
623
|
+ FT_FREE( face->hdmx_records );
|
615
|
624
|
FT_FRAME_RELEASE( face->hdmx_table );
|
616
|
625
|
}
|
617
|
626
|
|
... |
... |
@@ -619,27 +628,34 @@ |
619
|
628
|
/**************************************************************************
|
620
|
629
|
*
|
621
|
630
|
* Return the advance width table for a given pixel size if it is found
|
622
|
|
- * in the font's `hdmx' table (if any).
|
|
631
|
+ * in the font's `hdmx' table (if any). The records must be sorted for
|
|
632
|
+ * the binary search to work properly.
|
623
|
633
|
*/
|
624
|
634
|
FT_LOCAL_DEF( FT_Byte* )
|
625
|
635
|
tt_face_get_device_metrics( TT_Face face,
|
626
|
636
|
FT_UInt ppem,
|
627
|
637
|
FT_UInt gindex )
|
628
|
638
|
{
|
629
|
|
- FT_UInt nn;
|
|
639
|
+ FT_UInt min = 0;
|
|
640
|
+ FT_UInt max = face->hdmx_record_count;
|
|
641
|
+ FT_UInt mid;
|
630
|
642
|
FT_Byte* result = NULL;
|
631
|
|
- FT_ULong record_size = face->hdmx_record_size;
|
632
|
|
- FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 );
|
633
|
643
|
|
634
|
644
|
|
635
|
|
- for ( nn = 0; nn < face->hdmx_record_count; nn++ )
|
636
|
|
- if ( face->hdmx_record_sizes[nn] == ppem )
|
|
645
|
+ while ( min < max )
|
|
646
|
+ {
|
|
647
|
+ mid = ( min + max ) >> 1;
|
|
648
|
+
|
|
649
|
+ if ( face->hdmx_records[mid][0] > ppem )
|
|
650
|
+ max = mid;
|
|
651
|
+ else if ( face->hdmx_records[mid][0] < ppem )
|
|
652
|
+ min = mid + 1;
|
|
653
|
+ else
|
637
|
654
|
{
|
638
|
|
- gindex += 2;
|
639
|
|
- if ( gindex < record_size )
|
640
|
|
- result = record + nn * record_size + gindex;
|
|
655
|
+ result = face->hdmx_records[mid] + gindex + 2;
|
641
|
656
|
break;
|
642
|
657
|
}
|
|
658
|
+ }
|
643
|
659
|
|
644
|
660
|
return result;
|
645
|
661
|
}
|