summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h10
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-gpos.c217
2 files changed, 170 insertions, 57 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
index 63ba90797d..b363b81d87 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
@@ -39,6 +39,10 @@ HB_BEGIN_HEADER
#define VR_X_ADVANCE_DEVICE 2
#define VR_Y_ADVANCE_DEVICE 3
+#ifndef HB_SUPPORT_MULTIPLE_MASTER
+# define HB_USE_FLEXIBLE_VALUE_RECORD
+#endif
+
struct HB_ValueRecord_
{
HB_Short XPlacement; /* horizontal adjustment for
@@ -242,7 +246,11 @@ typedef struct HB_Class2Record_ HB_Class2Record;
struct HB_Class1Record_
{
- HB_Class2Record* Class2Record; /* array of Class2Record tables */
+ hb_uint8 IsFlexible;
+ union {
+ HB_Class2Record* Class2Record; /* array of Class2Record tables */
+ HB_Short* ValueRecords;
+ } c2r;
};
typedef struct HB_Class1Record_ HB_Class1Record;
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
index a21600579e..2a86cb21e9 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
@@ -194,6 +194,43 @@ HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
/* ValueRecord */
+static HB_Error Get_FlexibleValueRecord( GPOS_Instance* gpi,
+ HB_Short* vr,
+ HB_UShort format,
+ HB_Position gd )
+{
+ HB_Error error = HB_Err_Ok;
+
+ HB_16Dot16 x_scale, y_scale;
+
+ if ( !format )
+ return HB_Err_Ok;
+
+ x_scale = gpi->font->x_scale;
+ y_scale = gpi->font->y_scale;
+
+ /* design units -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT ) {
+ gd->x_pos += *vr * x_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT ) {
+ gd->y_pos += *vr * y_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE ) {
+ gd->x_advance += *vr * x_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE ) {
+ gd->y_advance += *vr * y_scale / 0x10000;
+ vr++;
+ }
+
+ return error;
+}
+
/* There is a subtle difference in the specs between a `table' and a
`record' -- offsets for device tables in ValueRecords are taken from
the parent table and not the parent record. */
@@ -1245,6 +1282,19 @@ static void Free_PairPos1( HB_PairPosFormat1* ppf1,
}
}
+static HB_UInt Calculate_Class2RecordSize(HB_UShort format1, HB_UShort format2)
+{
+ // Return number of 16 bit values in two value records with given formats
+ return (format1 & 0x01) + (format2 & 0x01)
+ + ((format1 & 0x02) >> 1) + ((format2 & 0x02) >> 1)
+ + ((format1 & 0x04) >> 2) + ((format2 & 0x04) >> 2)
+ + ((format1 & 0x08) >> 3) + ((format2 & 0x08) >> 3)
+ + ((format1 & 0x10) >> 4) + ((format2 & 0x10) >> 4)
+ + ((format1 & 0x20) >> 5) + ((format2 & 0x20) >> 5)
+ + ((format1 & 0x40) >> 6) + ((format2 & 0x40) >> 6)
+ + ((format1 & 0x80) >> 7) + ((format2 & 0x80) >> 7);
+}
+
/* PairPosFormat2 */
@@ -1256,11 +1306,14 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
HB_Error error;
HB_UShort m, n, k, count1, count2;
- HB_UInt cur_offset, new_offset1, new_offset2, base_offset;
+ HB_UInt cur_offset, new_offset1, new_offset2, base_offset, cls2_record_size = 0;
HB_Class1Record* c1r;
HB_Class2Record* c2r;
+ HB_Short* vr;
+
+ hb_uint8 use_flexible_value_records;
base_offset = FILE_Pos() - 8L;
@@ -1276,6 +1329,13 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
count1 = ppf2->Class1Count = GET_UShort();
count2 = ppf2->Class2Count = GET_UShort();
+#ifndef HB_USE_FLEXIBLE_VALUE_RECORD
+ use_flexible_value_records = 0;
+#else
+ use_flexible_value_records = !((format1 & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES) ||
+ (format2 & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES));
+#endif
+
FORGET_Frame();
cur_offset = FILE_Pos();
@@ -1296,35 +1356,55 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
c1r = ppf2->Class1Record;
+ if ( use_flexible_value_records )
+ cls2_record_size = Calculate_Class2RecordSize(format1, format2);
+
for ( m = 0; m < count1; m++ )
{
- c1r[m].Class2Record = NULL;
-
- if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
- goto Fail1;
-
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- {
- error = Load_ValueRecord( &c2r[n].Value1, format1,
- base_offset, stream );
- if ( error )
- goto Fail0;
- }
- if ( format2 )
- {
- error = Load_ValueRecord( &c2r[n].Value2, format2,
- base_offset, stream );
- if ( error )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- goto Fail0;
- }
- }
+ c1r[m].IsFlexible = use_flexible_value_records;
+ if ( use_flexible_value_records ) {
+ c1r[m].c2r.ValueRecords = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].c2r.ValueRecords, count2 * cls2_record_size, HB_UShort ) )
+ goto Fail1;
+
+ vr = c1r[m].c2r.ValueRecords;
+
+ if ( ACCESS_Frame( count2 * cls2_record_size * 2L ))
+ goto Fail1;
+
+ for ( n = 0; n < count2 * cls2_record_size; n++ )
+ vr[n] = GET_Short();
+
+ FORGET_Frame();
+ } else {
+ c1r[m].c2r.Class2Record = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].c2r.Class2Record, count2, HB_Class2Record ) )
+ goto Fail1;
+
+ c2r = c1r[m].c2r.Class2Record;
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail0;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ goto Fail0;
+ }
+ }
+ }
}
continue;
@@ -1345,17 +1425,21 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
Fail1:
for ( k = 0; k < m; k++ )
{
- c2r = c1r[k].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2 );
- }
-
- FREE( c2r );
+ if ( !use_flexible_value_records ) {
+ c2r = c1r[k].c2r.Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2 );
+ }
+
+ FREE( c2r );
+ } else {
+ FREE( c1r[k].c2r.ValueRecords );
+ }
}
FREE( c1r );
@@ -1387,17 +1471,21 @@ static void Free_PairPos2( HB_PairPosFormat2* ppf2,
for ( m = 0; m < count1; m++ )
{
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2 );
- }
-
- FREE( c2r );
+ if ( !c1r[m].IsFlexible ) {
+ c2r = c1r[m].c2r.Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2 );
+ }
+
+ FREE( c2r );
+ } else {
+ FREE( c1r[m].c2r.ValueRecords );
+ }
}
FREE( c1r );
@@ -1544,6 +1632,10 @@ static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
HB_Class1Record* c1r;
HB_Class2Record* c2r;
+ HB_Short* vr;
+
+ HB_UShort vr1_size;
+ HB_UShort vr2_size;
error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
@@ -1558,14 +1650,27 @@ static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
c1r = &ppf2->Class1Record[cl1];
if ( !c1r )
return ERR(HB_Err_Invalid_SubTable);
- c2r = &c1r->Class2Record[cl2];
- error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
- if ( error )
- return error;
- return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
-}
+ if ( !c1r->IsFlexible ) {
+ c2r = &c1r->c2r.Class2Record[cl2];
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
+ } else {
+ vr1_size = Calculate_Class2RecordSize( format1, 0 );
+ vr2_size = Calculate_Class2RecordSize( format2, 0 );
+
+ vr = c1r->c2r.ValueRecords + (cl2 * ( vr1_size + vr2_size ));
+
+ error = Get_FlexibleValueRecord( gpi, vr, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ vr += vr1_size; // Skip to second record
+ return Get_FlexibleValueRecord( gpi, vr, format2, POSITION( buffer->in_pos ) );
+ }
+}
static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
HB_GPOS_SubTable* st,