BASE_FUNC(FT_Error) FT_Read_Fields(FT_Stream stream, const FT_Frame_Field *fields, void *structure) { FT_Error error; FT_Bool frame_accessed = 0; if(!fields || !stream) { return FT_Err_Invalid_Argument; } error = FT_Err_Ok; do { FT_ULong value; FT_Int sign_shift; FT_Byte *p; switch(fields->value) { case ft_frame_start: /* access a new frame */ error = FT_Access_Frame(stream, fields->offset); if(error) { goto Exit; } frame_accessed = 1; fields++; continue; /* loop! */ case ft_frame_bytes: /* read a byte sequence */ case ft_frame_skip: /* skip some bytes */ { FT_Int len = fields->size; if(stream->cursor + len > stream->limit) { error = FT_Err_Invalid_Stream_Operation; goto Exit; } if(fields->value == ft_frame_bytes) { p = (FT_Byte *)structure + fields->offset; MEM_Copy(p, stream->cursor, len); } stream->cursor += len; fields++; continue; } case ft_frame_byte: case ft_frame_schar: /* read a single byte */ value = GET_Byte(); sign_shift = 24; break; case ft_frame_short_be: case ft_frame_ushort_be: /* read a 2-byte big-endian short */ value = GET_UShort(); sign_shift = 16; break; case ft_frame_short_le: case ft_frame_ushort_le: /* read a 2-byte little-endian short */ { FT_Byte *p; value = 0; p = stream->cursor; if(p + 1 < stream->limit) { value = (FT_UShort)p[0] | ((FT_UShort)p[1] << 8); stream->cursor += 2; } sign_shift = 16; break; } case ft_frame_long_be: case ft_frame_ulong_be: /* read a 4-byte big-endian long */ value = GET_ULong(); sign_shift = 0; break; case ft_frame_long_le: case ft_frame_ulong_le: /* read a 4-byte little-endian long */ { FT_Byte *p; value = 0; p = stream->cursor; if(p + 3 < stream->limit) { value = (FT_ULong)p[0] | ((FT_ULong)p[1] << 8) | ((FT_ULong)p[2] << 16) | ((FT_ULong)p[3] << 24); stream->cursor += 4; } sign_shift = 0; break; } case ft_frame_off3_be: case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ value = GET_UOffset(); sign_shift = 8; break; case ft_frame_off3_le: case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ { FT_Byte *p; value = 0; p = stream->cursor; if(p + 2 < stream->limit) { value = (FT_ULong)p[0] | ((FT_ULong)p[1] << 8) | ((FT_ULong)p[2] << 16); stream->cursor += 3; } sign_shift = 8; break; } default: /* otherwise, exit the loop */ goto Exit; } /* now, compute the signed value is necessary */ if(fields->value & FT_FRAME_OP_SIGNED) { value = (FT_ULong)((FT_Int32)(value << sign_shift) >> sign_shift); } /* finally, store the value in the object */ p = (FT_Byte *)structure + fields->offset; switch(fields->size) { case 1: *(FT_Byte *)p = (FT_Byte)value; break; case 2: *(FT_UShort *)p = (FT_UShort)value; break; case 4: *(FT_UInt32 *)p = (FT_UInt32)value; break; default: /* for 64-bit systems */ *(FT_ULong *)p = (FT_ULong)value; } /* go to next field */ fields++; }
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 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; }