static FT_Error Load_LigGlyph( HB_LigGlyph* lg, FT_Stream stream ) { FT_Memory memory = stream->memory; FT_Error error; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_CaretValue* cv; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = lg->CaretCount = GET_UShort(); FORGET_Frame(); lg->CaretValue = NULL; if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) ) return error; cv = lg->CaretValue; 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_CaretValue( &cv[n], stream ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok; Fail: for ( m = 0; m < n; m++ ) Free_CaretValue( &cv[m], memory ); FREE( cv ); return error; }
FT_LOCAL FT_Error TT_Init_Face( FT_Stream stream, TT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Library library; SFNT_Interface* sfnt; library = face->root.driver->root.library; sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) goto Bad_Format; /* create input stream from resource */ if ( FILE_Seek( 0 ) ) goto Exit; /* check that we have a valid TrueType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; /* We must also be able to accept Mac/GX fonts, as well as OT ones */ if ( face->format_tag != 0x00010000L && /* MS fonts */ face->format_tag != TTAG_true ) /* Mac fonts */ { FT_TRACE2(( "[not a valid TTF font]\n" )); goto Bad_Format; } /* If we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return TT_Err_Ok; /* Load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE ) error = TT_Load_Locations( face, stream ) || TT_Load_CVT ( face, stream ) || TT_Load_Programs ( face, stream ); /* initialize standard glyph loading routines */ TT_Init_Glyph_Loading( face ); Exit: return error; Bad_Format: error = FT_Err_Unknown_File_Format; goto Exit; }
static FT_Error fnt_font_load( FNT_Font* font, FT_Stream stream ) { FT_Error error; WinFNT_Header* header = &font->header; /* first of all, read the FNT header */ if ( FILE_Seek( font->offset ) || READ_Fields( winfnt_header_fields, header ) ) goto Exit; /* check header */ if ( header->version != 0x200 && header->version != 0x300 ) { FT_TRACE2(( "[not a valid FNT file]\n" )); error = FNT_Err_Unknown_File_Format; goto Exit; } if ( header->file_type & 1 ) { FT_TRACE2(( "[can't handle vector FNT fonts]\n" )); error = FNT_Err_Unknown_File_Format; goto Exit; } /* small fixup -- some fonts have the `pixel_width' field set to 0 */ if ( header->pixel_width == 0 ) header->pixel_width = header->pixel_height; /* this is a FNT file/table, we now extract its frame */ if ( FILE_Seek( font->offset ) || EXTRACT_Frame( header->file_size, font->fnt_frame ) ) goto Exit; Exit: return error; }
EXPORT_FUNC TT_Error TT_Load_Kerning_Table( TT_Face face, TT_UShort kern_index ) { TT_Error error; TT_Stream stream; TT_Kerning* kern; TT_Kern_Subtable* sub; PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; error = TT_Extension_Get( faze, KERNING_ID, (void**)&kern ); if ( error ) return error; if ( kern->nTables == 0 ) return TT_Err_Table_Missing; if ( kern_index >= kern->nTables ) return TT_Err_Invalid_Argument; sub = kern->tables + kern_index; if ( sub->format != 0 && sub->format != 2 ) return TT_Err_Invalid_Kerning_Table_Format; /* now access stream */ if ( USE_Stream( faze->stream, stream ) ) return error; if ( FILE_Seek( sub->offset ) ) goto Fail; if ( sub->format == 0 ) error = Subtable_Load_0( &sub->t.kern0, faze ); else if ( sub->format == 2 ) error = Subtable_Load_2( &sub->t.kern2, faze ); if ( !error ) sub->loaded = TRUE; Fail: /* release stream */ DONE_Stream( stream ); return error; }
static FT_Error GDEF_Create( void* ext, PFace face ) { DEFINE_LOAD_LOCALS( face->stream ); HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext; Long table; /* by convention */ if ( !gdef ) return FT_Err_Ok; /* a null offset indicates that there is no GDEF table */ gdef->offset = 0; /* we store the start offset and the size of the subtable */ table = HB_LookUp_Table( face, TTAG_GDEF ); if ( table < 0 ) return FT_Err_Ok; /* The table is optional */ if ( FILE_Seek( face->dirTables[table].Offset ) || ACCESS_Frame( 4L ) ) return error; gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ gdef->Version = GET_ULong(); FORGET_Frame(); gdef->loaded = FALSE; return FT_Err_Ok; }
static FT_Error Load_CaretValue( HB_CaretValue* cv, FT_Stream stream ) { FT_Error error; FT_ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; cv->CaretValueFormat = GET_UShort(); FORGET_Frame(); switch ( cv->CaretValueFormat ) { case 1: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf1.Coordinate = GET_Short(); FORGET_Frame(); break; case 2: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf2.CaretValuePoint = GET_UShort(); FORGET_Frame(); break; case 3: if ( ACCESS_Frame( 4L ) ) return error; cv->cvf.cvf3.Coordinate = GET_Short(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); break; case 4: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf4.IdCaretValue = GET_UShort(); FORGET_Frame(); break; default: return HB_Err_Invalid_GDEF_SubTable_Format; } return FT_Err_Ok; }
static FT_Error Load_AttachList( HB_AttachList* al, FT_Stream stream ) { FT_Memory memory = stream->memory; FT_Error error; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_AttachPoint* ap; base_offset = FILE_Pos(); 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( &al->Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = al->GlyphCount = GET_UShort(); FORGET_Frame(); al->AttachPoint = NULL; if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) ) goto Fail2; ap = al->AttachPoint; 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_AttachPoint( &ap[n], stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } al->loaded = TRUE; return FT_Err_Ok; Fail1: for ( m = 0; m < n; m++ ) Free_AttachPoint( &ap[m], memory ); FREE( ap ); Fail2: _HB_OPEN_Free_Coverage( &al->Coverage, memory ); return error; }
FT_Error HB_Load_GDEF_Table( FT_Face face, HB_GDEFHeader** retptr ) { FT_Error error; FT_Memory memory = face->memory; FT_Stream stream = face->stream; FT_ULong cur_offset, new_offset, base_offset; HB_GDEFHeader* gdef; if ( !retptr ) return FT_Err_Invalid_Argument; if (( error = _hb_ftglue_face_goto_table( face, TTAG_GDEF, stream ) )) return error; if (( error = HB_New_GDEF_Table ( face, &gdef ) )) return error; base_offset = FILE_Pos(); /* skip version */ if ( FILE_Seek( base_offset + 4L ) || ACCESS_Frame( 2L ) ) goto Fail0; new_offset = GET_UShort(); FORGET_Frame(); /* all GDEF subtables are optional */ if ( new_offset ) { new_offset += base_offset; /* only classes 1-4 are allowed here */ cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5, stream ) ) != FT_Err_Ok ) goto Fail0; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail1; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_AttachList( &gdef->AttachList, stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail2; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_LigCaretList( &gdef->LigCaretList, stream ) ) != FT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); } /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We first have to scan the LookupFlag values to find out whether we must load it or not. Here we only store the offset of the table. */ if ( ACCESS_Frame( 2L ) ) goto Fail3; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) gdef->MarkAttachClassDef_offset = new_offset + base_offset; else gdef->MarkAttachClassDef_offset = 0; *retptr = gdef; return FT_Err_Ok; Fail3: Free_LigCaretList( &gdef->LigCaretList, memory ); Fail2: Free_AttachList( &gdef->AttachList, memory ); Fail1: _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory ); Fail0: FREE( gdef ); return error; }
static FT_Error fnt_face_get_dll_fonts( FNT_Face face ) { FT_Error error; FT_Stream stream = FT_FACE(face)->stream; FT_Memory memory = FT_FACE(face)->memory; WinMZ_Header mz_header; face->fonts = 0; face->num_fonts = 0; /* does it begin with a MZ header? */ if ( FILE_Seek( 0 ) || READ_Fields( winmz_header_fields, &mz_header ) ) goto Exit; error = FNT_Err_Unknown_File_Format; if ( mz_header.magic == WINFNT_MZ_MAGIC ) { /* yes, now look for a NE header in the file */ WinNE_Header ne_header; if ( FILE_Seek( mz_header.lfanew ) || READ_Fields( winne_header_fields, &ne_header ) ) goto Exit; error = FNT_Err_Unknown_File_Format; if ( ne_header.magic == WINFNT_NE_MAGIC ) { /* good, now look in the resource table for each FNT resource */ FT_ULong res_offset = mz_header.lfanew + ne_header.resource_tab_offset; FT_UShort size_shift; FT_UShort font_count = 0; FT_ULong font_offset = 0; if ( FILE_Seek( res_offset ) || ACCESS_Frame( ne_header.rname_tab_offset - ne_header.resource_tab_offset ) ) goto Exit; size_shift = GET_UShortLE(); for (;;) { FT_UShort type_id, count; type_id = GET_UShortLE(); if ( !type_id ) break; count = GET_UShortLE(); if ( type_id == 0x8008 ) { font_count = count; font_offset = (FT_ULong)( FILE_Pos() + 4 + ( stream->cursor - stream->limit ) ); break; } stream->cursor += 4 + count * 12; } FORGET_Frame(); if ( !font_count || !font_offset ) { FT_TRACE2(( "this file doesn't contain any FNT resources!\n" )); error = FNT_Err_Unknown_File_Format; goto Exit; } if ( FILE_Seek( font_offset ) || ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) ) goto Exit; face->num_fonts = font_count; if ( ACCESS_Frame( (FT_Long)font_count * 12 ) ) goto Exit; /* now read the offset and position of each FNT font */ { FNT_Font* cur = face->fonts; FNT_Font* limit = cur + font_count; for ( ; cur < limit; cur++ ) { cur->offset = (FT_ULong)GET_UShortLE() << size_shift; cur->fnt_size = (FT_ULong)GET_UShortLE() << size_shift; cur->size_shift = size_shift; stream->cursor += 8; } } FORGET_Frame(); /* finally, try to load each font there */ { FNT_Font* cur = face->fonts; FNT_Font* limit = cur + font_count; for ( ; cur < limit; cur++ ) { error = fnt_font_load( cur, stream ); if ( error ) goto Fail; } } } } Fail: if ( error ) fnt_face_done_fonts( face ); Exit: return error; }
Load_TrueType_Glyph( PInstance instance, PGlyph glyph, UShort glyph_index, UShort load_flags ) { enum TPhases_ { Load_Exit, Load_Glyph, Load_Header, Load_Simple, Load_Composite, Load_End }; typedef enum TPhases_ TPhases; DEFINE_ALL_LOCALS; PFace face; UShort num_points; Short num_contours; UShort left_points; Short left_contours; UShort num_elem_points; Long table; UShort load_top; Long k, l; UShort new_flags; Long index; UShort u, v; Long glyph_offset, offset; TT_F26Dot6 x, y, nx, ny; Fixed xx, xy, yx, yy; PExecution_Context exec; PSubglyph_Record subglyph, subglyph2; TGlyph_Zone base_pts; TPhases phase; PByte widths; /* TT_Glyph_Loader_Callback cacheCb; */ /* TT_Outline cached_outline; */ /* first of all, check arguments */ if ( !glyph ) return TT_Err_Invalid_Glyph_Handle; face = glyph->face; if ( !face ) return TT_Err_Invalid_Glyph_Handle; if ( glyph_index >= face->numGlyphs ) return TT_Err_Invalid_Glyph_Index; if ( instance && (load_flags & TTLOAD_SCALE_GLYPH) == 0 ) { instance = 0; load_flags &= ~( TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH ); } table = TT_LookUp_Table( face, TTAG_glyf ); if ( table < 0 ) { PTRACE0(( "ERROR: There is no glyph table in this font file!\n" )); return TT_Err_Glyf_Table_Missing; } glyph_offset = face->dirTables[table].Offset; /* query new execution context */ if ( instance && instance->debug ) exec = instance->context; else exec = New_Context( face ); if ( !exec ) return TT_Err_Could_Not_Find_Context; Context_Load( exec, face, instance ); if ( instance ) { if ( instance->GS.instruct_control & 2 ) exec->GS = Default_GraphicsState; else exec->GS = instance->GS; /* load default graphics state */ glyph->outline.high_precision = ( instance->metrics.y_ppem < 24 ); } /* save its critical pointers, as they'll be modified during load */ base_pts = exec->pts; /* init variables */ left_points = face->maxPoints; left_contours = face->maxContours; num_points = 0; num_contours = 0; load_top = 0; subglyph = exec->loadStack; Init_Glyph_Component( subglyph, NULL, exec ); subglyph->index = glyph_index; subglyph->is_hinted = load_flags & TTLOAD_HINT_GLYPH; /* when the cvt program has disabled hinting, the argument */ /* is ignored. */ if ( instance && instance->GS.instruct_control & 1 ) subglyph->is_hinted = FALSE; /* now access stream */ if ( USE_Stream( face->stream, stream ) ) goto Fin; /* Main loading loop */ phase = Load_Glyph; index = 0; while ( phase != Load_Exit ) { subglyph = exec->loadStack + load_top; switch ( phase ) { /************************************************************/ /* */ /* Load_Glyph state */ /* */ /* reading a glyph's generic header to determine */ /* whether it's simple or composite */ /* */ /* exit states: Load_Header and Load_End */ case Load_Glyph: /* check glyph index and table */ index = subglyph->index; if ( index < 0 || index >= face->numGlyphs ) { error = TT_Err_Invalid_Glyph_Index; goto Fail; } /* get horizontal metrics */ { Short left_bearing; UShort advance_width; Get_HMetrics( face, (UShort)index, !(load_flags & TTLOAD_IGNORE_GLOBAL_ADVANCE_WIDTH), &left_bearing, &advance_width ); subglyph->metrics.horiBearingX = left_bearing; subglyph->metrics.horiAdvance = advance_width; } phase = Load_Header; /* The cache callback isn't part of the FreeType release yet */ /* It is discarded for the moment.. */ /* */ #if 0 if ( instance ) { /* is the glyph in an outline cache ? */ cacheCb = instance->owner->engine->glCallback; if ( cacheCb && 0 ) /* disabled */ { /* we have a callback */ error = cacheCb( instance->generic, index, &cached_outline, &x, &y ); if ( !error ) { /* no error, then append the outline to the current subglyph */ /* error = Append_Outline( subglyph, &left_points, &left_contours, &cached_outline ); */ phase = Load_End; } } } #endif break; /************************************************************/ /* */ /* Load_Header state */ /* */ /* reading a glyph's generic header to determine */ /* wether it's simple or composite */ /* */ /* exit states: Load_Simple and Load_Composite */ /* */ case Load_Header: /* load glyph */ if ( (TT_UInt)( index + 1 ) < (TT_UInt)face->numLocations && face->glyphLocations[index] == face->glyphLocations[index + 1] ) { /* as described by Frederic Loyer, these are spaces, and */ /* not the unknown glyph. */ num_contours = 0; num_points = 0; subglyph->metrics.bbox.xMin = 0; subglyph->metrics.bbox.xMax = 0; subglyph->metrics.bbox.yMin = 0; subglyph->metrics.bbox.yMax = 0; subglyph->pp1.x = 0; subglyph->pp2.x = subglyph->metrics.horiAdvance; if (load_flags & TTLOAD_SCALE_GLYPH) subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x ); exec->glyphSize = 0; phase = Load_End; break; } offset = glyph_offset + face->glyphLocations[index]; /* read first glyph header */ if ( FILE_Seek( offset ) || ACCESS_Frame( 10L ) ) goto Fail_File; num_contours = GET_Short(); subglyph->metrics.bbox.xMin = GET_Short(); subglyph->metrics.bbox.yMin = GET_Short(); subglyph->metrics.bbox.xMax = GET_Short(); subglyph->metrics.bbox.yMax = GET_Short(); FORGET_Frame(); PTRACE6(( "Glyph %ld:\n", index )); PTRACE6(( " # of contours: %d\n", num_contours )); PTRACE6(( " xMin: %4d xMax: %4d\n", subglyph->metrics.bbox.xMin, subglyph->metrics.bbox.xMax )); PTRACE6(( " yMin: %4d yMax: %4d\n", subglyph->metrics.bbox.yMin, subglyph->metrics.bbox.yMax )); if ( num_contours > left_contours ) { PTRACE0(( "ERROR: Too many contours for glyph %ld\n", index )); error = TT_Err_Too_Many_Contours; goto Fail; } subglyph->pp1.x = subglyph->metrics.bbox.xMin - subglyph->metrics.horiBearingX; subglyph->pp1.y = 0; subglyph->pp2.x = subglyph->pp1.x + subglyph->metrics.horiAdvance; if (load_flags & TTLOAD_SCALE_GLYPH) { subglyph->pp1.x = Scale_X( &exec->metrics, subglyph->pp1.x ); subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x ); } /* is it a simple glyph ? */ if ( num_contours > 0 ) phase = Load_Simple; else phase = Load_Composite; break; /************************************************************/ /* */ /* Load_Simple state */ /* */ /* reading a simple glyph (num_contours must be set to */ /* the glyph's number of contours.) */ /* */ /* exit states : Load_End */ /* */ case Load_Simple: new_flags = load_flags; /* disable hinting when scaling */ if ( !subglyph->is_hinted ) new_flags &= ~TTLOAD_HINT_GLYPH; error = Load_Simple_Glyph( exec, stream, num_contours, left_contours, left_points, new_flags, subglyph ); if ( error ) goto Fail; /* Note: We could have put the simple loader source there */ /* but the code is fat enough already :-) */ num_points = exec->pts.n_points - 2; phase = Load_End; break; /************************************************************/ /* */ /* Load_Composite state */ /* */ /* reading a composite glyph header a pushing a new */ /* load element on the stack. */ /* */ /* exit states: Load_Glyph */ /* */ case Load_Composite: /* create a new element on the stack */ load_top++; if ( load_top > face->maxComponents ) { error = TT_Err_Invalid_Composite; goto Fail; } subglyph2 = exec->loadStack + load_top; Init_Glyph_Component( subglyph2, subglyph, NULL ); subglyph2->is_hinted = subglyph->is_hinted; /* now read composite header */ if ( ACCESS_Frame( 4L ) ) goto Fail_File; subglyph->element_flag = new_flags = GET_UShort(); subglyph2->index = GET_UShort(); FORGET_Frame(); k = 1 + 1; if ( new_flags & ARGS_ARE_WORDS ) k *= 2; if ( new_flags & WE_HAVE_A_SCALE ) k += 2; else if ( new_flags & WE_HAVE_AN_XY_SCALE ) k += 4; else if ( new_flags & WE_HAVE_A_2X2 ) k += 8; if ( ACCESS_Frame( k ) ) goto Fail_File; if ( new_flags & ARGS_ARE_WORDS ) { k = GET_Short(); l = GET_Short(); } else { k = GET_Char(); l = GET_Char(); } subglyph->arg1 = k; subglyph->arg2 = l; if ( new_flags & ARGS_ARE_XY_VALUES ) { subglyph->transform.ox = k; subglyph->transform.oy = l; } xx = 1L << 16; xy = 0; yx = 0; yy = 1L << 16; if ( new_flags & WE_HAVE_A_SCALE ) { xx = (Fixed)GET_Short() << 2; yy = xx; subglyph2->is_scaled = TRUE; } else if ( new_flags & WE_HAVE_AN_XY_SCALE ) { xx = (Fixed)GET_Short() << 2; yy = (Fixed)GET_Short() << 2; subglyph2->is_scaled = TRUE; } else if ( new_flags & WE_HAVE_A_2X2 ) { xx = (Fixed)GET_Short() << 2; xy = (Fixed)GET_Short() << 2; yx = (Fixed)GET_Short() << 2; yy = (Fixed)GET_Short() << 2; subglyph2->is_scaled = TRUE; } FORGET_Frame(); subglyph->transform.xx = xx; subglyph->transform.xy = xy; subglyph->transform.yx = yx; subglyph->transform.yy = yy; k = TT_MulFix( xx, yy ) - TT_MulFix( xy, yx ); /* disable hinting in case of scaling/slanting */ if ( ABS( k ) != (1L << 16) ) subglyph2->is_hinted = FALSE; subglyph->file_offset = FILE_Pos(); phase = Load_Glyph; break; /************************************************************/ /* */ /* Load_End state */ /* */ /* after loading a glyph, apply transformation and offset */ /* where necessary, pops element and continue or */ /* stop process. */ /* */ /* exit states : Load_Composite and Load_Exit */ /* */ case Load_End: if ( load_top > 0 ) { subglyph2 = subglyph; load_top--; subglyph = exec->loadStack + load_top; /* check advance width and left side bearing */ if ( !subglyph->preserve_pps && subglyph->element_flag & USE_MY_METRICS ) { subglyph->metrics.horiBearingX = subglyph2->metrics.horiBearingX; subglyph->metrics.horiAdvance = subglyph2->metrics.horiAdvance; subglyph->pp1 = subglyph2->pp1; subglyph->pp2 = subglyph2->pp2; subglyph->preserve_pps = TRUE; } /* apply scale */ if ( subglyph2->is_scaled ) { TT_Vector* cur = subglyph2->zone.cur; TT_Vector* org = subglyph2->zone.org; for ( u = 0; u < num_points; u++ ) { nx = TT_MulFix( cur->x, subglyph->transform.xx ) + TT_MulFix( cur->y, subglyph->transform.yx ); ny = TT_MulFix( cur->x, subglyph->transform.xy ) + TT_MulFix( cur->y, subglyph->transform.yy ); cur->x = nx; cur->y = ny; nx = TT_MulFix( org->x, subglyph->transform.xx ) + TT_MulFix( org->y, subglyph->transform.yx ); ny = TT_MulFix( org->x, subglyph->transform.xy ) + TT_MulFix( org->y, subglyph->transform.yy ); org->x = nx; org->y = ny; cur++; org++; } } /* adjust counts */ num_elem_points = subglyph->zone.n_points; for ( k = 0; k < num_contours; k++ ) subglyph2->zone.contours[k] += num_elem_points; subglyph->zone.n_points += num_points; subglyph->zone.n_contours += num_contours; left_points -= num_points; left_contours -= num_contours; if ( !(subglyph->element_flag & ARGS_ARE_XY_VALUES) ) { /* move second glyph according to control points */ /* the attach points are relative to the specific component */ u = (UShort)subglyph->arg1; v = (UShort)subglyph->arg2; if ( u >= num_elem_points || v >= num_points ) { error = TT_Err_Invalid_Composite; goto Fail; } /* adjust count */ v += num_elem_points; x = subglyph->zone.cur[u].x - subglyph->zone.cur[v].x; y = subglyph->zone.cur[u].y - subglyph->zone.cur[v].y; } else { /* apply offset */ x = subglyph->transform.ox; y = subglyph->transform.oy; if ( load_flags & TTLOAD_SCALE_GLYPH ) { x = Scale_X( &exec->metrics, x ); y = Scale_Y( &exec->metrics, y ); if ( subglyph->element_flag & ROUND_XY_TO_GRID ) { x = (x+32) & -64; y = (y+32) & -64; } } } translate_array( num_points, subglyph2->zone.cur, x, y ); cur_to_org( num_points, &subglyph2->zone ); num_points = subglyph->zone.n_points; num_contours = subglyph->zone.n_contours; /* check for last component */ if ( FILE_Seek( subglyph->file_offset ) ) goto Fail_File; if ( subglyph->element_flag & MORE_COMPONENTS ) phase = Load_Composite; else { error = Load_Composite_End( num_points, num_contours, exec, subglyph, load_flags, stream ); if ( error ) goto Fail; phase = Load_End; } } else phase = Load_Exit; break; case Load_Exit: break; } } /* finally, copy the points arrays to the glyph object */ exec->pts = base_pts; for ( u = 0; u < num_points + 2; u++ ) { glyph->outline.points[u] = exec->pts.cur[u]; glyph->outline.flags [u] = exec->pts.touch[u]; } for ( k = 0; k < num_contours; k++ ) glyph->outline.contours[k] = exec->pts.contours[k]; glyph->outline.n_points = num_points; glyph->outline.n_contours = num_contours; glyph->outline.second_pass = TRUE; /* translate array so that (0,0) is the glyph's origin */ translate_array( num_points + 2, glyph->outline.points, -subglyph->pp1.x, 0 ); TT_Get_Outline_BBox( &glyph->outline, &glyph->metrics.bbox ); if ( subglyph->is_hinted ) { /* grid-fit the bounding box */ glyph->metrics.bbox.xMin &= -64; glyph->metrics.bbox.yMin &= -64; glyph->metrics.bbox.xMax = (glyph->metrics.bbox.xMax+63) & -64; glyph->metrics.bbox.yMax = (glyph->metrics.bbox.yMax+63) & -64; } /* get the device-independent scaled horizontal metrics */ /* take care of fixed-pitch fonts... */ { TT_Pos left_bearing; TT_Pos advance; left_bearing = subglyph->metrics.horiBearingX; advance = subglyph->metrics.horiAdvance; if ( face->postscript.isFixedPitch ) advance = face->horizontalHeader.advance_Width_Max; if ( load_flags & TTLOAD_SCALE_GLYPH ) { left_bearing = Scale_X( &exec->metrics, left_bearing ); advance = Scale_X( &exec->metrics, advance ); } glyph->metrics.linearHoriBearingX = left_bearing; glyph->metrics.linearHoriAdvance = advance; } glyph->metrics.horiBearingX = glyph->metrics.bbox.xMin; glyph->metrics.horiBearingY = glyph->metrics.bbox.yMax; glyph->metrics.horiAdvance = subglyph->pp2.x - subglyph->pp1.x; /* Now take care of vertical metrics. In the case where there is */ /* no vertical information within the font (relatively common), make */ /* up some metrics `by hand' ... */ { Short top_bearing; /* vertical top side bearing (EM units) */ UShort advance_height; /* vertical advance height (EM units) */ TT_Pos left; /* scaled vertical left side bearing */ TT_Pos orig_top; /* scaled original vertical top side bearing */ TT_Pos top; /* scaled vertical top side bearing */ TT_Pos advance; /* scaled vertical advance height */ /* Get the unscaled `tsb' and `ah' values */ if ( face->verticalInfo && face->verticalHeader.number_Of_VMetrics > 0 ) { /* Don't assume that both the vertical header and vertical */ /* metrics are present in the same font :-) */ TT_Get_Metrics( (TT_Horizontal_Header*)&face->verticalHeader, glyph_index, &top_bearing, &advance_height ); } else { /* Make up the distances from the horizontal header.. */ /* NOTE: The OS/2 values are the only `portable' ones, */ /* which is why we use them... */ /* */ /* NOTE2: The sTypoDescender is negative, which is why */ /* we compute the baseline-to-baseline distance */ /* here with : */ /* ascender - descender + linegap */ /* */ /* XXX What happens here with these Apple fonts without OS/2 table ? */ top_bearing = (Short) (face->os2.sTypoLineGap / 2); advance_height = (UShort)(face->os2.sTypoAscender - face->os2.sTypoDescender + face->os2.sTypoLineGap); } /* We must adjust the top_bearing value from the bounding box */ /* given in the glyph header to te bounding box calculated with */ /* TT_Get_Outline_BBox() */ /* scale the metrics */ if ( load_flags & TTLOAD_SCALE_GLYPH ) { orig_top = Scale_Y( &exec->metrics, top_bearing ); top = Scale_Y( &exec->metrics, top_bearing + subglyph->metrics.bbox.yMax ) - glyph->metrics.bbox.yMax; advance = Scale_Y( &exec->metrics, advance_height ); } else { orig_top = top_bearing; top = top_bearing + subglyph->metrics.bbox.yMax - glyph->metrics.bbox.yMax; advance = advance_height; } glyph->metrics.linearVertBearingY = orig_top; glyph->metrics.linearVertAdvance = advance; /* XXX : for now, we have no better algo for the lsb, but it should */ /* work ok.. */ /* */ left = ( glyph->metrics.bbox.xMin - glyph->metrics.bbox.xMax ) / 2; /* grid-fit them if necessary */ if ( subglyph->is_hinted ) { left &= -64; top = (top + 63) & -64; advance = (advance + 32) & -64; } glyph->metrics.vertBearingX = left; glyph->metrics.vertBearingY = top; glyph->metrics.vertAdvance = advance; } /* Adjust advance width to the value contained in the hdmx table. */ if ( !exec->face->postscript.isFixedPitch && instance && subglyph->is_hinted ) { widths = Get_Advance_Widths( exec->face, exec->instance->metrics.x_ppem ); if ( widths ) glyph->metrics.horiAdvance = widths[glyph_index] << 6; } glyph->outline.dropout_mode = (Char)exec->GS.scan_type; error = TT_Err_Ok; Fail_File: Fail: DONE_Stream( stream ); Fin: /* reset the execution context */ exec->pts = base_pts; if ( !instance || !instance->debug ) Done_Context( exec ); return error; }
TT_Get_Face_Widths( TT_Face face, TT_UShort first_glyph, TT_UShort last_glyph, TT_UShort* widths, TT_UShort* heights ) { DEFINE_ALL_LOCALS; PFace faze = HANDLE_Face(face); UShort n; Long table; ULong glyf_offset; /* offset of glyph table in file */ UShort zero_width = 0; /* width of glyph 0 */ UShort zero_height = 0; /* height of glyph 0 */ Bool zero_loaded = 0; #ifndef TT_HUGE_PTR PStorage locations; #else Storage TT_HUGE_PTR * locations; #endif TT_BBox bbox; if ( !faze ) return TT_Err_Invalid_Face_Handle; if ( last_glyph >= faze->numGlyphs || first_glyph > last_glyph ) return TT_Err_Invalid_Argument; /* find "glyf" table */ table = TT_LookUp_Table( faze, TTAG_glyf ); if ( table < 0 ) { PERROR(( "ERROR: there is no glyph table in this font file!\n" )); return TT_Err_Glyf_Table_Missing; } glyf_offset = faze->dirTables[table].Offset; /* now access stream */ if ( USE_Stream( faze->stream, stream ) ) return error; locations = faze->glyphLocations + first_glyph; /* loop to load each glyph in the range */ for ( n = first_glyph; n <= last_glyph; n++ ) { if ( n + 1 < faze->numGlyphs && locations[0] == locations[1] ) { /* Note : Glyph 0 is always used to indicate a missing glyph */ /* in a range. We must thus return its width and height */ /* where appropriate when we find an undefined glyph. */ if ( zero_loaded == 0 ) { if ( FILE_Seek( glyf_offset + faze->glyphLocations[0] ) || ACCESS_Frame( 10L ) ) goto Fail; (void)GET_Short(); /* skip number of contours */ bbox.xMin = GET_Short(); bbox.yMin = GET_Short(); bbox.xMax = GET_Short(); bbox.yMax = GET_Short(); FORGET_Frame(); zero_width = (UShort)(bbox.xMax - bbox.xMin); zero_height = (UShort)(bbox.yMax - bbox.yMin); zero_loaded = 1; } if ( widths ) *widths++ = zero_width; if ( heights ) *heights++ = zero_height; } else { /* normal glyph, read header */ if ( FILE_Seek( glyf_offset + locations[0] ) || ACCESS_Frame( 10L ) ) goto Fail; (void)GET_Short(); /* skip number of contours */ bbox.xMin = GET_Short(); bbox.yMin = GET_Short(); bbox.xMax = GET_Short(); bbox.yMax = GET_Short(); FORGET_Frame(); if ( widths ) *widths++ = (UShort)(bbox.xMax - bbox.xMin); if ( heights ) *heights++ = (UShort)(bbox.yMax - bbox.yMin); } } Fail: DONE_Stream( stream ); return error; }
static TT_Error Kerning_Create( void* ext, PFace face ) { DEFINE_LOAD_LOCALS( face->stream ); TT_Kerning* kern = (TT_Kerning*)ext; UShort num_tables; Long table; TT_Kern_Subtable* sub; /* by convention */ if ( !kern ) return TT_Err_Ok; /* Now load the kerning directory. We're called from the face */ /* constructor. We thus need not use the stream. */ kern->version = 0; kern->nTables = 0; kern->tables = NULL; table = TT_LookUp_Table( face, TTAG_kern ); if ( table < 0 ) return TT_Err_Ok; /* The table is optional */ if ( FILE_Seek( face->dirTables[table].Offset ) || ACCESS_Frame( 4L ) ) return error; kern->version = GET_UShort(); num_tables = GET_UShort(); FORGET_Frame(); /* we don't set kern->nTables until we have allocated the array */ if ( ALLOC_ARRAY( kern->tables, num_tables, TT_Kern_Subtable ) ) return error; kern->nTables = num_tables; /* now load the directory entries, but do _not_ load the tables ! */ sub = kern->tables; for ( table = 0; table < num_tables; table++ ) { if ( ACCESS_Frame( 6L ) ) return error; sub->loaded = FALSE; /* redundant, but good to see */ sub->version = GET_UShort(); sub->length = GET_UShort() - 6; /* substract header length */ sub->format = GET_Byte(); sub->coverage = GET_Byte(); FORGET_Frame(); sub->offset = FILE_Pos(); /* now skip to the next table */ if ( FILE_Skip( sub->length ) ) return error; sub++; } /* that's fine, leave now */ return TT_Err_Ok; }
static TT_Error Subtable_Load_2( TT_Kern_2* kern2, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); Long table_base; UShort left_offset, right_offset, array_offset; ULong array_size; UShort left_max, right_max, n; /* record the table offset */ table_base = FILE_Pos(); if ( ACCESS_Frame( 8L ) ) return error; kern2->rowWidth = GET_UShort(); left_offset = GET_UShort(); right_offset = GET_UShort(); array_offset = GET_UShort(); FORGET_Frame(); /* first load left and right glyph classes */ if ( FILE_Seek( table_base + left_offset ) || ACCESS_Frame( 4L ) ) return error; kern2->leftClass.firstGlyph = GET_UShort(); kern2->leftClass.nGlyphs = GET_UShort(); FORGET_Frame(); if ( ALLOC_ARRAY( kern2->leftClass.classes, kern2->leftClass.nGlyphs, UShort ) ) return error; /* load left offsets */ if ( ACCESS_Frame( kern2->leftClass.nGlyphs * 2L ) ) goto Fail_Left; for ( n = 0; n < kern2->leftClass.nGlyphs; n++ ) kern2->leftClass.classes[n] = GET_UShort(); FORGET_Frame(); /* right class */ if ( FILE_Seek( table_base + right_offset ) || ACCESS_Frame( 4L ) ) goto Fail_Left; kern2->rightClass.firstGlyph = GET_UShort(); kern2->rightClass.nGlyphs = GET_UShort(); FORGET_Frame(); if ( ALLOC_ARRAY( kern2->rightClass.classes, kern2->rightClass.nGlyphs, UShort ) ) goto Fail_Left; /* load right offsets */ if ( ACCESS_Frame( kern2->rightClass.nGlyphs * 2L ) ) goto Fail_Right; for ( n = 0; n < kern2->rightClass.nGlyphs; n++ ) kern2->rightClass.classes[n] = GET_UShort(); FORGET_Frame(); /* Now load the kerning array. We don't have its size, we */ /* must compute it from what we know. */ /* We thus compute the maximum left and right offsets and */ /* add them to get the array size. */ left_max = right_max = 0; for ( n = 0; n < kern2->leftClass.nGlyphs; n++ ) left_max = MAX( left_max, kern2->leftClass.classes[n] ); for ( n = 0; n < kern2->rightClass.nGlyphs; n++ ) right_max = MAX( right_max, kern2->leftClass.classes[n] ); array_size = left_max + right_max + 2; if ( ALLOC( kern2->array, array_size ) ) goto Fail_Right; if ( ACCESS_Frame( array_size ) ) goto Fail_Array; for ( n = 0; (UInt)n < array_size/2; n++ ) kern2->array[n] = GET_Short(); FORGET_Frame(); /* we're good now */ return TT_Err_Ok; Fail_Array: FREE( kern2->array ); Fail_Right: FREE( kern2->rightClass.classes ); kern2->rightClass.nGlyphs = 0; Fail_Left: FREE( kern2->leftClass.classes ); kern2->leftClass.nGlyphs = 0; return error; }
FT_LOCAL_DEF FT_Error TT_CharMap_Load( TT_Face face, TT_CMapTable* cmap, FT_Stream stream ) { FT_Error error; FT_Memory memory; FT_UShort num_SH, num_Seg, i; FT_UShort u, l; TT_CMap0* cmap0; TT_CMap2* cmap2; TT_CMap4* cmap4; TT_CMap6* cmap6; TT_CMap2SubHeader* cmap2sub; TT_CMap4Segment* segments; if ( cmap->loaded ) return TT_Err_Ok; memory = stream->memory; if ( FILE_Seek( cmap->offset ) ) return error; switch ( cmap->format ) { case 0: cmap0 = &cmap->c.cmap0; if ( ALLOC( cmap0->glyphIdArray, 256L ) || FILE_Read( cmap0->glyphIdArray, 256L ) ) goto Fail; cmap->get_index = code_to_index0; break; case 2: num_SH = 0; cmap2 = &cmap->c.cmap2; /* allocate subheader keys */ if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) || ACCESS_Frame( 512L ) ) goto Fail; for ( i = 0; i < 256; i++ ) { u = GET_UShort() / 8; cmap2->subHeaderKeys[i] = u; if ( num_SH < u ) num_SH = u; } FORGET_Frame(); /* load subheaders */ cmap2->numGlyphId = l = ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2; if ( ALLOC_ARRAY( cmap2->subHeaders, num_SH + 1, TT_CMap2SubHeader ) || ACCESS_Frame( ( num_SH + 1 ) * 8L ) ) goto Fail; cmap2sub = cmap2->subHeaders; for ( i = 0; i <= num_SH; i++ ) { cmap2sub->firstCode = GET_UShort(); cmap2sub->entryCount = GET_UShort(); cmap2sub->idDelta = GET_Short(); /* we apply the location offset immediately */ cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2; cmap2sub++; } FORGET_Frame(); /* load glyph IDs */ if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap2->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index2; break; case 4: cmap4 = &cmap->c.cmap4; /* load header */ if ( ACCESS_Frame( 8L ) ) goto Fail; cmap4->segCountX2 = GET_UShort(); cmap4->searchRange = GET_UShort(); cmap4->entrySelector = GET_UShort(); cmap4->rangeShift = GET_UShort(); num_Seg = cmap4->segCountX2 / 2; FORGET_Frame(); /* load segments */ if ( ALLOC_ARRAY( cmap4->segments, num_Seg, TT_CMap4Segment ) || ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) ) goto Fail; segments = cmap4->segments; for ( i = 0; i < num_Seg; i++ ) segments[i].endCount = GET_UShort(); (void)GET_UShort(); for ( i = 0; i < num_Seg; i++ ) segments[i].startCount = GET_UShort(); for ( i = 0; i < num_Seg; i++ ) segments[i].idDelta = GET_Short(); for ( i = 0; i < num_Seg; i++ ) segments[i].idRangeOffset = GET_UShort(); FORGET_Frame(); cmap4->numGlyphId = l = ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2; /* load IDs */ if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap4->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index4; cmap4->last_segment = cmap4->segments; break; case 6: cmap6 = &cmap->c.cmap6; if ( ACCESS_Frame( 4L ) ) goto Fail; cmap6->firstCode = GET_UShort(); cmap6->entryCount = GET_UShort(); FORGET_Frame(); l = cmap6->entryCount; if ( ALLOC_ARRAY( cmap6->glyphIdArray, cmap6->entryCount, FT_Short ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap6->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index6; break; default: /* corrupt character mapping table */ return TT_Err_Invalid_CharMap_Format; } return TT_Err_Ok; Fail: TT_CharMap_Free( face, cmap ); return error; }
cid_load_glyph( T1_Decoder* decoder, FT_UInt glyph_index ) { CID_Face face = (CID_Face)decoder->builder.face; CID_Info* cid = &face->cid; FT_Byte* p; FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; FT_UInt fd_select; FT_ULong off1, glyph_len; FT_Stream stream = face->root.stream; FT_Error error = 0; /* read the CID font dict index and charstring offset from the CIDMap */ if ( FILE_Seek( cid->data_offset + cid->cidmap_offset + glyph_index * entry_len ) || ACCESS_Frame( 2 * entry_len ) ) goto Exit; p = (FT_Byte*)stream->cursor; fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); p += cid->fd_bytes; glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; FORGET_Frame(); /* now, if the glyph is not empty, set up the subrs array, and parse */ /* the charstrings */ if ( glyph_len > 0 ) { CID_FontDict* dict; CID_Subrs* cid_subrs = face->subrs + fd_select; FT_Byte* charstring; FT_Memory memory = face->root.memory; /* setup subrs */ decoder->num_subrs = cid_subrs->num_subrs; decoder->subrs = cid_subrs->code; decoder->subrs_len = 0; /* setup font matrix */ dict = cid->font_dicts + fd_select; decoder->font_matrix = dict->font_matrix; decoder->font_offset = dict->font_offset; decoder->lenIV = dict->private_dict.lenIV; /* the charstrings are encoded (stupid!) */ /* load the charstrings, then execute it */ if ( ALLOC( charstring, glyph_len ) ) goto Exit; if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) ) { FT_Int cs_offset; /* Adjustment for seed bytes. */ cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); /* Decrypt only if lenIV >= 0. */ if ( decoder->lenIV >= 0 ) cid_decrypt( charstring, glyph_len, 4330 ); error = decoder->funcs.parse_charstrings( decoder, charstring + cs_offset, glyph_len - cs_offset ); } FREE( charstring ); } Exit: return error; }
static FT_Error Load_LigCaretList( HB_LigCaretList* lcl, FT_Stream stream ) { FT_Memory memory = stream->memory; FT_Error error; FT_UShort m, n, count; FT_ULong cur_offset, new_offset, base_offset; HB_LigGlyph* lg; base_offset = FILE_Pos(); 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( &lcl->Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = lcl->LigGlyphCount = GET_UShort(); FORGET_Frame(); lcl->LigGlyph = NULL; if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) ) goto Fail2; lg = lcl->LigGlyph; 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_LigGlyph( &lg[n], stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } lcl->loaded = TRUE; return FT_Err_Ok; Fail1: for ( m = 0; m < n; m++ ) Free_LigGlyph( &lg[m], memory ); FREE( lg ); Fail2: _HB_OPEN_Free_Coverage( &lcl->Coverage, memory ); return error; }
static HB_Error Load_CaretValue( HB_CaretValue* cv, HB_Stream stream ) { HB_Error error; HB_UInt cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; cv->CaretValueFormat = GET_UShort(); FORGET_Frame(); switch ( cv->CaretValueFormat ) { case 1: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf1.Coordinate = GET_Short(); FORGET_Frame(); break; case 2: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf2.CaretValuePoint = GET_UShort(); FORGET_Frame(); break; case 3: if ( ACCESS_Frame( 4L ) ) return error; cv->cvf.cvf3.Coordinate = GET_Short(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device, stream ) ) != HB_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); break; case 4: if ( ACCESS_Frame( 2L ) ) return error; #ifdef HB_SUPPORT_MULTIPLE_MASTER cv->cvf.cvf4.IdCaretValue = GET_UShort(); #else (void) GET_UShort(); #endif FORGET_Frame(); break; default: return ERR(HB_Err_Invalid_SubTable_Format); } return HB_Err_Ok; }