static TT_Error Subtable_Load_0( TT_Kern_0* kern0, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort num_pairs, n; if ( ACCESS_Frame( 8L ) ) return error; num_pairs = GET_UShort(); kern0->nPairs = 0; kern0->searchRange = GET_UShort(); kern0->entrySelector = GET_UShort(); kern0->rangeShift = GET_UShort(); /* we only set kern0->nPairs if the subtable has been loaded */ FORGET_Frame(); if ( ALLOC_ARRAY( kern0->pairs, num_pairs, TT_Kern_0_Pair ) ) return error; if ( ACCESS_Frame( num_pairs * 6L ) ) goto Fail; for ( n = 0; n < num_pairs; n++ ) { kern0->pairs[n].left = GET_UShort(); kern0->pairs[n].right = GET_UShort(); kern0->pairs[n].value = GET_UShort(); if ( kern0->pairs[n].left >= input->numGlyphs || kern0->pairs[n].right >= input->numGlyphs ) { FORGET_Frame(); error = TT_Err_Invalid_Kerning_Table; goto Fail; } } FORGET_Frame(); /* we're ok, set the pairs count */ kern0->nPairs = num_pairs; /* the spec says that the kerning pairs must be sorted, but some brain damaged font producers don't do that correctly.. (JvR 3/4/2000) */ if ( !is_sorted( kern0->pairs, num_pairs ) ) sort_kern_pairs( kern0->pairs, num_pairs ); return TT_Err_Ok; Fail: FREE( kern0->pairs ); return error; }
static TT_Error Subtable_Load_0( TT_Kern_0* kern0, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort num_pairs, n; if ( ACCESS_Frame( 8L ) ) return error; num_pairs = GET_UShort(); kern0->nPairs = 0; kern0->searchRange = GET_UShort(); kern0->entrySelector = GET_UShort(); kern0->rangeShift = GET_UShort(); /* we only set kern0->nPairs if the subtable has been loaded */ FORGET_Frame(); if ( ALLOC_ARRAY( kern0->pairs, num_pairs, TT_Kern_0_Pair ) ) return error; if ( ACCESS_Frame( num_pairs * 6L ) ) goto Fail; for ( n = 0; n < num_pairs; n++ ) { kern0->pairs[n].left = GET_UShort(); kern0->pairs[n].right = GET_UShort(); kern0->pairs[n].value = GET_UShort(); if ( kern0->pairs[n].left >= input->numGlyphs || kern0->pairs[n].right >= input->numGlyphs ) { FORGET_Frame(); error = TT_Err_Invalid_Kerning_Table; goto Fail; } } FORGET_Frame(); /* we're ok, set the pairs count */ kern0->nPairs = num_pairs; return TT_Err_Ok; Fail: FREE( kern0->pairs ); 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 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; }
static TT_Error Load_Composite_End( UShort n_points, Short n_contours, PExecution_Context exec, PSubglyph_Record subg, UShort load_flags, TT_Stream input ) { DEFINE_LOAD_LOCALS( input ); UShort k, n_ins; PGlyph_Zone pts; if ( subg->is_hinted && subg->element_flag & WE_HAVE_INSTR ) { if ( ACCESS_Frame( 2L ) ) return error; n_ins = GET_UShort(); /* read size of instructions */ FORGET_Frame(); PTRACE4(( " Instructions size: %d\n", n_ins )); if ( n_ins > exec->face->maxProfile.maxSizeOfInstructions ) { PTRACE0(( "ERROR: Too many instructions in composite glyph %ld\n", subg->index )); return TT_Err_Too_Many_Ins; } if ( FILE_Read( exec->glyphIns, n_ins ) ) return error; error = Set_CodeRange( exec, TT_CodeRange_Glyph, exec->glyphIns, n_ins ); if ( error ) return error; } else n_ins = 0; /* prepare the execution context */ n_points += 2; exec->pts = subg->zone; pts = &exec->pts; pts->n_points = n_points; pts->n_contours = n_contours; /* add phantom points */ pts->cur[n_points - 2] = subg->pp1; pts->cur[n_points - 1] = subg->pp2; pts->touch[n_points - 1] = 0; pts->touch[n_points - 2] = 0; /* if hinting, round the phantom points */ if ( subg->is_hinted ) { pts->cur[n_points - 2].x = (subg->pp1.x + 32) & -64; pts->cur[n_points - 1].x = (subg->pp2.x + 32) & -64; } for ( k = 0; k < n_points; k++ ) pts->touch[k] &= TT_Flag_On_Curve; cur_to_org( n_points, pts ); /* now consider hinting */ if ( subg->is_hinted && n_ins > 0 ) { exec->is_composite = TRUE; exec->pedantic_hinting = load_flags & TTLOAD_PEDANTIC; error = Context_Run( exec, FALSE ); if (error && exec->pedantic_hinting) return error; } /* save glyph origin and advance points */ subg->pp1 = pts->cur[n_points - 2]; subg->pp2 = pts->cur[n_points - 1]; return TT_Err_Ok; }
static TT_Error Load_Simple_Glyph( PExecution_Context exec, TT_Stream input, Short n_contours, Short left_contours, UShort left_points, UShort load_flags, PSubglyph_Record subg ) { DEFINE_LOAD_LOCALS( input ); PGlyph_Zone pts; Short k; UShort j; UShort n_points, n_ins; PFace face; Byte* flag; TT_Vector* vec; TT_F26Dot6 x, y; face = exec->face; /* simple check */ if ( n_contours > left_contours ) { PTRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n", subg->index, n_contours, left_contours )); return TT_Err_Too_Many_Contours; } /* preparing the execution context */ mount_zone( &subg->zone, &exec->pts ); /* reading the contours endpoints */ if ( ACCESS_Frame( (n_contours + 1) * 2L ) ) return error; PTRACE4(( " Contour endpoints:" )); for ( k = 0; k < n_contours; k++ ) { exec->pts.contours[k] = GET_UShort(); PTRACE4(( " %d", exec->pts.contours[k] )); } PTRACE4(( "\n" )); if ( n_contours > 0 ) n_points = exec->pts.contours[n_contours - 1] + 1; else n_points = 0; n_ins = GET_UShort(); FORGET_Frame(); if ( n_points > left_points ) { PTRACE0(( "ERROR: Too many points in glyph %ld\n", subg->index )); return TT_Err_Too_Many_Points; } /* loading instructions */ PTRACE4(( " Instructions size: %d\n", n_ins )); if ( n_ins > face->maxProfile.maxSizeOfInstructions ) { PTRACE0(( "ERROR: Too many instructions!\n" )); return TT_Err_Too_Many_Ins; } if ( FILE_Read( exec->glyphIns, n_ins ) ) return error; if ( (error = Set_CodeRange( exec, TT_CodeRange_Glyph, exec->glyphIns, n_ins )) != TT_Err_Ok ) return error; /* read the flags */ if ( CHECK_AND_ACCESS_Frame( n_points * 5L ) ) return error; j = 0; flag = exec->pts.touch; while ( j < n_points ) { Byte c, cnt; flag[j] = c = GET_Byte(); j++; if ( c & 8 ) { cnt = GET_Byte(); while( cnt > 0 ) { flag[j++] = c; cnt--; } } } /* read the X */ x = 0; vec = exec->pts.org; for ( j = 0; j < n_points; j++ ) { if ( flag[j] & 2 ) { if ( flag[j] & 16 ) x += GET_Byte(); else x -= GET_Byte(); } else { if ( (flag[j] & 16) == 0 ) x += GET_Short(); } vec[j].x = x; } /* read the Y */ y = 0; for ( j = 0; j < n_points; j++ ) { if ( flag[j] & 4 ) { if ( flag[j] & 32 ) y += GET_Byte(); else y -= GET_Byte(); } else { if ( (flag[j] & 32) == 0 ) y += GET_Short(); } vec[j].y = y; } FORGET_Frame(); /* Now add the two shadow points at n and n + 1. */ /* We need the left side bearing and advance width. */ /* pp1 = xMin - lsb */ vec[n_points].x = subg->metrics.bbox.xMin - subg->metrics.horiBearingX; vec[n_points].y = 0; /* pp2 = pp1 + aw */ vec[n_points+1].x = vec[n_points].x + subg->metrics.horiAdvance; vec[n_points+1].y = 0; /* clear the touch flags */ for ( j = 0; j < n_points; j++ ) exec->pts.touch[j] &= TT_Flag_On_Curve; exec->pts.touch[n_points ] = 0; exec->pts.touch[n_points + 1] = 0; /* Note that we return two more points that are not */ /* part of the glyph outline. */ n_points += 2; /* now eventually scale and hint the glyph */ pts = &exec->pts; pts->n_points = n_points; pts->n_contours = n_contours; if ( (load_flags & TTLOAD_SCALE_GLYPH) == 0 ) { /* no scaling, just copy the orig arrays into the cur ones */ org_to_cur( n_points, pts ); } else { /* first scale the glyph points */ for ( j = 0; j < n_points; j++ ) { pts->org[j].x = Scale_X( &exec->metrics, pts->org[j].x ); pts->org[j].y = Scale_Y( &exec->metrics, pts->org[j].y ); } /* if hinting, round pp1, and shift the glyph accordingly */ if ( subg->is_hinted ) { x = pts->org[n_points - 2].x; x = ((x+32) & -64) - x; translate_array( n_points, pts->org, x, 0 ); org_to_cur( n_points, pts ); pts->cur[n_points - 1].x = (pts->cur[n_points - 1].x + 32) & -64; /* now consider hinting */ if ( n_ins > 0 ) { exec->is_composite = FALSE; exec->pedantic_hinting = load_flags & TTLOAD_PEDANTIC; error = Context_Run( exec, FALSE ); if (error && exec->pedantic_hinting) return error; } } else org_to_cur( n_points, pts ); } /* save glyph phantom points */ if (!subg->preserve_pps) { subg->pp1 = pts->cur[n_points - 2]; subg->pp2 = pts->cur[n_points - 1]; } return TT_Err_Ok; }