30#ifdef TT_USE_BYTECODE_INTERPRETER
34#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
46#define FT_COMPONENT ttinterp
49#define NO_SUBPIXEL_HINTING \
50 ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
51 TT_INTERPRETER_VERSION_35 )
53#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
54#define SUBPIXEL_HINTING_MINIMAL \
55 ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
56 TT_INTERPRETER_VERSION_40 )
59#define PROJECT( v1, v2 ) \
60 exc->func_project( exc, \
61 SUB_LONG( (v1)->x, (v2)->x ), \
62 SUB_LONG( (v1)->y, (v2)->y ) )
64#define DUALPROJ( v1, v2 ) \
65 exc->func_dualproj( exc, \
66 SUB_LONG( (v1)->x, (v2)->x ), \
67 SUB_LONG( (v1)->y, (v2)->y ) )
69#define FAST_PROJECT( v ) \
70 exc->func_project( exc, (v)->x, (v)->y )
72#define FAST_DUALPROJ( v ) \
73 exc->func_dualproj( exc, (v)->x, (v)->y )
80#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
81#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
106 const TT_GraphicsState tt_default_graphics_state =
109 { 0x4000, 0 }, { 0x4000, 0 }, { 0x4000, 0 },
110 1, 1, { 0, 0, 0, 0 },
147 TT_Set_CodeRange( TT_ExecContext exec,
152 FT_ASSERT( range >= 1 && range <= 3 );
154 exec->codeRangeTable[range - 1].base = base;
155 exec->codeRangeTable[range - 1].size = length;
158 exec->codeSize = length;
160 exec->curRange = range;
161 exec->iniRange = range;
182 TT_Clear_CodeRange( TT_ExecContext exec,
185 FT_ASSERT( range >= 1 && range <= 3 );
187 exec->codeRangeTable[range - 1].base = NULL;
188 exec->codeRangeTable[range - 1].size = 0;
215 TT_Done_Context( TT_ExecContext exec )
217 FT_Memory memory = exec->memory;
222 exec->maxContours = 0;
225 FT_FREE( exec->glyfCvt );
226 exec->glyfCvtSize = 0;
229 FT_FREE( exec->glyfStorage );
230 exec->glyfStoreSize = 0;
233 FT_FREE( exec->callStack );
238 FT_FREE( exec->glyphIns );
275 FT_LOCAL_DEF( FT_Error )
276 TT_Load_Context( TT_ExecContext exec,
280 FT_Memory memory = exec->memory;
288 exec->storage = exec->stack + exec->stackSize;
289 exec->cvt = exec->storage + exec->storeSize;
292 FT_FREE( exec->glyphIns );
295 exec->pointSize = size->point_size;
296 exec->tt_metrics = size->ttmetrics;
297 exec->metrics = *size->metrics;
299 exec->twilight = size->twilight;
325 TT_Save_Context( TT_ExecContext exec,
331 size->GS.minimum_distance = exec->GS.minimum_distance;
332 size->GS.control_value_cutin = exec->GS.control_value_cutin;
333 size->GS.single_width_cutin = exec->GS.single_width_cutin;
334 size->GS.single_width_value = exec->GS.single_width_value;
335 size->GS.delta_base = exec->GS.delta_base;
336 size->GS.delta_shift = exec->GS.delta_shift;
337 size->GS.auto_flip = exec->GS.auto_flip;
338 size->GS.instruct_control = exec->GS.instruct_control;
339 size->GS.scan_control = exec->GS.scan_control;
340 size->GS.scan_type = exec->GS.scan_type;
346 FT_EXPORT_DEF( TT_ExecContext )
347 TT_New_Context( TT_Driver driver )
352 TT_ExecContext exec = NULL;
353 FT_DebugHook_Func interp;
359 memory = driver->root.root.memory;
362 if ( FT_NEW( exec ) )
367 interp = driver->root.root.library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
370 exec->interpreter = (TT_Interpreter)interp;
372 exec->interpreter = (TT_Interpreter)TT_RunIns;
375 exec->memory = memory;
378 if ( FT_QNEW_ARRAY( exec->callStack, exec->callSize ) )
405#define PACK( x, y ) ( ( x << 4 ) | y )
409 const FT_Byte Pop_Push_Count[256] =
704#ifdef FT_DEBUG_LEVEL_TRACE
711 const char*
const opcode_name[256] =
877#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1011 const FT_Char opcode_length[256] =
1013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1014 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1015 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1016 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1018 -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1019 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1020 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1021 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1023 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1024 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1026 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
1028 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1029 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1030 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1031 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1039#define TT_MulFix14( a, b ) TT_MulFix14_64( a, b )
1041 static inline FT_F26Dot6
1042 TT_MulFix14_64( FT_F26Dot6 a,
1045 FT_Int64 ab = MUL_INT64( a, b );
1048 ab = ADD_INT64( ab, 0x2000 + ( ab >> 63 ) );
1050 return (FT_F26Dot6)( ab >> 14 );
1053#elif !defined( FT_CONFIG_OPTION_NO_ASSEMBLER )
1055#if defined( __arm__ ) && \
1056 ( defined( __thumb2__ ) || !defined( __thumb__ ) )
1058#define TT_MulFix14 TT_MulFix14_arm
1060 static __inline FT_Int32
1061 TT_MulFix14_arm( FT_Int32 a,
1066#if defined( __CC_ARM ) || defined( __ARMCC__ )
1076 orr a, a, t, lsl #18
1079#elif defined( __GNUC__ )
1081 __asm__ __volatile__ (
1082 "smull %1, %2, %4, %3\n\t"
1083 "mov %0, %2, asr #31\n\t"
1084#
if defined( __clang__ ) && defined( __thumb2__ )
1085 "add.w %0, %0, #0x2000\n\t"
1087 "add %0, %0, #0x2000\n\t"
1089 "adds %1, %1, %0\n\t"
1090 "adc %2, %2, #0\n\t"
1091 "mov %0, %1, lsr #14\n\t"
1092 "orr %0, %0, %2, lsl #18\n\t"
1093 :
"=r"(a),
"=&r"(t2),
"=&r"(t)
1102#elif defined( __i386__ ) || defined( _M_IX86 )
1104#define TT_MulFix14 TT_MulFix14_i386
1108 static __inline FT_Int32
1109 TT_MulFixi14_i386( FT_Int32 a,
1114#if defined( __GNUC__ )
1116 __asm__ __volatile__ (
1118 "movl %%edx, %%ecx\n"
1120 "addl $0x2000, %%ecx\n"
1121 "addl %%ecx, %%eax\n"
1125 "addl %%edx, %%eax\n"
1126 :
"=a"(result),
"=d"(b)
1130#elif defined( _MSC_VER)
1164 TT_MulFix14( FT_Int32 a,
1172 l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1173 m = ( a >> 16 ) * b;
1175 lo = l + ( (FT_UInt32)m << 16 );
1176 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
1179 l = lo + 0x2000U + (FT_UInt32)( hi >> 31 );
1182 return (FT_F26Dot6)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1191 static inline FT_F26Dot6
1192 TT_DotFix14( FT_F26Dot6 ax,
1197 FT_Int64 c = ADD_INT64( MUL_INT64( ax, bx ), MUL_INT64( ay, by ) );
1200 c = ADD_INT64( c, 0x2000 + ( c >> 63 ) );
1202 return (FT_F26Dot6)( c >> 14 );
1207 static inline FT_F26Dot6
1208 TT_DotFix14( FT_F26Dot6 ax,
1213 FT_Int32 m, hi1, hi2, hi;
1214 FT_UInt32 l, lo1, lo2, lo;
1218 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1219 m = ( ax >> 16 ) * bx;
1221 lo1 = l + ( (FT_UInt32)m << 16 );
1222 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
1225 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1226 m = ( ay >> 16 ) * by;
1228 lo2 = l + ( (FT_UInt32)m << 16 );
1229 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
1233 hi = hi1 + hi2 + ( lo < lo1 );
1236 l = lo + 0x2000U + (FT_UInt32)( hi >> 31 );
1239 return (FT_F26Dot6)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1258 Current_Ratio( TT_ExecContext exc )
1260 if ( !exc->tt_metrics.ratio )
1262 if ( exc->GS.projVector.y == 0 )
1263 exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
1265 else if ( exc->GS.projVector.x == 0 )
1266 exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
1273 x = TT_MulFix14( exc->tt_metrics.x_ratio,
1274 exc->GS.projVector.x );
1275 y = TT_MulFix14( exc->tt_metrics.y_ratio,
1276 exc->GS.projVector.y );
1277 exc->tt_metrics.ratio = FT_Hypot( x, y );
1280 return exc->tt_metrics.ratio;
1284 FT_CALLBACK_DEF( FT_Long )
1285 Current_Ppem( TT_ExecContext exc )
1287 return exc->tt_metrics.ppem;
1291 FT_CALLBACK_DEF( FT_Long )
1292 Current_Ppem_Stretched( TT_ExecContext exc )
1294 return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) );
1305 FT_CALLBACK_DEF( FT_F26Dot6 )
1306 Read_CVT( TT_ExecContext exc,
1309 return exc->cvt[idx];
1313 FT_CALLBACK_DEF( FT_F26Dot6 )
1314 Read_CVT_Stretched( TT_ExecContext exc,
1317 return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) );
1322 Modify_CVT_Check( TT_ExecContext exc )
1324 if ( exc->iniRange == tt_coderange_glyph &&
1325 exc->cvt != exc->glyfCvt )
1327 FT_Memory memory = exc->memory;
1331 FT_MEM_QRENEW_ARRAY( exc->glyfCvt, exc->glyfCvtSize, exc->cvtSize );
1336 exc->glyfCvtSize = exc->cvtSize;
1337 FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize );
1338 exc->cvt = exc->glyfCvt;
1343 FT_CALLBACK_DEF(
void )
1344 Write_CVT( TT_ExecContext exc,
1348 Modify_CVT_Check( exc );
1352 exc->cvt[idx] = value;
1356 FT_CALLBACK_DEF(
void )
1357 Write_CVT_Stretched( TT_ExecContext exc,
1361 Modify_CVT_Check( exc );
1365 exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
1369 FT_CALLBACK_DEF(
void )
1370 Move_CVT( TT_ExecContext exc,
1374 Modify_CVT_Check( exc );
1378 exc->cvt[idx] = ADD_LONG( exc->cvt[idx], value );
1382 FT_CALLBACK_DEF(
void )
1383 Move_CVT_Stretched( TT_ExecContext exc,
1387 Modify_CVT_Check( exc );
1391 exc->cvt[idx] = ADD_LONG( exc->cvt[idx],
1392 FT_DivFix( value, Current_Ratio( exc ) ) );
1415 Ins_Goto_CodeRange( TT_ExecContext exc,
1419 TT_CodeRange* range;
1422 if ( aRange < 1 || aRange > 3 )
1424 exc->error = FT_THROW( Bad_Argument );
1428 range = &exc->codeRangeTable[aRange - 1];
1432 exc->error = FT_THROW( Invalid_CodeRange );
1440 if ( aIP > range->size )
1442 exc->error = FT_THROW( Code_Overflow );
1446 exc->code = range->base;
1447 exc->codeSize = range->size;
1450 exc->curRange = aRange;
1507 Direct_Move( TT_ExecContext exc,
1510 FT_F26Dot6 distance )
1515 v = exc->moveVector.x;
1518#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1522 if ( !exc->backward_compatibility )
1524 zone->cur[point].x = ADD_LONG( zone->cur[point].x,
1525 FT_MulFix( distance, v ) );
1527 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1530 v = exc->moveVector.y;
1533#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1535 if ( exc->backward_compatibility != 0x7 )
1537 zone->cur[point].y = ADD_LONG( zone->cur[point].y,
1538 FT_MulFix( distance, v ) );
1540 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1566 Direct_Move_Orig( TT_ExecContext exc,
1569 FT_F26Dot6 distance )
1574 v = exc->moveVector.x;
1577 zone->org[point].x = ADD_LONG( zone->org[point].x,
1578 FT_MulFix( distance, v ) );
1580 v = exc->moveVector.y;
1583 zone->org[point].y = ADD_LONG( zone->org[point].y,
1584 FT_MulFix( distance, v ) );
1600 Direct_Move_X( TT_ExecContext exc,
1603 FT_F26Dot6 distance )
1605#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1606 if ( !exc->backward_compatibility )
1608 zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
1610 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1615 Direct_Move_Y( TT_ExecContext exc,
1618 FT_F26Dot6 distance )
1622#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1624 if ( exc->backward_compatibility != 0x7 )
1626 zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance );
1628 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1643 Direct_Move_Orig_X( TT_ExecContext exc,
1646 FT_F26Dot6 distance )
1650 zone->org[point].x = ADD_LONG( zone->org[point].x, distance );
1655 Direct_Move_Orig_Y( TT_ExecContext exc,
1658 FT_F26Dot6 distance )
1662 zone->org[point].y = ADD_LONG( zone->org[point].y, distance );
1684 Round_None( TT_ExecContext exc,
1685 FT_F26Dot6 distance,
1686 FT_F26Dot6 compensation )
1692 if ( distance >= 0 )
1694 val = ADD_LONG( distance, compensation );
1700 val = SUB_LONG( distance, compensation );
1727 Round_To_Grid( TT_ExecContext exc,
1728 FT_F26Dot6 distance,
1729 FT_F26Dot6 compensation )
1735 if ( distance >= 0 )
1737 val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) );
1743 val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation,
1772 Round_To_Half_Grid( TT_ExecContext exc,
1773 FT_F26Dot6 distance,
1774 FT_F26Dot6 compensation )
1780 if ( distance >= 0 )
1782 val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ),
1789 val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation,
1819 Round_Down_To_Grid( TT_ExecContext exc,
1820 FT_F26Dot6 distance,
1821 FT_F26Dot6 compensation )
1827 if ( distance >= 0 )
1829 val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) );
1835 val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) );
1863 Round_Up_To_Grid( TT_ExecContext exc,
1864 FT_F26Dot6 distance,
1865 FT_F26Dot6 compensation )
1871 if ( distance >= 0 )
1873 val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) );
1879 val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation,
1908 Round_To_Double_Grid( TT_ExecContext exc,
1909 FT_F26Dot6 distance,
1910 FT_F26Dot6 compensation )
1916 if ( distance >= 0 )
1918 val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 );
1924 val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ),
1959 Round_Super( TT_ExecContext exc,
1960 FT_F26Dot6 distance,
1961 FT_F26Dot6 compensation )
1966 if ( distance >= 0 )
1968 val = ADD_LONG( distance,
1969 exc->threshold - exc->phase + compensation ) &
1971 val = ADD_LONG( val, exc->phase );
1977 val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation,
1980 val = SUB_LONG( val, exc->phase );
2012 Round_Super_45( TT_ExecContext exc,
2013 FT_F26Dot6 distance,
2014 FT_F26Dot6 compensation )
2019 if ( distance >= 0 )
2021 val = ( ADD_LONG( distance,
2022 exc->threshold - exc->phase + compensation ) /
2023 exc->period ) * exc->period;
2024 val = ADD_LONG( val, exc->phase );
2030 val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation,
2032 exc->period ) * exc->period );
2033 val = SUB_LONG( val, exc->phase );
2058 SetSuperRound( TT_ExecContext exc,
2059 FT_F2Dot14 GridPeriod,
2062 switch ( (FT_Int)( selector & 0xC0 ) )
2065 exc->period = GridPeriod / 2;
2069 exc->period = GridPeriod;
2073 exc->period = GridPeriod * 2;
2078 exc->period = GridPeriod;
2082 switch ( (FT_Int)( selector & 0x30 ) )
2089 exc->phase = exc->period / 4;
2093 exc->phase = exc->period / 2;
2097 exc->phase = exc->period * 3 / 4;
2101 if ( ( selector & 0x0F ) == 0 )
2102 exc->threshold = exc->period - 1;
2104 exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8;
2109 exc->threshold >>= 8;
2132 Project( TT_ExecContext exc,
2136 return TT_DotFix14( dx, dy,
2137 exc->GS.projVector.x,
2138 exc->GS.projVector.y );
2161 Dual_Project( TT_ExecContext exc,
2165 return TT_DotFix14( dx, dy,
2166 exc->GS.dualVector.x,
2167 exc->GS.dualVector.y );
2190 Project_x( TT_ExecContext exc,
2220 Project_y( TT_ExecContext exc,
2241 Compute_Funcs( TT_ExecContext exc )
2244 ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
2245 (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y +
2249 if ( F_dot_P >= 0x3FFEL )
2252 exc->moveVector.x = exc->GS.freeVector.x * 4;
2253 exc->moveVector.y = exc->GS.freeVector.y * 4;
2255 else if ( -0x400L < F_dot_P && F_dot_P < 0x400L )
2258 exc->moveVector.x = 0;
2259 exc->moveVector.y = 0;
2263 exc->moveVector.x = exc->GS.freeVector.x * 0x10000L / F_dot_P;
2264 exc->moveVector.y = exc->GS.freeVector.y * 0x10000L / F_dot_P;
2267 if ( F_dot_P >= 0x3FFEL && exc->GS.freeVector.x == 0x4000 )
2269 exc->func_move = (TT_Move_Func)Direct_Move_X;
2270 exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2272 else if ( F_dot_P >= 0x3FFEL && exc->GS.freeVector.y == 0x4000 )
2274 exc->func_move = (TT_Move_Func)Direct_Move_Y;
2275 exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2279 exc->func_move = (TT_Move_Func)Direct_Move;
2280 exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig;
2283 if ( exc->GS.projVector.x == 0x4000 )
2284 exc->func_project = (TT_Project_Func)Project_x;
2285 else if ( exc->GS.projVector.y == 0x4000 )
2286 exc->func_project = (TT_Project_Func)Project_y;
2288 exc->func_project = (TT_Project_Func)Project;
2290 if ( exc->GS.dualVector.x == 0x4000 )
2291 exc->func_dualproj = (TT_Project_Func)Project_x;
2292 else if ( exc->GS.dualVector.y == 0x4000 )
2293 exc->func_dualproj = (TT_Project_Func)Project_y;
2295 exc->func_dualproj = (TT_Project_Func)Dual_Project;
2298 exc->tt_metrics.ratio = 0;
2328 Normalize( FT_F26Dot6 Vx,
2335 if ( Vx == 0 && Vy == 0 )
2345 FT_Vector_NormLen( &V );
2347 R->x = (FT_F2Dot14)( V.x / 4 );
2348 R->y = (FT_F2Dot14)( V.y / 4 );
2361#define ARRAY_BOUND_ERROR \
2364 exc->error = FT_THROW( Invalid_Reference ); \
2376 Ins_MPPEM( TT_ExecContext exc,
2379 args[0] = exc->func_cur_ppem( exc );
2390 Ins_MPS( TT_ExecContext exc,
2393 if ( NO_SUBPIXEL_HINTING )
2397 args[0] = exc->func_cur_ppem( exc );
2405 args[0] = exc->pointSize;
2417 Ins_DUP( FT_Long* args )
2443 Ins_CLEAR( TT_ExecContext exc )
2456 Ins_SWAP( FT_Long* args )
2474 Ins_DEPTH( TT_ExecContext exc,
2488 Ins_LT( FT_Long* args )
2490 args[0] = ( args[0] < args[1] );
2501 Ins_LTEQ( FT_Long* args )
2503 args[0] = ( args[0] <= args[1] );
2514 Ins_GT( FT_Long* args )
2516 args[0] = ( args[0] > args[1] );
2527 Ins_GTEQ( FT_Long* args )
2529 args[0] = ( args[0] >= args[1] );
2540 Ins_EQ( FT_Long* args )
2542 args[0] = ( args[0] == args[1] );
2553 Ins_NEQ( FT_Long* args )
2555 args[0] = ( args[0] != args[1] );
2566 Ins_ODD( TT_ExecContext exc,
2569 args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 64 ) == 64 );
2580 Ins_EVEN( TT_ExecContext exc,
2583 args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 64 ) == 0 );
2594 Ins_AND( FT_Long* args )
2596 args[0] = ( args[0] && args[1] );
2607 Ins_OR( FT_Long* args )
2609 args[0] = ( args[0] || args[1] );
2620 Ins_NOT( FT_Long* args )
2633 Ins_ADD( FT_Long* args )
2635 args[0] = ADD_LONG( args[0], args[1] );
2646 Ins_SUB( FT_Long* args )
2648 args[0] = SUB_LONG( args[0], args[1] );
2659 Ins_DIV( TT_ExecContext exc,
2663 exc->error = FT_THROW( Divide_By_Zero );
2665 args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
2676 Ins_MUL( FT_Long* args )
2678 args[0] = FT_MulDiv( args[0], args[1], 64L );
2689 Ins_ABS( FT_Long* args )
2692 args[0] = NEG_LONG( args[0] );
2703 Ins_NEG( FT_Long* args )
2705 args[0] = NEG_LONG( args[0] );
2716 Ins_FLOOR( FT_Long* args )
2718 args[0] = FT_PIX_FLOOR( args[0] );
2729 Ins_CEILING( FT_Long* args )
2731 args[0] = FT_PIX_CEIL_LONG( args[0] );
2742 Ins_RS( TT_ExecContext exc,
2745 FT_ULong I = (FT_ULong)args[0];
2748 if ( BOUNDSL( I, exc->storeSize ) )
2750 if ( exc->pedantic_hinting )
2756 args[0] = exc->storage[I];
2767 Ins_WS( TT_ExecContext exc,
2770 FT_ULong I = (FT_ULong)args[0];
2773 if ( BOUNDSL( I, exc->storeSize ) )
2775 if ( exc->pedantic_hinting )
2780 if ( exc->iniRange == tt_coderange_glyph &&
2781 exc->storage != exc->glyfStorage )
2783 FT_Memory memory = exc->memory;
2787 FT_MEM_QRENEW_ARRAY( exc->glyfStorage,
2794 exc->glyfStoreSize = exc->storeSize;
2795 FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize );
2796 exc->storage = exc->glyfStorage;
2799 exc->storage[I] = args[1];
2811 Ins_WCVTP( TT_ExecContext exc,
2814 FT_ULong I = (FT_ULong)args[0];
2817 if ( BOUNDSL( I, exc->cvtSize ) )
2819 if ( exc->pedantic_hinting )
2823 exc->func_write_cvt( exc, I, args[1] );
2834 Ins_WCVTF( TT_ExecContext exc,
2837 FT_ULong I = (FT_ULong)args[0];
2840 if ( BOUNDSL( I, exc->cvtSize ) )
2842 if ( exc->pedantic_hinting )
2846 exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale );
2857 Ins_RCVT( TT_ExecContext exc,
2860 FT_ULong I = (FT_ULong)args[0];
2863 if ( BOUNDSL( I, exc->cvtSize ) )
2865 if ( exc->pedantic_hinting )
2871 args[0] = exc->func_read_cvt( exc, I );
2897 Ins_DEBUG( TT_ExecContext exc )
2899 exc->error = FT_THROW( Debug_OpCode );
2910 Ins_ROUND( TT_ExecContext exc,
2913 args[0] = exc->func_round( exc, args[0],
2914 exc->GS.compensation[exc->opcode & 3] );
2925 Ins_NROUND( TT_ExecContext exc,
2928 args[0] = Round_None( exc, args[0],
2929 exc->GS.compensation[exc->opcode & 3] );
2940 Ins_MAX( FT_Long* args )
2942 if ( args[1] > args[0] )
2954 Ins_MIN( FT_Long* args )
2956 if ( args[1] < args[0] )
2968 Ins_MINDEX( TT_ExecContext exc,
2976 if ( L <= 0 || L > exc->args )
2978 if ( exc->pedantic_hinting )
2979 exc->error = FT_THROW( Invalid_Reference );
2985 FT_ARRAY_MOVE( args - L, args - L + 1, L - 1 );
2999 Ins_CINDEX( TT_ExecContext exc,
3007 if ( L <= 0 || L > exc->args )
3009 if ( exc->pedantic_hinting )
3010 exc->error = FT_THROW( Invalid_Reference );
3025 Ins_ROLL( FT_Long* args )
3054 Ins_SLOOP( TT_ExecContext exc,
3058 exc->error = FT_THROW( Bad_Argument );
3062 exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0];
3068 SkipCode( TT_ExecContext exc )
3070 exc->IP += exc->length;
3072 if ( exc->IP < exc->codeSize )
3074 exc->opcode = exc->code[exc->IP];
3076 exc->length = opcode_length[exc->opcode];
3077 if ( exc->length < 0 )
3079 if ( exc->IP + 1 >= exc->codeSize )
3081 exc->length = 2 - exc->length * exc->code[exc->IP + 1];
3088 exc->error = FT_THROW( Code_Overflow );
3100 Ins_IF( TT_ExecContext exc,
3115 if ( SkipCode( exc ) == FAILURE )
3118 switch ( exc->opcode )
3125 Out = FT_BOOL( nIfs == 1 );
3130 Out = FT_BOOL( nIfs == 0 );
3136 }
while ( Out == 0 );
3147 Ins_ELSE( TT_ExecContext exc )
3156 if ( SkipCode( exc ) == FAILURE )
3159 switch ( exc->opcode )
3172 }
while ( nIfs != 0 );
3196 Ins_JMPR( TT_ExecContext exc,
3199 if ( args[0] == 0 && exc->args == 0 )
3201 exc->error = FT_THROW( Bad_Argument );
3205 exc->IP = ADD_LONG( exc->IP, args[0] );
3207 ( exc->callTop > 0 &&
3208 exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
3210 exc->error = FT_THROW( Bad_Argument );
3218 if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max )
3219 exc->error = FT_THROW( Execution_Too_Long );
3231 Ins_JROT( TT_ExecContext exc,
3235 Ins_JMPR( exc, args );
3246 Ins_JROF( TT_ExecContext exc,
3250 Ins_JMPR( exc, args );
3268 Ins_FDEF( TT_ExecContext exc,
3273 TT_DefRecord* limit;
3277 if ( exc->iniRange == tt_coderange_glyph )
3279 exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
3287 limit = FT_OFFSET( rec, exc->numFDefs );
3288 n = (FT_ULong)args[0];
3290 for ( ; rec < limit; rec++ )
3292 if ( rec->opc == n )
3299 if ( exc->numFDefs >= exc->maxFDefs )
3301 exc->error = FT_THROW( Too_Many_Function_Defs );
3311 exc->error = FT_THROW( Too_Many_Function_Defs );
3315 rec->range = exc->curRange;
3316 rec->opc = (FT_UInt16)n;
3317 rec->start = exc->IP + 1;
3320 if ( n > exc->maxFunc )
3321 exc->maxFunc = (FT_UInt16)n;
3326 while ( SkipCode( exc ) == SUCCESS )
3328 switch ( exc->opcode )
3332 exc->error = FT_THROW( Nested_DEFS );
3353 Ins_ENDF( TT_ExecContext exc )
3358 if ( exc->callTop <= 0 )
3360 exc->error = FT_THROW( ENDF_In_Exec_Stream );
3366 pRec = &exc->callStack[exc->callTop];
3370 if ( pRec->Cur_Count > 0 )
3373 exc->IP = pRec->Def->start;
3378 Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP );
3397 Ins_CALL( TT_ExecContext exc,
3407 F = (FT_ULong)args[0];
3408 if ( BOUNDSL( F, exc->maxFunc + 1 ) )
3423 def = exc->FDefs + F;
3424 if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
3427 TT_DefRecord* limit;
3431 limit = def + exc->numFDefs;
3433 while ( def < limit && def->opc != F )
3445 if ( exc->callTop >= exc->callSize )
3447 exc->error = FT_THROW( Stack_Overflow );
3451 pCrec = exc->callStack + exc->callTop;
3453 pCrec->Caller_Range = exc->curRange;
3454 pCrec->Caller_IP = exc->IP + 1;
3455 pCrec->Cur_Count = 1;
3460 Ins_Goto_CodeRange( exc, def->range, def->start );
3465 exc->error = FT_THROW( Invalid_Reference );
3476 Ins_LOOPCALL( TT_ExecContext exc,
3485 F = (FT_ULong)args[1];
3486 if ( BOUNDSL( F, exc->maxFunc + 1 ) )
3498 def = FT_OFFSET( exc->FDefs, F );
3499 if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
3502 TT_DefRecord* limit;
3506 limit = FT_OFFSET( def, exc->numFDefs );
3508 while ( def < limit && def->opc != F )
3520 if ( exc->callTop >= exc->callSize )
3522 exc->error = FT_THROW( Stack_Overflow );
3528 pCrec = exc->callStack + exc->callTop;
3530 pCrec->Caller_Range = exc->curRange;
3531 pCrec->Caller_IP = exc->IP + 1;
3532 pCrec->Cur_Count = (FT_Int)args[0];
3537 Ins_Goto_CodeRange( exc, def->range, def->start );
3539 exc->loopcall_counter += (FT_ULong)args[0];
3540 if ( exc->loopcall_counter > exc->loopcall_counter_max )
3541 exc->error = FT_THROW( Execution_Too_Long );
3547 exc->error = FT_THROW( Invalid_Reference );
3558 Ins_IDEF( TT_ExecContext exc,
3562 TT_DefRecord* limit;
3566 if ( exc->iniRange == tt_coderange_glyph )
3568 exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
3575 limit = FT_OFFSET( def, exc->numIDefs );
3577 for ( ; def < limit; def++ )
3578 if ( def->opc == (FT_ULong)args[0] )
3584 if ( exc->numIDefs >= exc->maxIDefs )
3586 exc->error = FT_THROW( Too_Many_Instruction_Defs );
3593 if ( 0 > args[0] || args[0] > 0x00FF )
3595 exc->error = FT_THROW( Too_Many_Instruction_Defs );
3599 def->opc = (FT_Byte)args[0];
3600 def->start = exc->IP + 1;
3601 def->range = exc->curRange;
3604 if ( (FT_ULong)args[0] > exc->maxIns )
3605 exc->maxIns = (FT_Byte)args[0];
3610 while ( SkipCode( exc ) == SUCCESS )
3612 switch ( exc->opcode )
3616 exc->error = FT_THROW( Nested_DEFS );
3644 Ins_NPUSHB( TT_ExecContext exc,
3647 FT_Long IP = exc->IP;
3651 if ( ++IP >= exc->codeSize )
3653 exc->error = FT_THROW( Code_Overflow );
3659 if ( IP + L >= exc->codeSize )
3661 exc->error = FT_THROW( Code_Overflow );
3665 if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
3667 exc->error = FT_THROW( Stack_Overflow );
3671 for ( K = 0; K < L; K++ )
3672 args[K] = exc->code[++IP];
3686 Ins_NPUSHW( TT_ExecContext exc,
3689 FT_Long IP = exc->IP;
3693 if ( ++IP >= exc->codeSize )
3695 exc->error = FT_THROW( Code_Overflow );
3701 if ( IP + 2 * L >= exc->codeSize )
3703 exc->error = FT_THROW( Code_Overflow );
3707 if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
3709 exc->error = FT_THROW( Stack_Overflow );
3714 for ( K = 0; K < L; K++, IP += 2 )
3715 args[K] = (FT_Short)( exc->code[IP + 1] << 8 ) | exc->code[IP + 2];
3729 Ins_PUSHB( TT_ExecContext exc,
3732 FT_Long IP = exc->IP;
3736 L = exc->opcode - 0xB0 + 1;
3738 if ( IP + L >= exc->codeSize )
3740 exc->error = FT_THROW( Code_Overflow );
3744 if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
3746 exc->error = FT_THROW( Stack_Overflow );
3750 for ( K = 0; K < L; K++ )
3751 args[K] = exc->code[++IP];
3764 Ins_PUSHW( TT_ExecContext exc,
3767 FT_Long IP = exc->IP;
3771 L = exc->opcode - 0xB8 + 1;
3773 if ( IP + 2 * L >= exc->codeSize )
3775 exc->error = FT_THROW( Code_Overflow );
3779 if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
3781 exc->error = FT_THROW( Stack_Overflow );
3786 for ( K = 0; K < L; K++, IP += 2 )
3787 args[K] = (FT_Short)( exc->code[IP + 1] << 8 ) | exc->code[IP + 2];
3801 Ins_SxVTL( TT_ExecContext exc,
3804 FT_UnitVector* Vec )
3810 FT_Byte opcode = exc->opcode;
3813 if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
3814 BOUNDS( aIdx2, exc->zp1.n_points ) )
3816 if ( exc->pedantic_hinting )
3817 exc->error = FT_THROW( Invalid_Reference );
3821 p1 = exc->zp1.cur + aIdx2;
3822 p2 = exc->zp2.cur + aIdx1;
3824 A = SUB_LONG( p1->x, p2->x );
3825 B = SUB_LONG( p1->y, p2->y );
3832 if ( A == 0 && B == 0 )
3838 if ( ( opcode & 1 ) != 0 )
3845 Normalize( A, B, Vec );
3866 Ins_SxyTCA( TT_ExecContext exc )
3870 FT_Byte opcode = exc->opcode;
3873 AA = (FT_Short)( ( opcode & 1 ) << 14 );
3874 BB = (FT_Short)( AA ^ 0x4000 );
3878 exc->GS.projVector.x = AA;
3879 exc->GS.projVector.y = BB;
3881 exc->GS.dualVector.x = AA;
3882 exc->GS.dualVector.y = BB;
3885 if ( ( opcode & 2 ) == 0 )
3887 exc->GS.freeVector.x = AA;
3888 exc->GS.freeVector.y = BB;
3891 Compute_Funcs( exc );
3902 Ins_SPVTL( TT_ExecContext exc,
3905 if ( Ins_SxVTL( exc,
3908 &exc->GS.projVector ) == SUCCESS )
3910 exc->GS.dualVector = exc->GS.projVector;
3911 Compute_Funcs( exc );
3923 Ins_SFVTL( TT_ExecContext exc,
3926 if ( Ins_SxVTL( exc,
3929 &exc->GS.freeVector ) == SUCCESS )
3931 Compute_Funcs( exc );
3943 Ins_SFVTPV( TT_ExecContext exc )
3945 exc->GS.freeVector = exc->GS.projVector;
3946 Compute_Funcs( exc );
3957 Ins_SPVFS( TT_ExecContext exc,
3964 Y = (FT_Short)args[1];
3965 X = (FT_Short)args[0];
3967 Normalize( X, Y, &exc->GS.projVector );
3969 exc->GS.dualVector = exc->GS.projVector;
3970 Compute_Funcs( exc );
3981 Ins_SFVFS( TT_ExecContext exc,
3988 Y = (FT_Short)args[1];
3989 X = (FT_Short)args[0];
3991 Normalize( X, Y, &exc->GS.freeVector );
3992 Compute_Funcs( exc );
4003 Ins_GPV( TT_ExecContext exc,
4006 args[0] = exc->GS.projVector.x;
4007 args[1] = exc->GS.projVector.y;
4018 Ins_GFV( TT_ExecContext exc,
4021 args[0] = exc->GS.freeVector.x;
4022 args[1] = exc->GS.freeVector.y;
4033 Ins_SRP0( TT_ExecContext exc,
4036 exc->GS.rp0 = (FT_UShort)args[0];
4047 Ins_SRP1( TT_ExecContext exc,
4050 exc->GS.rp1 = (FT_UShort)args[0];
4061 Ins_SRP2( TT_ExecContext exc,
4064 exc->GS.rp2 = (FT_UShort)args[0];
4075 Ins_SMD( TT_ExecContext exc,
4078 exc->GS.minimum_distance = args[0];
4089 Ins_SCVTCI( TT_ExecContext exc,
4092 exc->GS.control_value_cutin = (FT_F26Dot6)args[0];
4103 Ins_SSWCI( TT_ExecContext exc,
4106 exc->GS.single_width_cutin = (FT_F26Dot6)args[0];
4117 Ins_SSW( TT_ExecContext exc,
4120 exc->GS.single_width_value = FT_MulFix( args[0],
4121 exc->tt_metrics.scale );
4132 Ins_FLIPON( TT_ExecContext exc )
4134 exc->GS.auto_flip = TRUE;
4145 Ins_FLIPOFF( TT_ExecContext exc )
4147 exc->GS.auto_flip = FALSE;
4171 Ins_SDB( TT_ExecContext exc,
4174 exc->GS.delta_base = (FT_UShort)args[0];
4185 Ins_SDS( TT_ExecContext exc,
4188 if ( (FT_ULong)args[0] > 6UL )
4189 exc->error = FT_THROW( Bad_Argument );
4191 exc->GS.delta_shift = (FT_UShort)args[0];
4202 Ins_RTHG( TT_ExecContext exc )
4204 exc->GS.round_state = TT_Round_To_Half_Grid;
4205 exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
4216 Ins_RTG( TT_ExecContext exc )
4218 exc->GS.round_state = TT_Round_To_Grid;
4219 exc->func_round = (TT_Round_Func)Round_To_Grid;
4229 Ins_RTDG( TT_ExecContext exc )
4231 exc->GS.round_state = TT_Round_To_Double_Grid;
4232 exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
4242 Ins_RUTG( TT_ExecContext exc )
4244 exc->GS.round_state = TT_Round_Up_To_Grid;
4245 exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
4256 Ins_RDTG( TT_ExecContext exc )
4258 exc->GS.round_state = TT_Round_Down_To_Grid;
4259 exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
4270 Ins_ROFF( TT_ExecContext exc )
4272 exc->GS.round_state = TT_Round_Off;
4273 exc->func_round = (TT_Round_Func)Round_None;
4284 Ins_SROUND( TT_ExecContext exc,
4287 SetSuperRound( exc, 0x4000, args[0] );
4289 exc->GS.round_state = TT_Round_Super;
4290 exc->func_round = (TT_Round_Func)Round_Super;
4301 Ins_S45ROUND( TT_ExecContext exc,
4304 SetSuperRound( exc, 0x2D41, args[0] );
4306 exc->GS.round_state = TT_Round_Super_45;
4307 exc->func_round = (TT_Round_Func)Round_Super_45;
4321 Ins_GC( TT_ExecContext exc,
4328 L = (FT_ULong)args[0];
4330 if ( BOUNDSL( L, exc->zp2.n_points ) )
4332 if ( exc->pedantic_hinting )
4333 exc->error = FT_THROW( Invalid_Reference );
4338 if ( exc->opcode & 1 )
4339 R = FAST_DUALPROJ( &exc->zp2.org[L] );
4341 R = FAST_PROJECT( &exc->zp2.cur[L] );
4359 Ins_SCFS( TT_ExecContext exc,
4366 L = (FT_UShort)args[0];
4368 if ( BOUNDS( L, exc->zp2.n_points ) )
4370 if ( exc->pedantic_hinting )
4371 exc->error = FT_THROW( Invalid_Reference );
4375 K = FAST_PROJECT( &exc->zp2.cur[L] );
4377 exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) );
4381 if ( exc->GS.gep2 == 0 )
4382 exc->zp2.org[L] = exc->zp2.cur[L];
4402 Ins_MD( TT_ExecContext exc,
4409 K = (FT_UShort)args[1];
4410 L = (FT_UShort)args[0];
4412 if ( BOUNDS( L, exc->zp0.n_points ) ||
4413 BOUNDS( K, exc->zp1.n_points ) )
4415 if ( exc->pedantic_hinting )
4416 exc->error = FT_THROW( Invalid_Reference );
4421 if ( exc->opcode & 1 )
4422 D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K );
4427 if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
4429 FT_Vector* vec1 = exc->zp0.org + L;
4430 FT_Vector* vec2 = exc->zp1.org + K;
4433 D = DUALPROJ( vec1, vec2 );
4437 FT_Vector* vec1 = exc->zp0.orus + L;
4438 FT_Vector* vec2 = exc->zp1.orus + K;
4441 if ( exc->metrics.x_scale == exc->metrics.y_scale )
4444 D = DUALPROJ( vec1, vec2 );
4445 D = FT_MulFix( D, exc->metrics.x_scale );
4452 vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
4453 vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
4455 D = FAST_DUALPROJ( &vec );
4472 Ins_SDPVTL( TT_ExecContext exc,
4478 FT_Byte opcode = exc->opcode;
4481 p1 = (FT_UShort)args[1];
4482 p2 = (FT_UShort)args[0];
4484 if ( BOUNDS( p2, exc->zp1.n_points ) ||
4485 BOUNDS( p1, exc->zp2.n_points ) )
4487 if ( exc->pedantic_hinting )
4488 exc->error = FT_THROW( Invalid_Reference );
4493 FT_Vector* v1 = exc->zp1.org + p2;
4494 FT_Vector* v2 = exc->zp2.org + p1;
4497 A = SUB_LONG( v1->x, v2->x );
4498 B = SUB_LONG( v1->y, v2->y );
4505 if ( A == 0 && B == 0 )
4512 if ( ( opcode & 1 ) != 0 )
4519 Normalize( A, B, &exc->GS.dualVector );
4522 FT_Vector* v1 = exc->zp1.cur + p2;
4523 FT_Vector* v2 = exc->zp2.cur + p1;
4526 A = SUB_LONG( v1->x, v2->x );
4527 B = SUB_LONG( v1->y, v2->y );
4529 if ( A == 0 && B == 0 )
4536 if ( ( opcode & 1 ) != 0 )
4543 Normalize( A, B, &exc->GS.projVector );
4544 Compute_Funcs( exc );
4555 Ins_SZP0( TT_ExecContext exc,
4558 switch ( (FT_Int)args[0] )
4561 exc->zp0 = exc->twilight;
4565 exc->zp0 = exc->pts;
4569 if ( exc->pedantic_hinting )
4570 exc->error = FT_THROW( Invalid_Reference );
4574 exc->GS.gep0 = (FT_UShort)args[0];
4585 Ins_SZP1( TT_ExecContext exc,
4588 switch ( (FT_Int)args[0] )
4591 exc->zp1 = exc->twilight;
4595 exc->zp1 = exc->pts;
4599 if ( exc->pedantic_hinting )
4600 exc->error = FT_THROW( Invalid_Reference );
4604 exc->GS.gep1 = (FT_UShort)args[0];
4615 Ins_SZP2( TT_ExecContext exc,
4618 switch ( (FT_Int)args[0] )
4621 exc->zp2 = exc->twilight;
4625 exc->zp2 = exc->pts;
4629 if ( exc->pedantic_hinting )
4630 exc->error = FT_THROW( Invalid_Reference );
4634 exc->GS.gep2 = (FT_UShort)args[0];
4645 Ins_SZPS( TT_ExecContext exc,
4648 switch ( (FT_Int)args[0] )
4651 exc->zp0 = exc->twilight;
4655 exc->zp0 = exc->pts;
4659 if ( exc->pedantic_hinting )
4660 exc->error = FT_THROW( Invalid_Reference );
4664 exc->zp1 = exc->zp0;
4665 exc->zp2 = exc->zp0;
4667 exc->GS.gep0 = (FT_UShort)args[0];
4668 exc->GS.gep1 = (FT_UShort)args[0];
4669 exc->GS.gep2 = (FT_UShort)args[0];
4680 Ins_INSTCTRL( TT_ExecContext exc,
4686 K = (FT_ULong)args[1];
4687 L = (FT_ULong)args[0];
4691 if ( K < 1 || K > 3 )
4693 if ( exc->pedantic_hinting )
4694 exc->error = FT_THROW( Invalid_Reference );
4699 Kf = 1 << ( K - 1 );
4706 if ( exc->pedantic_hinting )
4707 exc->error = FT_THROW( Invalid_Reference );
4713 if ( exc->iniRange == tt_coderange_cvt )
4715 exc->GS.instruct_control &= ~(FT_Byte)Kf;
4716 exc->GS.instruct_control |= (FT_Byte)L;
4720 else if ( exc->iniRange == tt_coderange_glyph && K == 3 )
4722#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4726 if ( SUBPIXEL_HINTING_MINIMAL )
4727 exc->backward_compatibility = ( L & 4 ) ^ 4;
4730 else if ( exc->pedantic_hinting )
4731 exc->error = FT_THROW( Invalid_Reference );
4742 Ins_SCANCTRL( TT_ExecContext exc,
4749 A = (FT_Int)( args[0] & 0xFF );
4753 exc->GS.scan_control = TRUE;
4758 exc->GS.scan_control = FALSE;
4762 if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A )
4763 exc->GS.scan_control = TRUE;
4765 if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated )
4766 exc->GS.scan_control = TRUE;
4768 if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched )
4769 exc->GS.scan_control = TRUE;
4771 if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A )
4772 exc->GS.scan_control = FALSE;
4774 if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated )
4775 exc->GS.scan_control = FALSE;
4777 if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched )
4778 exc->GS.scan_control = FALSE;
4789 Ins_SCANTYPE( TT_ExecContext exc,
4793 exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF;
4811 Ins_FLIPPT( TT_ExecContext exc,
4814 FT_Long loop = exc->GS.loop;
4818 if ( exc->new_top < loop )
4820 if ( exc->pedantic_hinting )
4821 exc->error = FT_THROW( Too_Few_Arguments );
4825 exc->new_top -= loop;
4827#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4829 if ( exc->backward_compatibility == 0x7 )
4835 point = (FT_UShort)*(--args);
4837 if ( BOUNDS( point, exc->pts.n_points ) )
4839 if ( exc->pedantic_hinting )
4841 exc->error = FT_THROW( Invalid_Reference );
4846 exc->pts.tags[point] ^= FT_CURVE_TAG_ON;
4861 Ins_FLIPRGON( TT_ExecContext exc,
4867#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4869 if ( exc->backward_compatibility == 0x7 )
4873 K = (FT_UShort)args[1];
4874 L = (FT_UShort)args[0];
4876 if ( BOUNDS( K, exc->pts.n_points ) ||
4877 BOUNDS( L, exc->pts.n_points ) )
4879 if ( exc->pedantic_hinting )
4880 exc->error = FT_THROW( Invalid_Reference );
4884 for ( I = L; I <= K; I++ )
4885 exc->pts.tags[I] |= FT_CURVE_TAG_ON;
4896 Ins_FLIPRGOFF( TT_ExecContext exc,
4902#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4904 if ( exc->backward_compatibility == 0x7 )
4908 K = (FT_UShort)args[1];
4909 L = (FT_UShort)args[0];
4911 if ( BOUNDS( K, exc->pts.n_points ) ||
4912 BOUNDS( L, exc->pts.n_points ) )
4914 if ( exc->pedantic_hinting )
4915 exc->error = FT_THROW( Invalid_Reference );
4919 for ( I = L; I <= K; I++ )
4920 exc->pts.tags[I] &= ~FT_CURVE_TAG_ON;
4925 Compute_Point_Displacement( TT_ExecContext exc,
4936 if ( exc->opcode & 1 )
4947 if ( BOUNDS( p, zp.n_points ) )
4949 if ( exc->pedantic_hinting )
4950 exc->error = FT_THROW( Invalid_Reference );
4958 d = PROJECT( zp.cur + p, zp.org + p );
4960 *x = FT_MulFix( d, exc->moveVector.x );
4961 *y = FT_MulFix( d, exc->moveVector.y );
4969 Move_Zp2_Point( TT_ExecContext exc,
4975 if ( exc->GS.freeVector.x != 0 )
4977#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4979 if ( !exc->backward_compatibility )
4981 exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx );
4984 exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
4987 if ( exc->GS.freeVector.y != 0 )
4989#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
4991 if ( exc->backward_compatibility != 0x7 )
4993 exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy );
4996 exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5008 Ins_SHP( TT_ExecContext exc,
5011 FT_Long loop = exc->GS.loop;
5019 if ( exc->new_top < loop )
5021 if ( exc->pedantic_hinting )
5022 exc->error = FT_THROW( Too_Few_Arguments );
5026 exc->new_top -= loop;
5028 if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
5033 point = (FT_UShort)*(--args);
5035 if ( BOUNDS( point, exc->zp2.n_points ) )
5037 if ( exc->pedantic_hinting )
5039 exc->error = FT_THROW( Invalid_Reference );
5044 Move_Zp2_Point( exc, point, dx, dy, TRUE );
5063 Ins_SHC( TT_ExecContext exc,
5070 FT_UShort contour, bounds;
5071 FT_UShort start, limit, i;
5074 contour = (FT_UShort)args[0];
5075 bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
5077 if ( BOUNDS( contour, bounds ) )
5079 if ( exc->pedantic_hinting )
5080 exc->error = FT_THROW( Invalid_Reference );
5084 if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
5090 start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
5093 if ( exc->GS.gep2 == 0 )
5094 limit = exc->zp2.n_points;
5096 limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
5098 for ( i = start; i < limit; i++ )
5100 if ( zp.cur != exc->zp2.cur || refp != i )
5101 Move_Zp2_Point( exc, i, dx, dy, TRUE );
5113 Ins_SHZ( TT_ExecContext exc,
5124 if ( BOUNDS( args[0], 2 ) )
5126 if ( exc->pedantic_hinting )
5127 exc->error = FT_THROW( Invalid_Reference );
5131 if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
5138 if ( exc->GS.gep2 == 0 )
5139 limit = exc->zp2.n_points;
5140 else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
5141 limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
5146 for ( i = 0; i < limit; i++ )
5148 if ( zp.cur != exc->zp2.cur || refp != i )
5149 Move_Zp2_Point( exc, i, dx, dy, FALSE );
5161 Ins_SHPIX( TT_ExecContext exc,
5164 FT_Long loop = exc->GS.loop;
5167#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
5168 FT_Bool in_twilight = FT_BOOL( exc->GS.gep0 == 0 ||
5169 exc->GS.gep1 == 0 ||
5170 exc->GS.gep2 == 0 );
5174 if ( exc->new_top < loop )
5176 if ( exc->pedantic_hinting )
5177 exc->error = FT_THROW( Too_Few_Arguments );
5181 exc->new_top -= loop;
5183 dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
5184 dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
5188 point = (FT_UShort)*(--args);
5190 if ( BOUNDS( point, exc->zp2.n_points ) )
5192 if ( exc->pedantic_hinting )
5194 exc->error = FT_THROW( Invalid_Reference );
5199#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
5200 if ( exc->backward_compatibility )
5208 ( exc->backward_compatibility != 0x7 &&
5209 ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
5210 ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ) ) )
5211 Move_Zp2_Point( exc, point, 0, dy, TRUE );
5215 Move_Zp2_Point( exc, point, dx, dy, TRUE );
5230 Ins_MSIRP( TT_ExecContext exc,
5233 FT_UShort point = 0;
5234 FT_F26Dot6 distance;
5237 point = (FT_UShort)args[0];
5239 if ( BOUNDS( point, exc->zp1.n_points ) ||
5240 BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
5242 if ( exc->pedantic_hinting )
5243 exc->error = FT_THROW( Invalid_Reference );
5249 if ( exc->GS.gep1 == 0 )
5251 exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0];
5252 exc->func_move_orig( exc, &exc->zp1, point, args[1] );
5253 exc->zp1.cur[point] = exc->zp1.org[point];
5256 distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
5258 exc->func_move( exc,
5261 SUB_LONG( args[1], distance ) );
5263 exc->GS.rp1 = exc->GS.rp0;
5264 exc->GS.rp2 = point;
5266 if ( ( exc->opcode & 1 ) != 0 )
5267 exc->GS.rp0 = point;
5278 Ins_MDAP( TT_ExecContext exc,
5282 FT_F26Dot6 cur_dist;
5283 FT_F26Dot6 distance;
5286 point = (FT_UShort)args[0];
5288 if ( BOUNDS( point, exc->zp0.n_points ) )
5290 if ( exc->pedantic_hinting )
5291 exc->error = FT_THROW( Invalid_Reference );
5295 if ( ( exc->opcode & 1 ) != 0 )
5297 cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
5298 distance = SUB_LONG( exc->func_round( exc, cur_dist, 0 ), cur_dist );
5303 exc->func_move( exc, &exc->zp0, point, distance );
5305 exc->GS.rp0 = point;
5306 exc->GS.rp1 = point;
5317 Ins_MIAP( TT_ExecContext exc,
5322 FT_F26Dot6 distance;
5323 FT_F26Dot6 org_dist;
5326 cvtEntry = (FT_ULong)args[1];
5327 point = (FT_UShort)args[0];
5329 if ( BOUNDS( point, exc->zp0.n_points ) ||
5330 BOUNDSL( cvtEntry, exc->cvtSize ) )
5332 if ( exc->pedantic_hinting )
5333 exc->error = FT_THROW( Invalid_Reference );
5357 distance = exc->func_read_cvt( exc, cvtEntry );
5359 if ( exc->GS.gep0 == 0 )
5361 exc->zp0.org[point].x = TT_MulFix14( distance,
5362 exc->GS.freeVector.x );
5363 exc->zp0.org[point].y = TT_MulFix14( distance,
5364 exc->GS.freeVector.y );
5365 exc->zp0.cur[point] = exc->zp0.org[point];
5368 org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
5370 if ( ( exc->opcode & 1 ) != 0 )
5372 FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin;
5376 delta = SUB_LONG( distance, org_dist );
5378 delta = NEG_LONG( delta );
5380 if ( delta > control_value_cutin )
5381 distance = org_dist;
5383 distance = exc->func_round( exc, distance, 0 );
5386 exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) );
5389 exc->GS.rp0 = point;
5390 exc->GS.rp1 = point;
5401 Ins_MDRP( TT_ExecContext exc,
5404 FT_UShort point = 0;
5405 FT_F26Dot6 org_dist, distance, compensation;
5408 point = (FT_UShort)args[0];
5410 if ( BOUNDS( point, exc->zp1.n_points ) ||
5411 BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
5413 if ( exc->pedantic_hinting )
5414 exc->error = FT_THROW( Invalid_Reference );
5423 if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
5425 FT_Vector* vec1 = &exc->zp1.org[point];
5426 FT_Vector* vec2 = &exc->zp0.org[exc->GS.rp0];
5429 org_dist = DUALPROJ( vec1, vec2 );
5433 FT_Vector* vec1 = &exc->zp1.orus[point];
5434 FT_Vector* vec2 = &exc->zp0.orus[exc->GS.rp0];
5437 if ( exc->metrics.x_scale == exc->metrics.y_scale )
5440 org_dist = DUALPROJ( vec1, vec2 );
5441 org_dist = FT_MulFix( org_dist, exc->metrics.x_scale );
5448 vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ),
5449 exc->metrics.x_scale );
5450 vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ),
5451 exc->metrics.y_scale );
5453 org_dist = FAST_DUALPROJ( &vec );
5460 if ( exc->GS.single_width_cutin > 0 &&
5461 org_dist < exc->GS.single_width_value +
5462 exc->GS.single_width_cutin &&
5463 org_dist > exc->GS.single_width_value -
5464 exc->GS.single_width_cutin )
5466 if ( org_dist >= 0 )
5467 org_dist = exc->GS.single_width_value;
5469 org_dist = -exc->GS.single_width_value;
5474 compensation = exc->GS.compensation[exc->opcode & 3];
5476 if ( ( exc->opcode & 4 ) != 0 )
5477 distance = exc->func_round( exc, org_dist, compensation );
5479 distance = Round_None( exc, org_dist, compensation );
5483 if ( ( exc->opcode & 8 ) != 0 )
5485 FT_F26Dot6 minimum_distance = exc->GS.minimum_distance;
5488 if ( org_dist >= 0 )
5490 if ( distance < minimum_distance )
5491 distance = minimum_distance;
5495 if ( distance > NEG_LONG( minimum_distance ) )
5496 distance = NEG_LONG( minimum_distance );
5502 org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
5504 exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) );
5507 exc->GS.rp1 = exc->GS.rp0;
5508 exc->GS.rp2 = point;
5510 if ( ( exc->opcode & 16 ) != 0 )
5511 exc->GS.rp0 = point;
5522 Ins_MIRP( TT_ExecContext exc,
5528 FT_F26Dot6 cvt_dist,
5537 point = (FT_UShort)args[0];
5538 cvtEntry = (FT_ULong)( ADD_LONG( args[1], 1 ) );
5542 if ( BOUNDS( point, exc->zp1.n_points ) ||
5543 BOUNDSL( cvtEntry, exc->cvtSize + 1 ) ||
5544 BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
5546 if ( exc->pedantic_hinting )
5547 exc->error = FT_THROW( Invalid_Reference );
5554 cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 );
5558 delta = SUB_LONG( cvt_dist, exc->GS.single_width_value );
5560 delta = NEG_LONG( delta );
5562 if ( delta < exc->GS.single_width_cutin )
5564 if ( cvt_dist >= 0 )
5565 cvt_dist = exc->GS.single_width_value;
5567 cvt_dist = -exc->GS.single_width_value;
5572 if ( exc->GS.gep1 == 0 )
5574 exc->zp1.org[point].x = ADD_LONG(
5575 exc->zp0.org[exc->GS.rp0].x,
5576 TT_MulFix14( cvt_dist,
5577 exc->GS.freeVector.x ) );
5578 exc->zp1.org[point].y = ADD_LONG(
5579 exc->zp0.org[exc->GS.rp0].y,
5580 TT_MulFix14( cvt_dist,
5581 exc->GS.freeVector.y ) );
5582 exc->zp1.cur[point] = exc->zp1.org[point];
5585 org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] );
5586 cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] );
5590 if ( exc->GS.auto_flip )
5592 if ( ( org_dist ^ cvt_dist ) < 0 )
5593 cvt_dist = NEG_LONG( cvt_dist );
5598 compensation = exc->GS.compensation[exc->opcode & 3];
5600 if ( ( exc->opcode & 4 ) != 0 )
5605 if ( exc->GS.gep0 == exc->GS.gep1 )
5607 FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin;
5622 delta = SUB_LONG( cvt_dist, org_dist );
5624 delta = NEG_LONG( delta );
5626 if ( delta > control_value_cutin )
5627 cvt_dist = org_dist;
5630 distance = exc->func_round( exc, cvt_dist, compensation );
5633 distance = Round_None( exc, cvt_dist, compensation );
5637 if ( ( exc->opcode & 8 ) != 0 )
5639 FT_F26Dot6 minimum_distance = exc->GS.minimum_distance;
5642 if ( org_dist >= 0 )
5644 if ( distance < minimum_distance )
5645 distance = minimum_distance;
5649 if ( distance > NEG_LONG( minimum_distance ) )
5650 distance = NEG_LONG( minimum_distance );
5654 exc->func_move( exc,
5657 SUB_LONG( distance, cur_dist ) );
5660 exc->GS.rp1 = exc->GS.rp0;
5661 exc->GS.rp2 = point;
5663 if ( ( exc->opcode & 16 ) != 0 )
5664 exc->GS.rp0 = point;
5675 Ins_ALIGNRP( TT_ExecContext exc,
5678 FT_Long loop = exc->GS.loop;
5680 FT_F26Dot6 distance;
5683 if ( exc->new_top < loop )
5685 if ( exc->pedantic_hinting )
5686 exc->error = FT_THROW( Too_Few_Arguments );
5690 exc->new_top -= loop;
5692 if ( BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
5694 if ( exc->pedantic_hinting )
5695 exc->error = FT_THROW( Invalid_Reference );
5701 point = (FT_UShort)*(--args);
5703 if ( BOUNDS( point, exc->zp1.n_points ) )
5705 if ( exc->pedantic_hinting )
5707 exc->error = FT_THROW( Invalid_Reference );
5713 distance = PROJECT( exc->zp1.cur + point,
5714 exc->zp0.cur + exc->GS.rp0 );
5716 exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) );
5732 Ins_ISECT( TT_ExecContext exc,
5739 FT_F26Dot6 discriminant, dotproduct;
5750 point = (FT_UShort)args[0];
5752 a0 = (FT_UShort)args[1];
5753 a1 = (FT_UShort)args[2];
5754 b0 = (FT_UShort)args[3];
5755 b1 = (FT_UShort)args[4];
5757 if ( BOUNDS( b0, exc->zp0.n_points ) ||
5758 BOUNDS( b1, exc->zp0.n_points ) ||
5759 BOUNDS( a0, exc->zp1.n_points ) ||
5760 BOUNDS( a1, exc->zp1.n_points ) ||
5761 BOUNDS( point, exc->zp2.n_points ) )
5763 if ( exc->pedantic_hinting )
5764 exc->error = FT_THROW( Invalid_Reference );
5770 dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x );
5771 dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y );
5773 dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x );
5774 day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y );
5776 dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x );
5777 dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y );
5779 discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ),
5780 FT_MulDiv( day, dbx, 0x40 ) );
5781 dotproduct = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ),
5782 FT_MulDiv( day, dby, 0x40 ) );
5792 if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) )
5794 val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ),
5795 FT_MulDiv( dy, dbx, 0x40 ) );
5797 R.x = FT_MulDiv( val, dax, discriminant );
5798 R.y = FT_MulDiv( val, day, discriminant );
5801 exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x );
5802 exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y );
5809 exc->zp2.cur[point].x =
5810 ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ),
5811 ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4;
5812 exc->zp2.cur[point].y =
5813 ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ),
5814 ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4;
5817 exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
5828 Ins_ALIGNPTS( TT_ExecContext exc,
5832 FT_F26Dot6 distance;
5835 p1 = (FT_UShort)args[0];
5836 p2 = (FT_UShort)args[1];
5838 if ( BOUNDS( p1, exc->zp1.n_points ) ||
5839 BOUNDS( p2, exc->zp0.n_points ) )
5841 if ( exc->pedantic_hinting )
5842 exc->error = FT_THROW( Invalid_Reference );
5846 distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
5848 exc->func_move( exc, &exc->zp1, p1, distance );
5849 exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) );
5863 Ins_IP( TT_ExecContext exc,
5866 FT_Long loop = exc->GS.loop;
5867 FT_F26Dot6 old_range, cur_range;
5868 FT_Vector* orus_base;
5869 FT_Vector* cur_base;
5873 if ( exc->new_top < loop )
5875 if ( exc->pedantic_hinting )
5876 exc->error = FT_THROW( Too_Few_Arguments );
5880 exc->new_top -= loop;
5882 if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
5884 if ( exc->pedantic_hinting )
5885 exc->error = FT_THROW( Invalid_Reference );
5894 twilight = ( exc->GS.gep0 == 0 ||
5895 exc->GS.gep1 == 0 ||
5896 exc->GS.gep2 == 0 );
5899 orus_base = &exc->zp0.org[exc->GS.rp1];
5901 orus_base = &exc->zp0.orus[exc->GS.rp1];
5903 cur_base = &exc->zp0.cur[exc->GS.rp1];
5909 if ( BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
5917 old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base );
5918 else if ( exc->metrics.x_scale == exc->metrics.y_scale )
5919 old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base );
5925 vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x,
5927 exc->metrics.x_scale );
5928 vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y,
5930 exc->metrics.y_scale );
5932 old_range = FAST_DUALPROJ( &vec );
5935 cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
5940 FT_UInt point = (FT_UInt)*(--args);
5941 FT_F26Dot6 org_dist, cur_dist, new_dist;
5945 if ( BOUNDS( point, exc->zp2.n_points ) )
5947 if ( exc->pedantic_hinting )
5949 exc->error = FT_THROW( Invalid_Reference );
5956 org_dist = DUALPROJ( &exc->zp2.org[point], orus_base );
5957 else if ( exc->metrics.x_scale == exc->metrics.y_scale )
5958 org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base );
5964 vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x,
5966 exc->metrics.x_scale );
5967 vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y,
5969 exc->metrics.y_scale );
5971 org_dist = FAST_DUALPROJ( &vec );
5974 cur_dist = PROJECT( &exc->zp2.cur[point], cur_base );
5979 new_dist = FT_MulDiv( org_dist, cur_range, old_range );
5998 new_dist = org_dist;
6004 exc->func_move( exc,
6007 SUB_LONG( new_dist, cur_dist ) );
6022 Ins_UTP( TT_ExecContext exc,
6029 point = (FT_UShort)args[0];
6031 if ( BOUNDS( point, exc->zp0.n_points ) )
6033 if ( exc->pedantic_hinting )
6034 exc->error = FT_THROW( Invalid_Reference );
6040 if ( exc->GS.freeVector.x != 0 )
6041 mask &= ~FT_CURVE_TAG_TOUCH_X;
6043 if ( exc->GS.freeVector.y != 0 )
6044 mask &= ~FT_CURVE_TAG_TOUCH_Y;
6046 exc->zp0.tags[point] &= mask;
6051 typedef struct IUP_WorkerRec_
6058 } IUP_WorkerRec, *IUP_Worker;
6062 iup_worker_shift_( IUP_Worker worker,
6071 dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x );
6074 for ( i = p1; i < p; i++ )
6075 worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
6077 for ( i = p + 1; i <= p2; i++ )
6078 worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
6084 iup_worker_interpolate_( IUP_Worker worker,
6091 FT_F26Dot6 orus1, orus2, org1, org2, cur1, cur2, delta1, delta2;
6097 if ( BOUNDS( ref1, worker->max_points ) ||
6098 BOUNDS( ref2, worker->max_points ) )
6101 orus1 = worker->orus[ref1].x;
6102 orus2 = worker->orus[ref2].x;
6104 if ( orus1 > orus2 )
6119 org1 = worker->orgs[ref1].x;
6120 org2 = worker->orgs[ref2].x;
6121 cur1 = worker->curs[ref1].x;
6122 cur2 = worker->curs[ref2].x;
6123 delta1 = SUB_LONG( cur1, org1 );
6124 delta2 = SUB_LONG( cur2, org2 );
6126 if ( cur1 == cur2 || orus1 == orus2 )
6130 for ( i = p1; i <= p2; i++ )
6132 FT_F26Dot6 x = worker->orgs[i].x;
6136 x = ADD_LONG( x, delta1 );
6138 else if ( x >= org2 )
6139 x = ADD_LONG( x, delta2 );
6144 worker->curs[i].x = x;
6150 FT_Bool scale_valid = 0;
6154 for ( i = p1; i <= p2; i++ )
6156 FT_F26Dot6 x = worker->orgs[i].x;
6160 x = ADD_LONG( x, delta1 );
6162 else if ( x >= org2 )
6163 x = ADD_LONG( x, delta2 );
6170 scale = FT_DivFix( SUB_LONG( cur2, cur1 ),
6171 SUB_LONG( orus2, orus1 ) );
6175 FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ),
6178 worker->curs[i].x = x;
6191 Ins_IUP( TT_ExecContext exc )
6196 FT_UInt first_point;
6199 FT_UInt first_touched;
6200 FT_UInt cur_touched;
6206#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
6210 if ( exc->backward_compatibility == 0x7 )
6212 else if ( exc->backward_compatibility )
6213 exc->backward_compatibility |= 1 << ( exc->opcode & 1 );
6217 if ( exc->pts.n_contours == 0 )
6220 if ( exc->opcode & 1 )
6222 mask = FT_CURVE_TAG_TOUCH_X;
6223 V.orgs = exc->pts.org;
6224 V.curs = exc->pts.cur;
6225 V.orus = exc->pts.orus;
6229 mask = FT_CURVE_TAG_TOUCH_Y;
6230 V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 );
6231 V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 );
6232 V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 );
6234 V.max_points = exc->pts.n_points;
6241 end_point = exc->pts.contours[contour] - exc->pts.first_point;
6242 first_point = point;
6244 if ( BOUNDS( end_point, exc->pts.n_points ) )
6245 end_point = exc->pts.n_points - 1;
6247 while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
6250 if ( point <= end_point )
6252 first_touched = point;
6253 cur_touched = point;
6257 while ( point <= end_point )
6259 if ( ( exc->pts.tags[point] & mask ) != 0 )
6261 iup_worker_interpolate_( &V,
6266 cur_touched = point;
6272 if ( cur_touched == first_touched )
6273 iup_worker_shift_( &V, first_point, end_point, cur_touched );
6276 iup_worker_interpolate_( &V,
6277 (FT_UShort)( cur_touched + 1 ),
6282 if ( first_touched > 0 )
6283 iup_worker_interpolate_( &V,
6291 }
while ( contour < exc->pts.n_contours );
6302 Ins_DELTAP( TT_ExecContext exc,
6312 if ( nump < 0 || nump > exc->new_top / 2 )
6314 if ( exc->pedantic_hinting )
6315 exc->error = FT_THROW( Too_Few_Arguments );
6317 nump = exc->new_top / 2;
6320 exc->new_top -= 2 * nump;
6322 P = exc->func_cur_ppem( exc ) - exc->GS.delta_base;
6324 switch ( exc->opcode )
6343 F = 1L << ( 6 - exc->GS.delta_shift );
6347 A = (FT_UShort)*(--args);
6356 if ( BOUNDS( A, exc->zp0.n_points ) )
6358 if ( exc->pedantic_hinting )
6360 exc->error = FT_THROW( Invalid_Reference );
6366 if ( ( B & 0xF0 ) == P )
6368 B = ( B & 0xF ) - 8;
6373#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
6375 if ( exc->backward_compatibility )
6377 if ( exc->backward_compatibility != 0x7 &&
6378 ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
6379 ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) )
6380 exc->func_move( exc, &exc->zp0, A, B );
6384 exc->func_move( exc, &exc->zp0, A, B );
6398 Ins_DELTAC( TT_ExecContext exc,
6408 if ( nump < 0 || nump > exc->new_top / 2 )
6410 if ( exc->pedantic_hinting )
6411 exc->error = FT_THROW( Too_Few_Arguments );
6413 nump = exc->new_top / 2;
6416 exc->new_top -= 2 * nump;
6418 P = exc->func_cur_ppem( exc ) - exc->GS.delta_base;
6420 switch ( exc->opcode )
6439 F = 1L << ( 6 - exc->GS.delta_shift );
6443 A = (FT_ULong)*(--args);
6446 if ( BOUNDSL( A, exc->cvtSize ) )
6448 if ( exc->pedantic_hinting )
6450 exc->error = FT_THROW( Invalid_Reference );
6456 if ( ( B & 0xF0 ) == P )
6458 B = ( B & 0xF ) - 8;
6463 exc->func_move_cvt( exc, A, B );
6484 Ins_GETINFO( TT_ExecContext exc,
6488 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
6493 if ( ( args[0] & 1 ) != 0 )
6494 K = driver->interpreter_version;
6501 if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
6509 if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
6512#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
6518 if ( (args[0] & 8 ) != 0 && exc->face->blend )
6528 if ( ( args[0] & 32 ) != 0 && exc->grayscale )
6531#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
6536 if ( SUBPIXEL_HINTING_MINIMAL && exc->mode != FT_RENDER_MODE_MONO )
6545 if ( ( args[0] & 64 ) != 0 )
6553 if ( ( args[0] & 256 ) != 0 && exc->mode == FT_RENDER_MODE_LCD_V )
6563 if ( ( args[0] & 1024 ) != 0 )
6574 if ( ( args[0] & 2048 ) != 0 && exc->mode != FT_RENDER_MODE_MONO )
6586 if ( ( args[0] & 4096 ) != 0 &&
6587 exc->mode != FT_RENDER_MODE_MONO &&
6588 exc->mode != FT_RENDER_MODE_LCD &&
6589 exc->mode != FT_RENDER_MODE_LCD_V )
6598#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
6611 Ins_GETVARIATION( TT_ExecContext exc,
6614 FT_UInt num_axes = exc->face->blend->num_axis;
6615 FT_Fixed* coords = exc->face->blend->normalizedcoords;
6620 if ( BOUNDS( num_axes, exc->stackSize + 1 - exc->top ) )
6622 exc->error = FT_THROW( Stack_Overflow );
6628 for ( i = 0; i < num_axes; i++ )
6629 args[i] = coords[i] >> 2;
6633 for ( i = 0; i < num_axes; i++ )
6637 exc->new_top += num_axes;
6651 Ins_GETDATA( FT_Long* args )
6660 Ins_UNKNOWN( TT_ExecContext exc )
6662 TT_DefRecord* def = exc->IDefs;
6663 TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs );
6666 for ( ; def < limit; def++ )
6668 if ( (FT_Byte)def->opc == exc->opcode && def->active )
6673 if ( exc->callTop >= exc->callSize )
6675 exc->error = FT_THROW( Stack_Overflow );
6679 call = exc->callStack + exc->callTop++;
6681 call->Caller_Range = exc->curRange;
6682 call->Caller_IP = exc->IP + 1;
6683 call->Cur_Count = 1;
6686 Ins_Goto_CodeRange( exc, def->range, def->start );
6692 exc->error = FT_THROW( Invalid_Opcode );
6728 FT_EXPORT_DEF( FT_Error )
6729 TT_RunIns(
void* exec )
6731 TT_ExecContext exc = (TT_ExecContext)exec;
6732 FT_ULong ins_counter = 0;
6739 if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
6741 exc->error = FT_THROW( Execution_Too_Long );
6745 exc->error = FT_Err_Ok;
6746 exc->opcode = exc->code[exc->IP];
6749#ifdef FT_DEBUG_LEVEL_TRACE
6750 if ( ft_trace_levels[trace_ttinterp] >= 6 )
6752 FT_Long cnt = FT_MIN( 8, exc->top );
6759 FT_TRACE7((
"%06ld ", exc->IP ));
6760 FT_TRACE6((
"%s", opcode_name[exc->opcode] + 2 ));
6761 FT_TRACE7((
"%*s", *opcode_name[exc->opcode] ==
'A'
6763 : 12 - ( *opcode_name[exc->opcode] -
'0' ),
6765 for ( n = 1; n <= cnt; n++ )
6766 FT_TRACE7((
" %ld", exc->stack[exc->top - n] ));
6767 FT_TRACE6((
"\n" ));
6772 exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 );
6776 if ( exc->args < 0 )
6781 if ( exc->pedantic_hinting )
6783 exc->error = FT_THROW( Too_Few_Arguments );
6788 for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ )
6793 exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 );
6798 if ( exc->new_top > exc->stackSize )
6800 exc->error = FT_THROW( Stack_Overflow );
6805 FT_Long* args = exc->stack + exc->args;
6806 FT_Byte opcode = exc->opcode;
6822 Ins_SPVTL( exc, args );
6827 Ins_SFVTL( exc, args );
6831 Ins_SPVFS( exc, args );
6835 Ins_SFVFS( exc, args );
6839 Ins_GPV( exc, args );
6843 Ins_GFV( exc, args );
6851 Ins_ISECT( exc, args );
6855 Ins_SRP0( exc, args );
6859 Ins_SRP1( exc, args );
6863 Ins_SRP2( exc, args );
6867 Ins_SZP0( exc, args );
6871 Ins_SZP1( exc, args );
6875 Ins_SZP2( exc, args );
6879 Ins_SZPS( exc, args );
6883 Ins_SLOOP( exc, args );
6895 Ins_SMD( exc, args );
6903 Ins_JMPR( exc, args );
6907 Ins_SCVTCI( exc, args );
6911 Ins_SSWCI( exc, args );
6915 Ins_SSW( exc, args );
6935 Ins_DEPTH( exc, args );
6939 Ins_CINDEX( exc, args );
6943 Ins_MINDEX( exc, args );
6947 Ins_ALIGNPTS( exc, args );
6955 Ins_UTP( exc, args );
6959 Ins_LOOPCALL( exc, args );
6963 Ins_CALL( exc, args );
6967 Ins_FDEF( exc, args );
6976 Ins_MDAP( exc, args );
6986 Ins_SHP( exc, args );
6991 Ins_SHC( exc, args );
6996 Ins_SHZ( exc, args );
7000 Ins_SHPIX( exc, args );
7004 Ins_IP( exc, args );
7009 Ins_MSIRP( exc, args );
7013 Ins_ALIGNRP( exc, args );
7022 Ins_MIAP( exc, args );
7026 Ins_NPUSHB( exc, args );
7030 Ins_NPUSHW( exc, args );
7034 Ins_WS( exc, args );
7038 Ins_RS( exc, args );
7042 Ins_WCVTP( exc, args );
7046 Ins_RCVT( exc, args );
7051 Ins_GC( exc, args );
7055 Ins_SCFS( exc, args );
7060 Ins_MD( exc, args );
7064 Ins_MPPEM( exc, args );
7068 Ins_MPS( exc, args );
7108 Ins_ODD( exc, args );
7112 Ins_EVEN( exc, args );
7116 Ins_IF( exc, args );
7136 Ins_DELTAP( exc, args );
7140 Ins_SDB( exc, args );
7144 Ins_SDS( exc, args );
7156 Ins_DIV( exc, args );
7176 Ins_CEILING( args );
7183 Ins_ROUND( exc, args );
7190 Ins_NROUND( exc, args );
7194 Ins_WCVTF( exc, args );
7199 Ins_DELTAP( exc, args );
7205 Ins_DELTAC( exc, args );
7209 Ins_SROUND( exc, args );
7213 Ins_S45ROUND( exc, args );
7217 Ins_JROT( exc, args );
7221 Ins_JROF( exc, args );
7249 Ins_FLIPPT( exc, args );
7253 Ins_FLIPRGON( exc, args );
7257 Ins_FLIPRGOFF( exc, args );
7266 Ins_SCANCTRL( exc, args );
7271 Ins_SDPVTL( exc, args );
7275 Ins_GETINFO( exc, args );
7279 Ins_IDEF( exc, args );
7295 Ins_SCANTYPE( exc, args );
7299 Ins_INSTCTRL( exc, args );
7307#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
7312 if ( exc->face->blend )
7313 Ins_GETVARIATION( exc, args );
7322 if ( exc->face->blend )
7323 Ins_GETDATA( args );
7330 if ( opcode >= 0xE0 )
7331 Ins_MIRP( exc, args );
7332 else if ( opcode >= 0xC0 )
7333 Ins_MDRP( exc, args );
7334 else if ( opcode >= 0xB8 )
7335 Ins_PUSHW( exc, args );
7336 else if ( opcode >= 0xB0 )
7337 Ins_PUSHB( exc, args );
7345 switch ( exc->error )
7347 case FT_ERR( Invalid_Opcode ):
7349 TT_DefRecord* def = exc->IDefs;
7350 TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs );
7354 for ( ; def < limit; def++ )
7356 if ( def->active && exc->opcode == (FT_Byte)def->opc )
7358 TT_CallRec* callrec;
7361 if ( exc->callTop >= exc->callSize )
7363 exc->error = FT_THROW( Invalid_Reference );
7367 callrec = &exc->callStack[exc->callTop];
7369 callrec->Caller_Range = exc->curRange;
7370 callrec->Caller_IP = exc->IP + 1;
7371 callrec->Cur_Count = 1;
7374 if ( Ins_Goto_CodeRange( exc,
7376 def->start ) == FAILURE )
7390 exc->top = exc->new_top;
7391 exc->IP += exc->length;
7394 if ( exc->IP >= exc->codeSize )
7396 if ( exc->callTop > 0 )
7398 exc->error = FT_THROW( Code_Overflow );
7404 }
while ( !exc->instruction_trap );
7407 FT_TRACE4((
" %lu instruction%s executed\n",
7409 ins_counter == 1 ?
"" :
"s" ));
7414 if ( exc->error && !exc->instruction_trap )
7415 FT_TRACE1((
" The interpreter returned error 0x%x\n", exc->error ));
7436 FT_LOCAL_DEF( FT_Error )
7437 TT_Run_Context( TT_ExecContext exec,
7440 FT_ULong num_twilight_points;
7443 exec->zp0 = exec->pts;
7444 exec->zp1 = exec->pts;
7445 exec->zp2 = exec->pts;
7452 num_twilight_points = FT_MAX( 30,
7453 2 * ( exec->pts.n_points + exec->cvtSize ) );
7454 if ( exec->twilight.n_points > num_twilight_points )
7456 if ( num_twilight_points > 0xFFFFU )
7457 num_twilight_points = 0xFFFFU;
7459 FT_TRACE5((
"TT_RunIns: Resetting number of twilight points\n" ));
7460 FT_TRACE5((
" from %d to the more reasonable value %lu\n",
7461 exec->twilight.n_points,
7462 num_twilight_points ));
7463 exec->twilight.n_points = (FT_UShort)num_twilight_points;
7476 exec->loopcall_counter = 0;
7477 exec->neg_jump_counter = 0;
7480 if ( exec->pts.n_points )
7481 exec->loopcall_counter_max = FT_MAX( 50,
7482 10 * exec->pts.n_points ) +
7484 exec->cvtSize / 10 );
7486 exec->loopcall_counter_max = 300 + 22 * exec->cvtSize;
7490 if ( exec->loopcall_counter_max >
7491 100 * (FT_ULong)exec->face->root.num_glyphs )
7492 exec->loopcall_counter_max = 100 * (FT_ULong)exec->face->root.num_glyphs;
7494 FT_TRACE5((
"TT_RunIns: Limiting total number of loops in LOOPCALL"
7495 " to %lu\n", exec->loopcall_counter_max ));
7497 exec->neg_jump_counter_max = exec->loopcall_counter_max;
7498 FT_TRACE5((
"TT_RunIns: Limiting total number of backward jumps"
7499 " to %lu\n", exec->neg_jump_counter_max ));
7502 if ( exec->metrics.x_ppem != exec->metrics.y_ppem )
7505 exec->func_cur_ppem = Current_Ppem_Stretched;
7506 exec->func_read_cvt = Read_CVT_Stretched;
7507 exec->func_write_cvt = Write_CVT_Stretched;
7508 exec->func_move_cvt = Move_CVT_Stretched;
7513 exec->func_cur_ppem = Current_Ppem;
7514 exec->func_read_cvt = Read_CVT;
7515 exec->func_write_cvt = Write_CVT;
7516 exec->func_move_cvt = Move_CVT;
7520 exec->GS = size->GS;
7521 exec->func_round = (TT_Round_Func)Round_To_Grid;
7522 Compute_Funcs( exec );
7524#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
7527 exec->backward_compatibility &= ~0x3;
7535 exec->instruction_trap = FALSE;
7537 return exec->interpreter( exec );
7543 typedef int tt_interp_dummy_;