OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* ttinterp.c */ | 3 /* ttinterp.c */ |
4 /* */ | 4 /* */ |
5 /* TrueType bytecode interpreter (body). */ | 5 /* TrueType bytecode interpreter (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 1996-2011 */ | 7 /* Copyright 1996-2012 */ |
8 /* by David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* by David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 10 /* This file is part of the FreeType project, and may only be used, */ |
11 /* modified, and distributed under the terms of the FreeType project */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 /* <Note> */ | 708 /* <Note> */ |
709 /* Only the glyph loader and debugger should call this function. */ | 709 /* Only the glyph loader and debugger should call this function. */ |
710 /* */ | 710 /* */ |
711 FT_LOCAL_DEF( FT_Error ) | 711 FT_LOCAL_DEF( FT_Error ) |
712 TT_Run_Context( TT_ExecContext exec, | 712 TT_Run_Context( TT_ExecContext exec, |
713 FT_Bool debug ) | 713 FT_Bool debug ) |
714 { | 714 { |
715 FT_Error error; | 715 FT_Error error; |
716 | 716 |
717 | 717 |
718 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) | 718 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) |
719 != TT_Err_Ok ) | 719 != TT_Err_Ok ) |
720 return error; | 720 return error; |
721 | 721 |
722 exec->zp0 = exec->pts; | 722 exec->zp0 = exec->pts; |
723 exec->zp1 = exec->pts; | 723 exec->zp1 = exec->pts; |
724 exec->zp2 = exec->pts; | 724 exec->zp2 = exec->pts; |
725 | 725 |
726 exec->GS.gep0 = 1; | 726 exec->GS.gep0 = 1; |
727 exec->GS.gep1 = 1; | 727 exec->GS.gep1 = 1; |
728 exec->GS.gep2 = 1; | 728 exec->GS.gep2 = 1; |
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 range = &CUR.codeRangeTable[aRange - 1]; | 1793 range = &CUR.codeRangeTable[aRange - 1]; |
1794 | 1794 |
1795 if ( range->base == NULL ) /* invalid coderange */ | 1795 if ( range->base == NULL ) /* invalid coderange */ |
1796 { | 1796 { |
1797 CUR.error = TT_Err_Invalid_CodeRange; | 1797 CUR.error = TT_Err_Invalid_CodeRange; |
1798 return FAILURE; | 1798 return FAILURE; |
1799 } | 1799 } |
1800 | 1800 |
1801 /* NOTE: Because the last instruction of a program may be a CALL */ | 1801 /* NOTE: Because the last instruction of a program may be a CALL */ |
1802 /* which will return to the first byte *after* the code */ | 1802 /* which will return to the first byte *after* the code */ |
1803 /* range, we test for AIP <= Size, instead of AIP < Size. */ | 1803 /* range, we test for aIP <= Size, instead of aIP < Size. */ |
1804 | 1804 |
1805 if ( aIP > range->size ) | 1805 if ( aIP > range->size ) |
1806 { | 1806 { |
1807 CUR.error = TT_Err_Code_Overflow; | 1807 CUR.error = TT_Err_Code_Overflow; |
1808 return FAILURE; | 1808 return FAILURE; |
1809 } | 1809 } |
1810 | 1810 |
1811 CUR.code = range->base; | 1811 CUR.code = range->base; |
1812 CUR.codeSize = range->size; | 1812 CUR.codeSize = range->size; |
1813 CUR.IP = aIP; | 1813 CUR.IP = aIP; |
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2750 } | 2750 } |
2751 | 2751 |
2752 W = TT_VecLen( Vx, Vy ); | 2752 W = TT_VecLen( Vx, Vy ); |
2753 | 2753 |
2754 Vx = FT_MulDiv( Vx, 0x4000L, W ); | 2754 Vx = FT_MulDiv( Vx, 0x4000L, W ); |
2755 Vy = FT_MulDiv( Vy, 0x4000L, W ); | 2755 Vy = FT_MulDiv( Vy, 0x4000L, W ); |
2756 | 2756 |
2757 W = Vx * Vx + Vy * Vy; | 2757 W = Vx * Vx + Vy * Vy; |
2758 | 2758 |
2759 /* Now, we want that Sqrt( W ) = 0x4000 */ | 2759 /* Now, we want that Sqrt( W ) = 0x4000 */ |
2760 /* Or 0x10000000 <= W < 0x10004000 */ | 2760 /* Or 0x10000000 <= W < 0x10004000 */ |
2761 | 2761 |
2762 if ( Vx < 0 ) | 2762 if ( Vx < 0 ) |
2763 { | 2763 { |
2764 Vx = -Vx; | 2764 Vx = -Vx; |
2765 S1 = TRUE; | 2765 S1 = TRUE; |
2766 } | 2766 } |
2767 else | 2767 else |
2768 S1 = FALSE; | 2768 S1 = FALSE; |
2769 | 2769 |
2770 if ( Vy < 0 ) | 2770 if ( Vy < 0 ) |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3192 { \ | 3192 { \ |
3193 if ( CUR.pedantic_hinting ) \ | 3193 if ( CUR.pedantic_hinting ) \ |
3194 CUR.error = TT_Err_Invalid_Reference; \ | 3194 CUR.error = TT_Err_Invalid_Reference; \ |
3195 args[0] = 0; \ | 3195 args[0] = 0; \ |
3196 } \ | 3196 } \ |
3197 else \ | 3197 else \ |
3198 args[0] = CUR.stack[CUR.args - L]; \ | 3198 args[0] = CUR.stack[CUR.args - L]; \ |
3199 } | 3199 } |
3200 | 3200 |
3201 | 3201 |
3202 #define DO_JROT \ | 3202 #define DO_JROT \ |
3203 if ( args[1] != 0 ) \ | 3203 if ( args[1] != 0 ) \ |
3204 { \ | 3204 { \ |
3205 if ( args[0] == 0 && CUR.args == 0 ) \ | 3205 if ( args[0] == 0 && CUR.args == 0 ) \ |
3206 CUR.error = TT_Err_Bad_Argument; \ | 3206 CUR.error = TT_Err_Bad_Argument; \ |
3207 CUR.IP += args[0]; \ | 3207 CUR.IP += args[0]; \ |
3208 if ( CUR.IP < 0 ) \ | 3208 if ( CUR.IP < 0 || \ |
3209 CUR.error = TT_Err_Bad_Argument; \ | 3209 ( CUR.callTop > 0 && \ |
3210 CUR.step_ins = FALSE; \ | 3210 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ |
| 3211 CUR.error = TT_Err_Bad_Argument; \ |
| 3212 CUR.step_ins = FALSE; \ |
3211 } | 3213 } |
3212 | 3214 |
3213 | 3215 |
3214 #define DO_JMPR \ | 3216 #define DO_JMPR \ |
3215 if ( args[0] == 0 && CUR.args == 0 ) \ | 3217 if ( args[0] == 0 && CUR.args == 0 ) \ |
3216 CUR.error = TT_Err_Bad_Argument; \ | 3218 CUR.error = TT_Err_Bad_Argument; \ |
3217 CUR.IP += args[0]; \ | 3219 CUR.IP += args[0]; \ |
3218 if ( CUR.IP < 0 ) \ | 3220 if ( CUR.IP < 0 || \ |
3219 CUR.error = TT_Err_Bad_Argument; \ | 3221 ( CUR.callTop > 0 && \ |
| 3222 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ |
| 3223 CUR.error = TT_Err_Bad_Argument; \ |
3220 CUR.step_ins = FALSE; | 3224 CUR.step_ins = FALSE; |
3221 | 3225 |
3222 | 3226 |
3223 #define DO_JROF \ | 3227 #define DO_JROF \ |
3224 if ( args[1] == 0 ) \ | 3228 if ( args[1] == 0 ) \ |
3225 { \ | 3229 { \ |
3226 if ( args[0] == 0 && CUR.args == 0 ) \ | 3230 if ( args[0] == 0 && CUR.args == 0 ) \ |
3227 CUR.error = TT_Err_Bad_Argument; \ | 3231 CUR.error = TT_Err_Bad_Argument; \ |
3228 CUR.IP += args[0]; \ | 3232 CUR.IP += args[0]; \ |
3229 if ( CUR.IP < 0 ) \ | 3233 if ( CUR.IP < 0 || \ |
3230 CUR.error = TT_Err_Bad_Argument; \ | 3234 ( CUR.callTop > 0 && \ |
3231 CUR.step_ins = FALSE; \ | 3235 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ |
| 3236 CUR.error = TT_Err_Bad_Argument; \ |
| 3237 CUR.step_ins = FALSE; \ |
3232 } | 3238 } |
3233 | 3239 |
3234 | 3240 |
3235 #define DO_LT \ | 3241 #define DO_LT \ |
3236 args[0] = ( args[0] < args[1] ); | 3242 args[0] = ( args[0] < args[1] ); |
3237 | 3243 |
3238 | 3244 |
3239 #define DO_LTEQ \ | 3245 #define DO_LTEQ \ |
3240 args[0] = ( args[0] <= args[1] ); | 3246 args[0] = ( args[0] <= args[1] ); |
3241 | 3247 |
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4464 { | 4470 { |
4465 CUR.IP += CUR.length; | 4471 CUR.IP += CUR.length; |
4466 | 4472 |
4467 if ( CUR.IP < CUR.codeSize ) | 4473 if ( CUR.IP < CUR.codeSize ) |
4468 { | 4474 { |
4469 CUR.opcode = CUR.code[CUR.IP]; | 4475 CUR.opcode = CUR.code[CUR.IP]; |
4470 | 4476 |
4471 CUR.length = opcode_length[CUR.opcode]; | 4477 CUR.length = opcode_length[CUR.opcode]; |
4472 if ( CUR.length < 0 ) | 4478 if ( CUR.length < 0 ) |
4473 { | 4479 { |
4474 if ( CUR.IP + 1 > CUR.codeSize ) | 4480 if ( CUR.IP + 1 >= CUR.codeSize ) |
4475 goto Fail_Overflow; | 4481 goto Fail_Overflow; |
4476 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1]; | 4482 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1]; |
4477 } | 4483 } |
4478 | 4484 |
4479 if ( CUR.IP + CUR.length <= CUR.codeSize ) | 4485 if ( CUR.IP + CUR.length <= CUR.codeSize ) |
4480 return SUCCESS; | 4486 return SUCCESS; |
4481 } | 4487 } |
4482 | 4488 |
4483 Fail_Overflow: | 4489 Fail_Overflow: |
4484 CUR.error = TT_Err_Code_Overflow; | 4490 CUR.error = TT_Err_Code_Overflow; |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4633 while ( SKIP_Code() == SUCCESS ) | 4639 while ( SKIP_Code() == SUCCESS ) |
4634 { | 4640 { |
4635 switch ( CUR.opcode ) | 4641 switch ( CUR.opcode ) |
4636 { | 4642 { |
4637 case 0x89: /* IDEF */ | 4643 case 0x89: /* IDEF */ |
4638 case 0x2C: /* FDEF */ | 4644 case 0x2C: /* FDEF */ |
4639 CUR.error = TT_Err_Nested_DEFS; | 4645 CUR.error = TT_Err_Nested_DEFS; |
4640 return; | 4646 return; |
4641 | 4647 |
4642 case 0x2D: /* ENDF */ | 4648 case 0x2D: /* ENDF */ |
| 4649 rec->end = CUR.IP; |
4643 return; | 4650 return; |
4644 } | 4651 } |
4645 } | 4652 } |
4646 } | 4653 } |
4647 | 4654 |
4648 | 4655 |
4649 /*************************************************************************/ | 4656 /*************************************************************************/ |
4650 /* */ | 4657 /* */ |
4651 /* ENDF[]: END Function definition */ | 4658 /* ENDF[]: END Function definition */ |
4652 /* Opcode range: 0x2D */ | 4659 /* Opcode range: 0x2D */ |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4750 CUR.error = TT_Err_Stack_Overflow; | 4757 CUR.error = TT_Err_Stack_Overflow; |
4751 return; | 4758 return; |
4752 } | 4759 } |
4753 | 4760 |
4754 pCrec = CUR.callStack + CUR.callTop; | 4761 pCrec = CUR.callStack + CUR.callTop; |
4755 | 4762 |
4756 pCrec->Caller_Range = CUR.curRange; | 4763 pCrec->Caller_Range = CUR.curRange; |
4757 pCrec->Caller_IP = CUR.IP + 1; | 4764 pCrec->Caller_IP = CUR.IP + 1; |
4758 pCrec->Cur_Count = 1; | 4765 pCrec->Cur_Count = 1; |
4759 pCrec->Cur_Restart = def->start; | 4766 pCrec->Cur_Restart = def->start; |
| 4767 pCrec->Cur_End = def->end; |
4760 | 4768 |
4761 CUR.callTop++; | 4769 CUR.callTop++; |
4762 | 4770 |
4763 INS_Goto_CodeRange( def->range, | 4771 INS_Goto_CodeRange( def->range, |
4764 def->start ); | 4772 def->start ); |
4765 | 4773 |
4766 CUR.step_ins = FALSE; | 4774 CUR.step_ins = FALSE; |
4767 return; | 4775 return; |
4768 | 4776 |
4769 Fail: | 4777 Fail: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4828 } | 4836 } |
4829 | 4837 |
4830 if ( args[0] > 0 ) | 4838 if ( args[0] > 0 ) |
4831 { | 4839 { |
4832 pCrec = CUR.callStack + CUR.callTop; | 4840 pCrec = CUR.callStack + CUR.callTop; |
4833 | 4841 |
4834 pCrec->Caller_Range = CUR.curRange; | 4842 pCrec->Caller_Range = CUR.curRange; |
4835 pCrec->Caller_IP = CUR.IP + 1; | 4843 pCrec->Caller_IP = CUR.IP + 1; |
4836 pCrec->Cur_Count = (FT_Int)args[0]; | 4844 pCrec->Cur_Count = (FT_Int)args[0]; |
4837 pCrec->Cur_Restart = def->start; | 4845 pCrec->Cur_Restart = def->start; |
| 4846 pCrec->Cur_End = def->end; |
4838 | 4847 |
4839 CUR.callTop++; | 4848 CUR.callTop++; |
4840 | 4849 |
4841 INS_Goto_CodeRange( def->range, def->start ); | 4850 INS_Goto_CodeRange( def->range, def->start ); |
4842 | 4851 |
4843 CUR.step_ins = FALSE; | 4852 CUR.step_ins = FALSE; |
4844 } | 4853 } |
4845 return; | 4854 return; |
4846 | 4855 |
4847 Fail: | 4856 Fail: |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5043 /* */ | 5052 /* */ |
5044 /*************************************************************************/ | 5053 /*************************************************************************/ |
5045 | 5054 |
5046 | 5055 |
5047 /*************************************************************************/ | 5056 /*************************************************************************/ |
5048 /* */ | 5057 /* */ |
5049 /* GC[a]: Get Coordinate projected onto */ | 5058 /* GC[a]: Get Coordinate projected onto */ |
5050 /* Opcode range: 0x46-0x47 */ | 5059 /* Opcode range: 0x46-0x47 */ |
5051 /* Stack: uint32 --> f26.6 */ | 5060 /* Stack: uint32 --> f26.6 */ |
5052 /* */ | 5061 /* */ |
5053 /* BULLSHIT: Measures from the original glyph must be taken along the */ | 5062 /* XXX: UNDOCUMENTED: Measures from the original glyph must be taken */ |
5054 /* dual projection vector! */ | 5063 /* along the dual projection vector! */ |
5055 /* */ | 5064 /* */ |
5056 static void | 5065 static void |
5057 Ins_GC( INS_ARG ) | 5066 Ins_GC( INS_ARG ) |
5058 { | 5067 { |
5059 FT_ULong L; | 5068 FT_ULong L; |
5060 FT_F26Dot6 R; | 5069 FT_F26Dot6 R; |
5061 | 5070 |
5062 | 5071 |
5063 L = (FT_ULong)args[0]; | 5072 L = (FT_ULong)args[0]; |
5064 | 5073 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5116 CUR.zp2.org[L] = CUR.zp2.cur[L]; | 5125 CUR.zp2.org[L] = CUR.zp2.cur[L]; |
5117 } | 5126 } |
5118 | 5127 |
5119 | 5128 |
5120 /*************************************************************************/ | 5129 /*************************************************************************/ |
5121 /* */ | 5130 /* */ |
5122 /* MD[a]: Measure Distance */ | 5131 /* MD[a]: Measure Distance */ |
5123 /* Opcode range: 0x49-0x4A */ | 5132 /* Opcode range: 0x49-0x4A */ |
5124 /* Stack: uint32 uint32 --> f26.6 */ | 5133 /* Stack: uint32 uint32 --> f26.6 */ |
5125 /* */ | 5134 /* */ |
5126 /* BULLSHIT: Measure taken in the original glyph must be along the dual */ | 5135 /* XXX: UNDOCUMENTED: Measure taken in the original glyph must be along */ |
5127 /* projection vector. */ | 5136 /* the dual projection vector. */ |
5128 /* */ | 5137 /* */ |
5129 /* Second BULLSHIT: Flag attributes are inverted! */ | 5138 /* XXX: UNDOCUMENTED: Flag attributes are inverted! */ |
5130 /* 0 => measure distance in original outline */ | 5139 /* 0 => measure distance in original outline */ |
5131 /* 1 => measure distance in grid-fitted outline */ | 5140 /* 1 => measure distance in grid-fitted outline */ |
5132 /* */ | 5141 /* */ |
5133 /* Third one: `zp0 - zp1', and not `zp2 - zp1! */ | 5142 /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */ |
5134 /* */ | 5143 /* */ |
5135 static void | 5144 static void |
5136 Ins_MD( INS_ARG ) | 5145 Ins_MD( INS_ARG ) |
5137 { | 5146 { |
5138 FT_UShort K, L; | 5147 FT_UShort K, L; |
5139 FT_F26Dot6 D; | 5148 FT_F26Dot6 D; |
5140 | 5149 |
5141 | 5150 |
5142 K = (FT_UShort)args[1]; | 5151 K = (FT_UShort)args[1]; |
5143 L = (FT_UShort)args[0]; | 5152 L = (FT_UShort)args[0]; |
5144 | 5153 |
5145 if ( BOUNDS( L, CUR.zp0.n_points ) || | 5154 if ( BOUNDS( L, CUR.zp0.n_points ) || |
5146 BOUNDS( K, CUR.zp1.n_points ) ) | 5155 BOUNDS( K, CUR.zp1.n_points ) ) |
5147 { | 5156 { |
5148 if ( CUR.pedantic_hinting ) | 5157 if ( CUR.pedantic_hinting ) |
5149 CUR.error = TT_Err_Invalid_Reference; | 5158 CUR.error = TT_Err_Invalid_Reference; |
5150 D = 0; | 5159 D = 0; |
5151 } | 5160 } |
5152 else | 5161 else |
5153 { | 5162 { |
5154 if ( CUR.opcode & 1 ) | 5163 if ( CUR.opcode & 1 ) |
5155 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); | 5164 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); |
5156 else | 5165 else |
5157 { | 5166 { |
5158 FT_Vector* vec1 = CUR.zp0.orus + L; | 5167 /* XXX: UNDOCUMENTED: twilight zone special case */ |
5159 FT_Vector* vec2 = CUR.zp1.orus + K; | 5168 |
| 5169 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 ) |
| 5170 { |
| 5171 FT_Vector* vec1 = CUR.zp0.org + L; |
| 5172 FT_Vector* vec2 = CUR.zp1.org + K; |
5160 | 5173 |
5161 | 5174 |
5162 if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) | |
5163 { | |
5164 /* this should be faster */ | |
5165 D = CUR_Func_dualproj( vec1, vec2 ); | 5175 D = CUR_Func_dualproj( vec1, vec2 ); |
5166 D = TT_MULFIX( D, CUR.metrics.x_scale ); | |
5167 } | 5176 } |
5168 else | 5177 else |
5169 { | 5178 { |
5170 FT_Vector vec; | 5179 FT_Vector* vec1 = CUR.zp0.orus + L; |
| 5180 FT_Vector* vec2 = CUR.zp1.orus + K; |
5171 | 5181 |
5172 | 5182 |
5173 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); | 5183 if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) |
5174 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); | 5184 { |
| 5185 /* this should be faster */ |
| 5186 D = CUR_Func_dualproj( vec1, vec2 ); |
| 5187 D = TT_MULFIX( D, CUR.metrics.x_scale ); |
| 5188 } |
| 5189 else |
| 5190 { |
| 5191 FT_Vector vec; |
5175 | 5192 |
5176 D = CUR_fast_dualproj( &vec ); | 5193 |
| 5194 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); |
| 5195 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); |
| 5196 |
| 5197 D = CUR_fast_dualproj( &vec ); |
| 5198 } |
5177 } | 5199 } |
5178 } | 5200 } |
5179 } | 5201 } |
5180 | 5202 |
5181 args[0] = D; | 5203 args[0] = D; |
5182 } | 5204 } |
5183 | 5205 |
5184 | 5206 |
5185 /*************************************************************************/ | 5207 /*************************************************************************/ |
5186 /* */ | 5208 /* */ |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5741 CUR.new_top = CUR.args; | 5763 CUR.new_top = CUR.args; |
5742 } | 5764 } |
5743 | 5765 |
5744 | 5766 |
5745 /*************************************************************************/ | 5767 /*************************************************************************/ |
5746 /* */ | 5768 /* */ |
5747 /* SHC[a]: SHift Contour */ | 5769 /* SHC[a]: SHift Contour */ |
5748 /* Opcode range: 0x34-35 */ | 5770 /* Opcode range: 0x34-35 */ |
5749 /* Stack: uint32 --> */ | 5771 /* Stack: uint32 --> */ |
5750 /* */ | 5772 /* */ |
| 5773 /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */ |
| 5774 /* contour in the twilight zone, namely contour number */ |
| 5775 /* zero. */ |
| 5776 /* */ |
5751 static void | 5777 static void |
5752 Ins_SHC( INS_ARG ) | 5778 Ins_SHC( INS_ARG ) |
5753 { | 5779 { |
5754 TT_GlyphZoneRec zp; | 5780 TT_GlyphZoneRec zp; |
5755 FT_UShort refp; | 5781 FT_UShort refp; |
5756 FT_F26Dot6 dx, | 5782 FT_F26Dot6 dx, dy; |
5757 dy; | |
5758 | 5783 |
5759 FT_Short contour; | 5784 FT_Short contour, bounds; |
5760 FT_UShort first_point, last_point, i; | 5785 FT_UShort start, limit, i; |
5761 | 5786 |
5762 | 5787 |
5763 contour = (FT_UShort)args[0]; | 5788 contour = (FT_UShort)args[0]; |
| 5789 bounds = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours; |
5764 | 5790 |
5765 if ( BOUNDS( contour, CUR.pts.n_contours ) ) | 5791 if ( BOUNDS( contour, bounds ) ) |
5766 { | 5792 { |
5767 if ( CUR.pedantic_hinting ) | 5793 if ( CUR.pedantic_hinting ) |
5768 CUR.error = TT_Err_Invalid_Reference; | 5794 CUR.error = TT_Err_Invalid_Reference; |
5769 return; | 5795 return; |
5770 } | 5796 } |
5771 | 5797 |
5772 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) | 5798 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) |
5773 return; | 5799 return; |
5774 | 5800 |
5775 if ( contour == 0 ) | 5801 if ( contour == 0 ) |
5776 first_point = 0; | 5802 start = 0; |
5777 else | 5803 else |
5778 first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 - | 5804 start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 - |
5779 CUR.pts.first_point ); | 5805 CUR.zp2.first_point ); |
5780 | 5806 |
5781 last_point = (FT_UShort)( CUR.pts.contours[contour] - | 5807 /* we use the number of points if in the twilight zone */ |
5782 CUR.pts.first_point ); | 5808 if ( CUR.GS.gep2 == 0 ) |
| 5809 limit = CUR.zp2.n_points; |
| 5810 else |
| 5811 limit = (FT_UShort)( CUR.zp2.contours[contour] - |
| 5812 CUR.zp2.first_point + 1 ); |
5783 | 5813 |
5784 /* XXX: this is probably wrong... at least it prevents memory */ | 5814 for ( i = start; i < limit; i++ ) |
5785 /* corruption when zp2 is the twilight zone */ | |
5786 if ( BOUNDS( last_point, CUR.zp2.n_points ) ) | |
5787 { | |
5788 if ( CUR.zp2.n_points > 0 ) | |
5789 last_point = (FT_UShort)(CUR.zp2.n_points - 1); | |
5790 else | |
5791 last_point = 0; | |
5792 } | |
5793 | |
5794 for ( i = first_point; i <= last_point; i++ ) | |
5795 { | 5815 { |
5796 if ( zp.cur != CUR.zp2.cur || refp != i ) | 5816 if ( zp.cur != CUR.zp2.cur || refp != i ) |
5797 MOVE_Zp2_Point( i, dx, dy, TRUE ); | 5817 MOVE_Zp2_Point( i, dx, dy, TRUE ); |
5798 } | 5818 } |
5799 } | 5819 } |
5800 | 5820 |
5801 | 5821 |
5802 /*************************************************************************/ | 5822 /*************************************************************************/ |
5803 /* */ | 5823 /* */ |
5804 /* SHZ[a]: SHift Zone */ | 5824 /* SHZ[a]: SHift Zone */ |
5805 /* Opcode range: 0x36-37 */ | 5825 /* Opcode range: 0x36-37 */ |
5806 /* Stack: uint32 --> */ | 5826 /* Stack: uint32 --> */ |
5807 /* */ | 5827 /* */ |
5808 static void | 5828 static void |
5809 Ins_SHZ( INS_ARG ) | 5829 Ins_SHZ( INS_ARG ) |
5810 { | 5830 { |
5811 TT_GlyphZoneRec zp; | 5831 TT_GlyphZoneRec zp; |
5812 FT_UShort refp; | 5832 FT_UShort refp; |
5813 FT_F26Dot6 dx, | 5833 FT_F26Dot6 dx, |
5814 dy; | 5834 dy; |
5815 | 5835 |
5816 FT_UShort last_point, i; | 5836 FT_UShort limit, i; |
5817 | 5837 |
5818 | 5838 |
5819 if ( BOUNDS( args[0], 2 ) ) | 5839 if ( BOUNDS( args[0], 2 ) ) |
5820 { | 5840 { |
5821 if ( CUR.pedantic_hinting ) | 5841 if ( CUR.pedantic_hinting ) |
5822 CUR.error = TT_Err_Invalid_Reference; | 5842 CUR.error = TT_Err_Invalid_Reference; |
5823 return; | 5843 return; |
5824 } | 5844 } |
5825 | 5845 |
5826 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) | 5846 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) |
5827 return; | 5847 return; |
5828 | 5848 |
5829 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ | 5849 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ |
5830 /* Twilight zone has no contours, so use `n_points'. */ | 5850 /* Twilight zone has no real contours, so use `n_points'. */ |
5831 /* Normal zone's `n_points' includes phantoms, so must */ | 5851 /* Normal zone's `n_points' includes phantoms, so must */ |
5832 /* use end of last contour. */ | 5852 /* use end of last contour. */ |
5833 if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 ) | 5853 if ( CUR.GS.gep2 == 0 ) |
5834 last_point = (FT_UShort)( CUR.zp2.n_points - 1 ); | 5854 limit = (FT_UShort)CUR.zp2.n_points; |
5835 else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 ) | 5855 else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 ) |
5836 { | 5856 limit = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] + 1 ); |
5837 last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] ); | |
5838 | |
5839 if ( BOUNDS( last_point, CUR.zp2.n_points ) ) | |
5840 { | |
5841 if ( CUR.pedantic_hinting ) | |
5842 CUR.error = TT_Err_Invalid_Reference; | |
5843 return; | |
5844 } | |
5845 } | |
5846 else | 5857 else |
5847 last_point = 0; | 5858 limit = 0; |
5848 | 5859 |
5849 /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ | 5860 /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ |
5850 for ( i = 0; i <= last_point; i++ ) | 5861 for ( i = 0; i < limit; i++ ) |
5851 { | 5862 { |
5852 if ( zp.cur != CUR.zp2.cur || refp != i ) | 5863 if ( zp.cur != CUR.zp2.cur || refp != i ) |
5853 MOVE_Zp2_Point( i, dx, dy, FALSE ); | 5864 MOVE_Zp2_Point( i, dx, dy, FALSE ); |
5854 } | 5865 } |
5855 } | 5866 } |
5856 | 5867 |
5857 | 5868 |
5858 /*************************************************************************/ | 5869 /*************************************************************************/ |
5859 /* */ | 5870 /* */ |
5860 /* SHPIX[]: SHift points by a PIXel amount */ | 5871 /* SHPIX[]: SHift points by a PIXel amount */ |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6246 /* UNDOCUMENTED! The MS rasterizer does that with */ | 6257 /* UNDOCUMENTED! The MS rasterizer does that with */ |
6247 /* twilight points (confirmed by Greg Hitchcock) */ | 6258 /* twilight points (confirmed by Greg Hitchcock) */ |
6248 if ( CUR.GS.gep1 == 0 ) | 6259 if ( CUR.GS.gep1 == 0 ) |
6249 { | 6260 { |
6250 CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + | 6261 CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + |
6251 TT_MulFix14( (FT_UInt32)cvt_dist, | 6262 TT_MulFix14( (FT_UInt32)cvt_dist, |
6252 CUR.GS.freeVector.x ); | 6263 CUR.GS.freeVector.x ); |
6253 CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + | 6264 CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + |
6254 TT_MulFix14( (FT_UInt32)cvt_dist, | 6265 TT_MulFix14( (FT_UInt32)cvt_dist, |
6255 CUR.GS.freeVector.y ); | 6266 CUR.GS.freeVector.y ); |
6256 CUR.zp1.cur[point] = CUR.zp0.cur[point]; | 6267 CUR.zp1.cur[point] = CUR.zp1.org[point]; |
6257 } | 6268 } |
6258 | 6269 |
6259 org_dist = CUR_Func_dualproj( &CUR.zp1.org[point], | 6270 org_dist = CUR_Func_dualproj( &CUR.zp1.org[point], |
6260 &CUR.zp0.org[CUR.GS.rp0] ); | 6271 &CUR.zp0.org[CUR.GS.rp0] ); |
6261 cur_dist = CUR_Func_project ( &CUR.zp1.cur[point], | 6272 cur_dist = CUR_Func_project ( &CUR.zp1.cur[point], |
6262 &CUR.zp0.cur[CUR.GS.rp0] ); | 6273 &CUR.zp0.cur[CUR.GS.rp0] ); |
6263 | 6274 |
6264 /* auto-flip test */ | 6275 /* auto-flip test */ |
6265 | 6276 |
6266 if ( CUR.GS.auto_flip ) | 6277 if ( CUR.GS.auto_flip ) |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6555 BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) ) | 6566 BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) ) |
6556 { | 6567 { |
6557 old_range = 0; | 6568 old_range = 0; |
6558 cur_range = 0; | 6569 cur_range = 0; |
6559 } | 6570 } |
6560 else | 6571 else |
6561 { | 6572 { |
6562 if ( twilight ) | 6573 if ( twilight ) |
6563 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2], | 6574 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2], |
6564 orus_base ); | 6575 orus_base ); |
6565 else | 6576 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) |
6566 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2], | 6577 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2], |
6567 orus_base ); | 6578 orus_base ); |
| 6579 else |
| 6580 { |
| 6581 FT_Vector vec; |
| 6582 |
| 6583 |
| 6584 vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x, |
| 6585 CUR.metrics.x_scale ); |
| 6586 vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y, |
| 6587 CUR.metrics.y_scale ); |
| 6588 |
| 6589 old_range = CUR_fast_dualproj( &vec ); |
| 6590 } |
6568 | 6591 |
6569 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base ); | 6592 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base ); |
6570 } | 6593 } |
6571 | 6594 |
6572 for ( ; CUR.GS.loop > 0; --CUR.GS.loop ) | 6595 for ( ; CUR.GS.loop > 0; --CUR.GS.loop ) |
6573 { | 6596 { |
6574 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args]; | 6597 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args]; |
6575 FT_F26Dot6 org_dist, cur_dist, new_dist; | 6598 FT_F26Dot6 org_dist, cur_dist, new_dist; |
6576 | 6599 |
6577 | 6600 |
6578 /* check point bounds */ | 6601 /* check point bounds */ |
6579 if ( BOUNDS( point, CUR.zp2.n_points ) ) | 6602 if ( BOUNDS( point, CUR.zp2.n_points ) ) |
6580 { | 6603 { |
6581 if ( CUR.pedantic_hinting ) | 6604 if ( CUR.pedantic_hinting ) |
6582 { | 6605 { |
6583 CUR.error = TT_Err_Invalid_Reference; | 6606 CUR.error = TT_Err_Invalid_Reference; |
6584 return; | 6607 return; |
6585 } | 6608 } |
6586 continue; | 6609 continue; |
6587 } | 6610 } |
6588 | 6611 |
6589 if ( twilight ) | 6612 if ( twilight ) |
6590 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base ); | 6613 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base ); |
| 6614 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) |
| 6615 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base ); |
6591 else | 6616 else |
6592 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base ); | 6617 { |
| 6618 FT_Vector vec; |
| 6619 |
| 6620 |
| 6621 vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x, |
| 6622 CUR.metrics.x_scale ); |
| 6623 vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y, |
| 6624 CUR.metrics.y_scale ); |
| 6625 |
| 6626 org_dist = CUR_fast_dualproj( &vec ); |
| 6627 } |
6593 | 6628 |
6594 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base ); | 6629 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base ); |
6595 | 6630 |
6596 if ( org_dist ) | 6631 if ( org_dist ) |
6597 new_dist = ( old_range != 0 ) | 6632 new_dist = ( old_range != 0 ) |
6598 ? TT_MULDIV( org_dist, cur_range, old_range ) | 6633 ? TT_MULDIV( org_dist, cur_range, old_range ) |
6599 : cur_dist; | 6634 : cur_dist; |
6600 else | 6635 else |
6601 new_dist = 0; | 6636 new_dist = 0; |
6602 | 6637 |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7129 CUR.error = TT_Err_Stack_Overflow; | 7164 CUR.error = TT_Err_Stack_Overflow; |
7130 return; | 7165 return; |
7131 } | 7166 } |
7132 | 7167 |
7133 call = CUR.callStack + CUR.callTop++; | 7168 call = CUR.callStack + CUR.callTop++; |
7134 | 7169 |
7135 call->Caller_Range = CUR.curRange; | 7170 call->Caller_Range = CUR.curRange; |
7136 call->Caller_IP = CUR.IP + 1; | 7171 call->Caller_IP = CUR.IP + 1; |
7137 call->Cur_Count = 1; | 7172 call->Cur_Count = 1; |
7138 call->Cur_Restart = def->start; | 7173 call->Cur_Restart = def->start; |
| 7174 call->Cur_End = def->end; |
7139 | 7175 |
7140 INS_Goto_CodeRange( def->range, def->start ); | 7176 INS_Goto_CodeRange( def->range, def->start ); |
7141 | 7177 |
7142 CUR.step_ins = FALSE; | 7178 CUR.step_ins = FALSE; |
7143 return; | 7179 return; |
7144 } | 7180 } |
7145 } | 7181 } |
7146 | 7182 |
7147 CUR.error = TT_Err_Invalid_Opcode; | 7183 CUR.error = TT_Err_Invalid_Opcode; |
7148 } | 7184 } |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7501 do | 7537 do |
7502 { | 7538 { |
7503 CUR.opcode = CUR.code[CUR.IP]; | 7539 CUR.opcode = CUR.code[CUR.IP]; |
7504 | 7540 |
7505 FT_TRACE7(( " " )); | 7541 FT_TRACE7(( " " )); |
7506 FT_TRACE7(( opcode_name[CUR.opcode] )); | 7542 FT_TRACE7(( opcode_name[CUR.opcode] )); |
7507 FT_TRACE7(( "\n" )); | 7543 FT_TRACE7(( "\n" )); |
7508 | 7544 |
7509 if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) | 7545 if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) |
7510 { | 7546 { |
7511 if ( CUR.IP + 1 > CUR.codeSize ) | 7547 if ( CUR.IP + 1 >= CUR.codeSize ) |
7512 goto LErrorCodeOverflow_; | 7548 goto LErrorCodeOverflow_; |
7513 | 7549 |
7514 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1]; | 7550 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1]; |
7515 } | 7551 } |
7516 | 7552 |
7517 if ( CUR.IP + CUR.length > CUR.codeSize ) | 7553 if ( CUR.IP + CUR.length > CUR.codeSize ) |
7518 goto LErrorCodeOverflow_; | 7554 goto LErrorCodeOverflow_; |
7519 | 7555 |
7520 /* First, let's check for empty stack and overflow */ | 7556 /* First, let's check for empty stack and overflow */ |
7521 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 ); | 7557 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 ); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8137 CUR.error = TT_Err_Invalid_Reference; | 8173 CUR.error = TT_Err_Invalid_Reference; |
8138 goto LErrorLabel_; | 8174 goto LErrorLabel_; |
8139 } | 8175 } |
8140 | 8176 |
8141 callrec = &CUR.callStack[CUR.callTop]; | 8177 callrec = &CUR.callStack[CUR.callTop]; |
8142 | 8178 |
8143 callrec->Caller_Range = CUR.curRange; | 8179 callrec->Caller_Range = CUR.curRange; |
8144 callrec->Caller_IP = CUR.IP + 1; | 8180 callrec->Caller_IP = CUR.IP + 1; |
8145 callrec->Cur_Count = 1; | 8181 callrec->Cur_Count = 1; |
8146 callrec->Cur_Restart = def->start; | 8182 callrec->Cur_Restart = def->start; |
| 8183 callrec->Cur_End = def->end; |
8147 | 8184 |
8148 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE ) | 8185 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE ) |
8149 goto LErrorLabel_; | 8186 goto LErrorLabel_; |
8150 | 8187 |
8151 goto LSuiteLabel_; | 8188 goto LSuiteLabel_; |
8152 } | 8189 } |
8153 } | 8190 } |
8154 } | 8191 } |
8155 | 8192 |
8156 CUR.error = TT_Err_Invalid_Opcode; | 8193 CUR.error = TT_Err_Invalid_Opcode; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8210 #ifdef TT_CONFIG_OPTION_STATIC_RASTER | 8247 #ifdef TT_CONFIG_OPTION_STATIC_RASTER |
8211 *exc = cur; | 8248 *exc = cur; |
8212 #endif | 8249 #endif |
8213 | 8250 |
8214 /* If any errors have occurred, function tables may be broken. */ | 8251 /* If any errors have occurred, function tables may be broken. */ |
8215 /* Force a re-execution of `prep' and `fpgm' tables if no */ | 8252 /* Force a re-execution of `prep' and `fpgm' tables if no */ |
8216 /* bytecode debugger is run. */ | 8253 /* bytecode debugger is run. */ |
8217 if ( CUR.error && !CUR.instruction_trap ) | 8254 if ( CUR.error && !CUR.instruction_trap ) |
8218 { | 8255 { |
8219 FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error )); | 8256 FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error )); |
8220 exc->size->cvt_ready = FALSE; | 8257 exc->size->cvt_ready = FALSE; |
8221 } | 8258 } |
8222 | 8259 |
8223 return CUR.error; | 8260 return CUR.error; |
8224 } | 8261 } |
8225 | 8262 |
8226 | 8263 |
8227 #endif /* TT_USE_BYTECODE_INTERPRETER */ | 8264 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
8228 | 8265 |
8229 | 8266 |
8230 /* END */ | 8267 /* END */ |
OLD | NEW |