📄 ttgload.c
字号:
/******************************************************************* * * ttgload.c 1.0 * * TrueType Glyph Loader. * * Copyright 1996-1999 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify, or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/#include "tttypes.h"#include "ttdebug.h"#include "ttcalc.h"#include "ttfile.h"#include "tttables.h"#include "ttobjs.h"#include "ttgload.h"#include "ttmemory.h"#include "tttags.h"#include "ttload.h"/* required by the tracing mode */#undef TT_COMPONENT#define TT_COMPONENT trace_gload/* composite font flags */#define ARGS_ARE_WORDS 0x001#define ARGS_ARE_XY_VALUES 0x002#define ROUND_XY_TO_GRID 0x004#define WE_HAVE_A_SCALE 0x008/* reserved 0x010 */#define MORE_COMPONENTS 0x020#define WE_HAVE_AN_XY_SCALE 0x040#define WE_HAVE_A_2X2 0x080#define WE_HAVE_INSTR 0x100#define USE_MY_METRICS 0x200/********************************************************//* Return horizontal or vertical metrics in font units *//* for a given glyph. The metrics are the left side *//* bearing (resp. top side bearing) and advance width *//* (resp. advance height). *//* *//* This function will much probably move to another *//* component in the short future, but I haven't decided *//* which yet... */ LOCAL_FUNC void TT_Get_Metrics( TT_Horizontal_Header* header, UShort index, Short* bearing, UShort* advance ) { PLongMetrics longs_m; UShort k = header->number_Of_HMetrics; if ( index < k ) { longs_m = (PLongMetrics)header->long_metrics + index; *bearing = longs_m->bearing; *advance = longs_m->advance; } else { *bearing = ((PShortMetrics)header->short_metrics)[index - k]; *advance = ((PLongMetrics)header->long_metrics)[k - 1].advance; } }/********************************************************//* Return horizontal metrics in font units for a given *//* glyph. If `check' is true, take care of mono-spaced *//* fonts by returning the advance width max. */ static void Get_HMetrics( PFace face, UShort index, Bool check, Short* lsb, UShort* aw ) { TT_Get_Metrics( &face->horizontalHeader, index, lsb, aw ); if ( check && face->postscript.isFixedPitch ) *aw = face->horizontalHeader.advance_Width_Max; }/********************************************************//* Return advance width table for a given pixel size *//* if it is found in the font's `hdmx' table (if any). */ static PByte Get_Advance_Widths( PFace face, UShort ppem ) { UShort n; for ( n = 0; n < face->hdmx.num_records; n++ ) if ( face->hdmx.records[n].ppem == ppem ) return face->hdmx.records[n].widths; return NULL; }/********************************************************//* Copy current glyph into original one. */#define cur_to_org( n, zone ) \ MEM_Copy( (zone)->org, (zone)->cur, (n) * sizeof ( TT_Vector ) )/********************************************************//* copy original glyph into current one */#define org_to_cur( n, zone ) \ MEM_Copy( (zone)->cur, (zone)->org, (n) * sizeof ( TT_Vector ) )/********************************************************//* translate an array of coordinates */ static void translate_array( UShort n, TT_Vector* coords, TT_Pos delta_x, TT_Pos delta_y ) { UShort k; if ( delta_x ) for ( k = 0; k < n; k++ ) coords[k].x += delta_x; if ( delta_y ) for ( k = 0; k < n; k++ ) coords[k].y += delta_y; }/********************************************************//* mount one zone on top of another */ static void mount_zone( PGlyph_Zone source, PGlyph_Zone target ) { UShort np; Short nc; np = source->n_points; nc = source->n_contours; target->org = source->org + np; target->cur = source->cur + np; target->touch = source->touch + np; target->contours = source->contours + nc; target->n_points = 0; target->n_contours = 0; }/******************************************************************* * * Function: Load_Simple_Glyph * ******************************************************************/ 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_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; }/******************************************************************* * * Function : Load_Composite_End * ******************************************************************/ 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 ));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -