| Index: third_party/harfbuzz/src/harfbuzz-gpos.c
|
| diff --git a/third_party/harfbuzz/src/harfbuzz-gpos.c b/third_party/harfbuzz/src/harfbuzz-gpos.c
|
| deleted file mode 100644
|
| index 356dc0109992516d901118cb3127b935a9262b09..0000000000000000000000000000000000000000
|
| --- a/third_party/harfbuzz/src/harfbuzz-gpos.c
|
| +++ /dev/null
|
| @@ -1,6055 +0,0 @@
|
| -/*
|
| - * Copyright (C) 1998-2004 David Turner and Werner Lemberg
|
| - * Copyright (C) 2006 Behdad Esfahbod
|
| - * Copyright (C) 2007 Red Hat, Inc.
|
| - *
|
| - * This is part of HarfBuzz, an OpenType Layout engine library.
|
| - *
|
| - * Permission is hereby granted, without written agreement and without
|
| - * license or royalty fees, to use, copy, modify, and distribute this
|
| - * software and its documentation for any purpose, provided that the
|
| - * above copyright notice and the following two paragraphs appear in
|
| - * all copies of this software.
|
| - *
|
| - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
| - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
| - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
| - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
| - * DAMAGE.
|
| - *
|
| - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
| - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
| - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
| - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
| - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
| - *
|
| - * Red Hat Author(s): Behdad Esfahbod
|
| - */
|
| -
|
| -#include "harfbuzz-impl.h"
|
| -#include "harfbuzz-gpos-private.h"
|
| -#include "harfbuzz-open-private.h"
|
| -#include "harfbuzz-gdef-private.h"
|
| -#include "harfbuzz-shaper.h"
|
| -
|
| -struct GPOS_Instance_
|
| -{
|
| - HB_GPOSHeader* gpos;
|
| - HB_Font font;
|
| - HB_Bool dvi;
|
| - HB_UShort load_flags; /* how the glyph should be loaded */
|
| - HB_Bool r2l;
|
| -
|
| - HB_UShort last; /* the last valid glyph -- used
|
| - with cursive positioning */
|
| - HB_Fixed anchor_x; /* the coordinates of the anchor point */
|
| - HB_Fixed anchor_y; /* of the last valid glyph */
|
| -};
|
| -
|
| -typedef struct GPOS_Instance_ GPOS_Instance;
|
| -
|
| -
|
| -static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
|
| - HB_UShort lookup_index,
|
| - HB_Buffer buffer,
|
| - HB_UShort context_length,
|
| - int nesting_level );
|
| -
|
| -
|
| -
|
| -/* the client application must replace this with something more
|
| - meaningful if multiple master fonts are to be supported. */
|
| -
|
| -static HB_Error default_mmfunc( HB_Font font,
|
| - HB_UShort metric_id,
|
| - HB_Fixed* metric_value,
|
| - void* data )
|
| -{
|
| - HB_UNUSED(font);
|
| - HB_UNUSED(metric_id);
|
| - HB_UNUSED(metric_value);
|
| - HB_UNUSED(data);
|
| - return ERR(HB_Err_Not_Covered); /* ERR() call intended */
|
| -}
|
| -
|
| -
|
| -
|
| -HB_Error HB_Load_GPOS_Table( HB_Stream stream,
|
| - HB_GPOSHeader** retptr,
|
| - HB_GDEFHeader* gdef,
|
| - HB_Stream gdefStream )
|
| -{
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_GPOSHeader* gpos;
|
| -
|
| - HB_Error error;
|
| -
|
| -
|
| - if ( !retptr )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - if ( GOTO_Table( TTAG_GPOS ) )
|
| - return error;
|
| -
|
| - base_offset = FILE_Pos();
|
| -
|
| - if ( ALLOC ( gpos, sizeof( *gpos ) ) )
|
| - return error;
|
| -
|
| - gpos->mmfunc = default_mmfunc;
|
| -
|
| - /* skip version */
|
| -
|
| - if ( FILE_Seek( base_offset + 4L ) ||
|
| - ACCESS_Frame( 2L ) )
|
| - goto Fail4;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail4;
|
| - (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 = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
|
| - stream ) ) != HB_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 = _HB_OPEN_Load_LookupList( &gpos->LookupList,
|
| - stream, HB_Type_GPOS ) ) != HB_Err_Ok )
|
| - goto Fail2;
|
| -
|
| - gpos->gdef = gdef; /* can be NULL */
|
| -
|
| - if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
|
| - gpos->LookupList.Lookup,
|
| - gpos->LookupList.LookupCount ) ) )
|
| - goto Fail1;
|
| -
|
| - *retptr = gpos;
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
|
| -
|
| -Fail4:
|
| - FREE( gpos );
|
| -
|
| - return error;
|
| -}
|
| -
|
| -
|
| -HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
|
| -{
|
| - _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
|
| - _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
|
| - _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
|
| -
|
| - FREE( gpos );
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/*****************************
|
| - * 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 HB_Error Load_ValueRecord( HB_ValueRecord* vr,
|
| - HB_UShort format,
|
| - HB_UInt base_offset,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UInt cur_offset, new_offset;
|
| -
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - vr->XPlacement = GET_Short();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->XPlacement = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - vr->YPlacement = GET_Short();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->YPlacement = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - vr->XAdvance = GET_Short();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->XAdvance = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - vr->YAdvance = GET_Short();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->YAdvance = 0;
|
| -
|
| - if ( format & HB_GPOS_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 = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
|
| - stream ) ) != HB_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 & HB_GPOS_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 = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
|
| - stream ) ) != HB_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 & HB_GPOS_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 = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
|
| - stream ) ) != HB_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 & HB_GPOS_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 = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
|
| - stream ) ) != HB_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 & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail1;
|
| -
|
| - vr->XIdPlacement = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->XIdPlacement = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail1;
|
| -
|
| - vr->YIdPlacement = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->YIdPlacement = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail1;
|
| -
|
| - vr->XIdAdvance = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->XIdAdvance = 0;
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail1;
|
| -
|
| - vr->YIdAdvance = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| - }
|
| - else
|
| - vr->YIdAdvance = 0;
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_Device( &vr->YPlacementDevice );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ValueRecord( HB_ValueRecord* vr,
|
| - HB_UShort format )
|
| -{
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
|
| - _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
|
| - _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
|
| - _HB_OPEN_Free_Device( &vr->YPlacementDevice );
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
|
| - _HB_OPEN_Free_Device( &vr->XPlacementDevice );
|
| -}
|
| -
|
| -
|
| -static HB_Error Get_ValueRecord( GPOS_Instance* gpi,
|
| - HB_ValueRecord* vr,
|
| - HB_UShort format,
|
| - HB_Position gd )
|
| -{
|
| - HB_Fixed value;
|
| - HB_Short pixel_value;
|
| - HB_Error error = HB_Err_Ok;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_UShort x_ppem, y_ppem;
|
| - HB_16Dot16 x_scale, y_scale;
|
| -
|
| -
|
| - if ( !format )
|
| - return HB_Err_Ok;
|
| -
|
| - x_ppem = gpi->font->x_ppem;
|
| - y_ppem = gpi->font->y_ppem;
|
| - x_scale = gpi->font->x_scale;
|
| - y_scale = gpi->font->y_scale;
|
| -
|
| - /* design units -> fractional pixel */
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
|
| - gd->x_pos += x_scale * vr->XPlacement / 0x10000;
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
|
| - gd->y_pos += y_scale * vr->YPlacement / 0x10000;
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
|
| - gd->x_advance += x_scale * vr->XAdvance / 0x10000;
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
|
| - gd->y_advance += y_scale * vr->YAdvance / 0x10000;
|
| -
|
| - if ( !gpi->dvi )
|
| - {
|
| - /* pixel -> fractional pixel */
|
| -
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
|
| - {
|
| - _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
|
| - gd->x_pos += pixel_value << 6;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
|
| - {
|
| - _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
|
| - gd->y_pos += pixel_value << 6;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
|
| - {
|
| - _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
|
| - gd->x_advance += pixel_value << 6;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
|
| - {
|
| - _HB_OPEN_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 & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
|
| - {
|
| - error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement,
|
| - &value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| - gd->x_pos += value;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
|
| - {
|
| - error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement,
|
| - &value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| - gd->y_pos += value;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
|
| - {
|
| - error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance,
|
| - &value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| - gd->x_advance += value;
|
| - }
|
| - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
|
| - {
|
| - error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance,
|
| - &value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| - gd->y_advance += value;
|
| - }
|
| -
|
| - return error;
|
| -}
|
| -
|
| -
|
| -/* AnchorFormat1 */
|
| -/* AnchorFormat2 */
|
| -/* AnchorFormat3 */
|
| -/* AnchorFormat4 */
|
| -
|
| -static HB_Error Load_Anchor( HB_Anchor* an,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UInt 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 = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
|
| - stream ) ) != HB_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 = NULL;
|
| - }
|
| -
|
| - 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 = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
|
| - stream ) ) != HB_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 = NULL;
|
| - }
|
| - 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 ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_Anchor( HB_Anchor* an)
|
| -{
|
| - if ( an->PosFormat == 3 )
|
| - {
|
| - _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable );
|
| - _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
|
| - }
|
| -}
|
| -
|
| -
|
| -static HB_Error Get_Anchor( GPOS_Instance* gpi,
|
| - HB_Anchor* an,
|
| - HB_UShort glyph_index,
|
| - HB_Fixed* x_value,
|
| - HB_Fixed* y_value )
|
| -{
|
| - HB_Error error = HB_Err_Ok;
|
| -
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_UShort ap;
|
| -
|
| - HB_Short pixel_value;
|
| -
|
| - HB_UShort x_ppem, y_ppem;
|
| - HB_16Dot16 x_scale, y_scale;
|
| -
|
| -
|
| - x_ppem = gpi->font->x_ppem;
|
| - y_ppem = gpi->font->y_ppem;
|
| - x_scale = gpi->font->x_scale;
|
| - y_scale = gpi->font->y_scale;
|
| -
|
| - switch ( an->PosFormat )
|
| - {
|
| - case 0:
|
| - /* The special case of an empty AnchorTable */
|
| - default:
|
| -
|
| - return HB_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:
|
| - if ( !gpi->dvi )
|
| - {
|
| - hb_uint32 n_points = 0;
|
| - ap = an->af.af2.AnchorPoint;
|
| - if (!gpi->font->klass->getPointInOutline)
|
| - goto no_contour_point;
|
| - error = gpi->font->klass->getPointInOutline(gpi->font, glyph_index, gpi->load_flags, ap, x_value, y_value, &n_points);
|
| - if (error)
|
| - return error;
|
| - /* if n_points is set to zero, we use the design coordinate value pair.
|
| - * This can happen e.g. for sbit glyphs. */
|
| - if (!n_points)
|
| - goto no_contour_point;
|
| - }
|
| - 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:
|
| - if ( !gpi->dvi )
|
| - {
|
| - _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
|
| - *x_value = pixel_value << 6;
|
| - _HB_OPEN_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->font, an->af.af4.XIdAnchor,
|
| - x_value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| -
|
| - error = (gpos->mmfunc)( gpi->font, an->af.af4.YIdAnchor,
|
| - y_value, gpos->data );
|
| - if ( error )
|
| - return error;
|
| - break;
|
| - }
|
| -
|
| - return error;
|
| -}
|
| -
|
| -
|
| -/* MarkArray */
|
| -
|
| -static HB_Error Load_MarkArray ( HB_MarkArray* ma,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_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, stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_Anchor( &mr[m].MarkAnchor );
|
| -
|
| - FREE( mr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_MarkArray( HB_MarkArray* ma )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 */
|
| -
|
| -static HB_Error Load_SinglePos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_SinglePos* sp = &st->single;
|
| -
|
| - HB_UShort n, m, count, format;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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 ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != HB_Err_Ok )
|
| - return error;
|
| - (void)FILE_Seek( cur_offset );
|
| -
|
| - switch ( sp->PosFormat )
|
| - {
|
| - case 1:
|
| - error = Load_ValueRecord( &sp->spf.spf1.Value, format,
|
| - base_offset, stream );
|
| - 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, HB_ValueRecord ) )
|
| - goto Fail2;
|
| -
|
| - vr = sp->spf.spf2.Value;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - {
|
| - error = Load_ValueRecord( &vr[n], format, base_offset, stream );
|
| - if ( error )
|
| - goto Fail1;
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_ValueRecord( &vr[m], format );
|
| -
|
| - FREE( vr );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &sp->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_SinglePos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_UShort n, count, format;
|
| - HB_SinglePos* sp = &st->single;
|
| -
|
| - HB_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;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - _HB_OPEN_Free_Coverage( &sp->Coverage );
|
| -}
|
| -
|
| -static HB_Error Lookup_SinglePos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_SinglePos* sp = &st->single;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 1 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - switch ( sp->PosFormat )
|
| - {
|
| - case 1:
|
| - error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
|
| - sp->ValueFormat, POSITION( buffer->in_pos ) );
|
| - if ( error )
|
| - return error;
|
| - break;
|
| -
|
| - case 2:
|
| - if ( index >= sp->spf.spf2.ValueCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| - error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
|
| - sp->ValueFormat, POSITION( buffer->in_pos ) );
|
| - if ( error )
|
| - return error;
|
| - break;
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| - }
|
| -
|
| - (buffer->in_pos)++;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* LookupType 2 */
|
| -
|
| -/* PairSet */
|
| -
|
| -static HB_Error Load_PairSet ( HB_PairSet* ps,
|
| - HB_UShort format1,
|
| - HB_UShort format2,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt base_offset;
|
| -
|
| - HB_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, HB_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, stream );
|
| - if ( error )
|
| - goto Fail;
|
| - }
|
| - if ( format2 )
|
| - {
|
| - error = Load_ValueRecord( &pvr[n].Value2, format2,
|
| - base_offset, stream );
|
| - if ( error )
|
| - {
|
| - if ( format1 )
|
| - Free_ValueRecord( &pvr[n].Value1, format1 );
|
| - goto Fail;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - {
|
| - if ( format1 )
|
| - Free_ValueRecord( &pvr[m].Value1, format1 );
|
| - if ( format2 )
|
| - Free_ValueRecord( &pvr[m].Value2, format2 );
|
| - }
|
| -
|
| - FREE( pvr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PairSet( HB_PairSet* ps,
|
| - HB_UShort format1,
|
| - HB_UShort format2 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_PairPos1( HB_PairPosFormat1* ppf1,
|
| - HB_UShort format1,
|
| - HB_UShort format2,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_PairSet ) )
|
| - return error;
|
| -
|
| - 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, stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_PairSet( &ps[m], format1, format2 );
|
| -
|
| - FREE( ps );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PairPos1( HB_PairPosFormat1* ppf1,
|
| - HB_UShort format1,
|
| - HB_UShort format2 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
|
| - HB_UShort format1,
|
| - HB_UShort format2,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort m, n, k, count1, count2;
|
| - HB_UInt cur_offset, new_offset1, new_offset2, base_offset;
|
| -
|
| - HB_Class1Record* c1r;
|
| - HB_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 = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
|
| - stream ) ) != HB_Err_Ok )
|
| - return error;
|
| - if ( FILE_Seek( new_offset2 ) ||
|
| - ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail3;
|
| - (void)FILE_Seek( cur_offset );
|
| -
|
| - ppf2->Class1Record = NULL;
|
| -
|
| - if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
|
| - goto Fail2;
|
| -
|
| - c1r = ppf2->Class1Record;
|
| -
|
| - for ( m = 0; m < count1; m++ )
|
| - {
|
| - c1r[m].Class2Record = NULL;
|
| -
|
| - if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
|
| - goto Fail1;
|
| -
|
| - c2r = c1r[m].Class2Record;
|
| -
|
| - for ( n = 0; n < count2; n++ )
|
| - {
|
| - if ( format1 )
|
| - {
|
| - error = Load_ValueRecord( &c2r[n].Value1, format1,
|
| - base_offset, stream );
|
| - if ( error )
|
| - goto Fail0;
|
| - }
|
| - if ( format2 )
|
| - {
|
| - error = Load_ValueRecord( &c2r[n].Value2, format2,
|
| - base_offset, stream );
|
| - if ( error )
|
| - {
|
| - if ( format1 )
|
| - Free_ValueRecord( &c2r[n].Value1, format1 );
|
| - goto Fail0;
|
| - }
|
| - }
|
| - }
|
| -
|
| - continue;
|
| -
|
| - Fail0:
|
| - for ( k = 0; k < n; k++ )
|
| - {
|
| - if ( format1 )
|
| - Free_ValueRecord( &c2r[k].Value1, format1 );
|
| - if ( format2 )
|
| - Free_ValueRecord( &c2r[k].Value2, format2 );
|
| - }
|
| - goto Fail1;
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( k = 0; k < m; k++ )
|
| - {
|
| - c2r = c1r[k].Class2Record;
|
| -
|
| - for ( n = 0; n < count2; n++ )
|
| - {
|
| - if ( format1 )
|
| - Free_ValueRecord( &c2r[n].Value1, format1 );
|
| - if ( format2 )
|
| - Free_ValueRecord( &c2r[n].Value2, format2 );
|
| - }
|
| -
|
| - FREE( c2r );
|
| - }
|
| -
|
| - FREE( c1r );
|
| -Fail2:
|
| -
|
| - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PairPos2( HB_PairPosFormat2* ppf2,
|
| - HB_UShort format1,
|
| - HB_UShort format2)
|
| -{
|
| - HB_UShort m, n, count1, count2;
|
| -
|
| - HB_Class1Record* c1r;
|
| - HB_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 );
|
| -
|
| - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
|
| - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
|
| - }
|
| -}
|
| -
|
| -
|
| -static HB_Error Load_PairPos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_PairPos* pp = &st->pair;
|
| -
|
| - HB_UShort format1, format2;
|
| - HB_UInt 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 = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != HB_Err_Ok )
|
| - return error;
|
| - (void)FILE_Seek( cur_offset );
|
| -
|
| - switch ( pp->PosFormat )
|
| - {
|
| - case 1:
|
| - error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
|
| - if ( error )
|
| - goto Fail;
|
| - break;
|
| -
|
| - case 2:
|
| - error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
|
| - if ( error )
|
| - goto Fail;
|
| - break;
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - _HB_OPEN_Free_Coverage( &pp->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PairPos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_UShort format1, format2;
|
| - HB_PairPos* pp = &st->pair;
|
| -
|
| -
|
| - 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;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - _HB_OPEN_Free_Coverage( &pp->Coverage );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_PairPos1( GPOS_Instance* gpi,
|
| - HB_PairPosFormat1* ppf1,
|
| - HB_Buffer buffer,
|
| - HB_UInt first_pos,
|
| - HB_UShort index,
|
| - HB_UShort format1,
|
| - HB_UShort format2 )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort numpvr, glyph2;
|
| -
|
| - HB_PairValueRecord* pvr;
|
| -
|
| -
|
| - if ( index >= ppf1->PairSetCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - pvr = ppf1->PairSet[index].PairValueRecord;
|
| - if ( !pvr )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - glyph2 = IN_CURGLYPH();
|
| -
|
| - for ( numpvr = ppf1->PairSet[index].PairValueCount;
|
| - numpvr;
|
| - numpvr--, pvr++ )
|
| - {
|
| - if ( glyph2 == pvr->SecondGlyph )
|
| - {
|
| - error = Get_ValueRecord( gpi, &pvr->Value1, format1,
|
| - POSITION( first_pos ) );
|
| - if ( error )
|
| - return error;
|
| - return Get_ValueRecord( gpi, &pvr->Value2, format2,
|
| - POSITION( buffer->in_pos ) );
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
|
| - HB_PairPosFormat2* ppf2,
|
| - HB_Buffer buffer,
|
| - HB_UInt first_pos,
|
| - HB_UShort format1,
|
| - HB_UShort format2 )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort cl1 = 0, cl2 = 0; /* shut compiler up */
|
| -
|
| - HB_Class1Record* c1r;
|
| - HB_Class2Record* c2r;
|
| -
|
| -
|
| - error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
|
| - &cl1, NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| - error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
|
| - &cl2, NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - c1r = &ppf2->Class1Record[cl1];
|
| - if ( !c1r )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| - c2r = &c1r->Class2Record[cl2];
|
| -
|
| - error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
|
| - if ( error )
|
| - return error;
|
| - return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort index, property;
|
| - HB_UInt first_pos;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_PairPos* pp = &st->pair;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( buffer->in_pos >= buffer->in_length - 1 )
|
| - return HB_Err_Not_Covered; /* Not enough glyphs in stream */
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 2 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* second glyph */
|
| -
|
| - first_pos = buffer->in_pos;
|
| - (buffer->in_pos)++;
|
| -
|
| - while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
| - flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( buffer->in_pos == buffer->in_length )
|
| - {
|
| - buffer->in_pos = first_pos;
|
| - return HB_Err_Not_Covered;
|
| - }
|
| - (buffer->in_pos)++;
|
| -
|
| - }
|
| -
|
| - switch ( pp->PosFormat )
|
| - {
|
| - case 1:
|
| - error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
|
| - first_pos, index,
|
| - pp->ValueFormat1, pp->ValueFormat2 );
|
| - break;
|
| -
|
| - case 2:
|
| - error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
|
| - pp->ValueFormat1, pp->ValueFormat2 );
|
| - break;
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - /* if we don't have coverage for the second glyph don't skip it for
|
| - further lookups but reset in_pos back to the first_glyph and let
|
| - the caller in Do_String_Lookup increment in_pos */
|
| - if ( error == HB_Err_Not_Covered )
|
| - buffer->in_pos = first_pos;
|
| -
|
| - /* adjusting the `next' glyph */
|
| -
|
| - if ( pp->ValueFormat2 )
|
| - (buffer->in_pos)++;
|
| -
|
| - return error;
|
| -}
|
| -
|
| -
|
| -/* LookupType 3 */
|
| -
|
| -/* CursivePosFormat1 */
|
| -
|
| -static HB_Error Load_CursivePos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_CursivePos* cp = &st->cursive;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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 = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != HB_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, HB_EntryExitRecord ) )
|
| - goto Fail2;
|
| -
|
| - eer = cp->EntryExitRecord;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - {
|
| - HB_UInt entry_offset;
|
| -
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - entry_offset = 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,
|
| - stream ) ) != HB_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,
|
| - stream ) ) != HB_Err_Ok )
|
| - {
|
| - if ( entry_offset )
|
| - Free_Anchor( &eer[n].EntryAnchor );
|
| - goto Fail1;
|
| - }
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| - else
|
| - eer[n].ExitAnchor.PosFormat = 0;
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; m++ )
|
| - {
|
| - Free_Anchor( &eer[m].EntryAnchor );
|
| - Free_Anchor( &eer[m].ExitAnchor );
|
| - }
|
| -
|
| - FREE( eer );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &cp->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_CursivePos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_UShort n, count;
|
| - HB_CursivePos* cp = &st->cursive;
|
| -
|
| - HB_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 );
|
| - }
|
| -
|
| - _HB_OPEN_Free_Coverage( &cp->Coverage );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_CursivePos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_CursivePos* cp = &st->cursive;
|
| -
|
| - HB_EntryExitRecord* eer;
|
| - HB_Fixed entry_x, entry_y;
|
| - HB_Fixed exit_x, exit_y;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 1 )
|
| - {
|
| - gpi->last = 0xFFFF;
|
| - return HB_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_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - /* We don't handle mark glyphs here. According to Andrei, this isn't
|
| - possible, but who knows... */
|
| -
|
| - if ( property == HB_GDEF_MARK )
|
| - {
|
| - gpi->last = 0xFFFF;
|
| - return HB_Err_Not_Covered;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
|
| - if ( error )
|
| - {
|
| - gpi->last = 0xFFFF;
|
| - return error;
|
| - }
|
| -
|
| - if ( index >= cp->EntryExitCount )
|
| - return ERR(HB_Err_Invalid_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 HB_Err_Not_Covered if there is no anchor
|
| - table. */
|
| -
|
| - error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
|
| - &entry_x, &entry_y );
|
| - if ( error == HB_Err_Not_Covered )
|
| - goto end;
|
| - if ( error )
|
| - return error;
|
| -
|
| - if ( gpi->r2l )
|
| - {
|
| - POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
|
| - POSITION( buffer->in_pos )->new_advance = TRUE;
|
| - }
|
| - else
|
| - {
|
| - POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
|
| - POSITION( gpi->last )->new_advance = TRUE;
|
| - }
|
| -
|
| - if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
|
| - {
|
| - POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
|
| - POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
|
| - }
|
| - else
|
| - {
|
| - POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
|
| - POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
|
| - }
|
| -
|
| -end:
|
| - error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
|
| - &exit_x, &exit_y );
|
| - if ( error == HB_Err_Not_Covered )
|
| - gpi->last = 0xFFFF;
|
| - else
|
| - {
|
| - gpi->last = buffer->in_pos;
|
| - gpi->anchor_x = exit_x;
|
| - gpi->anchor_y = exit_y;
|
| - }
|
| - if ( error )
|
| - return error;
|
| -
|
| - (buffer->in_pos)++;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* LookupType 4 */
|
| -
|
| -/* BaseArray */
|
| -
|
| -static HB_Error Load_BaseArray( HB_BaseArray* ba,
|
| - HB_UShort num_classes,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort m, n, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_BaseRecord *br;
|
| - HB_Anchor *ban, *bans;
|
| -
|
| -
|
| - 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, HB_BaseRecord ) )
|
| - return error;
|
| -
|
| - br = ba->BaseRecord;
|
| -
|
| - bans = NULL;
|
| -
|
| - if ( ALLOC_ARRAY( bans, count * num_classes, HB_Anchor ) )
|
| - goto Fail;
|
| -
|
| - for ( m = 0; m < count; m++ )
|
| - {
|
| - br[m].BaseAnchor = NULL;
|
| -
|
| - ban = br[m].BaseAnchor = bans + m * num_classes;
|
| -
|
| - for ( n = 0; n < num_classes; n++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - if (new_offset == base_offset) {
|
| - /* XXX
|
| - * Doulos SIL Regular is buggy and has zero offsets here.
|
| - * Skip it
|
| - */
|
| - ban[n].PosFormat = 0;
|
| - continue;
|
| - }
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = Load_Anchor( &ban[n], stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - FREE( bans );
|
| - FREE( br );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_BaseArray( HB_BaseArray* ba,
|
| - HB_UShort num_classes )
|
| -{
|
| - HB_BaseRecord *br;
|
| - HB_Anchor *bans;
|
| -
|
| - if ( ba->BaseRecord )
|
| - {
|
| - br = ba->BaseRecord;
|
| -
|
| - if ( ba->BaseCount )
|
| - {
|
| - HB_UShort i, count;
|
| - count = num_classes * ba->BaseCount;
|
| - bans = br[0].BaseAnchor;
|
| - for (i = 0; i < count; i++)
|
| - Free_Anchor (&bans[i]);
|
| - FREE( bans );
|
| - }
|
| -
|
| - FREE( br );
|
| - }
|
| -}
|
| -
|
| -
|
| -/* MarkBasePosFormat1 */
|
| -
|
| -static HB_Error Load_MarkBasePos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_MarkBasePos* mbp = &st->markbase;
|
| -
|
| - HB_UInt 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();
|
| -
|
| - if (mbp->PosFormat != 1)
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != HB_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 = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != HB_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, stream ) ) != HB_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,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail1;
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - Free_MarkArray( &mbp->MarkArray );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_MarkBasePos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_MarkBasePos* mbp = &st->markbase;
|
| -
|
| - Free_BaseArray( &mbp->BaseArray, mbp->ClassCount );
|
| - Free_MarkArray( &mbp->MarkArray );
|
| - _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
|
| - _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort i, j, mark_index, base_index, property, class;
|
| - HB_Fixed x_mark_value, y_mark_value, x_base_value, y_base_value;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_MarkBasePos* mbp = &st->markbase;
|
| -
|
| - HB_MarkArray* ma;
|
| - HB_BaseArray* ba;
|
| - HB_BaseRecord* br;
|
| - HB_Anchor* mark_anchor;
|
| - HB_Anchor* base_anchor;
|
| -
|
| - HB_Position o;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 1 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
| - flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
|
| - &mark_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* now we search backwards for a non-mark glyph */
|
| -
|
| - i = 1;
|
| - j = buffer->in_pos - 1;
|
| -
|
| - while ( i <= buffer->in_pos )
|
| - {
|
| - error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
| - &property );
|
| - if ( error )
|
| - return error;
|
| -
|
| - if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
| - break;
|
| -
|
| - i++;
|
| - j--;
|
| - }
|
| -
|
| - /* The following assertion is too strong -- at least for mangal.ttf. */
|
| -#if 0
|
| - if ( property != HB_GDEF_BASE_GLYPH )
|
| - return HB_Err_Not_Covered;
|
| -#endif
|
| -
|
| - if ( i > buffer->in_pos )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
|
| - &base_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - ma = &mbp->MarkArray;
|
| -
|
| - if ( mark_index >= ma->MarkCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - class = ma->MarkRecord[mark_index].Class;
|
| - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
|
| -
|
| - if ( class >= mbp->ClassCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - ba = &mbp->BaseArray;
|
| -
|
| - if ( base_index >= ba->BaseCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - br = &ba->BaseRecord[base_index];
|
| - base_anchor = &br->BaseAnchor[class];
|
| -
|
| - error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
|
| - &x_mark_value, &y_mark_value );
|
| - if ( error )
|
| - return error;
|
| -
|
| - error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
|
| - &x_base_value, &y_base_value );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* anchor points are not cumulative */
|
| -
|
| - o = POSITION( buffer->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;
|
| -
|
| - (buffer->in_pos)++;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* LookupType 5 */
|
| -
|
| -/* LigatureAttach */
|
| -
|
| -static HB_Error Load_LigatureAttach( HB_LigatureAttach* lat,
|
| - HB_UShort num_classes,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort m, n, k, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_ComponentRecord* cr;
|
| - HB_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, HB_ComponentRecord ) )
|
| - return error;
|
| -
|
| - cr = lat->ComponentRecord;
|
| -
|
| - for ( m = 0; m < count; m++ )
|
| - {
|
| - cr[m].LigatureAnchor = NULL;
|
| -
|
| - if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
|
| - goto Fail;
|
| -
|
| - lan = cr[m].LigatureAnchor;
|
| -
|
| - for ( n = 0; n < num_classes; n++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail0;
|
| -
|
| - 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], stream ) ) != HB_Err_Ok )
|
| - goto Fail0;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| - else
|
| - lan[n].PosFormat = 0;
|
| - }
|
| -
|
| - continue;
|
| - Fail0:
|
| - for ( k = 0; k < n; k++ )
|
| - Free_Anchor( &lan[k] );
|
| - goto Fail;
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( k = 0; k < m; k++ )
|
| - {
|
| - lan = cr[k].LigatureAnchor;
|
| -
|
| - for ( n = 0; n < num_classes; n++ )
|
| - Free_Anchor( &lan[n] );
|
| -
|
| - FREE( lan );
|
| - }
|
| -
|
| - FREE( cr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_LigatureAttach( HB_LigatureAttach* lat,
|
| - HB_UShort num_classes )
|
| -{
|
| - HB_UShort m, n, count;
|
| -
|
| - HB_ComponentRecord* cr;
|
| - HB_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 HB_Error Load_LigatureArray( HB_LigatureArray* la,
|
| - HB_UShort num_classes,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_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,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_LigatureAttach( &lat[m], num_classes );
|
| -
|
| - FREE( lat );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_LigatureArray( HB_LigatureArray* la,
|
| - HB_UShort num_classes )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 */
|
| -
|
| -static HB_Error Load_MarkLigPos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_MarkLigPos* mlp = &st->marklig;
|
| -
|
| - HB_UInt 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 = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != HB_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 = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
|
| - stream ) ) != HB_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, stream ) ) != HB_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,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail1;
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - Free_MarkArray( &mlp->MarkArray );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_MarkLigPos( HB_GPOS_SubTable* st)
|
| -{
|
| - HB_MarkLigPos* mlp = &st->marklig;
|
| -
|
| - Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount );
|
| - Free_MarkArray( &mlp->MarkArray );
|
| - _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
|
| - _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort i, j, mark_index, lig_index, property, class;
|
| - HB_UShort mark_glyph;
|
| - HB_Fixed x_mark_value, y_mark_value, x_lig_value, y_lig_value;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_MarkLigPos* mlp = &st->marklig;
|
| -
|
| - HB_MarkArray* ma;
|
| - HB_LigatureArray* la;
|
| - HB_LigatureAttach* lat;
|
| - HB_ComponentRecord* cr;
|
| - HB_UShort comp_index;
|
| - HB_Anchor* mark_anchor;
|
| - HB_Anchor* lig_anchor;
|
| -
|
| - HB_Position o;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 1 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - mark_glyph = IN_CURGLYPH();
|
| -
|
| - if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* now we search backwards for a non-mark glyph */
|
| -
|
| - i = 1;
|
| - j = buffer->in_pos - 1;
|
| -
|
| - while ( i <= buffer->in_pos )
|
| - {
|
| - error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
| - &property );
|
| - if ( error )
|
| - return error;
|
| -
|
| - if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
| - break;
|
| -
|
| - i++;
|
| - j--;
|
| - }
|
| -
|
| - /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
|
| - too strong, thus it is commented out. */
|
| -#if 0
|
| - if ( property != HB_GDEF_LIGATURE )
|
| - return HB_Err_Not_Covered;
|
| -#endif
|
| -
|
| - if ( i > buffer->in_pos )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
|
| - &lig_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - ma = &mlp->MarkArray;
|
| -
|
| - if ( mark_index >= ma->MarkCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - class = ma->MarkRecord[mark_index].Class;
|
| - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
|
| -
|
| - if ( class >= mlp->ClassCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - la = &mlp->LigatureArray;
|
| -
|
| - if ( lig_index >= la->LigatureCount )
|
| - return ERR(HB_Err_Invalid_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_LIGID( j ) == IN_LIGID( buffer->in_pos) )
|
| - {
|
| - comp_index = IN_COMPONENT( buffer->in_pos );
|
| - if ( comp_index >= lat->ComponentCount )
|
| - return HB_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_CURGLYPH(),
|
| - &x_mark_value, &y_mark_value );
|
| - if ( error )
|
| - return error;
|
| - error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
|
| - &x_lig_value, &y_lig_value );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* anchor points are not cumulative */
|
| -
|
| - o = POSITION( buffer->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;
|
| -
|
| - (buffer->in_pos)++;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* LookupType 6 */
|
| -
|
| -/* Mark2Array */
|
| -
|
| -static HB_Error Load_Mark2Array( HB_Mark2Array* m2a,
|
| - HB_UShort num_classes,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort m, n, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_Mark2Record *m2r;
|
| - HB_Anchor *m2an, *m2ans;
|
| -
|
| -
|
| - 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, HB_Mark2Record ) )
|
| - return error;
|
| -
|
| - m2r = m2a->Mark2Record;
|
| -
|
| - m2ans = NULL;
|
| -
|
| - if ( ALLOC_ARRAY( m2ans, count * num_classes, HB_Anchor ) )
|
| - goto Fail;
|
| -
|
| - for ( m = 0; m < count; m++ )
|
| - {
|
| - m2an = m2r[m].Mark2Anchor = m2ans + m * num_classes;
|
| -
|
| - for ( n = 0; n < num_classes; n++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - if (new_offset == base_offset) {
|
| - /* Anchor table not provided. Skip loading.
|
| - * Some versions of FreeSans hit this. */
|
| - m2an[n].PosFormat = 0;
|
| - continue;
|
| - }
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = Load_Anchor( &m2an[n], stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - FREE( m2ans );
|
| - FREE( m2r );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_Mark2Array( HB_Mark2Array* m2a,
|
| - HB_UShort num_classes )
|
| -{
|
| - HB_Mark2Record *m2r;
|
| - HB_Anchor *m2ans;
|
| -
|
| - HB_UNUSED(num_classes);
|
| -
|
| - if ( m2a->Mark2Record )
|
| - {
|
| - m2r = m2a->Mark2Record;
|
| -
|
| - if ( m2a->Mark2Count )
|
| - {
|
| - m2ans = m2r[0].Mark2Anchor;
|
| - FREE( m2ans );
|
| - }
|
| -
|
| - FREE( m2r );
|
| - }
|
| -}
|
| -
|
| -
|
| -/* MarkMarkPosFormat1 */
|
| -
|
| -static HB_Error Load_MarkMarkPos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_MarkMarkPos* mmp = &st->markmark;
|
| -
|
| - HB_UInt 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 = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
|
| - stream ) ) != HB_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 = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
|
| - stream ) ) != HB_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, stream ) ) != HB_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,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail1;
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - Free_MarkArray( &mmp->Mark1Array );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_MarkMarkPos( HB_GPOS_SubTable* st)
|
| -{
|
| - HB_MarkMarkPos* mmp = &st->markmark;
|
| -
|
| - Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount );
|
| - Free_MarkArray( &mmp->Mark1Array );
|
| - _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
|
| - _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort i, j, mark1_index, mark2_index, property, class;
|
| - HB_Fixed x_mark1_value, y_mark1_value,
|
| - x_mark2_value, y_mark2_value;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_MarkMarkPos* mmp = &st->markmark;
|
| -
|
| - HB_MarkArray* ma1;
|
| - HB_Mark2Array* ma2;
|
| - HB_Mark2Record* m2r;
|
| - HB_Anchor* mark1_anchor;
|
| - HB_Anchor* mark2_anchor;
|
| -
|
| - HB_Position o;
|
| -
|
| - HB_UNUSED(nesting_level);
|
| -
|
| - if ( context_length != 0xFFFF && context_length < 1 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
| - flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
|
| - &mark1_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* now we search backwards for a suitable mark glyph until a non-mark
|
| - glyph */
|
| -
|
| - if ( buffer->in_pos == 0 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - i = 1;
|
| - j = buffer->in_pos - 1;
|
| - while ( i <= buffer->in_pos )
|
| - {
|
| - error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
| - &property );
|
| - if ( error )
|
| - return error;
|
| -
|
| - if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
|
| - {
|
| - if ( property == (flags & 0xFF00) )
|
| - break;
|
| - }
|
| - else
|
| - break;
|
| -
|
| - i++;
|
| - j--;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
|
| - &mark2_index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - ma1 = &mmp->Mark1Array;
|
| -
|
| - if ( mark1_index >= ma1->MarkCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - class = ma1->MarkRecord[mark1_index].Class;
|
| - mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
|
| -
|
| - if ( class >= mmp->ClassCount )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - ma2 = &mmp->Mark2Array;
|
| -
|
| - if ( mark2_index >= ma2->Mark2Count )
|
| - return ERR(HB_Err_Invalid_SubTable);
|
| -
|
| - m2r = &ma2->Mark2Record[mark2_index];
|
| - mark2_anchor = &m2r->Mark2Anchor[class];
|
| -
|
| - error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
|
| - &x_mark1_value, &y_mark1_value );
|
| - if ( error )
|
| - return error;
|
| - error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
|
| - &x_mark2_value, &y_mark2_value );
|
| - if ( error )
|
| - return error;
|
| -
|
| - /* anchor points are not cumulative */
|
| -
|
| - o = POSITION( buffer->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;
|
| -
|
| - (buffer->in_pos)++;
|
| -
|
| - return HB_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 stream
|
| - matches the subrule. */
|
| -
|
| -static HB_Error Do_ContextPos( GPOS_Instance* gpi,
|
| - HB_UShort GlyphCount,
|
| - HB_UShort PosCount,
|
| - HB_PosLookupRecord* pos,
|
| - HB_Buffer buffer,
|
| - int nesting_level )
|
| -{
|
| - HB_Error error;
|
| - HB_UInt i, old_pos;
|
| -
|
| -
|
| - i = 0;
|
| -
|
| - while ( i < GlyphCount )
|
| - {
|
| - if ( PosCount && i == pos->SequenceIndex )
|
| - {
|
| - old_pos = buffer->in_pos;
|
| -
|
| - /* Do a positioning */
|
| -
|
| - error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
|
| - GlyphCount, nesting_level );
|
| -
|
| - if ( error )
|
| - return error;
|
| -
|
| - pos++;
|
| - PosCount--;
|
| - i += buffer->in_pos - old_pos;
|
| - }
|
| - else
|
| - {
|
| - i++;
|
| - (buffer->in_pos)++;
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* LookupType 7 */
|
| -
|
| -/* PosRule */
|
| -
|
| -static HB_Error Load_PosRule( HB_PosRule* pr,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, count;
|
| - HB_UShort* i;
|
| -
|
| - HB_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, HB_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, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - FREE( i );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PosRule( HB_PosRule* pr )
|
| -{
|
| - FREE( pr->PosLookupRecord );
|
| - FREE( pr->Input );
|
| -}
|
| -
|
| -
|
| -/* PosRuleSet */
|
| -
|
| -static HB_Error Load_PosRuleSet( HB_PosRuleSet* prs,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_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], stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_PosRule( &pr[m] );
|
| -
|
| - FREE( pr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PosRuleSet( HB_PosRuleSet* prs )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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 = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != HB_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, HB_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], stream ) ) != HB_Err_Ok )
|
| - goto Fail1;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_PosRuleSet( &prs[m] );
|
| -
|
| - FREE( prs );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &cpf1->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ContextPos1( HB_ContextPosFormat1* cpf1 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_PosRuleSet* prs;
|
| -
|
| -
|
| - if ( cpf1->PosRuleSet )
|
| - {
|
| - count = cpf1->PosRuleSetCount;
|
| - prs = cpf1->PosRuleSet;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - Free_PosRuleSet( &prs[n] );
|
| -
|
| - FREE( prs );
|
| - }
|
| -
|
| - _HB_OPEN_Free_Coverage( &cpf1->Coverage );
|
| -}
|
| -
|
| -
|
| -/* PosClassRule */
|
| -
|
| -static HB_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2,
|
| - HB_PosClassRule* pcr,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, count;
|
| -
|
| - HB_UShort* c;
|
| - HB_PosLookupRecord* plr;
|
| -
|
| -
|
| - 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, HB_UShort ) )
|
| - return error;
|
| -
|
| - c = pcr->Class;
|
| -
|
| - if ( ACCESS_Frame( count * 2L ) )
|
| - goto Fail2;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - c[n] = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| -
|
| - pcr->PosLookupRecord = NULL;
|
| -
|
| - count = pcr->PosCount;
|
| -
|
| - if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - FREE( c );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PosClassRule( HB_PosClassRule* pcr )
|
| -{
|
| - FREE( pcr->PosLookupRecord );
|
| - FREE( pcr->Class );
|
| -}
|
| -
|
| -
|
| -/* PosClassSet */
|
| -
|
| -static HB_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2,
|
| - HB_PosClassSet* pcs,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_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],
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_PosClassRule( &pcr[m] );
|
| -
|
| - FREE( pcr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_PosClassSet( HB_PosClassSet* pcs )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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 = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != HB_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 = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail3;
|
| - (void)FILE_Seek( cur_offset );
|
| -
|
| - cpf2->PosClassSet = NULL;
|
| - cpf2->MaxContextLength = 0;
|
| -
|
| - if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_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],
|
| - stream ) ) != HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; n++ )
|
| - Free_PosClassSet( &pcs[m] );
|
| -
|
| - FREE( pcs );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_Coverage( &cpf2->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ContextPos2( HB_ContextPosFormat2* cpf2 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_PosClassSet* pcs;
|
| -
|
| -
|
| - if ( cpf2->PosClassSet )
|
| - {
|
| - count = cpf2->PosClassSetCount;
|
| - pcs = cpf2->PosClassSet;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - Free_PosClassSet( &pcs[n] );
|
| -
|
| - FREE( pcs );
|
| - }
|
| -
|
| - _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
|
| - _HB_OPEN_Free_Coverage( &cpf2->Coverage );
|
| -}
|
| -
|
| -
|
| -/* ContextPosFormat3 */
|
| -
|
| -static HB_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_Coverage* c;
|
| - HB_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, HB_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 = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
|
| - goto Fail2;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - cpf3->PosLookupRecord = NULL;
|
| -
|
| - count = cpf3->PosCount;
|
| -
|
| - if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - for ( n = 0; n < count; n++ )
|
| - _HB_OPEN_Free_Coverage( &c[n] );
|
| -
|
| - FREE( c );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ContextPos3( HB_ContextPosFormat3* cpf3 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_Coverage* c;
|
| -
|
| -
|
| - FREE( cpf3->PosLookupRecord );
|
| -
|
| - if ( cpf3->Coverage )
|
| - {
|
| - count = cpf3->GlyphCount;
|
| - c = cpf3->Coverage;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - _HB_OPEN_Free_Coverage( &c[n] );
|
| -
|
| - FREE( c );
|
| - }
|
| -}
|
| -
|
| -
|
| -/* ContextPos */
|
| -
|
| -static HB_Error Load_ContextPos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_ContextPos* cp = &st->context;
|
| -
|
| -
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - cp->PosFormat = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| -
|
| - switch ( cp->PosFormat )
|
| - {
|
| - case 1:
|
| - return Load_ContextPos1( &cp->cpf.cpf1, stream );
|
| -
|
| - case 2:
|
| - return Load_ContextPos2( &cp->cpf.cpf2, stream );
|
| -
|
| - case 3:
|
| - return Load_ContextPos3( &cp->cpf.cpf3, stream );
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok; /* never reached */
|
| -}
|
| -
|
| -
|
| -static void Free_ContextPos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_ContextPos* cp = &st->context;
|
| -
|
| - switch ( cp->PosFormat )
|
| - {
|
| - case 1: Free_ContextPos1( &cp->cpf.cpf1 ); break;
|
| - case 2: Free_ContextPos2( &cp->cpf.cpf2 ); break;
|
| - case 3: Free_ContextPos3( &cp->cpf.cpf3 ); break;
|
| - default: break;
|
| - }
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi,
|
| - HB_ContextPosFormat1* cpf1,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_UShort i, j, k, numpr;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_PosRule* pr;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &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 )
|
| - goto next_posrule;
|
| -
|
| - if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
|
| - goto next_posrule; /* context is too long */
|
| -
|
| - for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + pr[k].GlyphCount - i == (HB_Int)buffer->in_length )
|
| - goto next_posrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
|
| - goto next_posrule;
|
| - }
|
| -
|
| - return Do_ContextPos( gpi, pr[k].GlyphCount,
|
| - pr[k].PosCount, pr[k].PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| -
|
| - next_posrule:
|
| - ;
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,
|
| - HB_ContextPosFormat2* cpf2,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_Error error;
|
| - HB_UShort i, j, k, known_classes;
|
| -
|
| - HB_UShort* classes;
|
| - HB_UShort* cl;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_PosClassSet* pcs;
|
| - HB_PosClassRule* pr;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), 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 = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - if (cpf2->MaxContextLength < 1)
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
|
| - &classes[0], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End;
|
| - known_classes = 0;
|
| -
|
| - pcs = &cpf2->PosClassSet[classes[0]];
|
| - if ( !pcs )
|
| - {
|
| - error = ERR(HB_Err_Invalid_SubTable);
|
| - goto End;
|
| - }
|
| -
|
| - for ( k = 0; k < pcs->PosClassRuleCount; k++ )
|
| - {
|
| - pr = &pcs->PosClassRule[k];
|
| -
|
| - if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
|
| - goto next_posclassrule;
|
| -
|
| - if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
|
| - goto next_posclassrule; /* context is too long */
|
| -
|
| - cl = pr->Class;
|
| -
|
| - /* Start at 1 because [0] is implied */
|
| -
|
| - for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End;
|
| -
|
| - if ( j + pr->GlyphCount - i == (HB_Int)buffer->in_length )
|
| - goto next_posclassrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( i > known_classes )
|
| - {
|
| - /* Keeps us from having to do this for each rule */
|
| -
|
| - error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End;
|
| - known_classes = i;
|
| - }
|
| -
|
| - if ( cl[i - 1] != classes[i] )
|
| - goto next_posclassrule;
|
| - }
|
| -
|
| - error = Do_ContextPos( gpi, pr->GlyphCount,
|
| - pr->PosCount, pr->PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| - goto End;
|
| -
|
| - next_posclassrule:
|
| - ;
|
| - }
|
| -
|
| - error = HB_Err_Not_Covered;
|
| -
|
| -End:
|
| - FREE( classes );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,
|
| - HB_ContextPosFormat3* cpf3,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort index, i, j, property;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_Coverage* c;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
|
| - return HB_Err_Not_Covered; /* context is too long */
|
| -
|
| - c = cpf3->Coverage;
|
| -
|
| - for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + cpf3->GlyphCount - i == (HB_Int)buffer->in_length )
|
| - return HB_Err_Not_Covered;
|
| - j++;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
|
| - if ( error )
|
| - return error;
|
| - }
|
| -
|
| - return Do_ContextPos( gpi, cpf3->GlyphCount,
|
| - cpf3->PosCount, cpf3->PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ContextPos( GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_ContextPos* cp = &st->context;
|
| -
|
| - switch ( cp->PosFormat )
|
| - {
|
| - case 1:
|
| - return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
|
| - flags, context_length, nesting_level );
|
| -
|
| - case 2:
|
| - return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
|
| - flags, context_length, nesting_level );
|
| -
|
| - case 3:
|
| - return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
|
| - flags, context_length, nesting_level );
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok; /* never reached */
|
| -}
|
| -
|
| -
|
| -/* LookupType 8 */
|
| -
|
| -/* ChainPosRule */
|
| -
|
| -static HB_Error Load_ChainPosRule( HB_ChainPosRule* cpr,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, count;
|
| - HB_UShort* b;
|
| - HB_UShort* i;
|
| - HB_UShort* l;
|
| -
|
| - HB_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, HB_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, HB_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, HB_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, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - FREE( l );
|
| -
|
| -Fail3:
|
| - FREE( i );
|
| -
|
| -Fail4:
|
| - FREE( b );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainPosRule( HB_ChainPosRule* cpr )
|
| -{
|
| - FREE( cpr->PosLookupRecord );
|
| - FREE( cpr->Lookahead );
|
| - FREE( cpr->Input );
|
| - FREE( cpr->Backtrack );
|
| -}
|
| -
|
| -
|
| -/* ChainPosRuleSet */
|
| -
|
| -static HB_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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, HB_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], stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_ChainPosRule( &cpr[m] );
|
| -
|
| - FREE( cpr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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 = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != HB_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, HB_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], stream ) ) != HB_Err_Ok )
|
| - goto Fail1;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_ChainPosRuleSet( &cprs[m] );
|
| -
|
| - FREE( cprs );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_ChainPosRuleSet* cprs;
|
| -
|
| -
|
| - if ( ccpf1->ChainPosRuleSet )
|
| - {
|
| - count = ccpf1->ChainPosRuleSetCount;
|
| - cprs = ccpf1->ChainPosRuleSet;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - Free_ChainPosRuleSet( &cprs[n] );
|
| -
|
| - FREE( cprs );
|
| - }
|
| -
|
| - _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
|
| -}
|
| -
|
| -
|
| -/* ChainPosClassRule */
|
| -
|
| -static HB_Error Load_ChainPosClassRule(
|
| - HB_ChainContextPosFormat2* ccpf2,
|
| - HB_ChainPosClassRule* cpcr,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, count;
|
| -
|
| - HB_UShort* b;
|
| - HB_UShort* i;
|
| - HB_UShort* l;
|
| - HB_PosLookupRecord* plr;
|
| -
|
| -
|
| - 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, HB_UShort ) )
|
| - return error;
|
| -
|
| - b = cpcr->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;
|
| -
|
| - 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, HB_UShort ) )
|
| - goto Fail4;
|
| -
|
| - i = cpcr->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;
|
| -
|
| - 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, HB_UShort ) )
|
| - goto Fail3;
|
| -
|
| - l = cpcr->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;
|
| -
|
| - cpcr->PosCount = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| -
|
| - cpcr->PosLookupRecord = NULL;
|
| -
|
| - count = cpcr->PosCount;
|
| -
|
| - if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - FREE( l );
|
| -
|
| -Fail3:
|
| - FREE( i );
|
| -
|
| -Fail4:
|
| - FREE( b );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr )
|
| -{
|
| - FREE( cpcr->PosLookupRecord );
|
| - FREE( cpcr->Lookahead );
|
| - FREE( cpcr->Input );
|
| - FREE( cpcr->Backtrack );
|
| -}
|
| -
|
| -
|
| -/* PosClassSet */
|
| -
|
| -static HB_Error Load_ChainPosClassSet(
|
| - HB_ChainContextPosFormat2* ccpf2,
|
| - HB_ChainPosClassSet* cpcs,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_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,
|
| - HB_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],
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail;
|
| - (void)FILE_Seek( cur_offset );
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -
|
| -Fail:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_ChainPosClassRule( &cpcr[m] );
|
| -
|
| - FREE( cpcr );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_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 HB_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, m, count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| - HB_UInt backtrack_offset, input_offset, lookahead_offset;
|
| -
|
| - HB_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 = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != HB_Err_Ok )
|
| - return error;
|
| - (void)FILE_Seek( cur_offset );
|
| -
|
| - if ( ACCESS_Frame( 8L ) )
|
| - goto Fail5;
|
| -
|
| - backtrack_offset = GET_UShort();
|
| - input_offset = GET_UShort();
|
| - lookahead_offset = GET_UShort();
|
| -
|
| - /* `ChainPosClassSetCount' is the upper limit for input class values,
|
| - thus we read it now to make an additional safety check. No limit
|
| - is known or needed for the other two class definitions */
|
| -
|
| - count = ccpf2->ChainPosClassSetCount = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| -
|
| - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
|
| - backtrack_offset, base_offset,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail5;
|
| - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
|
| - input_offset, base_offset,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail4;
|
| - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
|
| - lookahead_offset, base_offset,
|
| - stream ) ) != HB_Err_Ok )
|
| - goto Fail3;
|
| -
|
| - ccpf2->ChainPosClassSet = NULL;
|
| - ccpf2->MaxBacktrackLength = 0;
|
| - ccpf2->MaxInputLength = 0;
|
| - ccpf2->MaxLookaheadLength = 0;
|
| -
|
| - if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_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],
|
| - stream ) ) != HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - for ( m = 0; m < n; m++ )
|
| - Free_ChainPosClassSet( &cpcs[m] );
|
| -
|
| - FREE( cpcs );
|
| -
|
| -Fail2:
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
|
| -
|
| -Fail3:
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
|
| -
|
| -Fail4:
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
|
| -
|
| -Fail5:
|
| - _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_ChainPosClassSet* cpcs;
|
| -
|
| -
|
| - if ( ccpf2->ChainPosClassSet )
|
| - {
|
| - count = ccpf2->ChainPosClassSetCount;
|
| - cpcs = ccpf2->ChainPosClassSet;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - Free_ChainPosClassSet( &cpcs[n] );
|
| -
|
| - FREE( cpcs );
|
| - }
|
| -
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
|
| - _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
|
| -
|
| - _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
|
| -}
|
| -
|
| -
|
| -/* ChainContextPosFormat3 */
|
| -
|
| -static HB_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| -
|
| - HB_UShort n, nb, ni, nl, m, count;
|
| - HB_UShort backtrack_count, input_count, lookahead_count;
|
| - HB_UInt cur_offset, new_offset, base_offset;
|
| -
|
| - HB_Coverage* b;
|
| - HB_Coverage* i;
|
| - HB_Coverage* l;
|
| - HB_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,
|
| - HB_Coverage ) )
|
| - return error;
|
| -
|
| - b = ccpf3->BacktrackCoverage;
|
| -
|
| - for ( nb = 0; nb < backtrack_count; nb++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail4;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_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, HB_Coverage ) )
|
| - goto Fail4;
|
| -
|
| - i = ccpf3->InputCoverage;
|
| -
|
| - for ( ni = 0; ni < input_count; ni++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail3;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_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,
|
| - HB_Coverage ) )
|
| - goto Fail3;
|
| -
|
| - l = ccpf3->LookaheadCoverage;
|
| -
|
| - for ( nl = 0; nl < lookahead_count; nl++ )
|
| - {
|
| - if ( ACCESS_Frame( 2L ) )
|
| - goto Fail2;
|
| -
|
| - new_offset = GET_UShort() + base_offset;
|
| -
|
| - FORGET_Frame();
|
| -
|
| - cur_offset = FILE_Pos();
|
| - if ( FILE_Seek( new_offset ) ||
|
| - ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_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, HB_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 HB_Err_Ok;
|
| -
|
| -Fail1:
|
| - FREE( plr );
|
| -
|
| -Fail2:
|
| - for ( m = 0; m < nl; m++ )
|
| - _HB_OPEN_Free_Coverage( &l[m] );
|
| -
|
| - FREE( l );
|
| -
|
| -Fail3:
|
| - for ( m = 0; m < ni; m++ )
|
| - _HB_OPEN_Free_Coverage( &i[m] );
|
| -
|
| - FREE( i );
|
| -
|
| -Fail4:
|
| - for ( m = 0; m < nb; m++ )
|
| - _HB_OPEN_Free_Coverage( &b[m] );
|
| -
|
| - FREE( b );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3 )
|
| -{
|
| - HB_UShort n, count;
|
| -
|
| - HB_Coverage* c;
|
| -
|
| -
|
| - FREE( ccpf3->PosLookupRecord );
|
| -
|
| - if ( ccpf3->LookaheadCoverage )
|
| - {
|
| - count = ccpf3->LookaheadGlyphCount;
|
| - c = ccpf3->LookaheadCoverage;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - _HB_OPEN_Free_Coverage( &c[n] );
|
| -
|
| - FREE( c );
|
| - }
|
| -
|
| - if ( ccpf3->InputCoverage )
|
| - {
|
| - count = ccpf3->InputGlyphCount;
|
| - c = ccpf3->InputCoverage;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - _HB_OPEN_Free_Coverage( &c[n] );
|
| -
|
| - FREE( c );
|
| - }
|
| -
|
| - if ( ccpf3->BacktrackCoverage )
|
| - {
|
| - count = ccpf3->BacktrackGlyphCount;
|
| - c = ccpf3->BacktrackCoverage;
|
| -
|
| - for ( n = 0; n < count; n++ )
|
| - _HB_OPEN_Free_Coverage( &c[n] );
|
| -
|
| - FREE( c );
|
| - }
|
| -}
|
| -
|
| -
|
| -/* ChainContextPos */
|
| -
|
| -static HB_Error Load_ChainContextPos( HB_GPOS_SubTable* st,
|
| - HB_Stream stream )
|
| -{
|
| - HB_Error error;
|
| - HB_ChainContextPos* ccp = &st->chain;
|
| -
|
| -
|
| - if ( ACCESS_Frame( 2L ) )
|
| - return error;
|
| -
|
| - ccp->PosFormat = GET_UShort();
|
| -
|
| - FORGET_Frame();
|
| -
|
| - switch ( ccp->PosFormat )
|
| - {
|
| - case 1:
|
| - return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
|
| -
|
| - case 2:
|
| - return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
|
| -
|
| - case 3:
|
| - return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok; /* never reached */
|
| -}
|
| -
|
| -
|
| -static void Free_ChainContextPos( HB_GPOS_SubTable* st )
|
| -{
|
| - HB_ChainContextPos* ccp = &st->chain;
|
| -
|
| - switch ( ccp->PosFormat )
|
| - {
|
| - case 1: Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break;
|
| - case 2: Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break;
|
| - case 3: Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break;
|
| - default: break;
|
| - }
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ChainContextPos1(
|
| - GPOS_Instance* gpi,
|
| - HB_ChainContextPosFormat1* ccpf1,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_UShort i, j, k, num_cpr;
|
| - HB_UShort bgc, igc, lgc;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_ChainPosRule* cpr;
|
| - HB_ChainPosRule curr_cpr;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &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 )
|
| - goto next_chainposrule;
|
| -
|
| - /* check whether context is too long; it is a first guess only */
|
| -
|
| - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
|
| - goto next_chainposrule;
|
| -
|
| - 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 */
|
| -
|
| - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + 1 == bgc - i )
|
| - goto next_chainposrule;
|
| - j--;
|
| - }
|
| -
|
| - /* In OpenType 1.3, it is undefined whether the offsets of
|
| - backtrack glyphs is in logical order or not. Version 1.4
|
| - will clarify this:
|
| -
|
| - Logical order - a b c d e f g h i j
|
| - i
|
| - Input offsets - 0 1
|
| - Backtrack offsets - 3 2 1 0
|
| - Lookahead offsets - 0 1 2 3 */
|
| -
|
| - if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
|
| - goto next_chainposrule;
|
| - }
|
| - }
|
| -
|
| - /* Start at 1 because [0] is implied */
|
| -
|
| - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
|
| - goto next_chainposrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
|
| - goto next_chainposrule;
|
| - }
|
| -
|
| - /* we are starting to check for lookahead glyphs right after the
|
| - last context glyph */
|
| -
|
| - for ( i = 0; i < lgc; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + lgc - i == (HB_Int)buffer->in_length )
|
| - goto next_chainposrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
|
| - goto next_chainposrule;
|
| - }
|
| -
|
| - return Do_ContextPos( gpi, igc,
|
| - curr_cpr.PosCount,
|
| - curr_cpr.PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| -
|
| - next_chainposrule:
|
| - ;
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ChainContextPos2(
|
| - GPOS_Instance* gpi,
|
| - HB_ChainContextPosFormat2* ccpf2,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, property;
|
| - HB_Error error;
|
| - HB_UShort i, j, k;
|
| - HB_UShort bgc, igc, lgc;
|
| - HB_UShort known_backtrack_classes,
|
| - known_input_classes,
|
| - known_lookahead_classes;
|
| -
|
| - HB_UShort* backtrack_classes;
|
| - HB_UShort* input_classes;
|
| - HB_UShort* lookahead_classes;
|
| -
|
| - HB_UShort* bc;
|
| - HB_UShort* ic;
|
| - HB_UShort* lc;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_ChainPosClassSet* cpcs;
|
| - HB_ChainPosClassRule cpcr;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), 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 = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
|
| - if ( error )
|
| - return error;
|
| -
|
| - if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, HB_UShort ) )
|
| - return error;
|
| - known_backtrack_classes = 0;
|
| -
|
| - if (ccpf2->MaxInputLength < 1)
|
| - return HB_Err_Not_Covered;
|
| -
|
| - if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) )
|
| - goto End3;
|
| - known_input_classes = 1;
|
| -
|
| - if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, HB_UShort ) )
|
| - goto End2;
|
| - known_lookahead_classes = 0;
|
| -
|
| - error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
|
| - &input_classes[0], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| -
|
| - cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
|
| - if ( !cpcs )
|
| - {
|
| - error = ERR(HB_Err_Invalid_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 )
|
| - goto next_chainposclassrule;
|
| -
|
| - /* check whether context is too long; it is a first guess only */
|
| -
|
| - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
|
| - goto next_chainposclassrule;
|
| -
|
| - 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. */
|
| -
|
| - bc = cpcr.Backtrack;
|
| -
|
| - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| -
|
| - if ( j + 1 == bgc - i )
|
| - goto next_chainposclassrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( i >= known_backtrack_classes )
|
| - {
|
| - /* Keeps us from having to do this for each rule */
|
| -
|
| - error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
|
| - &backtrack_classes[i], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| - known_backtrack_classes = i;
|
| - }
|
| -
|
| - if ( bc[i] != backtrack_classes[i] )
|
| - goto next_chainposclassrule;
|
| - }
|
| - }
|
| -
|
| - ic = cpcr.Input;
|
| -
|
| - /* Start at 1 because [0] is implied */
|
| -
|
| - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| -
|
| - if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
|
| - goto next_chainposclassrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( i >= known_input_classes )
|
| - {
|
| - error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
|
| - &input_classes[i], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| - known_input_classes = i;
|
| - }
|
| -
|
| - if ( ic[i - 1] != input_classes[i] )
|
| - goto next_chainposclassrule;
|
| - }
|
| -
|
| - /* we are starting to check for lookahead glyphs right after the
|
| - last context glyph */
|
| -
|
| - lc = cpcr.Lookahead;
|
| -
|
| - for ( i = 0; i < lgc; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| -
|
| - if ( j + lgc - i == (HB_Int)buffer->in_length )
|
| - goto next_chainposclassrule;
|
| - j++;
|
| - }
|
| -
|
| - if ( i >= known_lookahead_classes )
|
| - {
|
| - error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
|
| - &lookahead_classes[i], NULL );
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - goto End1;
|
| - known_lookahead_classes = i;
|
| - }
|
| -
|
| - if ( lc[i] != lookahead_classes[i] )
|
| - goto next_chainposclassrule;
|
| - }
|
| -
|
| - error = Do_ContextPos( gpi, igc,
|
| - cpcr.PosCount,
|
| - cpcr.PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| - goto End1;
|
| -
|
| - next_chainposclassrule:
|
| - ;
|
| - }
|
| -
|
| - error = HB_Err_Not_Covered;
|
| -
|
| -End1:
|
| - FREE( lookahead_classes );
|
| -
|
| -End2:
|
| - FREE( input_classes );
|
| -
|
| -End3:
|
| - FREE( backtrack_classes );
|
| - return error;
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ChainContextPos3(
|
| - GPOS_Instance* gpi,
|
| - HB_ChainContextPosFormat3* ccpf3,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_UShort index, i, j, property;
|
| - HB_UShort bgc, igc, lgc;
|
| - HB_Error error;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_Coverage* bc;
|
| - HB_Coverage* ic;
|
| - HB_Coverage* lc;
|
| - HB_GDEFHeader* gdef;
|
| -
|
| -
|
| - gdef = gpos->gdef;
|
| -
|
| - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
| - return error;
|
| -
|
| - bgc = ccpf3->BacktrackGlyphCount;
|
| - igc = ccpf3->InputGlyphCount;
|
| - lgc = ccpf3->LookaheadGlyphCount;
|
| -
|
| - if ( context_length != 0xFFFF && context_length < igc )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - /* check whether context is too long; it is a first guess only */
|
| -
|
| - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
|
| - return HB_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 */
|
| -
|
| - bc = ccpf3->BacktrackCoverage;
|
| -
|
| - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + 1 == bgc - i )
|
| - return HB_Err_Not_Covered;
|
| - j--;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
|
| - if ( error )
|
| - return error;
|
| - }
|
| - }
|
| -
|
| - ic = ccpf3->InputCoverage;
|
| -
|
| - for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
|
| - {
|
| - /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
|
| - while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
|
| - return HB_Err_Not_Covered;
|
| - j++;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
|
| - if ( error )
|
| - return error;
|
| - }
|
| -
|
| - /* we are starting to check for lookahead glyphs right after the
|
| - last context glyph */
|
| -
|
| - lc = ccpf3->LookaheadCoverage;
|
| -
|
| - for ( i = 0; i < lgc; i++, j++ )
|
| - {
|
| - while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
| - {
|
| - if ( error && error != HB_Err_Not_Covered )
|
| - return error;
|
| -
|
| - if ( j + lgc - i == (HB_Int)buffer->in_length )
|
| - return HB_Err_Not_Covered;
|
| - j++;
|
| - }
|
| -
|
| - error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
|
| - if ( error )
|
| - return error;
|
| - }
|
| -
|
| - return Do_ContextPos( gpi, igc,
|
| - ccpf3->PosCount,
|
| - ccpf3->PosLookupRecord,
|
| - buffer,
|
| - nesting_level );
|
| -}
|
| -
|
| -
|
| -static HB_Error Lookup_ChainContextPos(
|
| - GPOS_Instance* gpi,
|
| - HB_GPOS_SubTable* st,
|
| - HB_Buffer buffer,
|
| - HB_UShort flags,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_ChainContextPos* ccp = &st->chain;
|
| -
|
| - switch ( ccp->PosFormat )
|
| - {
|
| - case 1:
|
| - return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
|
| - flags, context_length,
|
| - nesting_level );
|
| -
|
| - case 2:
|
| - return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
|
| - flags, context_length,
|
| - nesting_level );
|
| -
|
| - case 3:
|
| - return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
|
| - flags, context_length,
|
| - nesting_level );
|
| -
|
| - default:
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -
|
| - return HB_Err_Ok; /* never reached */
|
| -}
|
| -
|
| -
|
| -
|
| -/***********
|
| - * GPOS API
|
| - ***********/
|
| -
|
| -
|
| -
|
| -HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
|
| - HB_UInt script_tag,
|
| - HB_UShort* script_index )
|
| -{
|
| - HB_UShort n;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| -
|
| -
|
| - if ( !gpos || !script_index )
|
| - return ERR(HB_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 HB_Err_Ok;
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -
|
| -HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
|
| - HB_UInt language_tag,
|
| - HB_UShort script_index,
|
| - HB_UShort* language_index,
|
| - HB_UShort* req_feature_index )
|
| -{
|
| - HB_UShort n;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| - HB_ScriptTable* s;
|
| - HB_LangSysRecord* lsr;
|
| -
|
| -
|
| - if ( !gpos || !language_index || !req_feature_index )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - sl = &gpos->ScriptList;
|
| - sr = sl->ScriptRecord;
|
| -
|
| - if ( script_index >= sl->ScriptCount )
|
| - return ERR(HB_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 HB_Err_Ok;
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -/* selecting 0xFFFF for language_index asks for the values of the
|
| - default language (DefaultLangSys) */
|
| -
|
| -
|
| -HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
|
| - HB_UInt feature_tag,
|
| - HB_UShort script_index,
|
| - HB_UShort language_index,
|
| - HB_UShort* feature_index )
|
| -{
|
| - HB_UShort n;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| - HB_ScriptTable* s;
|
| - HB_LangSysRecord* lsr;
|
| - HB_LangSys* ls;
|
| - HB_UShort* fi;
|
| -
|
| - HB_FeatureList* fl;
|
| - HB_FeatureRecord* fr;
|
| -
|
| -
|
| - if ( !gpos || !feature_index )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - sl = &gpos->ScriptList;
|
| - sr = sl->ScriptRecord;
|
| -
|
| - fl = &gpos->FeatureList;
|
| - fr = fl->FeatureRecord;
|
| -
|
| - if ( script_index >= sl->ScriptCount )
|
| - return ERR(HB_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 ERR(HB_Err_Invalid_Argument);
|
| -
|
| - ls = &lsr[language_index].LangSys;
|
| - }
|
| -
|
| - fi = ls->FeatureIndex;
|
| -
|
| - for ( n = 0; n < ls->FeatureCount; n++ )
|
| - {
|
| - if ( fi[n] >= fl->FeatureCount )
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| -
|
| - if ( feature_tag == fr[fi[n]].FeatureTag )
|
| - {
|
| - *feature_index = fi[n];
|
| -
|
| - return HB_Err_Ok;
|
| - }
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -/* The next three functions return a null-terminated list */
|
| -
|
| -
|
| -HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
|
| - HB_UInt** script_tag_list )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort n;
|
| - HB_UInt* stl;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| -
|
| -
|
| - if ( !gpos || !script_tag_list )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - sl = &gpos->ScriptList;
|
| - sr = sl->ScriptRecord;
|
| -
|
| - if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
|
| - return error;
|
| -
|
| - for ( n = 0; n < sl->ScriptCount; n++ )
|
| - stl[n] = sr[n].ScriptTag;
|
| - stl[n] = 0;
|
| -
|
| - *script_tag_list = stl;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -
|
| -HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
|
| - HB_UShort script_index,
|
| - HB_UInt** language_tag_list )
|
| -{
|
| - HB_Error error;
|
| - HB_UShort n;
|
| - HB_UInt* ltl;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| - HB_ScriptTable* s;
|
| - HB_LangSysRecord* lsr;
|
| -
|
| -
|
| - if ( !gpos || !language_tag_list )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - sl = &gpos->ScriptList;
|
| - sr = sl->ScriptRecord;
|
| -
|
| - if ( script_index >= sl->ScriptCount )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - s = &sr[script_index].Script;
|
| - lsr = s->LangSysRecord;
|
| -
|
| - if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
|
| - return error;
|
| -
|
| - for ( n = 0; n < s->LangSysCount; n++ )
|
| - ltl[n] = lsr[n].LangSysTag;
|
| - ltl[n] = 0;
|
| -
|
| - *language_tag_list = ltl;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* selecting 0xFFFF for language_index asks for the values of the
|
| - default language (DefaultLangSys) */
|
| -
|
| -
|
| -HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
|
| - HB_UShort script_index,
|
| - HB_UShort language_index,
|
| - HB_UInt** feature_tag_list )
|
| -{
|
| - HB_UShort n;
|
| - HB_Error error;
|
| - HB_UInt* ftl;
|
| -
|
| - HB_ScriptList* sl;
|
| - HB_ScriptRecord* sr;
|
| - HB_ScriptTable* s;
|
| - HB_LangSysRecord* lsr;
|
| - HB_LangSys* ls;
|
| - HB_UShort* fi;
|
| -
|
| - HB_FeatureList* fl;
|
| - HB_FeatureRecord* fr;
|
| -
|
| -
|
| - if ( !gpos || !feature_tag_list )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - sl = &gpos->ScriptList;
|
| - sr = sl->ScriptRecord;
|
| -
|
| - fl = &gpos->FeatureList;
|
| - fr = fl->FeatureRecord;
|
| -
|
| - if ( script_index >= sl->ScriptCount )
|
| - return ERR(HB_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 ERR(HB_Err_Invalid_Argument);
|
| -
|
| - ls = &lsr[language_index].LangSys;
|
| - }
|
| -
|
| - fi = ls->FeatureIndex;
|
| -
|
| - if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
|
| - return error;
|
| -
|
| - for ( n = 0; n < ls->FeatureCount; n++ )
|
| - {
|
| - if ( fi[n] >= fl->FeatureCount )
|
| - {
|
| - FREE( ftl );
|
| - return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| - ftl[n] = fr[fi[n]].FeatureTag;
|
| - }
|
| - ftl[n] = 0;
|
| -
|
| - *feature_tag_list = ftl;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -/* Do an individual subtable lookup. Returns HB_Err_Ok if positioning
|
| - has been done, or HB_Err_Not_Covered if not. */
|
| -static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
|
| - HB_UShort lookup_index,
|
| - HB_Buffer buffer,
|
| - HB_UShort context_length,
|
| - int nesting_level )
|
| -{
|
| - HB_Error error = HB_Err_Not_Covered;
|
| - HB_UShort i, flags, lookup_count;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| - HB_Lookup* lo;
|
| - int lookup_type;
|
| -
|
| -
|
| - nesting_level++;
|
| -
|
| - if ( nesting_level > HB_MAX_NESTING_LEVEL )
|
| - return ERR(HB_Err_Not_Covered); /* ERR() call intended */
|
| -
|
| - lookup_count = gpos->LookupList.LookupCount;
|
| - if (lookup_index >= lookup_count)
|
| - return error;
|
| -
|
| - lo = &gpos->LookupList.Lookup[lookup_index];
|
| - flags = lo->LookupFlag;
|
| - lookup_type = lo->LookupType;
|
| -
|
| - for ( i = 0; i < lo->SubTableCount; i++ )
|
| - {
|
| - HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos;
|
| -
|
| - switch (lookup_type) {
|
| - case HB_GPOS_LOOKUP_SINGLE:
|
| - error = Lookup_SinglePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_PAIR:
|
| - error = Lookup_PairPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_CURSIVE:
|
| - error = Lookup_CursivePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_MARKBASE:
|
| - error = Lookup_MarkBasePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_MARKLIG:
|
| - error = Lookup_MarkLigPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_MARKMARK:
|
| - error = Lookup_MarkMarkPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_CONTEXT:
|
| - error = Lookup_ContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - case HB_GPOS_LOOKUP_CHAIN:
|
| - error = Lookup_ChainContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
|
| - /*case HB_GPOS_LOOKUP_EXTENSION:
|
| - error = Lookup_ExtensionPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;*/
|
| - default:
|
| - error = HB_Err_Not_Covered;
|
| - }
|
| -
|
| - /* Check whether we have a successful positioning or an error other
|
| - than HB_Err_Not_Covered */
|
| - if ( error != HB_Err_Not_Covered )
|
| - return error;
|
| - }
|
| -
|
| - return HB_Err_Not_Covered;
|
| -}
|
| -
|
| -
|
| -HB_INTERNAL HB_Error
|
| -_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
|
| - HB_Stream stream,
|
| - HB_UShort lookup_type )
|
| -{
|
| - switch ( lookup_type ) {
|
| - case HB_GPOS_LOOKUP_SINGLE: return Load_SinglePos ( st, stream );
|
| - case HB_GPOS_LOOKUP_PAIR: return Load_PairPos ( st, stream );
|
| - case HB_GPOS_LOOKUP_CURSIVE: return Load_CursivePos ( st, stream );
|
| - case HB_GPOS_LOOKUP_MARKBASE: return Load_MarkBasePos ( st, stream );
|
| - case HB_GPOS_LOOKUP_MARKLIG: return Load_MarkLigPos ( st, stream );
|
| - case HB_GPOS_LOOKUP_MARKMARK: return Load_MarkMarkPos ( st, stream );
|
| - case HB_GPOS_LOOKUP_CONTEXT: return Load_ContextPos ( st, stream );
|
| - case HB_GPOS_LOOKUP_CHAIN: return Load_ChainContextPos ( st, stream );
|
| - /*case HB_GPOS_LOOKUP_EXTENSION: return Load_ExtensionPos ( st, stream );*/
|
| - default: return ERR(HB_Err_Invalid_SubTable_Format);
|
| - }
|
| -}
|
| -
|
| -
|
| -HB_INTERNAL void
|
| -_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
|
| - HB_UShort lookup_type )
|
| -{
|
| - switch ( lookup_type ) {
|
| - case HB_GPOS_LOOKUP_SINGLE: Free_SinglePos ( st ); return;
|
| - case HB_GPOS_LOOKUP_PAIR: Free_PairPos ( st ); return;
|
| - case HB_GPOS_LOOKUP_CURSIVE: Free_CursivePos ( st ); return;
|
| - case HB_GPOS_LOOKUP_MARKBASE: Free_MarkBasePos ( st ); return;
|
| - case HB_GPOS_LOOKUP_MARKLIG: Free_MarkLigPos ( st ); return;
|
| - case HB_GPOS_LOOKUP_MARKMARK: Free_MarkMarkPos ( st ); return;
|
| - case HB_GPOS_LOOKUP_CONTEXT: Free_ContextPos ( st ); return;
|
| - case HB_GPOS_LOOKUP_CHAIN: Free_ChainContextPos ( st ); return;
|
| - /*case HB_GPOS_LOOKUP_EXTENSION: Free_ExtensionPos ( st ); return;*/
|
| - default: return;
|
| - }
|
| -}
|
| -
|
| -
|
| -/* apply one lookup to the input string object */
|
| -
|
| -static HB_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi,
|
| - HB_UShort lookup_index,
|
| - HB_Buffer buffer )
|
| -{
|
| - HB_Error error, retError = HB_Err_Not_Covered;
|
| - HB_GPOSHeader* gpos = gpi->gpos;
|
| -
|
| - HB_UInt* properties = gpos->LookupList.Properties;
|
| -
|
| - const int nesting_level = 0;
|
| - /* 0xFFFF indicates that we don't have a context length yet */
|
| - const HB_UShort context_length = 0xFFFF;
|
| -
|
| -
|
| - gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
|
| -
|
| - buffer->in_pos = 0;
|
| - while ( buffer->in_pos < buffer->in_length )
|
| - {
|
| - if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
|
| - {
|
| - /* 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 = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level );
|
| - if ( error && error != HB_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 = HB_Err_Not_Covered;
|
| - }
|
| -
|
| - if ( error == HB_Err_Not_Covered )
|
| - (buffer->in_pos)++;
|
| - else
|
| - retError = error;
|
| - }
|
| -
|
| - return retError;
|
| -}
|
| -
|
| -
|
| -static HB_Error Position_CursiveChain ( HB_Buffer buffer )
|
| -{
|
| - HB_UInt i, j;
|
| - HB_Position positions = buffer->positions;
|
| -
|
| - /* First handle all left-to-right connections */
|
| - for (j = 0; j < buffer->in_length; j++)
|
| - {
|
| - if (positions[j].cursive_chain > 0)
|
| - positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
|
| - }
|
| -
|
| - /* Then handle all right-to-left connections */
|
| - for (i = buffer->in_length; i > 0; i--)
|
| - {
|
| - j = i - 1;
|
| -
|
| - if (positions[j].cursive_chain < 0)
|
| - positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
|
| - HB_UShort feature_index,
|
| - HB_UInt property )
|
| -{
|
| - HB_UShort i;
|
| -
|
| - HB_Feature feature;
|
| - HB_UInt* properties;
|
| - HB_UShort* index;
|
| - HB_UShort lookup_count;
|
| -
|
| - /* Each feature can only be added once */
|
| -
|
| - if ( !gpos ||
|
| - feature_index >= gpos->FeatureList.FeatureCount ||
|
| - gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
|
| -
|
| - properties = gpos->LookupList.Properties;
|
| -
|
| - feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
|
| - index = feature.LookupListIndex;
|
| - lookup_count = gpos->LookupList.LookupCount;
|
| -
|
| - for ( i = 0; i < feature.LookupListCount; i++ )
|
| - {
|
| - HB_UShort lookup_index = index[i];
|
| - if (lookup_index < lookup_count)
|
| - properties[lookup_index] |= property;
|
| - }
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -
|
| -HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos )
|
| -{
|
| - HB_UShort i;
|
| -
|
| - HB_UInt* properties;
|
| -
|
| -
|
| - if ( !gpos )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - gpos->FeatureList.ApplyCount = 0;
|
| -
|
| - properties = gpos->LookupList.Properties;
|
| -
|
| - for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
|
| - properties[i] = 0;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -
|
| -
|
| -HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
|
| - HB_MMFunction mmfunc,
|
| - void* data )
|
| -{
|
| - if ( !gpos )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - gpos->mmfunc = mmfunc;
|
| - gpos->data = data;
|
| -
|
| - return HB_Err_Ok;
|
| -}
|
| -
|
| -/* If `dvi' is TRUE, glyph contour points for anchor points and device
|
| - tables are ignored -- you will get device independent values. */
|
| -
|
| -
|
| -HB_Error HB_GPOS_Apply_String( HB_Font font,
|
| - HB_GPOSHeader* gpos,
|
| - HB_UShort load_flags,
|
| - HB_Buffer buffer,
|
| - HB_Bool dvi,
|
| - HB_Bool r2l )
|
| -{
|
| - HB_Error error, retError = HB_Err_Not_Covered;
|
| - GPOS_Instance gpi;
|
| - int i, j, lookup_count, num_features;
|
| -
|
| - if ( !font || !gpos || !buffer )
|
| - return ERR(HB_Err_Invalid_Argument);
|
| -
|
| - if ( buffer->in_length == 0 )
|
| - return HB_Err_Not_Covered;
|
| -
|
| - gpi.font = font;
|
| - gpi.gpos = gpos;
|
| - gpi.load_flags = load_flags;
|
| - gpi.r2l = r2l;
|
| - gpi.dvi = dvi;
|
| -
|
| - lookup_count = gpos->LookupList.LookupCount;
|
| - num_features = gpos->FeatureList.ApplyCount;
|
| -
|
| - if ( num_features )
|
| - {
|
| - error = _hb_buffer_clear_positions( buffer );
|
| - if ( error )
|
| - return error;
|
| - }
|
| -
|
| - for ( i = 0; i < num_features; i++ )
|
| - {
|
| - HB_UShort feature_index = gpos->FeatureList.ApplyOrder[i];
|
| - HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
|
| -
|
| - for ( j = 0; j < feature.LookupListCount; j++ )
|
| - {
|
| - HB_UShort lookup_index = feature.LookupListIndex[j];
|
| -
|
| - /* Skip nonexistant lookups */
|
| - if (lookup_index >= lookup_count)
|
| - continue;
|
| -
|
| - error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
|
| - if ( error )
|
| - {
|
| - if ( error != HB_Err_Not_Covered )
|
| - return error;
|
| - }
|
| - else
|
| - retError = error;
|
| - }
|
| - }
|
| -
|
| - if ( num_features )
|
| - {
|
| - error = Position_CursiveChain ( buffer );
|
| - if ( error )
|
| - return error;
|
| - }
|
| -
|
| - return retError;
|
| -}
|
| -
|
| -/* END */
|
|
|