diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2009-03-20 07:35:59 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2009-03-20 07:35:59 +0000 |
commit | 70a2688732ce8e027c0bbf4cbdc55621c9ca5b57 (patch) | |
tree | 0a618c7df46f5a6c6334bcc5b2264cc23ebdbc89 /Build/source/libs/libttf/extend/ftxgpos.c | |
parent | 200cfaafaed3d870382579503f73a3838b427d51 (diff) |
new build system
git-svn-id: svn://tug.org/texlive/trunk@12443 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/libttf/extend/ftxgpos.c')
-rw-r--r-- | Build/source/libs/libttf/extend/ftxgpos.c | 6169 |
1 files changed, 0 insertions, 6169 deletions
diff --git a/Build/source/libs/libttf/extend/ftxgpos.c b/Build/source/libs/libttf/extend/ftxgpos.c deleted file mode 100644 index 25eff3ade52..00000000000 --- a/Build/source/libs/libttf/extend/ftxgpos.c +++ /dev/null @@ -1,6169 +0,0 @@ -/******************************************************************* - * - * ftxgpos.c - * - * TrueType Open GPOS table support. - * - * Copyright 1996-2000 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used - * modified and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - ******************************************************************/ - -/* XXX There is *a lot* of duplicated code (cf. formats 7 and 8), but - I don't care currently. I believe that it would be possible to - save about 50% of TTO code by carefully designing the structures, - sharing as much as possible with extensive use of macros. This - is something for a volunteer :-) */ - -#include "tttypes.h" -#include "tttags.h" -#include "ttload.h" -#include "ttextend.h" -#include "ttmemory.h" -#include "ttfile.h" - -#include "ftxopen.h" -#include "ftxopenf.h" - - -#define GPOS_ID Build_Extension_ID( 'G', 'P', 'O', 'S' ) - - - struct GPOS_Instance_ - { - TTO_GPOSHeader* gpos; - TT_Instance instance; - TT_Glyph glyph; - UShort load_flags; /* how the glyph should be loaded */ - TT_Bool r2l; - - UShort last; /* the last valid glyph -- used - with cursive positioning */ - TT_Pos anchor_x; /* the coordinates of the anchor point */ - TT_Pos anchor_y; /* of the last valid glyph */ - }; - - typedef struct GPOS_Instance_ GPOS_Instance; - - - static TT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, - UShort lookup_index, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort context_length, - int nesting_level ); - - - - /********************** - * Extension Functions - **********************/ - - /* the client application must replace this with something more - meaningful if multiple master fonts are to be supported. */ - - static TT_Error default_mmfunc( TT_Instance instance, - TT_UShort metric_id, - TT_Pos* metric_value, - void* data ) - { - return TTO_Err_No_MM_Interpreter; - } - - - static TT_Error GPOS_Create( void* ext, - PFace face ) - { - DEFINE_LOAD_LOCALS( face->stream ); - - TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext; - Long table; - - - /* by convention */ - - if ( !gpos ) - return TT_Err_Ok; - - /* a null offset indicates that there is no GPOS table */ - - gpos->offset = 0; - - /* we store the start offset and the size of the subtable */ - - table = TT_LookUp_Table( face, TTAG_GPOS ); - if ( table < 0 ) - return TT_Err_Ok; /* The table is optional */ - - if ( FILE_Seek( face->dirTables[table].Offset ) || - ACCESS_Frame( 4L ) ) - return error; - - gpos->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ - gpos->Version = GET_ULong(); - - FORGET_Frame(); - - /* a default mmfunc() handler which just returns an error */ - - gpos->mmfunc = default_mmfunc; - - /* the default glyph function is TT_Load_Glyph() */ - - gpos->gfunc = TT_Load_Glyph; - - gpos->loaded = FALSE; - - return TT_Err_Ok; - } - - - static TT_Error GPOS_Destroy( void* ext, - PFace face ) - { - TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext; - - - /* by convention */ - - if ( !gpos ) - return TT_Err_Ok; - - if ( gpos->loaded ) - { - Free_LookupList( &gpos->LookupList, GPOS ); - Free_FeatureList( &gpos->FeatureList ); - Free_ScriptList( &gpos->ScriptList ); - } - - return TT_Err_Ok; - } - - - EXPORT_FUNC - TT_Error TT_Init_GPOS_Extension( TT_Engine engine ) - { - PEngine_Instance _engine = HANDLE_Engine( engine ); - - - if ( !_engine ) - return TT_Err_Invalid_Engine; - - return TT_Register_Extension( _engine, - GPOS_ID, - sizeof ( TTO_GPOSHeader ), - GPOS_Create, - GPOS_Destroy ); - } - - - EXPORT_FUNC - TT_Error TT_Load_GPOS_Table( TT_Face face, - TTO_GPOSHeader* retptr, - TTO_GDEFHeader* gdef ) - { - ULong cur_offset, new_offset, base_offset; - - UShort i, num_lookups; - TT_Error error; - TT_Stream stream; - TTO_GPOSHeader* gpos; - TTO_Lookup* lo; - - PFace faze = HANDLE_Face( face ); - - - if ( !retptr ) - return TT_Err_Invalid_Argument; - - if ( !faze ) - return TT_Err_Invalid_Face_Handle; - - error = TT_Extension_Get( faze, GPOS_ID, (void**)&gpos ); - if ( error ) - return error; - - if ( gpos->offset == 0 ) - return TT_Err_Table_Missing; /* no GPOS table; nothing to do */ - - /* now access stream */ - - if ( USE_Stream( faze->stream, stream ) ) - return error; - - base_offset = gpos->offset; - - /* skip version */ - - if ( FILE_Seek( base_offset + 4L ) || - ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ScriptList( &gpos->ScriptList, - faze ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_FeatureList( &gpos->FeatureList, - faze ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LookupList( &gpos->LookupList, - faze, GPOS ) ) != TT_Err_Ok ) - goto Fail2; - - gpos->gdef = gdef; /* can be NULL */ - - /* We now check the LookupFlags for values larger than 0xFF to find - out whether we need to load the `MarkAttachClassDef' field of the - GDEF table -- this hack is necessary for OpenType 1.2 tables since - the version field of the GDEF table hasn't been incremented. - - For constructed GDEF tables, we only load it if - `MarkAttachClassDef_offset' is not zero (nevertheless, a build of - a constructed mark attach table is not supported currently). */ - - if ( gdef && - gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) - { - lo = gpos->LookupList.Lookup; - num_lookups = gpos->LookupList.LookupCount; - - for ( i = 0; i < num_lookups; i++ ) - { - if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS ) - { - if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || - ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( !new_offset ) - return TTO_Err_Invalid_GDEF_SubTable; - - new_offset += base_offset; - - if ( FILE_Seek( new_offset ) || - ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef, - 256, faze ) ) != TT_Err_Ok ) - goto Fail1; - - break; - } - } - } - - gpos->loaded = TRUE; - *retptr = *gpos; - DONE_Stream( stream ); - - return TT_Err_Ok; - - Fail1: - Free_LookupList( &gpos->LookupList, GPOS ); - - Fail2: - Free_FeatureList( &gpos->FeatureList ); - - Fail3: - Free_ScriptList( &gpos->ScriptList ); - - /* release stream */ - - DONE_Stream( stream ); - - return error; - } - - - - /***************************** - * SubTable related functions - *****************************/ - - /* shared tables */ - - /* ValueRecord */ - - /* 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. */ - - static TT_Error Load_ValueRecord( TTO_ValueRecord* vr, - UShort format, - ULong base_offset, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - ULong cur_offset, new_offset; - - - if ( format & HAVE_X_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->XPlacement = GET_Short(); - - FORGET_Frame(); - } - else - vr->XPlacement = 0; - - if ( format & HAVE_Y_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->YPlacement = GET_Short(); - - FORGET_Frame(); - } - else - vr->YPlacement = 0; - - if ( format & HAVE_X_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->XAdvance = GET_Short(); - - FORGET_Frame(); - } - else - vr->XAdvance = 0; - - if ( format & HAVE_Y_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->YAdvance = GET_Short(); - - FORGET_Frame(); - } - else - vr->YAdvance = 0; - - if ( format & HAVE_X_PLACEMENT_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &vr->XPlacementDevice, - input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - } - else - goto empty1; - } - else - { - empty1: - vr->XPlacementDevice.StartSize = 0; - vr->XPlacementDevice.EndSize = 0; - vr->XPlacementDevice.DeltaValue = NULL; - } - - if ( format & HAVE_Y_PLACEMENT_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &vr->YPlacementDevice, - input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - else - goto empty2; - } - else - { - empty2: - vr->YPlacementDevice.StartSize = 0; - vr->YPlacementDevice.EndSize = 0; - vr->YPlacementDevice.DeltaValue = NULL; - } - - if ( format & HAVE_X_ADVANCE_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &vr->XAdvanceDevice, - input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - else - goto empty3; - } - else - { - empty3: - vr->XAdvanceDevice.StartSize = 0; - vr->XAdvanceDevice.EndSize = 0; - vr->XAdvanceDevice.DeltaValue = NULL; - } - - if ( format & HAVE_Y_ADVANCE_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &vr->YAdvanceDevice, - input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - goto empty4; - } - else - { - empty4: - vr->YAdvanceDevice.StartSize = 0; - vr->YAdvanceDevice.EndSize = 0; - vr->YAdvanceDevice.DeltaValue = NULL; - } - - if ( format & HAVE_X_ID_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->XIdPlacement = GET_UShort(); - - FORGET_Frame(); - } - else - vr->XIdPlacement = 0; - - if ( format & HAVE_Y_ID_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->YIdPlacement = GET_UShort(); - - FORGET_Frame(); - } - else - vr->YIdPlacement = 0; - - if ( format & HAVE_X_ID_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->XIdAdvance = GET_UShort(); - - FORGET_Frame(); - } - else - vr->XIdAdvance = 0; - - if ( format & HAVE_Y_ID_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->YIdAdvance = GET_UShort(); - - FORGET_Frame(); - } - else - vr->YIdAdvance = 0; - - return TT_Err_Ok; - - Fail1: - Free_Device( &vr->YAdvanceDevice ); - - Fail2: - Free_Device( &vr->XAdvanceDevice ); - - Fail3: - Free_Device( &vr->YPlacementDevice ); - return error; - } - - - static void Free_ValueRecord( TTO_ValueRecord* vr, - UShort format ) - { - if ( format & HAVE_Y_ADVANCE_DEVICE ) - Free_Device( &vr->YAdvanceDevice ); - if ( format & HAVE_X_ADVANCE_DEVICE ) - Free_Device( &vr->XAdvanceDevice ); - if ( format & HAVE_Y_PLACEMENT_DEVICE ) - Free_Device( &vr->YPlacementDevice ); - if ( format & HAVE_X_PLACEMENT_DEVICE ) - Free_Device( &vr->XPlacementDevice ); - } - - - static TT_Error Get_ValueRecord( GPOS_Instance* gpi, - TTO_ValueRecord* vr, - UShort format, - TTO_GPOS_Data* gd ) - { - TT_Pos value; - Short pixel_value; - TT_Error error = TT_Err_Ok; - TTO_GPOSHeader* gpos = gpi->gpos; - PInstance ins; - - UShort x_ppem, y_ppem; - Fixed x_scale, y_scale; - - - if ( !format ) - return TT_Err_Ok; - - ins = HANDLE_Instance( gpi->instance ); - - x_ppem = ins->metrics.x_ppem; - y_ppem = ins->metrics.y_ppem; - x_scale = TT_MulDiv( 0x10000, - ins->metrics.x_scale1, - ins->metrics.x_scale2 ); - y_scale = TT_MulDiv( 0x10000, - ins->metrics.y_scale1, - ins->metrics.y_scale2 ); - - /* design units -> fractional pixel */ - - if ( format & HAVE_X_PLACEMENT ) - gd->x_pos += x_scale * vr->XPlacement / 0x10000; - if ( format & HAVE_Y_PLACEMENT ) - gd->y_pos += y_scale * vr->YPlacement / 0x10000; - if ( format & HAVE_X_ADVANCE ) - gd->x_advance += x_scale * vr->XAdvance / 0x10000; - if ( format & HAVE_Y_ADVANCE ) - gd->y_advance += y_scale * vr->YAdvance / 0x10000; - - /* we use the device tables only if gpi->glyph.z is not NULL */ - - if ( gpi->glyph.z ) - { - /* pixel -> fractional pixel */ - - if ( format & HAVE_X_PLACEMENT_DEVICE ) - { - Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value ); - gd->x_pos += pixel_value << 6; - } - if ( format & HAVE_Y_PLACEMENT_DEVICE ) - { - Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value ); - gd->y_pos += pixel_value << 6; - } - if ( format & HAVE_X_ADVANCE_DEVICE ) - { - Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value ); - gd->x_advance += pixel_value << 6; - } - if ( format & HAVE_Y_ADVANCE_DEVICE ) - { - Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value ); - gd->y_advance += pixel_value << 6; - } - } - - /* values returned from mmfunc() are already in fractional pixels */ - - if ( format & HAVE_X_ID_PLACEMENT ) - { - error = (gpos->mmfunc)( gpi->instance, vr->XIdPlacement, - &value, gpos->data ); - if ( error ) - return error; - gd->x_pos += value; - } - if ( format & HAVE_Y_ID_PLACEMENT ) - { - error = (gpos->mmfunc)( gpi->instance, vr->YIdPlacement, - &value, gpos->data ); - if ( error ) - return error; - gd->y_pos += value; - } - if ( format & HAVE_X_ID_ADVANCE ) - { - error = (gpos->mmfunc)( gpi->instance, vr->XIdAdvance, - &value, gpos->data ); - if ( error ) - return error; - gd->x_advance += value; - } - if ( format & HAVE_Y_ID_ADVANCE ) - { - error = (gpos->mmfunc)( gpi->instance, vr->YIdAdvance, - &value, gpos->data ); - if ( error ) - return error; - gd->y_advance += value; - } - - return error; - } - - - /* AnchorFormat1 */ - /* AnchorFormat2 */ - /* AnchorFormat3 */ - /* AnchorFormat4 */ - - static TT_Error Load_Anchor( TTO_Anchor* an, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - ULong cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - an->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( an->PosFormat ) - { - case 1: - if ( ACCESS_Frame( 4L ) ) - return error; - - an->af.af1.XCoordinate = GET_Short(); - an->af.af1.YCoordinate = GET_Short(); - - FORGET_Frame(); - break; - - case 2: - if ( ACCESS_Frame( 6L ) ) - return error; - - an->af.af2.XCoordinate = GET_Short(); - an->af.af2.YCoordinate = GET_Short(); - an->af.af2.AnchorPoint = GET_UShort(); - - FORGET_Frame(); - break; - - case 3: - if ( ACCESS_Frame( 6L ) ) - return error; - - an->af.af3.XCoordinate = GET_Short(); - an->af.af3.YCoordinate = GET_Short(); - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &an->af.af3.XDeviceTable, - input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - } - else - { - an->af.af3.XDeviceTable.StartSize = 0; - an->af.af3.XDeviceTable.EndSize = 0; - an->af.af3.XDeviceTable.DeltaValue = 0; - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Device( &an->af.af3.YDeviceTable, - input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - else - { - an->af.af3.YDeviceTable.StartSize = 0; - an->af.af3.YDeviceTable.EndSize = 0; - an->af.af3.YDeviceTable.DeltaValue = 0; - } - break; - - case 4: - if ( ACCESS_Frame( 4L ) ) - return error; - - an->af.af4.XIdAnchor = GET_UShort(); - an->af.af4.YIdAnchor = GET_UShort(); - - FORGET_Frame(); - break; - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; - - Fail: - Free_Device( &an->af.af3.XDeviceTable ); - return error; - } - - - static void Free_Anchor( TTO_Anchor* an ) - { - if ( an->PosFormat == 3 ) - { - Free_Device( &an->af.af3.YDeviceTable ); - Free_Device( &an->af.af3.XDeviceTable ); - } - } - - - static TT_Error Get_Anchor( GPOS_Instance* gpi, - TTO_Anchor* an, - TT_UShort glyph_index, - TT_Pos* x_value, - TT_Pos* y_value ) - { - TT_Error error = TT_Err_Ok; - - PInstance ins; - PGlyph glyph; - TTO_GPOSHeader* gpos = gpi->gpos; - UShort ap; - - Short pixel_value; - UShort load_flags; - - UShort x_ppem, y_ppem; - Fixed x_scale, y_scale; - - - ins = HANDLE_Instance( gpi->instance ); - - x_ppem = ins->metrics.x_ppem; - y_ppem = ins->metrics.y_ppem; - x_scale = TT_MulDiv( 0x10000, - ins->metrics.x_scale1, - ins->metrics.x_scale2 ); - y_scale = TT_MulDiv( 0x10000, - ins->metrics.y_scale1, - ins->metrics.y_scale2 ); - - switch ( an->PosFormat ) - { - case 0: - /* The special case of an empty AnchorTable */ - - return TTO_Err_Not_Covered; - - case 1: - *x_value = x_scale * an->af.af1.XCoordinate / 0x10000; - *y_value = y_scale * an->af.af1.YCoordinate / 0x10000; - break; - - case 2: - /* glyphs must be scaled */ - - load_flags = gpi->load_flags | TTLOAD_SCALE_GLYPH; - - /* we use the glyph contour point only if gpi->glyph.z is not NULL */ - - if ( gpi->glyph.z ) - { - error = (gpos->gfunc)( gpi->instance, gpi->glyph, - glyph_index, load_flags ); - if ( error ) - return error; - - glyph = HANDLE_Glyph( gpi->glyph ); - ap = an->af.af2.AnchorPoint; - - /* if outline.n_points is set to zero by gfunc(), we use the - design coordinate value pair. This can happen e.g. for - sbit glyphs */ - - if ( !glyph->outline.n_points ) - goto no_contour_point; - - if ( ap >= glyph->outline.n_points ) - return TTO_Err_Invalid_GPOS_SubTable; - - *x_value = glyph->outline.points[ap].x; - *y_value = glyph->outline.points[ap].y; - } - else - { - no_contour_point: - *x_value = x_scale * an->af.af3.XCoordinate / 0x10000; - *y_value = y_scale * an->af.af3.YCoordinate / 0x10000; - } - break; - - case 3: - /* we use the device tables only if gpi->glyph.z is not NULL */ - - if ( gpi->glyph.z ) - { - Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value ); - *x_value = pixel_value << 6; - Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value ); - *y_value = pixel_value << 6; - } - else - *x_value = *y_value = 0; - - *x_value += x_scale * an->af.af3.XCoordinate / 0x10000; - *y_value += y_scale * an->af.af3.YCoordinate / 0x10000; - break; - - case 4: - error = (gpos->mmfunc)( gpi->instance, an->af.af4.XIdAnchor, - x_value, gpos->data ); - if ( error ) - return error; - - error = (gpos->mmfunc)( gpi->instance, an->af.af4.YIdAnchor, - y_value, gpos->data ); - if ( error ) - return error; - break; - } - - return error; - } - - - /* MarkArray */ - - static TT_Error Load_MarkArray ( TTO_MarkArray* ma, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_MarkRecord* mr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ma->MarkCount = GET_UShort(); - - FORGET_Frame(); - - ma->MarkRecord = NULL; - - if ( ALLOC_ARRAY( ma->MarkRecord, count, TTO_MarkRecord ) ) - return error; - - mr = ma->MarkRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 4L ) ) - goto Fail; - - mr[n].Class = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &mr[n].MarkAnchor, input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_Anchor( &mr[n].MarkAnchor ); - - FREE( mr ); - return error; - } - - - static void Free_MarkArray( TTO_MarkArray* ma ) - { - UShort n, count; - - TTO_MarkRecord* mr; - - - if ( ma->MarkRecord ) - { - count = ma->MarkCount; - mr = ma->MarkRecord; - - for ( n = 0; n < count; n++ ) - Free_Anchor( &mr[n].MarkAnchor ); - - FREE( mr ); - } - } - - - /* LookupType 1 */ - - /* SinglePosFormat1 */ - /* SinglePosFormat2 */ - - TT_Error Load_SinglePos( TTO_SinglePos* sp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count, format; - ULong cur_offset, new_offset, base_offset; - - TTO_ValueRecord* vr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 6L ) ) - return error; - - sp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - format = sp->ValueFormat = GET_UShort(); - - FORGET_Frame(); - - if ( !format ) - return TTO_Err_Invalid_GPOS_SubTable; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &sp->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - switch ( sp->PosFormat ) - { - case 1: - error = Load_ValueRecord( &sp->spf.spf1.Value, format, - base_offset, input ); - if ( error ) - goto Fail2; - break; - - case 2: - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = sp->spf.spf2.ValueCount = GET_UShort(); - - FORGET_Frame(); - - sp->spf.spf2.Value = NULL; - - if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, TTO_ValueRecord ) ) - goto Fail2; - - vr = sp->spf.spf2.Value; - - for ( n = 0; n < count; n++ ) - { - error = Load_ValueRecord( &vr[n], format, base_offset, input ); - if ( error ) - goto Fail1; - } - break; - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - Free_ValueRecord( &vr[n], format ); - - FREE( vr ); - - Fail2: - Free_Coverage( &sp->Coverage ); - return error; - } - - - void Free_SinglePos( TTO_SinglePos* sp ) - { - UShort n, count, format; - - TTO_ValueRecord* v; - - - format = sp->ValueFormat; - - switch ( sp->PosFormat ) - { - case 1: - Free_ValueRecord( &sp->spf.spf1.Value, format ); - break; - - case 2: - if ( sp->spf.spf2.Value ) - { - count = sp->spf.spf2.ValueCount; - v = sp->spf.spf2.Value; - - for ( n = 0; n < count; n++ ) - Free_ValueRecord( &v[n], format ); - - FREE( v ); - } - break; - } - - Free_Coverage( &sp->Coverage ); - } - - - static TT_Error Lookup_SinglePos( GPOS_Instance* gpi, - TTO_SinglePos* sp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - UShort index, property; - TT_Error error; - TTO_GPOSHeader* gpos = gpi->gpos; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) - return error; - - error = Coverage_Index( &sp->Coverage, in->string[in->pos], &index ); - if ( error ) - return error; - - switch ( sp->PosFormat ) - { - case 1: - error = Get_ValueRecord( gpi, &sp->spf.spf1.Value, - sp->ValueFormat, &out[in->pos] ); - if ( error ) - return error; - break; - - case 2: - if ( index >= sp->spf.spf2.ValueCount ) - return TTO_Err_Invalid_GPOS_SubTable; - error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index], - sp->ValueFormat, &out[in->pos] ); - if ( error ) - return error; - break; - - default: - return TTO_Err_Invalid_GPOS_SubTable; - } - - (in->pos)++; - - return TT_Err_Ok; - } - - - /* LookupType 2 */ - - /* PairSet */ - - static TT_Error Load_PairSet ( TTO_PairSet* ps, - UShort format1, - UShort format2, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong base_offset; - - TTO_PairValueRecord* pvr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ps->PairValueCount = GET_UShort(); - - FORGET_Frame(); - - ps->PairValueRecord = NULL; - - if ( ALLOC_ARRAY( ps->PairValueRecord, count, TTO_PairValueRecord ) ) - return error; - - pvr = ps->PairValueRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - pvr[n].SecondGlyph = GET_UShort(); - - FORGET_Frame(); - - if ( format1 ) - { - error = Load_ValueRecord( &pvr[n].Value1, format1, - base_offset, input ); - if ( error ) - goto Fail; - } - if ( format2 ) - { - error = Load_ValueRecord( &pvr[n].Value2, format2, - base_offset, input ); - if ( error ) - goto Fail; - } - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - { - if ( format1 ) - Free_ValueRecord( &pvr[n].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &pvr[n].Value2, format2 ); - } - - FREE( pvr ); - return error; - } - - - static void Free_PairSet( TTO_PairSet* ps, - UShort format1, - UShort format2 ) - { - UShort n, count; - - TTO_PairValueRecord* pvr; - - - if ( ps->PairValueRecord ) - { - count = ps->PairValueCount; - pvr = ps->PairValueRecord; - - for ( n = 0; n < count; n++ ) - { - if ( format1 ) - Free_ValueRecord( &pvr[n].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &pvr[n].Value2, format2 ); - } - - FREE( pvr ); - } - } - - - /* PairPosFormat1 */ - - static TT_Error Load_PairPos1( TTO_PairPosFormat1* ppf1, - UShort format1, - UShort format2, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_PairSet* ps; - - - base_offset = FILE_Pos() - 8L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ppf1->PairSetCount = GET_UShort(); - - FORGET_Frame(); - - ppf1->PairSet = NULL; - - if ( ALLOC_ARRAY( ppf1->PairSet, count, TTO_PairSet ) ) - goto Fail; - - ps = ppf1->PairSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PairSet( &ps[n], format1, - format2, input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_PairSet( &ps[n], format1, format2 ); - - FREE( ps ); - return error; - } - - - static void Free_PairPos1( TTO_PairPosFormat1* ppf1, - UShort format1, - UShort format2 ) - { - UShort n, count; - - TTO_PairSet* ps; - - - if ( ppf1->PairSet ) - { - count = ppf1->PairSetCount; - ps = ppf1->PairSet; - - for ( n = 0; n < count; n++ ) - Free_PairSet( &ps[n], format1, format2 ); - - FREE( ps ); - } - } - - - /* PairPosFormat2 */ - - static TT_Error Load_PairPos2( TTO_PairPosFormat2* ppf2, - UShort format1, - UShort format2, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort m, n, count1, count2; - ULong cur_offset, new_offset1, new_offset2, base_offset; - - TTO_Class1Record* c1r; - TTO_Class2Record* c2r; - - - base_offset = FILE_Pos() - 8L; - - if ( ACCESS_Frame( 8L ) ) - return error; - - new_offset1 = GET_UShort() + base_offset; - new_offset2 = GET_UShort() + base_offset; - - /* `Class1Count' and `Class2Count' are the upper limits for class - values, thus we read it now to make additional safety checks. */ - - count1 = ppf2->Class1Count = GET_UShort(); - count2 = ppf2->Class2Count = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset1 ) || - ( error = Load_ClassDefinition( &ppf2->ClassDef1, count1, - input ) ) != TT_Err_Ok ) - return error; - if ( FILE_Seek( new_offset2 ) || - ( error = Load_ClassDefinition( &ppf2->ClassDef2, count2, - input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - ppf2->Class1Record = NULL; - - if ( ALLOC_ARRAY( ppf2->Class1Record, count1, TTO_Class1Record ) ) - goto Fail1; - - c1r = ppf2->Class1Record; - - for ( m = 0; m < count1; m++ ) - { - c1r[m].Class2Record = NULL; - - if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, TTO_Class2Record ) ) - goto Fail1; - - c2r = c1r[m].Class2Record; - - for ( n = 0; n < count2; n++ ) - { - if ( format1 ) - { - error = Load_ValueRecord( &c2r[n].Value1, format1, - base_offset, input ); - if ( error ) - goto Fail1; - } - if ( format2 ) - { - error = Load_ValueRecord( &c2r[n].Value2, format2, - base_offset, input ); - if ( error ) - goto Fail1; - } - } - } - - return TT_Err_Ok; - - Fail1: - 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 ); - } - - FREE( c1r ); - - Free_ClassDefinition( &ppf2->ClassDef2 ); - - Fail2: - Free_ClassDefinition( &ppf2->ClassDef1 ); - return error; - } - - - static void Free_PairPos2( TTO_PairPosFormat2* ppf2, - UShort format1, - UShort format2 ) - { - UShort m, n, count1, count2; - - TTO_Class1Record* c1r; - TTO_Class2Record* c2r; - - - if ( ppf2->Class1Record ) - { - c1r = ppf2->Class1Record; - count1 = ppf2->Class1Count; - count2 = ppf2->Class2Count; - - 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 ); - } - - FREE( c1r ); - - Free_ClassDefinition( &ppf2->ClassDef2 ); - Free_ClassDefinition( &ppf2->ClassDef1 ); - } - } - - - TT_Error Load_PairPos( TTO_PairPos* pp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort format1, format2; - ULong cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 8L ) ) - return error; - - pp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - format1 = pp->ValueFormat1 = GET_UShort(); - format2 = pp->ValueFormat2 = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &pp->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - switch ( pp->PosFormat ) - { - case 1: - error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, input ); - if ( error ) - goto Fail; - break; - - case 2: - error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, input ); - if ( error ) - goto Fail; - break; - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; - - Fail: - Free_Coverage( &pp->Coverage ); - return error; - } - - - void Free_PairPos( TTO_PairPos* pp ) - { - UShort format1, format2; - - - format1 = pp->ValueFormat1; - format2 = pp->ValueFormat2; - - switch ( pp->PosFormat ) - { - case 1: - Free_PairPos1( &pp->ppf.ppf1, format1, format2 ); - break; - - case 2: - Free_PairPos2( &pp->ppf.ppf2, format1, format2 ); - break; - } - - Free_Coverage( &pp->Coverage ); - } - - - static TT_Error Lookup_PairPos1( GPOS_Instance* gpi, - TTO_PairPosFormat1* ppf1, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort first_pos, - UShort index, - UShort format1, - UShort format2 ) - { - TT_Error error; - UShort numpvr, glyph2; - - TTO_PairValueRecord* pvr; - - - if ( index >= ppf1->PairSetCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - pvr = ppf1->PairSet[index].PairValueRecord; - if ( !pvr ) - return TTO_Err_Invalid_GPOS_SubTable; - - glyph2 = in->string[in->pos]; - - for ( numpvr = ppf1->PairSet[index].PairValueCount; - numpvr; - numpvr--, pvr++ ) - { - if ( glyph2 == pvr->SecondGlyph ) - { - error = Get_ValueRecord( gpi, &pvr->Value1, format1, - &out[first_pos] ); - if ( error ) - return error; - return Get_ValueRecord( gpi, &pvr->Value2, format2, - &out[in->pos] ); - } - } - - return TTO_Err_Not_Covered; - } - - - static TT_Error Lookup_PairPos2( GPOS_Instance* gpi, - TTO_PairPosFormat2* ppf2, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort first_pos, - UShort format1, - UShort format2 ) - { - TT_Error error; - UShort cl1, cl2; - - TTO_Class1Record* c1r; - TTO_Class2Record* c2r; - - - error = Get_Class( &ppf2->ClassDef1, in->string[first_pos], - &cl1, NULL ); - if ( error ) - return error; - error = Get_Class( &ppf2->ClassDef2, in->string[in->pos], - &cl2, NULL ); - if ( error ) - return error; - - c1r = &ppf2->Class1Record[cl1]; - if ( !c1r ) - return TTO_Err_Invalid_GPOS_SubTable; - c2r = &c1r->Class2Record[cl2]; - - error = Get_ValueRecord( gpi, &c2r->Value1, format1, &out[first_pos] ); - if ( error ) - return error; - return Get_ValueRecord( gpi, &c2r->Value2, format2, &out[in->pos] ); - } - - - static TT_Error Lookup_PairPos( GPOS_Instance* gpi, - TTO_PairPos* pp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - TT_Error error; - UShort index, property, first_pos; - TTO_GPOSHeader* gpos = gpi->gpos; - - - if ( in->pos >= in->length ) - return TTO_Err_Not_Covered; /* Not enough glyphs in input */ - - if ( context_length != 0xFFFF && context_length < 2 ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) - return error; - - error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index ); - if ( error ) - return error; - - /* second glyph */ - - first_pos = in->pos; - (in->pos)++; - - while ( CHECK_Property( gpos->gdef, in->string[in->pos], - flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( in->pos < in->length ) - (in->pos)++; - else - break; - } - - switch ( pp->PosFormat ) - { - case 1: - error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out, - first_pos, index, - pp->ValueFormat1, pp->ValueFormat2 ); - break; - - case 2: - error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, in, out, first_pos, - pp->ValueFormat1, pp->ValueFormat2 ); - break; - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - /* adjusting the `next' glyph */ - - if ( pp->ValueFormat2 ) - (in->pos)++; - - return error; - } - - - /* LookupType 3 */ - - /* CursivePosFormat1 */ - - TT_Error Load_CursivePos( TTO_CursivePos* cp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_EntryExitRecord* eer; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - cp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &cp->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = cp->EntryExitCount = GET_UShort(); - - FORGET_Frame(); - - cp->EntryExitRecord = NULL; - - if ( ALLOC_ARRAY( cp->EntryExitRecord, count, TTO_EntryExitRecord ) ) - goto Fail2; - - eer = cp->EntryExitRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &eer[n].EntryAnchor, - input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - eer[n].EntryAnchor.PosFormat = 0; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &eer[n].ExitAnchor, - input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - eer[n].ExitAnchor.PosFormat = 0; - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - { - Free_Anchor( &eer[n].EntryAnchor ); - Free_Anchor( &eer[n].ExitAnchor ); - } - - FREE( eer ); - - Fail2: - Free_Coverage( &cp->Coverage ); - return error; - } - - - void Free_CursivePos( TTO_CursivePos* cp ) - { - UShort n, count; - - TTO_EntryExitRecord* eer; - - - if ( cp->EntryExitRecord ) - { - count = cp->EntryExitCount; - eer = cp->EntryExitRecord; - - for ( n = 0; n < count; n++ ) - { - Free_Anchor( &eer[n].EntryAnchor ); - Free_Anchor( &eer[n].ExitAnchor ); - } - - FREE( eer ); - } - - Free_Coverage( &cp->Coverage ); - } - - - static TT_Error Lookup_CursivePos( GPOS_Instance* gpi, - TTO_CursivePos* cp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - UShort index, property; - TT_Error error; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_EntryExitRecord* eer; - TT_Pos entry_x, entry_y; - TT_Pos exit_x, exit_y; - - - if ( context_length != 0xFFFF && context_length < 1 ) - { - gpi->last = 0xFFFF; - return TTO_Err_Not_Covered; - } - - /* Glyphs not having the right GDEF properties will be ignored, i.e., - gpi->last won't be reset (contrary to user defined properties). */ - - if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) - return error; - - /* We don't handle mark glyphs here. According to Andrei, this isn't - possible, but who knows... */ - - if ( property == MARK_GLYPH ) - { - gpi->last = 0xFFFF; - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &cp->Coverage, in->string[in->pos], &index ); - if ( error ) - { - gpi->last = 0xFFFF; - return error; - } - - if ( index >= cp->EntryExitCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - eer = &cp->EntryExitRecord[index]; - - /* Now comes the messiest part of the whole OpenType - specification. At first glance, cursive connections seem easy - to understand, but there are pitfalls! The reason is, that - the specs don't mention how to compute the advance values - resp. glyph offsets. I was told it would be an omission, to - be fixed in the next OpenType version... Again many thanks to - Andrei Burago <andreib@microsoft.com> for clarifications. - - Consider the following example: - - | xadv1 | - +---------+ - | | - +-----+--+ 1 | - | | .| | - | 0+--+------+ - | 2 | - | | - 0+--------+ - | xadv2 | - - glyph1: advance width = 12 - anchor point = (3,1) - - glyph2: advance width = 11 - anchor point = (9,4) - - LSB is 1 for both glyphs (so the boxes drawn above are glyph - bboxes). Writing direction is R2L; `0' denotes the glyph's - coordinate origin. - - Now the surprising part: The advance width of the *left* glyph - (resp. of the *bottom* glyph) will be modified, no matter - whether the writing direction is L2R or R2L (resp. T2B or - B2T)! This assymetry is caused by the fact that the glyph's - coordinate origin is always the lower left corner for all - writing directions. - - Continuing the above example, we can compute the new - (horizontal) advance width of glyph2 as - - 9 - 3 = 6 , - - and the new vertical offset of glyph2 as - - 1 - 4 = -3 . - - - Vertical writing direction is far more complicated: - - a) Assuming that we recompute the advance height of the lower glyph: - - -- - +---------+ - -- | | - +-----+--+ 1 | yadv1 - | | .| | - yadv2 | 0+--+------+ -- BSB1 -- - | 2 | -- -- y_offset - | | - BSB2 -- 0+--------+ -- - -- -- - - glyph1: advance height = 6 - anchor point = (3,1) - - glyph2: advance height = 7 - anchor point = (9,4) - - TSB is 1 for both glyphs; writing direction is T2B. - - - BSB1 = yadv1 - (TSB1 + ymax1) - BSB2 = yadv2 - (TSB2 + ymax2) - y_offset = y2 - y1 - - vertical advance width of glyph2 - = y_offset + BSB2 - BSB1 - = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1)) - = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1) - = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1 - - - b) Assuming that we recompute the advance height of the upper glyph: - - -- -- - +---------+ -- TSB1 - -- -- | | - TSB2 -- +-----+--+ 1 | yadv1 ymax1 - | | .| | - yadv2 | 0+--+------+ -- -- - ymax2 | 2 | -- y_offset - | | - -- 0+--------+ -- - -- - - glyph1: advance height = 6 - anchor point = (3,1) - - glyph2: advance height = 7 - anchor point = (9,4) - - TSB is 1 for both glyphs; writing direction is T2B. - - y_offset = y2 - y1 - - vertical advance width of glyph2 - = TSB1 + ymax1 + y_offset - (TSB2 + ymax2) - = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2 - - - Comparing a) with b) shows that b) is easier to compute. I'll wait - for a reply from Andrei to see what should really be implemented... - - Since horizontal advance widths or vertical advance heights - can be used alone but not together, no ambiguity occurs. */ - - if ( gpi->last == 0xFFFF ) - goto end; - - /* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor - table. */ - - error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos], - &entry_x, &entry_y ); - if ( error == TTO_Err_Not_Covered ) - goto end; - if ( error ) - return error; - - if ( gpi->r2l ) - { - out[in->pos].x_advance = entry_x - gpi->anchor_x; - out[in->pos].new_advance = TRUE; - } - else - { - out[gpi->last].x_advance = gpi->anchor_x - entry_x; - out[gpi->last].new_advance = TRUE; - } - - out[in->pos].y_pos = gpi->anchor_y - entry_y + out[gpi->last].y_pos; - - end: - error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos], - &exit_x, &exit_y ); - if ( error == TTO_Err_Not_Covered ) - gpi->last = 0xFFFF; - else - { - gpi->last = in->pos; - gpi->anchor_x = exit_x; - gpi->anchor_y = exit_y; - } - if ( error ) - return error; - - (in->pos)++; - - return TT_Err_Ok; - } - - - /* LookupType 4 */ - - /* BaseArray */ - - static TT_Error Load_BaseArray( TTO_BaseArray* ba, - UShort num_classes, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort m, n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_BaseRecord* br; - TTO_Anchor* ban; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ba->BaseCount = GET_UShort(); - - FORGET_Frame(); - - ba->BaseRecord = NULL; - - if ( ALLOC_ARRAY( ba->BaseRecord, count, TTO_BaseRecord ) ) - return error; - - br = ba->BaseRecord; - - for ( m = 0; m < count; m++ ) - { - br[m].BaseAnchor = NULL; - - if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, TTO_Anchor ) ) - goto Fail; - - ban = br[m].BaseAnchor; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &ban[n], input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < count; m++ ) - { - ban = br[m].BaseAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &ban[n] ); - - FREE( ban ); - } - - FREE( br ); - return error; - } - - - static void Free_BaseArray( TTO_BaseArray* ba, - UShort num_classes ) - { - UShort m, n, count; - - TTO_BaseRecord* br; - TTO_Anchor* ban; - - - if ( ba->BaseRecord ) - { - count = ba->BaseCount; - br = ba->BaseRecord; - - for ( m = 0; m < count; m++ ) - { - ban = br[m].BaseAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &ban[n] ); - - FREE( ban ); - } - - FREE( br ); - } - } - - - /* MarkBasePosFormat1 */ - - TT_Error Load_MarkBasePos( TTO_MarkBasePos* mbp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - ULong cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mbp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mbp->MarkCoverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mbp->BaseCoverage, input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mbp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mbp->MarkArray, input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount, - input ) ) != TT_Err_Ok ) - goto Fail1; - - return TT_Err_Ok; - - Fail1: - Free_MarkArray( &mbp->MarkArray ); - - Fail2: - Free_Coverage( &mbp->BaseCoverage ); - - Fail3: - Free_Coverage( &mbp->MarkCoverage ); - return error; - } - - - void Free_MarkBasePos( TTO_MarkBasePos* mbp ) - { - Free_BaseArray( &mbp->BaseArray, mbp->ClassCount ); - Free_MarkArray( &mbp->MarkArray ); - Free_Coverage( &mbp->BaseCoverage ); - Free_Coverage( &mbp->MarkCoverage ); - } - - - static TT_Error Lookup_MarkBasePos( GPOS_Instance* gpi, - TTO_MarkBasePos* mbp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - UShort i, j, mark_index, base_index, property, class; - TT_Pos x_mark_value, y_mark_value, x_base_value, y_base_value; - TT_Error error; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_MarkArray* ma; - TTO_BaseArray* ba; - TTO_BaseRecord* br; - TTO_Anchor* mark_anchor; - TTO_Anchor* base_anchor; - - TTO_GPOS_Data* o; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( flags & IGNORE_BASE_GLYPHS ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gpos->gdef, in->string[in->pos], - flags, &property ) ) - return error; - - error = Coverage_Index( &mbp->MarkCoverage, in->string[in->pos], - &mark_index ); - if ( error ) - return error; - - /* now we search backwards for a base glyph */ - - i = 1; - j = in->pos - 1; - - while ( i <= in->pos ) - { - error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], - &property ); - if ( error ) - return error; - - if ( property != TTO_MARK ) - break; - - i++; - j--; - } - - if ( property != TTO_BASE_GLYPH ) - return TTO_Err_Not_Covered; - - if ( i > in->pos ) - return TTO_Err_Not_Covered; - - error = Coverage_Index( &mbp->BaseCoverage, in->string[j], - &base_index ); - if ( error ) - return error; - - ma = &mbp->MarkArray; - - if ( mark_index >= ma->MarkCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - class = ma->MarkRecord[mark_index].Class; - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; - - if ( class >= mbp->ClassCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - ba = &mbp->BaseArray; - - if ( base_index >= ba->BaseCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - br = &ba->BaseRecord[base_index]; - base_anchor = &br->BaseAnchor[class]; - - error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], - &x_mark_value, &y_mark_value ); - if ( error ) - return error; - error = Get_Anchor( gpi, base_anchor, in->string[j], - &x_base_value, &y_base_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = &out[in->pos]; - - o->x_pos = x_base_value - x_mark_value; - o->y_pos = y_base_value - y_mark_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = i; - - (in->pos)++; - - return TT_Err_Ok; - } - - - /* LookupType 5 */ - - /* LigatureAttach */ - - static TT_Error Load_LigatureAttach( TTO_LigatureAttach* lat, - UShort num_classes, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort m, n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_ComponentRecord* cr; - TTO_Anchor* lan; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = lat->ComponentCount = GET_UShort(); - - FORGET_Frame(); - - lat->ComponentRecord = NULL; - - if ( ALLOC_ARRAY( lat->ComponentRecord, count, TTO_ComponentRecord ) ) - return error; - - cr = lat->ComponentRecord; - - for ( m = 0; m < count; m++ ) - { - cr[m].LigatureAnchor = NULL; - - if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, TTO_Anchor ) ) - goto Fail; - - lan = cr[m].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &lan[n], input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - else - lan[n].PosFormat = 0; - } - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < count; m++ ) - { - lan = cr[m].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &lan[n] ); - - FREE( lan ); - } - - FREE( cr ); - return error; - } - - - static void Free_LigatureAttach( TTO_LigatureAttach* lat, - UShort num_classes ) - { - UShort m, n, count; - - TTO_ComponentRecord* cr; - TTO_Anchor* lan; - - - if ( lat->ComponentRecord ) - { - count = lat->ComponentCount; - cr = lat->ComponentRecord; - - for ( m = 0; m < count; m++ ) - { - lan = cr[m].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &lan[n] ); - - FREE( lan ); - } - - FREE( cr ); - } - } - - - /* LigatureArray */ - - static TT_Error Load_LigatureArray( TTO_LigatureArray* la, - UShort num_classes, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_LigatureAttach* lat; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = la->LigatureCount = GET_UShort(); - - FORGET_Frame(); - - la->LigatureAttach = NULL; - - if ( ALLOC_ARRAY( la->LigatureAttach, count, TTO_LigatureAttach ) ) - return error; - - lat = la->LigatureAttach; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigatureAttach( &lat[n], num_classes, - input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_LigatureAttach( &lat[n], num_classes ); - - FREE( lat ); - return error; - } - - - static void Free_LigatureArray( TTO_LigatureArray* la, - UShort num_classes ) - { - UShort n, count; - - TTO_LigatureAttach* lat; - - - if ( la->LigatureAttach ) - { - count = la->LigatureCount; - lat = la->LigatureAttach; - - for ( n = 0; n < count; n++ ) - Free_LigatureAttach( &lat[n], num_classes ); - - FREE( lat ); - } - } - - - /* MarkLigPosFormat1 */ - - TT_Error Load_MarkLigPos( TTO_MarkLigPos* mlp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - ULong cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mlp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mlp->MarkCoverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mlp->LigatureCoverage, - input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mlp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mlp->MarkArray, input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, - input ) ) != TT_Err_Ok ) - goto Fail1; - - return TT_Err_Ok; - - Fail1: - Free_MarkArray( &mlp->MarkArray ); - - Fail2: - Free_Coverage( &mlp->LigatureCoverage ); - - Fail3: - Free_Coverage( &mlp->MarkCoverage ); - return error; - } - - - void Free_MarkLigPos( TTO_MarkLigPos* mlp ) - { - Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount ); - Free_MarkArray( &mlp->MarkArray ); - Free_Coverage( &mlp->LigatureCoverage ); - Free_Coverage( &mlp->MarkCoverage ); - } - - - static TT_Error Lookup_MarkLigPos( GPOS_Instance* gpi, - TTO_MarkLigPos* mlp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - UShort i, j, mark_index, lig_index, property, class; - UShort mark_glyph; - TT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value; - TT_Error error; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_MarkArray* ma; - TTO_LigatureArray* la; - TTO_LigatureAttach* lat; - TTO_ComponentRecord* cr; - UShort comp_index; - TTO_Anchor* mark_anchor; - TTO_Anchor* lig_anchor; - - TTO_GPOS_Data* o; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( flags & IGNORE_LIGATURES ) - return TTO_Err_Not_Covered; - - mark_glyph = in->string[in->pos]; - - if ( CHECK_Property( gpos->gdef, mark_glyph, flags, &property ) ) - return error; - - error = Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index ); - if ( error ) - return error; - - /* now we search backwards for a ligature */ - - i = 1; - j = in->pos - 1; - - while ( i <= in->pos ) - { - error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], - &property ); - if ( error ) - return error; - - if ( property != TTO_MARK ) - break; - - i++; - j--; - } - - if ( property != TTO_LIGATURE ) - return TTO_Err_Not_Covered; - - if ( i > in->pos ) - return TTO_Err_Not_Covered; - - error = Coverage_Index( &mlp->LigatureCoverage, in->string[j], - &lig_index ); - if ( error ) - return error; - - ma = &mlp->MarkArray; - - if ( mark_index >= ma->MarkCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - class = ma->MarkRecord[mark_index].Class; - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; - - if ( class >= mlp->ClassCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - la = &mlp->LigatureArray; - - if ( lig_index >= la->LigatureCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - lat = &la->LigatureAttach[lig_index]; - - /* We must now check whether the ligature ID of the current mark glyph - is identical to the ligature ID of the found ligature. If yes, we - can directly use the component index. If not, we attach the mark - glyph to the last component of the ligature. */ - - if ( in->ligIDs && in->components && - in->ligIDs[j] == in->ligIDs[in->pos] ) - { - comp_index = in->components[in->pos]; - if ( comp_index >= lat->ComponentCount ) - return TTO_Err_Not_Covered; - } - else - comp_index = lat->ComponentCount - 1; - - cr = &lat->ComponentRecord[comp_index]; - lig_anchor = &cr->LigatureAnchor[class]; - - error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], - &x_mark_value, &y_mark_value ); - if ( error ) - return error; - error = Get_Anchor( gpi, lig_anchor, in->string[j], - &x_lig_value, &y_lig_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = &out[in->pos]; - - o->x_pos = x_lig_value - x_mark_value; - o->y_pos = y_lig_value - y_mark_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = i; - - (in->pos)++; - - return TT_Err_Ok; - } - - - /* LookupType 6 */ - - /* Mark2Array */ - - static TT_Error Load_Mark2Array( TTO_Mark2Array* m2a, - UShort num_classes, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort m, n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_Mark2Record* m2r; - TTO_Anchor* m2an; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = m2a->Mark2Count = GET_UShort(); - - FORGET_Frame(); - - m2a->Mark2Record = NULL; - - if ( ALLOC_ARRAY( m2a->Mark2Record, count, TTO_Mark2Record ) ) - return error; - - m2r = m2a->Mark2Record; - - for ( m = 0; m < count; m++ ) - { - m2r[m].Mark2Anchor = NULL; - - if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, TTO_Anchor ) ) - goto Fail; - - m2an = m2r[m].Mark2Anchor; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &m2an[n], input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < count; m++ ) - { - m2an = m2r[m].Mark2Anchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &m2an[n] ); - - FREE( m2an ); - } - - FREE( m2r ); - return error; - } - - - static void Free_Mark2Array( TTO_Mark2Array* m2a, - UShort num_classes ) - { - UShort m, n, count; - - TTO_Mark2Record* m2r; - TTO_Anchor* m2an; - - - if ( m2a->Mark2Record ) - { - count = m2a->Mark2Count; - m2r = m2a->Mark2Record; - - for ( m = 0; m < count; m++ ) - { - m2an = m2r[m].Mark2Anchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &m2an[n] ); - - FREE( m2an ); - } - - FREE( m2r ); - } - } - - - /* MarkMarkPosFormat1 */ - - TT_Error Load_MarkMarkPos( TTO_MarkMarkPos* mmp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - ULong cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mmp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mmp->Mark1Coverage, - input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &mmp->Mark2Coverage, - input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mmp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mmp->Mark1Array, input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, - input ) ) != TT_Err_Ok ) - goto Fail1; - - return TT_Err_Ok; - - Fail1: - Free_MarkArray( &mmp->Mark1Array ); - - Fail2: - Free_Coverage( &mmp->Mark2Coverage ); - - Fail3: - Free_Coverage( &mmp->Mark1Coverage ); - return error; - } - - - void Free_MarkMarkPos( TTO_MarkMarkPos* mmp ) - { - Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount ); - Free_MarkArray( &mmp->Mark1Array ); - Free_Coverage( &mmp->Mark2Coverage ); - Free_Coverage( &mmp->Mark1Coverage ); - } - - - static TT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi, - TTO_MarkMarkPos* mmp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length ) - { - UShort j, mark1_index, mark2_index, property, class; - TT_Pos x_mark1_value, y_mark1_value, - x_mark2_value, y_mark2_value; - TT_Error error; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_MarkArray* ma1; - TTO_Mark2Array* ma2; - TTO_Mark2Record* m2r; - TTO_Anchor* mark1_anchor; - TTO_Anchor* mark2_anchor; - - TTO_GPOS_Data* o; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( flags & IGNORE_MARKS ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gpos->gdef, in->string[in->pos], - flags, &property ) ) - return error; - - error = Coverage_Index( &mmp->Mark1Coverage, in->string[in->pos], - &mark1_index ); - if ( error ) - return error; - - /* now we check the preceding glyph whether it is a suitable - mark glyph */ - - if ( in->pos == 0 ) - return TTO_Err_Not_Covered; - - j = in->pos - 1; - error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], - &property ); - if ( error ) - return error; - - if ( flags & IGNORE_SPECIAL_MARKS ) - { - if ( property != (flags & 0xFF00) ) - return TTO_Err_Not_Covered; - } - else - { - if ( property != TTO_MARK ) - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &mmp->Mark2Coverage, in->string[j], - &mark2_index ); - if ( error ) - return error; - - ma1 = &mmp->Mark1Array; - - if ( mark1_index >= ma1->MarkCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - class = ma1->MarkRecord[mark1_index].Class; - mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor; - - if ( class >= mmp->ClassCount ) - return TTO_Err_Invalid_GPOS_SubTable; - - ma2 = &mmp->Mark2Array; - - if ( mark2_index >= ma2->Mark2Count ) - return TTO_Err_Invalid_GPOS_SubTable; - - m2r = &ma2->Mark2Record[mark2_index]; - mark2_anchor = &m2r->Mark2Anchor[class]; - - error = Get_Anchor( gpi, mark1_anchor, in->string[in->pos], - &x_mark1_value, &y_mark1_value ); - if ( error ) - return error; - error = Get_Anchor( gpi, mark2_anchor, in->string[j], - &x_mark2_value, &y_mark2_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = &out[in->pos]; - - o->x_pos = x_mark2_value - x_mark1_value; - o->y_pos = y_mark2_value - y_mark1_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = 1; - - (in->pos)++; - - return TT_Err_Ok; - } - - - /* Do the actual positioning for a context positioning (either format - 7 or 8). This is only called after we've determined that the input - matches the subrule. */ - - static TT_Error Do_ContextPos( GPOS_Instance* gpi, - UShort GlyphCount, - UShort PosCount, - TTO_PosLookupRecord* pos, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - int nesting_level ) - { - TT_Error error; - UShort i, old_pos; - - - i = 0; - - while ( i < GlyphCount ) - { - if ( PosCount && i == pos->SequenceIndex ) - { - old_pos = in->pos; - - /* Do a positioning */ - - error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, in, out, - GlyphCount, nesting_level ); - - if ( error ) - return error; - - pos++; - PosCount--; - i += in->pos - old_pos; - } - else - { - i++; - (in->pos)++; - } - } - - return TT_Err_Ok; - } - - - /* LookupType 7 */ - - /* PosRule */ - - static TT_Error Load_PosRule( TTO_PosRule* pr, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - UShort* i; - - TTO_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - pr->GlyphCount = GET_UShort(); - pr->PosCount = GET_UShort(); - - FORGET_Frame(); - - pr->Input = NULL; - - count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( pr->Input, count, UShort ) ) - return error; - - i = pr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - pr->PosLookupRecord = NULL; - - count = pr->PosCount; - - if ( ALLOC_ARRAY( pr->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = pr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - FREE( i ); - return error; - } - - - static void Free_PosRule( TTO_PosRule* pr ) - { - FREE( pr->PosLookupRecord ); - FREE( pr->Input ); - } - - - /* PosRuleSet */ - - static TT_Error Load_PosRuleSet( TTO_PosRuleSet* prs, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_PosRule* pr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = prs->PosRuleCount = GET_UShort(); - - FORGET_Frame(); - - prs->PosRule = NULL; - - if ( ALLOC_ARRAY( prs->PosRule, count, TTO_PosRule ) ) - return error; - - pr = prs->PosRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosRule( &pr[n], input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_PosRule( &pr[n] ); - - FREE( pr ); - return error; - } - - - static void Free_PosRuleSet( TTO_PosRuleSet* prs ) - { - UShort n, count; - - TTO_PosRule* pr; - - - if ( prs->PosRule ) - { - count = prs->PosRuleCount; - pr = prs->PosRule; - - for ( n = 0; n < count; n++ ) - Free_PosRule( &pr[n] ); - - FREE( pr ); - } - } - - - /* ContextPosFormat1 */ - - static TT_Error Load_ContextPos1( TTO_ContextPosFormat1* cpf1, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_PosRuleSet* prs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &cpf1->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = cpf1->PosRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - cpf1->PosRuleSet = NULL; - - if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, TTO_PosRuleSet ) ) - goto Fail2; - - prs = cpf1->PosRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosRuleSet( &prs[n], input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - Free_PosRuleSet( &prs[n] ); - - FREE( prs ); - - Fail2: - Free_Coverage( &cpf1->Coverage ); - return error; - } - - - static void Free_Context1( TTO_ContextPosFormat1* cpf1 ) - { - UShort n, count; - - TTO_PosRuleSet* prs; - - - if ( cpf1->PosRuleSet ) - { - count = cpf1->PosRuleSetCount; - prs = cpf1->PosRuleSet; - - for ( n = 0; n < count; n++ ) - Free_PosRuleSet( &prs[n] ); - - FREE( prs ); - } - - Free_Coverage( &cpf1->Coverage ); - } - - - /* PosClassRule */ - - static TT_Error Load_PosClassRule( TTO_ContextPosFormat2* cpf2, - TTO_PosClassRule* pcr, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - - UShort* c; - TTO_PosLookupRecord* plr; - Bool* d; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - pcr->GlyphCount = GET_UShort(); - pcr->PosCount = GET_UShort(); - - FORGET_Frame(); - - if ( pcr->GlyphCount > cpf2->MaxContextLength ) - cpf2->MaxContextLength = pcr->GlyphCount; - - pcr->Class = NULL; - - count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( pcr->Class, count, UShort ) ) - return error; - - c = pcr->Class; - d = cpf2->ClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - { - c[n] = GET_UShort(); - - /* We check whether the specific class is used at all. If not, - class 0 is used instead. */ - - if ( !d[c[n]] ) - c[n] = 0; - } - - FORGET_Frame(); - - pcr->PosLookupRecord = NULL; - - count = pcr->PosCount; - - if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = pcr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - FREE( c ); - return error; - } - - - static void Free_PosClassRule( TTO_PosClassRule* pcr ) - { - FREE( pcr->PosLookupRecord ); - FREE( pcr->Class ); - } - - - /* PosClassSet */ - - static TT_Error Load_PosClassSet( TTO_ContextPosFormat2* cpf2, - TTO_PosClassSet* pcs, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_PosClassRule* pcr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = pcs->PosClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - pcs->PosClassRule = NULL; - - if ( ALLOC_ARRAY( pcs->PosClassRule, count, TTO_PosClassRule ) ) - return error; - - pcr = pcs->PosClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosClassRule( cpf2, &pcr[n], - input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_PosClassRule( &pcr[n] ); - - FREE( pcr ); - return error; - } - - - static void Free_PosClassSet( TTO_PosClassSet* pcs ) - { - UShort n, count; - - TTO_PosClassRule* pcr; - - - if ( pcs->PosClassRule ) - { - count = pcs->PosClassRuleCount; - pcr = pcs->PosClassRule; - - for ( n = 0; n < count; n++ ) - Free_PosClassRule( &pcr[n] ); - - FREE( pcr ); - } - } - - - /* ContextPosFormat2 */ - - static TT_Error Load_ContextPos2( TTO_ContextPosFormat2* cpf2, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_PosClassSet* pcs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &cpf2->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - /* `PosClassSetCount' is the upper limit for class values, thus we - read it now to make an additional safety check. */ - - count = cpf2->PosClassSetCount = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ClassDefinition( &cpf2->ClassDef, count, - input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - cpf2->PosClassSet = NULL; - cpf2->MaxContextLength = 0; - - if ( ALLOC_ARRAY( cpf2->PosClassSet, count, TTO_PosClassSet ) ) - goto Fail2; - - pcs = cpf2->PosClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosClassSet( cpf2, &pcs[n], - input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a PosClassSet table with no entries */ - - cpf2->PosClassSet[n].PosClassRuleCount = 0; - cpf2->PosClassSet[n].PosClassRule = NULL; - } - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - Free_PosClassSet( &pcs[n] ); - - FREE( pcs ); - - Fail2: - Free_ClassDefinition( &cpf2->ClassDef ); - - Fail3: - Free_Coverage( &cpf2->Coverage ); - return error; - } - - - static void Free_Context2( TTO_ContextPosFormat2* cpf2 ) - { - UShort n, count; - - TTO_PosClassSet* pcs; - - - if ( cpf2->PosClassSet ) - { - count = cpf2->PosClassSetCount; - pcs = cpf2->PosClassSet; - - for ( n = 0; n < count; n++ ) - Free_PosClassSet( &pcs[n] ); - - FREE( pcs ); - } - - Free_ClassDefinition( &cpf2->ClassDef ); - Free_Coverage( &cpf2->Coverage ); - } - - - /* ContextPosFormat3 */ - - static TT_Error Load_ContextPos3( TTO_ContextPosFormat3* cpf3, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_Coverage* c; - TTO_PosLookupRecord* plr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 4L ) ) - return error; - - cpf3->GlyphCount = GET_UShort(); - cpf3->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpf3->Coverage = NULL; - - count = cpf3->GlyphCount; - - if ( ALLOC_ARRAY( cpf3->Coverage, count, TTO_Coverage ) ) - return error; - - c = cpf3->Coverage; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &c[n], input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - cpf3->PosLookupRecord = NULL; - - count = cpf3->PosCount; - - if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = cpf3->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n] ); - - FREE( c ); - return error; - } - - - static void Free_Context3( TTO_ContextPosFormat3* cpf3 ) - { - UShort n, count; - - TTO_Coverage* c; - - - FREE( cpf3->PosLookupRecord ); - - if ( cpf3->Coverage ) - { - count = cpf3->GlyphCount; - c = cpf3->Coverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n] ); - - FREE( c ); - } - } - - - /* ContextPos */ - - TT_Error Load_ContextPos( TTO_ContextPos* cp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cp->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( cp->PosFormat ) - { - case 1: - return Load_ContextPos1( &cp->cpf.cpf1, input ); - - case 2: - return Load_ContextPos2( &cp->cpf.cpf2, input ); - - case 3: - return Load_ContextPos3( &cp->cpf.cpf3, input ); - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - void Free_ContextPos( TTO_ContextPos* cp ) - { - switch ( cp->PosFormat ) - { - case 1: - Free_Context1( &cp->cpf.cpf1 ); - break; - - case 2: - Free_Context2( &cp->cpf.cpf2 ); - break; - - case 3: - Free_Context3( &cp->cpf.cpf3 ); - break; - } - } - - - static TT_Error Lookup_ContextPos1( GPOS_Instance* gpi, - TTO_ContextPosFormat1* cpf1, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - UShort index, property; - UShort i, j, k, numpr; - TT_Error error; - UShort* s_in; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_PosRule* pr; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - error = Coverage_Index( &cpf1->Coverage, in->string[in->pos], &index ); - if ( error ) - return error; - - pr = cpf1->PosRuleSet[index].PosRule; - numpr = cpf1->PosRuleSet[index].PosRuleCount; - - for ( k = 0; k < numpr; k++ ) - { - if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) - continue; - - if ( in->pos + pr[k].GlyphCount > in->length ) - continue; /* context is too long */ - - s_in = &in->string[in->pos]; - - for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( in->pos + j < in->length ) - j++; - else - break; - } - - if ( s_in[j] != pr[k].Input[i - 1] ) - break; - } - - if ( i == pr[k].GlyphCount ) - return Do_ContextPos( gpi, pr[k].GlyphCount, - pr[k].PosCount, pr[k].PosLookupRecord, - in, out, - nesting_level ); - } - - return TTO_Err_Not_Covered; - } - - - static TT_Error Lookup_ContextPos2( GPOS_Instance* gpi, - TTO_ContextPosFormat2* cpf2, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - UShort index, property; - TT_Error error; - UShort i, j, k, known_classes; - - UShort* classes; - UShort* s_in; - UShort* cl; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_PosClassSet* pcs; - TTO_PosClassRule* pr; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, UShort ) ) - return error; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = Coverage_Index( &cpf2->Coverage, in->string[in->pos], &index ); - if ( error ) - goto End; - - error = Get_Class( &cpf2->ClassDef, in->string[in->pos], - &classes[0], NULL ); - if ( error ) - goto End; - known_classes = 0; - - pcs = &cpf2->PosClassSet[classes[0]]; - if ( !pcs ) - { - error = TTO_Err_Invalid_GPOS_SubTable; - goto End; - } - - for ( k = 0; k < pcs->PosClassRuleCount; k++ ) - { - pr = &pcs->PosClassRule[k]; - - if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) - continue; - - if ( in->pos + pr->GlyphCount > in->length ) - continue; /* context is too long */ - - s_in = &in->string[in->pos]; - cl = pr->Class; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( in->pos + j < in->length ) - j++; - else - break; - } - - if ( i > known_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = Get_Class( &cpf2->ClassDef, s_in[j], &classes[i], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - known_classes = i; - } - - if ( cl[i - 1] != classes[i] ) - break; - } - - if ( i == pr->GlyphCount ) - { - error = Do_ContextPos( gpi, pr->GlyphCount, - pr->PosCount, pr->PosLookupRecord, - in, out, - nesting_level ); - goto End; - } - } - - error = TTO_Err_Not_Covered; - - End: - FREE( classes ); - return error; - } - - - static TT_Error Lookup_ContextPos3( GPOS_Instance* gpi, - TTO_ContextPosFormat3* cpf3, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - TT_Error error; - UShort index, i, j, property; - UShort* s_in; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_Coverage* c; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount ) - return TTO_Err_Not_Covered; - - if ( in->pos + cpf3->GlyphCount > in->length ) - return TTO_Err_Not_Covered; /* context is too long */ - - s_in = &in->string[in->pos]; - c = cpf3->Coverage; - - for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( in->pos + j < in->length ) - j++; - else - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &c[i], s_in[j], &index ); - if ( error ) - return error; - } - - return Do_ContextPos( gpi, cpf3->GlyphCount, - cpf3->PosCount, cpf3->PosLookupRecord, - in, out, - nesting_level ); - } - - - static TT_Error Lookup_ContextPos( GPOS_Instance* gpi, - TTO_ContextPos* cp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - switch ( cp->PosFormat ) - { - case 1: - return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, in, out, - flags, context_length, nesting_level ); - - case 2: - return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, in, out, - flags, context_length, nesting_level ); - - case 3: - return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, in, out, - flags, context_length, nesting_level ); - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - /* LookupType 8 */ - - /* ChainPosRule */ - - static TT_Error Load_ChainPosRule( TTO_ChainPosRule* cpr, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - UShort* b; - UShort* i; - UShort* l; - - TTO_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cpr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Backtrack = NULL; - - count = cpr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( cpr->Backtrack, count, UShort ) ) - return error; - - b = cpr->Backtrack; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - b[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - cpr->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Input = NULL; - - count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( cpr->Input, count, UShort ) ) - goto Fail4; - - i = cpr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - cpr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Lookahead = NULL; - - count = cpr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( cpr->Lookahead, count, UShort ) ) - goto Fail3; - - l = cpr->Lookahead; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - l[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - cpr->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpr->PosLookupRecord = NULL; - - count = cpr->PosCount; - - if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = cpr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - FREE( l ); - - Fail3: - FREE( i ); - - Fail4: - FREE( b ); - return error; - } - - - static void Free_ChainPosRule( TTO_ChainPosRule* cpr ) - { - FREE( cpr->PosLookupRecord ); - FREE( cpr->Lookahead ); - FREE( cpr->Input ); - FREE( cpr->Backtrack ); - } - - - /* ChainPosRuleSet */ - - static TT_Error Load_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_ChainPosRule* cpr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cprs->ChainPosRuleCount = GET_UShort(); - - FORGET_Frame(); - - cprs->ChainPosRule = NULL; - - if ( ALLOC_ARRAY( cprs->ChainPosRule, count, TTO_ChainPosRule ) ) - return error; - - cpr = cprs->ChainPosRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosRule( &cpr[n], input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_ChainPosRule( &cpr[n] ); - - FREE( cpr ); - return error; - } - - - static void Free_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs ) - { - UShort n, count; - - TTO_ChainPosRule* cpr; - - - if ( cprs->ChainPosRule ) - { - count = cprs->ChainPosRuleCount; - cpr = cprs->ChainPosRule; - - for ( n = 0; n < count; n++ ) - Free_ChainPosRule( &cpr[n] ); - - FREE( cpr ); - } - } - - - /* ChainContextPosFormat1 */ - - static TT_Error Load_ChainContextPos1( TTO_ChainContextPosFormat1* ccpf1, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_ChainPosRuleSet* cprs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &ccpf1->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ccpf1->ChainPosRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - ccpf1->ChainPosRuleSet = NULL; - - if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, TTO_ChainPosRuleSet ) ) - goto Fail2; - - cprs = ccpf1->ChainPosRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosRuleSet( &cprs[n], input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - Free_ChainPosRuleSet( &cprs[n] ); - - FREE( cprs ); - - Fail2: - Free_Coverage( &ccpf1->Coverage ); - return error; - } - - - static void Free_ChainContext1( TTO_ChainContextPosFormat1* ccpf1 ) - { - UShort n, count; - - TTO_ChainPosRuleSet* cprs; - - - if ( ccpf1->ChainPosRuleSet ) - { - count = ccpf1->ChainPosRuleSetCount; - cprs = ccpf1->ChainPosRuleSet; - - for ( n = 0; n < count; n++ ) - Free_ChainPosRuleSet( &cprs[n] ); - - FREE( cprs ); - } - - Free_Coverage( &ccpf1->Coverage ); - } - - - /* ChainPosClassRule */ - - static TT_Error Load_ChainPosClassRule( - TTO_ChainContextPosFormat2* ccpf2, - TTO_ChainPosClassRule* cpcr, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - - UShort* b; - UShort* i; - UShort* l; - TTO_PosLookupRecord* plr; - Bool* d; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cpcr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength ) - ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount; - - cpcr->Backtrack = NULL; - - count = cpcr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( cpcr->Backtrack, count, UShort ) ) - return error; - - b = cpcr->Backtrack; - d = ccpf2->BacktrackClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - { - b[n] = GET_UShort(); - - /* We check whether the specific class is used at all. If not, - class 0 is used instead. */ - - if ( !d[b[n]] ) - b[n] = 0; - } - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - cpcr->InputGlyphCount = GET_UShort(); - - if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength ) - ccpf2->MaxInputLength = cpcr->InputGlyphCount; - - FORGET_Frame(); - - cpcr->Input = NULL; - - count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( cpcr->Input, count, UShort ) ) - goto Fail4; - - i = cpcr->Input; - d = ccpf2->InputClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - { - i[n] = GET_UShort(); - - if ( !d[i[n]] ) - i[n] = 0; - } - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - cpcr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength ) - ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount; - - cpcr->Lookahead = NULL; - - count = cpcr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( cpcr->Lookahead, count, UShort ) ) - goto Fail3; - - l = cpcr->Lookahead; - d = ccpf2->LookaheadClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - { - l[n] = GET_UShort(); - - if ( !d[l[n]] ) - l[n] = 0; - } - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - cpcr->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpcr->PosLookupRecord = NULL; - - count = cpcr->PosCount; - - if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = cpcr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - FREE( l ); - - Fail3: - FREE( i ); - - Fail4: - FREE( b ); - return error; - } - - - static void Free_ChainPosClassRule( TTO_ChainPosClassRule* cpcr ) - { - FREE( cpcr->PosLookupRecord ); - FREE( cpcr->Lookahead ); - FREE( cpcr->Input ); - FREE( cpcr->Backtrack ); - } - - - /* PosClassSet */ - - static TT_Error Load_ChainPosClassSet( - TTO_ChainContextPosFormat2* ccpf2, - TTO_ChainPosClassSet* cpcs, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - - TTO_ChainPosClassRule* cpcr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cpcs->ChainPosClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - cpcs->ChainPosClassRule = NULL; - - if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count, - TTO_ChainPosClassRule ) ) - return error; - - cpcr = cpcs->ChainPosClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n], - input ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( n = 0; n < count; n++ ) - Free_ChainPosClassRule( &cpcr[n] ); - - FREE( cpcr ); - return error; - } - - - static void Free_ChainPosClassSet( TTO_ChainPosClassSet* cpcs ) - { - UShort n, count; - - TTO_ChainPosClassRule* cpcr; - - - if ( cpcs->ChainPosClassRule ) - { - count = cpcs->ChainPosClassRuleCount; - cpcr = cpcs->ChainPosClassRule; - - for ( n = 0; n < count; n++ ) - Free_ChainPosClassRule( &cpcr[n] ); - - FREE( cpcr ); - } - } - - - /* ChainContextPosFormat2 */ - - static TT_Error Load_ChainContextPos2( TTO_ChainContextPosFormat2* ccpf2, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - ULong cur_offset, new_offset, base_offset; - ULong backtrack_offset, input_offset, lookahead_offset; - - TTO_ChainPosClassSet* cpcs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &ccpf2->Coverage, input ) ) != TT_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 8L ) ) - goto Fail5; - - backtrack_offset = GET_UShort() + base_offset; - input_offset = GET_UShort() + base_offset; - lookahead_offset = GET_UShort() + base_offset; - - /* `ChainPosClassSetCount' is the upper limit for input class values, - thus we read it now to make an additional safety check. */ - - count = ccpf2->ChainPosClassSetCount = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( backtrack_offset ) || - ( error = Load_ClassDefinition( &ccpf2->BacktrackClassDef, count, - input ) ) != TT_Err_Ok ) - goto Fail5; - if ( FILE_Seek( input_offset ) || - ( error = Load_ClassDefinition( &ccpf2->InputClassDef, count, - input ) ) != TT_Err_Ok ) - goto Fail4; - if ( FILE_Seek( lookahead_offset ) || - ( error = Load_ClassDefinition( &ccpf2->LookaheadClassDef, count, - input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - ccpf2->ChainPosClassSet = NULL; - ccpf2->MaxBacktrackLength = 0; - ccpf2->MaxInputLength = 0; - ccpf2->MaxLookaheadLength = 0; - - if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, TTO_ChainPosClassSet ) ) - goto Fail2; - - cpcs = ccpf2->ChainPosClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n], - input ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a ChainPosClassSet table with no entries */ - - ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0; - ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL; - } - } - - return TT_Err_Ok; - - Fail1: - for ( n = 0; n < count; n++ ) - Free_ChainPosClassSet( &cpcs[n] ); - - FREE( cpcs ); - - Fail2: - Free_ClassDefinition( &ccpf2->LookaheadClassDef ); - - Fail3: - Free_ClassDefinition( &ccpf2->InputClassDef ); - - Fail4: - Free_ClassDefinition( &ccpf2->BacktrackClassDef ); - - Fail5: - Free_Coverage( &ccpf2->Coverage ); - return error; - } - - - static void Free_ChainContext2( TTO_ChainContextPosFormat2* ccpf2 ) - { - UShort n, count; - - TTO_ChainPosClassSet* cpcs; - - - if ( ccpf2->ChainPosClassSet ) - { - count = ccpf2->ChainPosClassSetCount; - cpcs = ccpf2->ChainPosClassSet; - - for ( n = 0; n < count; n++ ) - Free_ChainPosClassSet( &cpcs[n] ); - - FREE( cpcs ); - } - - Free_ClassDefinition( &ccpf2->LookaheadClassDef ); - Free_ClassDefinition( &ccpf2->InputClassDef ); - Free_ClassDefinition( &ccpf2->BacktrackClassDef ); - - Free_Coverage( &ccpf2->Coverage ); - } - - - /* ChainContextPosFormat3 */ - - static TT_Error Load_ChainContextPos3( TTO_ChainContextPosFormat3* ccpf3, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - UShort n, count; - UShort backtrack_count, input_count, lookahead_count; - ULong cur_offset, new_offset, base_offset; - - TTO_Coverage* b; - TTO_Coverage* i; - TTO_Coverage* l; - TTO_PosLookupRecord* plr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccpf3->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->BacktrackCoverage = NULL; - - backtrack_count = ccpf3->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count, - TTO_Coverage ) ) - return error; - - b = ccpf3->BacktrackCoverage; - - for ( n = 0; n < backtrack_count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &b[n], input ) ) != TT_Err_Ok ) - goto Fail4; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - ccpf3->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->InputCoverage = NULL; - - input_count = ccpf3->InputGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, TTO_Coverage ) ) - goto Fail4; - - i = ccpf3->InputCoverage; - - for ( n = 0; n < input_count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &i[n], input ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - ccpf3->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->LookaheadCoverage = NULL; - - lookahead_count = ccpf3->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count, - TTO_Coverage ) ) - goto Fail3; - - l = ccpf3->LookaheadCoverage; - - for ( n = 0; n < lookahead_count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Coverage( &l[n], input ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - ccpf3->PosCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->PosLookupRecord = NULL; - - count = ccpf3->PosCount; - - if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, TTO_PosLookupRecord ) ) - goto Fail2; - - plr = ccpf3->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return TT_Err_Ok; - - Fail1: - FREE( plr ); - - Fail2: - for ( n = 0; n < lookahead_count; n++ ) - Free_Coverage( &l[n] ); - - FREE( l ); - - Fail3: - for ( n = 0; n < input_count; n++ ) - Free_Coverage( &i[n] ); - - FREE( i ); - - Fail4: - for ( n = 0; n < backtrack_count; n++ ) - Free_Coverage( &b[n] ); - - FREE( b ); - return error; - } - - - static void Free_ChainContext3( TTO_ChainContextPosFormat3* ccpf3 ) - { - UShort n, count; - - TTO_Coverage* c; - - - FREE( ccpf3->PosLookupRecord ); - - if ( ccpf3->LookaheadCoverage ) - { - count = ccpf3->LookaheadGlyphCount; - c = ccpf3->LookaheadCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccpf3->InputCoverage ) - { - count = ccpf3->InputGlyphCount; - c = ccpf3->InputCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccpf3->BacktrackCoverage ) - { - count = ccpf3->BacktrackGlyphCount; - c = ccpf3->BacktrackCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n] ); - - FREE( c ); - } - } - - - /* ChainContextPos */ - - TT_Error Load_ChainContextPos( TTO_ChainContextPos* ccp, - PFace input ) - { - DEFINE_LOAD_LOCALS( input->stream ); - - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccp->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( ccp->PosFormat ) - { - case 1: - return Load_ChainContextPos1( &ccp->ccpf.ccpf1, input ); - - case 2: - return Load_ChainContextPos2( &ccp->ccpf.ccpf2, input ); - - case 3: - return Load_ChainContextPos3( &ccp->ccpf.ccpf3, input ); - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - void Free_ChainContextPos( TTO_ChainContextPos* ccp ) - { - switch ( ccp->PosFormat ) - { - case 1: - Free_ChainContext1( &ccp->ccpf.ccpf1 ); - break; - - case 2: - Free_ChainContext2( &ccp->ccpf.ccpf2 ); - break; - - case 3: - Free_ChainContext3( &ccp->ccpf.ccpf3 ); - break; - } - } - - - static TT_Error Lookup_ChainContextPos1( - GPOS_Instance* gpi, - TTO_ChainContextPosFormat1* ccpf1, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - UShort index, property; - UShort i, j, k, num_cpr, curr_pos; - UShort bgc, igc, lgc; - TT_Error error; - UShort* s_in; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_ChainPosRule* cpr; - TTO_ChainPosRule curr_cpr; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - error = Coverage_Index( &ccpf1->Coverage, in->string[in->pos], &index ); - if ( error ) - return error; - - cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule; - num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount; - - for ( k = 0; k < num_cpr; k++ ) - { - curr_cpr = cpr[k]; - bgc = curr_cpr.BacktrackGlyphCount; - igc = curr_cpr.InputGlyphCount; - lgc = curr_cpr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - continue; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > in->pos || in->pos + igc + lgc > in->length ) - continue; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - curr_pos = 0; - s_in = &in->string[curr_pos]; - - for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( j > curr_pos ) - j--; - else - break; - } - - if ( s_in[j] != curr_cpr.Backtrack[i - 1] ) - break; - } - - if ( i != 0 ) - continue; - } - - curr_pos = in->pos; - s_in = &in->string[curr_pos]; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( curr_pos + j < in->length ) - j++; - else - break; - } - - if ( s_in[j] != curr_cpr.Input[i - 1] ) - break; - } - - if ( i != igc ) - continue; - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - curr_pos = j; - s_in = &in->string[curr_pos]; - - for ( i = 0, j = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( curr_pos + j < in->length ) - j++; - else - break; - } - - if ( s_in[j] != curr_cpr.Lookahead[i] ) - break; - } - - if ( i == lgc ) - return Do_ContextPos( gpi, igc, - curr_cpr.PosCount, - curr_cpr.PosLookupRecord, - in, out, - nesting_level ); - } - - return TTO_Err_Not_Covered; - } - - - static TT_Error Lookup_ChainContextPos2( - GPOS_Instance* gpi, - TTO_ChainContextPosFormat2* ccpf2, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - UShort index, property; - TT_Error error; - UShort i, j, k, curr_pos; - UShort bgc, igc, lgc; - UShort known_backtrack_classes, - known_input_classes, - known_lookahead_classes; - - UShort* backtrack_classes; - UShort* input_classes; - UShort* lookahead_classes; - - UShort* s_in; - - UShort* bc; - UShort* ic; - UShort* lc; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_ChainPosClassSet* cpcs; - TTO_ChainPosClassRule cpcr; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = Coverage_Index( &ccpf2->Coverage, in->string[in->pos], &index ); - if ( error ) - return error; - - if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, UShort ) ) - return error; - known_backtrack_classes = 0; - - if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, UShort ) ) - goto End3; - known_input_classes = 1; - - if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, UShort ) ) - goto End2; - known_lookahead_classes = 0; - - error = Get_Class( &ccpf2->InputClassDef, in->string[in->pos], - &input_classes[0], NULL ); - if ( error ) - goto End1; - - cpcs = &ccpf2->ChainPosClassSet[input_classes[0]]; - if ( !cpcs ) - { - error = TTO_Err_Invalid_GPOS_SubTable; - goto End1; - } - - for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ ) - { - cpcr = cpcs->ChainPosClassRule[k]; - bgc = cpcr.BacktrackGlyphCount; - igc = cpcr.InputGlyphCount; - lgc = cpcr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - continue; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > in->pos || in->pos + igc + lgc > in->length ) - continue; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array. - Note that `known_backtrack_classes' starts at index 0. */ - - curr_pos = 0; - s_in = &in->string[curr_pos]; - bc = cpcr.Backtrack; - - for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( j > curr_pos ) - j--; - else - break; - } - - if ( i >= known_backtrack_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = Get_Class( &ccpf2->BacktrackClassDef, s_in[j], - &backtrack_classes[i], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - goto End1; - known_backtrack_classes = i; - } - - if ( bc[bgc - 1 - i] != backtrack_classes[i] ) - break; - } - - if ( i != bgc ) - continue; - } - - curr_pos = in->pos; - s_in = &in->string[curr_pos]; - ic = cpcr.Input; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - goto End1; - - if ( curr_pos + j < in->length ) - j++; - else - break; - } - - if ( i >= known_input_classes ) - { - error = Get_Class( &ccpf2->InputClassDef, s_in[j], - &input_classes[i], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - goto End1; - known_input_classes = i; - } - - if ( ic[i - 1] != input_classes[i] ) - break; - } - - if ( i != igc ) - continue; - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - curr_pos = j; - s_in = &in->string[curr_pos]; - lc = cpcr.Lookahead; - - for ( i = 0, j = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( curr_pos + j < in->length ) - j++; - else - break; - } - - if ( i >= known_lookahead_classes ) - { - error = Get_Class( &ccpf2->LookaheadClassDef, s_in[j], - &lookahead_classes[i], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - goto End1; - known_lookahead_classes = i; - } - - if ( lc[i] != lookahead_classes[i] ) - break; - } - - if ( i == lgc ) - { - error = Do_ContextPos( gpi, igc, - cpcr.PosCount, - cpcr.PosLookupRecord, - in, out, - nesting_level ); - goto End1; - } - } - - error = TTO_Err_Not_Covered; - - End1: - FREE( lookahead_classes ); - - End2: - FREE( input_classes ); - - End3: - FREE( backtrack_classes ); - return error; - } - - - static TT_Error Lookup_ChainContextPos3( - GPOS_Instance* gpi, - TTO_ChainContextPosFormat3* ccpf3, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - UShort index, i, j, curr_pos, property; - UShort bgc, igc, lgc; - TT_Error error; - UShort* s_in; - TTO_GPOSHeader* gpos = gpi->gpos; - - TTO_Coverage* bc; - TTO_Coverage* ic; - TTO_Coverage* lc; - TTO_GDEFHeader* gdef; - - - gdef = gpos->gdef; - - if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) - return error; - - bgc = ccpf3->BacktrackGlyphCount; - igc = ccpf3->InputGlyphCount; - lgc = ccpf3->LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - return TTO_Err_Not_Covered; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > in->pos || in->pos + igc + lgc > in->length ) - return TTO_Err_Not_Covered; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - curr_pos = 0; - s_in = &in->string[curr_pos]; - bc = ccpf3->BacktrackCoverage; - - for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( j > curr_pos ) - j--; - else - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &bc[i - 1], s_in[j], &index ); - if ( error ) - return error; - } - } - - curr_pos = in->pos; - s_in = &in->string[curr_pos]; - ic = ccpf3->InputCoverage; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( curr_pos + j < in->length ) - j++; - else - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &ic[i], s_in[j], &index ); - if ( error ) - return error; - } - - /* we are starting for lookahead glyphs right after the last context - glyph */ - - curr_pos = j; - s_in = &in->string[curr_pos]; - lc = ccpf3->LookaheadCoverage; - - for ( i = 0, j = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) - { - if ( error && error != TTO_Err_Not_Covered ) - return error; - - if ( curr_pos + j < in->length ) - j++; - else - return TTO_Err_Not_Covered; - } - - error = Coverage_Index( &lc[i], s_in[j], &index ); - if ( error ) - return error; - } - - return Do_ContextPos( gpi, igc, - ccpf3->PosCount, - ccpf3->PosLookupRecord, - in, out, - nesting_level ); - } - - - static TT_Error Lookup_ChainContextPos( - GPOS_Instance* gpi, - TTO_ChainContextPos* ccp, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort flags, - UShort context_length, - int nesting_level ) - { - switch ( ccp->PosFormat ) - { - case 1: - return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, in, out, - flags, context_length, - nesting_level ); - - case 2: - return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, in, out, - flags, context_length, - nesting_level ); - - case 3: - return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, in, out, - flags, context_length, - nesting_level ); - - default: - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - - /*********** - * GPOS API - ***********/ - - - EXPORT_FUNC - TT_Error TT_GPOS_Select_Script( TTO_GPOSHeader* gpos, - TT_ULong script_tag, - TT_UShort* script_index ) - { - UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - - - if ( !gpos || !script_index ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - for ( n = 0; n < sl->ScriptCount; n++ ) - if ( script_tag == sr[n].ScriptTag ) - { - *script_index = n; - - return TT_Err_Ok; - } - - return TTO_Err_Not_Covered; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Select_Language( TTO_GPOSHeader* gpos, - TT_ULong language_tag, - TT_UShort script_index, - TT_UShort* language_index, - TT_UShort* req_feature_index ) - { - UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - - - if ( !gpos || !language_index || !req_feature_index ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_Err_Invalid_Argument; - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - for ( n = 0; n < s->LangSysCount; n++ ) - if ( language_tag == lsr[n].LangSysTag ) - { - *language_index = n; - *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; - - return TT_Err_Ok; - } - - return TTO_Err_Not_Covered; - } - - - /* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - EXPORT_FUNC - TT_Error TT_GPOS_Select_Feature( TTO_GPOSHeader* gpos, - TT_ULong feature_tag, - TT_UShort script_index, - TT_UShort language_index, - TT_UShort* feature_index ) - { - UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - TTO_LangSys* ls; - UShort* fi; - - TTO_FeatureList* fl; - TTO_FeatureRecord* fr; - - - if ( !gpos || !feature_index ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - fl = &gpos->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_Err_Invalid_Argument; - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return TT_Err_Invalid_Argument; - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - return TTO_Err_Invalid_GPOS_SubTable_Format; - - if ( feature_tag == fr[fi[n]].FeatureTag ) - { - *feature_index = fi[n]; - - return TT_Err_Ok; - } - } - - return TTO_Err_Not_Covered; - } - - - /* The next three functions return a null-terminated list */ - - EXPORT_FUNC - TT_Error TT_GPOS_Query_Scripts( TTO_GPOSHeader* gpos, - TT_ULong** script_tag_list ) - { - UShort n; - TT_Error error; - ULong* stl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - - - if ( !gpos || !script_tag_list ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, ULong ) ) - return error; - - for ( n = 0; n < sl->ScriptCount; n++ ) - stl[n] = sr[n].ScriptTag; - stl[n] = 0; - - *script_tag_list = stl; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Query_Languages( TTO_GPOSHeader* gpos, - TT_UShort script_index, - TT_ULong** language_tag_list ) - { - UShort n; - TT_Error error; - ULong* ltl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - - - if ( !gpos || !language_tag_list ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_Err_Invalid_Argument; - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, ULong ) ) - return error; - - for ( n = 0; n < s->LangSysCount; n++ ) - ltl[n] = lsr[n].LangSysTag; - ltl[n] = 0; - - *language_tag_list = ltl; - - return TT_Err_Ok; - } - - - /* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - EXPORT_FUNC - TT_Error TT_GPOS_Query_Features( TTO_GPOSHeader* gpos, - TT_UShort script_index, - TT_UShort language_index, - TT_ULong** feature_tag_list ) - { - UShort n; - TT_Error error; - ULong* ftl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - TTO_LangSys* ls; - UShort* fi; - - TTO_FeatureList* fl; - TTO_FeatureRecord* fr; - - - if ( !gpos || !feature_tag_list ) - return TT_Err_Invalid_Argument; - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - fl = &gpos->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_Err_Invalid_Argument; - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return TT_Err_Invalid_Argument; - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, ULong ) ) - return error; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - { - FREE( ftl ); - return TTO_Err_Invalid_GPOS_SubTable_Format; - } - ftl[n] = fr[fi[n]].FeatureTag; - } - ftl[n] = 0; - - *feature_tag_list = ftl; - - return TT_Err_Ok; - } - - - /* Do an individual subtable lookup. Returns TT_Err_Ok if positioning - has been done, or TTO_Err_Not_Covered if not. */ - - static TT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, - UShort lookup_index, - TTO_GSUB_String* in, - TTO_GPOS_Data* out, - UShort context_length, - int nesting_level ) - { - TT_Error error = TT_Err_Ok; - UShort i, flags; - TTO_GPOSHeader* gpos = gpi->gpos; - TTO_Lookup* lo; - - - nesting_level++; - - if ( nesting_level > TTO_MAX_NESTING_LEVEL ) - return TTO_Err_Too_Many_Nested_Contexts; - - lo = &gpos->LookupList.Lookup[lookup_index]; - flags = lo->LookupFlag; - - for ( i = 0; i < lo->SubTableCount; i++ ) - { - switch ( lo->LookupType ) - { - case GPOS_LOOKUP_SINGLE: - error = Lookup_SinglePos( gpi, - &lo->SubTable[i].st.gpos.single, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_PAIR: - error = Lookup_PairPos( gpi, - &lo->SubTable[i].st.gpos.pair, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_CURSIVE: - error = Lookup_CursivePos( gpi, - &lo->SubTable[i].st.gpos.cursive, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_MARKBASE: - error = Lookup_MarkBasePos( gpi, - &lo->SubTable[i].st.gpos.markbase, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_MARKLIG: - error = Lookup_MarkLigPos( gpi, - &lo->SubTable[i].st.gpos.marklig, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_MARKMARK: - error = Lookup_MarkMarkPos( gpi, - &lo->SubTable[i].st.gpos.markmark, - in, out, - flags, context_length ); - break; - - case GPOS_LOOKUP_CONTEXT: - error = Lookup_ContextPos( gpi, - &lo->SubTable[i].st.gpos.context, - in, out, - flags, context_length, - nesting_level ); - break; - - case GPOS_LOOKUP_CHAIN: - error = Lookup_ChainContextPos( gpi, - &lo->SubTable[i].st.gpos.chain, - in, out, - flags, context_length, - nesting_level ); - break; - } - - /* Check whether we have a successful positioning or an error other - than TTO_Err_Not_Covered */ - - if ( error != TTO_Err_Not_Covered ) - return error; - } - - return TTO_Err_Not_Covered; - } - - - /* apply one lookup to the input string object */ - - static TT_Error Do_String_Lookup( GPOS_Instance* gpi, - UShort lookup_index, - TTO_GSUB_String* in, - TTO_GPOS_Data* out ) - { - TT_Error error = TTO_Err_Not_Covered; - TTO_GPOSHeader* gpos = gpi->gpos; - - UShort* properties = gpos->LookupList.Properties; - UShort* p_in = in->properties; - - int nesting_level = 0; - - - gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */ - - in->pos = 0; - - while ( in->pos < in->length ) - { - if ( ~p_in[in->pos] & properties[lookup_index] ) - { - /* 0xFFFF indicates that we don't have a context length yet. */ - - /* Note that the connection between mark and base glyphs hold - exactly one (string) lookup. For example, it would be possible - that in the first lookup, mark glyph X is attached to base - glyph A, and in the next lookup it is attached to base glyph B. - It is up to the font designer to provide meaningful lookups and - lookup order. */ - - error = Do_Glyph_Lookup( gpi, lookup_index, in, out, - 0xFFFF, nesting_level ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - else - { - /* Contrary to properties defined in GDEF, user-defined properties - will always stop a possible cursive positioning. */ - gpi->last = 0xFFFF; - - error = TTO_Err_Not_Covered; - } - - if ( error == TTO_Err_Not_Covered ) - (in->pos)++; - } - - return error; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos, - TT_UShort feature_index, - TT_UShort property ) - { - UShort i; - - TTO_Feature feature; - UShort* properties; - UShort* index; - - - if ( !gpos || - feature_index >= gpos->FeatureList.FeatureCount ) - return TT_Err_Invalid_Argument; - - properties = gpos->LookupList.Properties; - - feature = gpos->FeatureList.FeatureRecord[feature_index].Feature; - index = feature.LookupListIndex; - - for ( i = 0; i < feature.LookupListCount; i++ ) - properties[index[i]] |= property; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Clear_Features( TTO_GPOSHeader* gpos ) - { - UShort i; - - UShort* properties; - - - if ( !gpos ) - return TT_Err_Invalid_Argument; - - properties = gpos->LookupList.Properties; - - for ( i = 0; i < gpos->LookupList.LookupCount; i++ ) - properties[i] = 0; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Register_Glyph_Function( TTO_GPOSHeader* gpos, - TTO_GlyphFunction gfunc ) - { - if ( !gpos ) - return TT_Err_Invalid_Argument; - - gpos->gfunc = gfunc; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - TT_Error TT_GPOS_Register_MM_Function( TTO_GPOSHeader* gpos, - TTO_MMFunction mmfunc, - void* data ) - { - if ( !gpos ) - return TT_Err_Invalid_Argument; - - gpos->mmfunc = mmfunc; - gpos->data = data; - - return TT_Err_Ok; - } - - - /* If `dvi' is TRUE, glyph contour points for anchor points and device - tables are ignored -- you will get device independent values. */ - - EXPORT_FUNC - TT_Error TT_GPOS_Apply_String( TT_Instance instance, - TT_Glyph glyph, - TTO_GPOSHeader* gpos, - TT_UShort load_flags, - TTO_GSUB_String* in, - TTO_GPOS_Data** out, - TT_Bool dvi, - TT_Bool r2l ) - { - TT_Error error = TTO_Err_Not_Covered; - GPOS_Instance gpi; - - UShort j; - - UShort* properties; - - - if ( !instance.z || !gpos || - !in || in->length == 0 || in->pos >= in->length ) - return TT_Err_Invalid_Argument; - - properties = gpos->LookupList.Properties; - - gpi.instance = instance; - if ( dvi ) - gpi.glyph.z = NULL; - else - gpi.glyph = glyph; - gpi.gpos = gpos; - gpi.load_flags = load_flags; - gpi.r2l = r2l; - - if ( *out ) - FREE( *out ); - if ( ALLOC_ARRAY( *out, in->length, TTO_GPOS_Data ) ) - return error; - - for ( j = 0; j < gpos->LookupList.LookupCount; j++ ) - if ( !properties || properties[j] ) - { - error = Do_String_Lookup( &gpi, j, in, *out ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - - return error; - } - - -/* END */ |