ApwFreetypeLibrary

Check-in [8b3b803ceb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:initial version
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8b3b803cebb21bec8795d05a07c07110cea12cc9
User & Date: arnulf 2014-12-29 21:43:38
Context
2014-12-29
21:44
initial verwsion. check-in: ba5a7822b2 user: arnulf tags: trunk
21:43
initial version check-in: 8b3b803ceb user: arnulf tags: trunk
21:43
initial version. check-in: 4f1061340c user: arnulf tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added ftbase/TTCallRec.java.











































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTCallRec                                                          */
  /*                                                                       */
  /* This class defines a call record, used to manage function calls.      */
  /* ===================================================================== */

public class TTCallRec extends FTDebug {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTCallRec";

    public int CallerRange;
    public int CallerIP;
    public int CurCount;
    public int CurRestart;
    public int CurEnd;

    /* ==================== TTCallRec ================================== */
    public TTCallRec() {
      oid++;
      id = oid;
      
      CallerRange = 0;
      CallerIP = 0;
      CurCount = 0;
      CurRestart = 0;
      CurEnd = 0;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      str.append("  CallerRange: "+CallerRange+"\n");
      str.append("  CallerIP: "+CallerIP+"\n");
      str.append("  CurCount: "+CurCount+"\n");
      str.append("  CurRestart: "+CurRestart+"\n");
      str.append("  CurEnd: "+CurEnd+"\n");
      return str.toString();
    }
 
    /* ==================== setCallerRange ===================================== */
    public void setCallerRange(int val) {
        this.CallerRange = val;
    }

    /* ==================== setCallerIP ===================================== */
    public void setCallerIP(int val) {
        this.CallerIP = val;
    }

    /* ==================== setCurCount ===================================== */
    public void setCurCount(int val) {
        this.CurCount = val;
    }

    /* ==================== setCurRestart ===================================== */
    public void setCurRestart(int val) {
        this.CurRestart = val;
    }

    /* ==================== setCurEnd ===================================== */
    public void setCurEnd(int val) {
        this.CurEnd = val;
    }

    /* ==================== getCallerRange ===================================== */
    public int getCallerRange(int val) {
        return this.CallerRange;
    }

    /* ==================== getCallerIP ===================================== */
    public int getCallerIP(int val) {
        return this.CallerIP;
    }

    /* ==================== getCurCount ===================================== */
    public int getCurCount(int val) {
        return this.CurCount;
    }

    /* ==================== getCurRestart ===================================== */
    public int getCurRestart(int val) {
        return this.CurRestart;
    }

    /* ==================== getCurEnd ===================================== */
    public int getCurEnd(int val) {
        return this.CurEnd;
    }

}

Added ftbase/TTCodeRange.java.





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTCodeRange                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTCodeRange extends Object {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTCodeRange";

    public final static int TT_CODERANGE_NONE = 0;
    public final static int TT_CODERANGE_FONT = 1;
    public final static int TT_CODERANGE_CVT = 2;
    public final static int TT_CODERANGE_GLYPH = 3;

    public Long size = 0L;
    public byte[] base = null;
    public short[] short_base = null;

    /* ==================== TTCodeRange ================================== */
    public TTCodeRange() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTDefRec.java.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// ----------------------------------------------------------------
// TTDefRec.java --
//
// Copyright (c) 2014 by Arnulf P. Wiedemann
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//------------------------------------------------------------------------

package ftbase;

//import android.util.Log;

/* ======================================================================= */
/*  This Java implementation is derived from the Freetype code             */
/*  and has been implemented to work together with the Apache batik code   */
/*  for reading .ttf font files                                             */
/*                                                                         */
/*  Copyright (C) of the Java implementation 2014                          */
/*  Arnulf Wiedemann                                                       */
/*                                                                         */
/*  See the file "license.terms" for information on usage and              */
/*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.   */
/*                                                                         */
/*  in this directory the truetype opcode interpreter is ported to Java    */
/*                                                                         */
/*  the next blocks are taken from the original source code                */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
/*            2010 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/* ======================================================================= */

  /* ===================================================================== */
  /*    TTDefRec                                                           */
  /*                                                                       */
  /* Defines a function/instruction definition record.                     */
  /* ===================================================================== */

public class TTDefRec extends Object {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTDefRec";

    public int range = 0;          /* in which code range is it located?     */
    public int start = 0;          /* where does it start?                   */
    public int end = 0;            /* where does it end?                     */
    public int opc = 0;            /* function #, or instruction code        */
    public boolean active = false;         /* is it active?                          */
    public boolean inline_delta = false;   /* is function that defines inline delta? */
    public Long sph_fdef_flags = 0L; /* flags to identify special functions    */

    /* ==================== TTDefRec ================================== */
    public TTDefRec() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * =====================================================================
     */

}

Added ftbase/TTDefaultGraphicsStateClass.java.

































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// ----------------------------------------------------------------
// TTDefaultGraphicsStateClass.java --
//
// Copyright (c) 2014 by Arnulf P. Wiedemann
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//------------------------------------------------------------------------

package ftbase;

//import android.util.Log;

/* ======================================================================= */
/*  This Java implementation is derived from the Freetype code             */
/*  and has been implemented to work together with the Apache batik code   */
/*  for reading .ttf ont files                                             */
/*                                                                         */
/*  Copyright (C) of the Java implementation 2014                          */
/*  Arnulf Wiedemann                                                       */
/*                                                                         */
/*  See the file "license.terms" for information on usage and              */
/*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.   */
/*                                                                         */
/*  in this directory the truetype opcode interpreter is ported to Java    */
/*                                                                         */
/*  the next blocks are taken from the original source code                */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
/*            2010 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/* ======================================================================= */

  /* ===================================================================== */
  /*    TTDefaultGraphicsStateClass                                                    */
  /*                                                                       */
  /* <Struct>                                                              */
  /*    TTDefaultGraphicsStateClass                                                    */
  /*                                                                       */
  /* <Description>                                                         */
  /*    The TrueType graphics state used during bytecode interpretation.   */
  /* ===================================================================== */

public class TTDefaultGraphicsStateClass extends TTGraphicsStateRec {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTDefaultGraphicsStateClass";

    /* ================ TTDefaultGraphicsStateClass ========================== */
    public TTDefaultGraphicsStateClass() {
      oid++;
      id = oid;

      rp0 = 0;
      rp1 = 0;
      rp2 = 0;
      dualVector = new FTUnitVectorRec();
      dualVector.x = 0x4000L;
      dualVector.y = 0L;
      projVector = new FTUnitVectorRec();
      projVector.x = 0x4000L;
      projVector.y = 0L;
      freeVector = new FTUnitVectorRec();
      freeVector.x = 0x4000L;
      freeVector.y = 0L;

      loop = 1;
      minimum_distance = 64;
      round_state = 1;

      auto_flip = true;
      control_value_cutin = 68;
      single_width_cutin = 0;
      single_width_value = 0;
      delta_base = 9;
      delta_shift = 3;

      instruct_control = 0;
      scan_control = false;
      scan_type = 0;
      gep0 = 1;
      gep1 = 1;
      gep2 = 1;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTDriverClass.java.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTDriverClass                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTDriverClass extends FTDriverClassRec {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTDriverClass";

    /* ==================== TTDriverClass ================================== */
    public TTDriverClass() {
      super();
      oid++;
      id = oid;

Debug(0, DBG_INIT, TAG, "TTDriverClass constructor called!!");
      module_flags = (long)(FTModuleClassRec.FT_MODULE_FONT_DRIVER |
             FTModuleClassRec.FT_MODULE_DRIVER_SCALABLE |
             FTModuleClassRec.FT_MODULE_DRIVER_HAS_HINTER);  /* a font driver */
      module_type = FT_MODULE_TYPE_TT_DRIVER_REC;
      module_name = "truetype";    /* driver name */
      module_version = 0x10000L;   /* driver version 1.0 */
      module_requires = 0x20000L;  /* driver requires FreeType 2.0 or higher */
      module_interface = null;     /* driver specific interface */

      String class_name = "org.apwtcl.gles20.truetype.TTDriverFuncs";
      module_init = new FTInstanceMethod(class_name, "tt_driver_init", 1);
      module_done = new FTInstanceMethod(class_name, "tt_driver_done", 1);
      get_interface = new FTInstanceMethod(class_name, "tt_get_interface", 1);

      face_object_type = FACE_REC_TYPE_TT;
      size_object_type = SIZE_REC_TYPE_TT;
      slot_object_type = SLOT_REC_TYPE_FT_GLYPH;
      
      String loader_funcs_class_name = "org.apwtcl.gles20.truetype.TTLoaderFuncs"; 
      load_glyph = new FTInstanceMethod(loader_funcs_class_name, "tt_glyph_load", 4);
      attach_file = null;

      String face_class_name = "org.apwtcl.gles20.truetype.TTFaceFuncs";
      init_face = new FTInstanceMethod(face_class_name, "tt_face_init", 5);
      done_face = new FTInstanceMethod(face_class_name, "tt_face_done", 4);
      init_slot = new FTInstanceMethod(face_class_name, "tt_slot_init", 4);
      done_slot = null;
      get_advances = new FTInstanceMethod(face_class_name, "tt_get_advances", 4);
      get_kerning = new FTInstanceMethod(face_class_name, "tt_get_kerning", 4);

      String size_class_name = "org.apwtcl.gles20.truetype.TTSizeFuncs";
      init_size = new FTInstanceMethod(size_class_name, "tt_size_init", 4);
      done_size = new FTInstanceMethod(size_class_name, "tt_size_done", 4);
      request_size = new FTInstanceMethod(size_class_name, "tt_size_request", 4);
      select_size = null;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTDriverRec.java.

































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

import android.util.Log;

  /* ===================================================================== */
  /*    TTDriverRec                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTDriverRec extends FTDriverRec {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTDriverRec";

    public TTExecContextRec context; /* execution context        */
    public TTGlyphZoneRec zone;      /* glyph loader points zone */
    public Integer interpreter_version;

    /* ==================== TTDriverRec ================================== */
    public TTDriverRec() {
      super();
      oid++;
      id = oid;
      
      context = null;
      zone = null;
      interpreter_version = 0;
    }
    
    /* ==================== TTDriverRec ================================== */
    public TTDriverRec(FTDriverRec driver) {
      super();
      oid++;
      id = oid;
      
      this.module_clazz = driver.module_clazz;
      this.library = driver.library;
      this.driver_clazz = driver.driver_clazz;
      this.faces_list = driver.faces_list;
      this.glyph_loader = driver.glyph_loader;
      context = null;
      zone = null;
      interpreter_version = 0;
    }
    
    /* ==================== TTDriverRec ================================== */
    public TTDriverRec(FTDriverClassRec driver_clazz, FTLibraryRec library) {
      super();
Log.e(TAG, "calling constructor with params for TTDriverRec!!");
      oid++;
      id = oid;
      
      this.driver_clazz = driver_clazz;
      this.library = library;

      /* we duplicate the FTModuleRec info her and derive the class
       * from FTModuleRec, so we can cast it to FTModuleRec for
       * library.modules and are able to check the module_flags
       */

      this.library = library;
      this.module_clazz = new FTModuleClassRec();
      module_clazz.module_flags = driver_clazz.module_flags;  /* a font driver */
      module_clazz.module_type = driver_clazz.module_type;
      module_clazz.module_name = driver_clazz.module_name;
      module_clazz.module_version = driver_clazz.module_version;
      module_clazz.module_requires = driver_clazz.module_requires;
      module_clazz.module_interface = driver_clazz.module_interface;
      module_clazz.module_init = driver_clazz.module_init;
      module_clazz.module_done = driver_clazz.module_done;
      module_clazz.get_interface = driver_clazz.get_interface;

      context = null;
      zone = null;
      interpreter_version = 0;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * TTLoadContext
     *
     * <Description>
     *    Prepare an execution context for glyph hinting.
     *
     * <Input>
     *    face :: A handle to the source face object.
     *
     *    size :: A handle to the source size object.
     *
     * <InOut>
     *    exec :: A handle to the target execution context.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * <Note>
     *    Only the glyph loader and debugger should call this function.
     *
     * =====================================================================
     */
    public static int TTLoadContext(FTReference<TTExecContextRec> exec_ref, TTFaceRec face, TTSizeRec size) {
if (FTGlyphLoaderRec.glyph_debug > 2) {
System.out.println("TTLoadContext");
}
      TTExecContextRec exec = exec_ref.Get();
      int error = 0;
      int i;
      TTMaxProfile maxp ;

      exec.face = face;
      maxp = face.max_profile;
      exec.size = size;
      if (size != null) {
Debug(0, DBG_LOAD_GLYPH, TAG, "num_function_defs: "+size.num_function_defs+"!"+exec.numFDefs+"!");
Debug(0, DBG_LOAD_GLYPH, TAG, "max_function_defs: "+size.max_function_defs+"!"+exec.maxFDefs+"!");
Debug(0, DBG_LOAD_GLYPH, TAG, "function_defs: "+size.function_defs+"=="+exec.FDefs+"!");
        exec.numFDefs = size.num_function_defs;
        exec.maxFDefs = size.max_function_defs;
        exec.numIDefs = size.num_instruction_defs;
        exec.maxIDefs = size.max_instruction_defs;
        exec.FDefs = size.function_defs;
        exec.IDefs = size.instruction_defs;
        exec.tt_metrics = size.ttmetrics;
        exec.metrics  = size.metrics;
        exec.maxFunc = size.max_func;
        exec.maxIns = size.max_ins;
        for (i = 0; i < TTSizeRec.TT_MAX_CODE_RANGES; i++) {
          exec.codeRangeTable[i] = size.codeRangeTable[i];
        }
        /* set graphics state */
        exec.GS = size.GS;
        exec.cvtSize = (int)size.cvt_size;
        exec.cvt = size.cvt;
        exec.storeSize = size.storage_size;
        exec.storage = size.storage;
        exec.twilight = size.twilight;
        /* In case of multi-threading it can happen that the old size object */
        /* no longer exists, thus we must clear all glyph zone references.   */
        // ft_memset( &exec.zp0, 0, sizeof ( exec.zp0 ) );
        // exec.zp1 = exec.zp0;
        // exec.zp2 = exec.zp0;
	// ATTENTION!! have to call reset otherwise the references are wrong in
	// for example DirectMoveX!!
        exec.zp0.reset();
        exec.zp1.reset();
        exec.zp2.reset();
      }
      /* XXX: We reserve a little more elements on the stack to deal safely */
      /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
Debug(0, DBG_LOAD_GLYPH, TAG, "face.id: "+face+"!"+face.max_profile+"!");
      exec.stackSize = face.max_profile.maxStackElements + 32;
      // tmp = exec.stackSize;
//      error = UpdateMax(exec.memory, &tmp, sizeof ( FT_F26Dot6 ), (void*)&exec.stack, maxp.maxStackElements + 32 );
      long[] tmp1 = null;
      if (exec.stack != null) {
        tmp1 = new long[exec.stackSize];
        tmp1 = java.util.Arrays.copyOf(exec.stack, exec.stackSize);
      }
      exec.stack = new long[maxp.maxStackElements + 32];
      if (tmp1 != null) {
        exec.stack = java.util.Arrays.copyOf(tmp1, exec.stackSize);
      }
      for (int k = exec.stackSize; k < maxp.maxStackElements + 32; k++) {
        exec.stack[k] = 0;
      }
      exec.stackSize = maxp.maxStackElements + 32;
      if (exec.stackSize > exec.stack.length) {
        Log.e(TAG, "exec.stackSize > exec.stack!!");
        error = -999;
        return error;
      }
      if (error != 0) {
        return error;
      }
      exec.glyphSize = face.max_profile.maxSizeOfInstructions;
//      tmp = exec.glyphSize;
//      error = Update_Max(exec.memory, &tmp, sizeof ( FT_Byte ), (void*)&exec.glyphIns, maxp.maxSizeOfInstructions );
      byte[] tmp2 = null;
      if (exec.glyphIns != null) {
        tmp2 = new byte[exec.glyphSize];
        tmp2 = java.util.Arrays.copyOf(exec.glyphIns, exec.glyphSize);
      }
      exec.glyphIns = new byte[maxp.maxSizeOfInstructions];
      if (tmp2 != null) {
        exec.glyphIns = java.util.Arrays.copyOf(tmp2, exec.glyphSize);
      }
      for (int j = exec.glyphSize; j < maxp.maxSizeOfInstructions; j++) {
        exec.glyphIns[j] = 0;
      }
      exec.glyphSize = maxp.maxSizeOfInstructions;
      if (exec.glyphSize > exec.glyphIns.length) {
        Log.e(TAG, "exec.glyphSize > exec.glyphIns!!");
        error = -999;
        return error;
      }
      if (error != 0) {
        return error;
      }
      // exec.zp1 = exec.pts;
      // exec.zp2 = exec.pts;
      // exec.zp0 = exec.pts;
      exec.zp1.copy(exec.pts);
      exec.zp2.copy(exec.pts);
      exec.zp0.copy(exec.pts);
      exec.pts.n_points = 0;
      exec.pts.n_contours = 0;

      exec.instruction_trap = false;
      exec_ref.Set(exec);
      return error;
    }
 
    /* =====================================================================
     * FTGlyphLoaderRewind
     * =====================================================================
     */
    public static void FTGlyphLoaderRewind(FTReference<FTGlyphLoaderRec> loader_ref) {
      FTGlyphLoaderRec loader = loader_ref.Get();

      loader.base.outline.n_points = 0;
      loader.base.outline.n_contours = 0;
      loader.base.num_subglyphs = 0;
      loader.current.copy(loader.base);
      loader_ref.Set(loader);
    }

}

Added ftbase/TTExecContextRec.java.







































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTExecContextRec                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTExecContextRec extends Object {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTExecContextRec";
    private final static int MAX_STACK_SIZE = 32;
    private final static int MAX_CALL_SIZE = 32;
    private final static int MAX_ARGS = 4096;

    protected TTFaceRec face = null;
    protected TTSizeRec size = null;
//    FT_Memory memory;
    /* instructions state */
    protected int error = 0;                  /* last execution error */
    protected int top = 0;                    /* top of exec. stack   */
    protected int stackSize = MAX_STACK_SIZE; /* size of exec. stack  */
    protected long[] stack = null;            /* current exec. stack  */
    protected int numArgs = 0;
    protected int[] args = null;
    protected int new_top = 0;                /* new top after exec.  */
    protected TTGlyphZoneRec zp0 = null;      /* zone records */
    protected TTGlyphZoneRec zp1 = null;
    protected TTGlyphZoneRec zp2 = null;
    protected TTGlyphZoneRec pts = null;
    protected TTGlyphZoneRec twilight = null;
    protected FTSizeMetricsRec metrics = null;
    protected TTSizeMetricsRec tt_metrics = null; /* size metrics */
    protected TTGraphicsStateRec GS = null;       /* current graphics state */
    protected int curRange = 0;             /* current code range number   */
    protected byte[] code = null;           /* current code range          */
    protected short[] cvt_code = null;      /* current code range          */
    protected int IP = 0;                   /* current instruction pointer */
    protected int codeSize = 0;             /* size of current range       */
    protected short opcode = 0;             /* current opcode              */
    protected int length = 0;               /* length of current opcode    */
    protected boolean step_ins = false;     /* true if the interpreter must */
                                            /* increment IP after ins. exec */
    protected int cvtSize = 0;
    protected long[] cvt = null;
    protected int glyphSize = 0;            /* glyph instructions buffer size */
    public byte[] glyphIns = null;          /* glyph instructions buffer */
    protected int numFDefs = 0;             /* number of function defs         */
    protected int maxFDefs = 0;             /* maximum number of function defs */
    protected TTDefRec[] FDefs = null;      /* table of FDefs entries          */
    protected int numIDefs = 0;             /* number of instruction defs */
    protected int maxIDefs = 0;             /* maximum number of ins defs */
    protected TTDefRec[] IDefs = null;      /* table of IDefs entries     */
    protected int maxFunc = 0;              /* maximum function index     */
    protected int maxIns = 0;               /* maximum instruction index  */
    protected int callTop = 0;              /* top of call stack during execution */
    protected int callSize = MAX_CALL_SIZE; /* size of call stack */
    protected TTCallRec[] callStack = null; /* call stack */
    protected short maxPoints = 0;          /* capacity of this context's `pts' */
    protected short maxContours = 0;        /* record, expressed in points and  */
                                            /* contours.                        */
    public TTCodeRange[] codeRangeTable = null; /* table of valid code ranges */
                                            /* useful for the debugger   */
    protected short storeSize = 0;          /* size of current storage */
    protected long[] storage = null;        /* storage area            */
    protected int period = 0;               /* values used for the */
    protected int phase = 0;                /* `SuperRounding'     */
    protected int threshold = 0;
    protected boolean instruction_trap = false; /* If `True', the interpreter will */
                                            /* exit after each instruction     */
    protected TTGraphicsStateRec default_GS = null; /* graphics state resulting from   */
                                            /* the prep program                */
    protected boolean is_composite = false; /* true if the glyph is composite  */
    protected boolean pedantic_hinting = false; /* true if pedantic interpretation */
    /* latest interpreter additions */
    protected long F_dot_P = 0L;            /* dot product of freedom and projection vectors */
    protected FTInstanceMethod func_round = null;     /* current rounding function */
    protected FTInstanceMethod func_project = null;   /* current projection function */
    protected FTInstanceMethod func_dualproj = null;  /* current dual proj. function */
    protected FTInstanceMethod func_freeProj = null;  /* current freedom proj. func  */
    protected FTInstanceMethod func_move = null;      /* current point move function */
    protected FTInstanceMethod func_move_orig = null; /* move original position function */
    protected FTInstanceMethod func_read_cvt= null;   /* read a cvt entry              */
    protected FTInstanceMethod func_write_cvt = null; /* write a cvt entry (in pixels) */
    protected FTInstanceMethod func_move_cvt = null;  /* incr a cvt entry (in pixels)  */
    protected boolean grayscale = false;              /* are we hinting for grayscale? */

    /* ==================== TTExecContextRec ================================== */
    public TTExecContextRec() {
      oid++;
      id = oid;

      stack = new long[stackSize];
      args = new int[MAX_ARGS];
      zp0 = new TTGlyphZoneRec("TTExecContextRec.zp0");
      zp1 = new TTGlyphZoneRec("TTExecContextRec.zp1");
      zp2 = new TTGlyphZoneRec("TTExecContextRec.zp2");
      pts = new TTGlyphZoneRec("TTExecContextRec.pts");
      twilight = new TTGlyphZoneRec("TTExecContextRec.twilight");
      metrics = new FTSizeMetricsRec();;
      tt_metrics = new TTSizeMetricsRec();
      GS = new TTGraphicsStateRec();
      cvt = new long[1024];
      glyphIns = new byte[1];
      callStack = new TTCallRec[callSize];
      codeRangeTable = new TTCodeRange[TTSizeRec.TT_MAX_CODE_RANGES];
      for (int i = 0; i < TTSizeRec.TT_MAX_CODE_RANGES; i++) {
        codeRangeTable[i] = new TTCodeRange();
      }
      storage = new long[1024];
      default_GS = new TTDefaultGraphicsStateClass();
      /* latest interpreter additions */
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTFaceRec.java.















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
// ----------------------------------------------------------------
// TTFaceRec.java --
//
// Copyright (c) 2014 by Arnulf P. Wiedemann
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//------------------------------------------------------------------------

package ftbase;

//import android.util.Log;
import org.apwtcl.gles20.batikfont.ftraster.*;

/* ======================================================================= */
/*  This Java implementation is derived from the Freetype code             */
/*  and has been implemented to work together with the Apache batik code   */
/*  for reading .ttf font files                                             */
/*                                                                         */
/*  Copyright (C) of the Java implementation 2014                          */
/*  Arnulf Wiedemann                                                       */
/*                                                                         */
/*  See the file "license.terms" for information on usage and              */
/*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.   */
/*                                                                         */
/*  in this directory the truetype opcode interpreter is ported to Java    */
/*                                                                         */
/*  the next blocks are taken from the original source code                */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
/*            2010 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/* ======================================================================= */

  /* ===================================================================== */
  /*    TTFaceRec                                                          */
  /*                                                                       */
  /* <Description>                                                         */
  /*    The TrueType face class.  These objects model the resolution and   */
  /*    point-size independent data found in a TrueType font file.         */
  /*                                                                       */
  /* <Fields>                                                              */
  /*    root                 :: The base FT_Face structure, managed by the */
  /*                            base layer.                                */
  /*                                                                       */
  /*    ttc_header           :: The TrueType collection header, used when  */
  /*                            the file is a `ttc' rather than a `ttf'.   */
  /*                            For ordinary font files, the field         */
  /*                            `ttc_header.count' is set to 0.            */
  /*                                                                       */
  /*    format_tag           :: The font format tag.                       */
  /*                                                                       */
  /*    num_tables           :: The number of TrueType tables in this font */
  /*                            file.                                      */
  /*                                                                       */
  /*    dir_tables           :: The directory of TrueType tables for this  */
  /*                            font file.                                 */
  /*                                                                       */
  /*    header               :: The font's font header (`head' table).     */
  /*                            Read on font opening.                      */
  /*                                                                       */
  /*    horizontal           :: The font's horizontal header (`hhea'       */
  /*                            table).  This field also contains the      */
  /*                            associated horizontal metrics table        */
  /*                            (`hmtx').                                  */
  /*                                                                       */
  /*    max_profile          :: The font's maximum profile table.  Read on */
  /*                            font opening.  Note that some maximum      */
  /*                            values cannot be taken directly from this  */
  /*                            table.  We thus define additional fields   */
  /*                            below to hold the computed maxima.         */
  /*                                                                       */
  /*    vertical_info        :: A boolean which is set when the font file  */
  /*                            contains vertical metrics.  If not, the    */
  /*                            value of the `vertical' field is           */
  /*                            undefined.                                 */
  /*                                                                       */
  /*    vertical             :: The font's vertical header (`vhea' table). */
  /*                            This field also contains the associated    */
  /*                            vertical metrics table (`vmtx'), if found. */
  /*                            IMPORTANT: The contents of this field is   */
  /*                            undefined if the `verticalInfo' field is   */
  /*                            unset.                                     */
  /*                                                                       */
  /*    num_names            :: The number of name records within this     */
  /*                            TrueType font.                             */
  /*                                                                       */
  /*    name_table           :: The table of name records (`name').        */
  /*                                                                       */
  /*    os2                  :: The font's OS/2 table (`OS/2').            */
  /*                                                                       */
  /*    postscript           :: The font's PostScript table (`post'        */
  /*                            table).  The PostScript glyph names are    */
  /*                            not loaded by the driver on face opening.  */
  /*                            See the `ttpost' module for more details.  */
  /*                                                                       */
  /*    cmap_table           :: Address of the face's `cmap' SFNT table    */
  /*                            in memory (it's an extracted frame).       */
  /*                                                                       */
  /*    cmap_size            :: The size in bytes of the `cmap_table'      */
  /*                            described above.                           */
  /*                                                                       */
  /*    goto_table           :: A function called by each TrueType table   */
  /*                            loader to position a stream's cursor to    */
  /*                            the start of a given table according to    */
  /*                            its tag.  It defaults to TT_Goto_Face but  */
  /*                            can be different for strange formats (e.g. */
  /*                            Type 42).                                  */
  /*                                                                       */
  /*    access_glyph_frame   :: A function used to access the frame of a   */
  /*                            given glyph within the face's font file.   */
  /*                                                                       */
  /*    forget_glyph_frame   :: A function used to forget the frame of a   */
  /*                            given glyph when all data has been loaded. */
  /*                                                                       */
  /*    read_glyph_header    :: A function used to read a glyph header.    */
  /*                            It must be called between an `access' and  */
  /*                            `forget'.                                  */
  /*                                                                       */
  /*    read_simple_glyph    :: A function used to read a simple glyph.    */
  /*                            It must be called after the header was     */
  /*                            read, and before the `forget'.             */
  /*                                                                       */
  /*    read_composite_glyph :: A function used to read a composite glyph. */
  /*                            It must be called after the header was     */
  /*                            read, and before the `forget'.             */
  /*                                                                       */
  /*    sfnt                 :: A pointer to the SFNT service.             */
  /*                                                                       */
  /*    psnames              :: A pointer to the PostScript names service. */
  /*                                                                       */
  /*    hdmx                 :: The face's horizontal device metrics       */
  /*                            (`hdmx' table).  This table is optional in */
  /*                            TrueType/OpenType fonts.                   */
  /*                                                                       */
  /*    gasp                 :: The grid-fitting and scaling properties    */
  /*                            table (`gasp').  This table is optional in */
  /*                            TrueType/OpenType fonts.                   */
  /*                                                                       */
  /*    pclt                 :: The `pclt' SFNT table.                     */
  /*                                                                       */
  /*    num_sbit_strikes     :: The number of sbit strikes, i.e., bitmap   */
  /*                            sizes, embedded in this font.              */
  /*                                                                       */
  /*    sbit_strikes         :: An array of sbit strikes embedded in this  */
  /*                            font.  This table is optional in a         */
  /*                            TrueType/OpenType font.                    */
  /*                                                                       */
  /*    num_sbit_scales      :: The number of sbit scales for this font.   */
  /*                                                                       */
  /*    sbit_scales          :: Array of sbit scales embedded in this      */
  /*                            font.  This table is optional in a         */
  /*                            TrueType/OpenType font.                    */
  /*                                                                       */
  /*    postscript_names     :: A table used to store the Postscript names */
  /*                            of  the glyphs for this font.  See the     */
  /*                            file  `ttconfig.h' for comments on the     */
  /*                            TT_CONFIG_OPTION_POSTSCRIPT_NAMES option.  */
  /*                                                                       */
  /*    num_locations        :: The number of glyph locations in this      */
  /*                            TrueType file.  This should be             */
  /*                            identical to the number of glyphs.         */
  /*                            Ignored for Type 2 fonts.                  */
  /*                                                                       */
  /*    glyph_locations      :: An array of longs.  These are offsets to   */
  /*                            glyph data within the `glyf' table.        */
  /*                            Ignored for Type 2 font faces.             */
  /*                                                                       */
  /*    glyf_len             :: The length of the `glyf' table.  Needed    */
  /*                            for malformed `loca' tables.               */
  /*                                                                       */
  /*    font_program_size    :: Size in bytecodes of the face's font       */
  /*                            program.  0 if none defined.  Ignored for  */
  /*                            Type 2 fonts.                              */
  /*                                                                       */
  /*    font_program         :: The face's font program (bytecode stream)  */
  /*                            executed at load time, also used during    */
  /*                            glyph rendering.  Comes from the `fpgm'    */
  /*                            table.  Ignored for Type 2 font fonts.     */
  /*                                                                       */
  /*    cvt_program_size     :: The size in bytecodes of the face's cvt    */
  /*                            program.  Ignored for Type 2 fonts.        */
  /*                                                                       */
  /*    cvt_program          :: The face's cvt program (bytecode stream)   */
  /*                            executed each time an instance/size is     */
  /*                            changed/reset.  Comes from the `prep'      */
  /*                            table.  Ignored for Type 2 fonts.          */
  /*                                                                       */
  /*    cvt_size             :: Size of the control value table (in        */
  /*                            entries).   Ignored for Type 2 fonts.      */
  /*                                                                       */
  /*    cvt                  :: The face's original control value table.   */
  /*                            Coordinates are expressed in unscaled font */
  /*                            units.  Comes from the `cvt ' table.       */
  /*                            Ignored for Type 2 fonts.                  */
  /*                                                                       */
  /*    num_kern_pairs       :: The number of kerning pairs present in the */
  /*                            font file.  The engine only loads the      */
  /*                            first horizontal format 0 kern table it    */
  /*                            finds in the font file.  Ignored for       */
  /*                            Type 2 fonts.                              */
  /*                                                                       */
  /*    kern_table_index     :: The index of the kerning table in the font */
  /*                            kerning directory.  Ignored for Type 2     */
  /*                            fonts.                                     */
  /*                                                                       */
  /*    interpreter          :: A pointer to the TrueType bytecode         */
  /*                            interpreters field is also used to hook    */
  /*                            the debugger in `ttdebug'.                 */
  /*                                                                       */
  /*    unpatented_hinting   :: If true, use only unpatented methods in    */
  /*                            the bytecode interpreter.                  */
  /*                                                                       */
  /*    doblend              :: A boolean which is set if the font should  */
  /*                            be blended (this is for GX var).           */
  /*                                                                       */
  /*    blend                :: Contains the data needed to control GX     */
  /*                            variation tables (rather like Multiple     */
  /*                            Master data).                              */
  /*                                                                       */
  /*    extra                :: Reserved for third-party font drivers.     */
  /*                                                                       */
  /*    postscript_name      :: The PS name of the font.  Used by the      */
  /*                            postscript name service.                   */
  /*                                                                       */
  /* ===================================================================== */

public class TTFaceRec extends FTFaceRec {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTFaceRec";

    public TTCHeaderRec ttc_header = null;
    public long format_tag = 0L;
    public short num_tables = 0;
    public TTTableRec[] dir_tables = null;
    public TTHeaderRec header = null;           /* TrueType header table          */
    public TTHoriHeader horizontal = null;   /* TrueType horizontal header     */
    public TTMaxProfile max_profile = null;
    public boolean vertical_info = false;
    public TTVertHeader vertical = null;     /* TT Vertical header, if present */
    public short num_names = 0;              /* number of name records  */
    public TTNameTableRec name_table = null; /* name table              */
    public TTOS2 os2 = null;                 /* TrueType OS/2 table            */
    public TTPostscript postscript = null;   /* TrueType Postscript table      */
    public byte[] cmap_table = null;   /* extracted `cmap' table */
    public long cmap_size = 0L;
    public TTInstanceMethod goto_table = null;
    public TTInstanceMethod access_glyph_frame = null;
    public TTInstanceMethod forget_glyph_frame = null;
    public TTInstanceMethod read_glyph_header = null;
    public TTInstanceMethod read_simple_glyph = null;
    public TTInstanceMethod read_composite_glyph = null;
    /* a typeless pointer to the SFNT_Interface table used to load */
    /* the basic TrueType tables in the face object                */
    public FTModuleInterface sfnt = null;
    /* a typeless pointer to the FT_Service_PsCMapsRec table used to */
    /* handle glyph names <-> unicode & Mac values                   */
    public Object[] psnames = null;
    /* ===================================================================== */
    /*                                                                       */
    /* Optional TrueType/OpenType tables                                     */
    /*                                                                       */
    /* ===================================================================== */
    /* grid-fitting and scaling table */
    public TTGaspRec gasp = null;                 /* the `gasp' table */
    /* PCL 5 table */
    public TTPCLT pclt = null;
    /* embedded bitmaps support */
    public long num_sbit_scales = 0L;
//    public TTSBitScale sbit_scales = null;
    /* postscript names table */
//    public TTPostNamesRec postscript_names = null;
    /* ===================================================================== */
    /*                                                                     */
    /* TrueType-specific fields (ignored by the OTF-Type2 driver)          */
    /*                                                                     */
    /* ===================================================================== */
    /* the font program, if any */
    public long font_program_size = 0L;
    public byte[] font_program = null;
    /* the cvt program, if any */
    public long cvt_program_size = 0L;
    public byte[] cvt_program = null;
    /* the original, unscaled, control value table */
    public long cvt_size = 0L;
    public short[] cvt = null;
    /* A pointer to the bytecode interpreter to use.  This is also */
    /* used to hook the debugger for the `ttdebug' utility.        */
    public TTInstanceMethod interpreter = null;
    /* ===================================================================== */
    /*                                                                     */
    /* Other tables or fields. This is used by derivative formats like     */
    /* OpenType.                                                           */
    /*                                                                     */
    /* ===================================================================== */
//    FT_Generic            extra;
    public String postscript_name = null;
    public long glyf_len = 0L;
    /* since version 2.2 */
    public byte[] horz_metrics = null;
    public long horz_metrics_size = 0L;
    public byte[] vert_metrics = null;
    public long vert_metrics_size = 0L;
    public long num_locations = 0L; /* in broken TTF, gid > 0xFFFF */
    public byte[] glyph_locations = null;
    public byte[] hdmx_table = null;
    public long hdmx_table_size = 0L;
    public int hdmx_record_count = 0;
    public long hdmx_record_size = 0L;
    public byte[] hdmx_record_sizes = null;
    public byte[] sbit_table = null;
    public long sbit_table_size = 0L;
    public int sbit_num_strikes = 0;
    public byte[] kern_table = null;
    public long kern_table_size = 0L;
    public int num_kern_tables = 0;
    public int kern_avail_bits = 0;
    public int kern_order_bits = 0;
    /* since 2.3.0 */
    public long horz_metrics_offset = 0L;
    public long vert_metrics_offset = 0L;
 
    /* ==================== TTFaceRec ================================== */
    public TTFaceRec() {
      super("TTFaceRec");
      oid++;
      id = oid; 
      ttc_header = new TTCHeaderRec();
      header = new TTHeaderRec();
if (FTInit.initDebug > 2) {
System.out.println("ttface1: "+cvt+"!"+mySelf()+"!");
}
    }
        
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * TTInitGlyphLoading
     * =====================================================================
     */
    public static void TTInitGlyphLoading(TTFaceRec face) {
      String class_name = "org.apwtcl.gles20.truetype.TTGlyphLoadingFuncs";
      face.access_glyph_frame = new TTInstanceMethod(class_name, "tt_access_glyph_frame", 1);
      face.read_glyph_header = new TTInstanceMethod(class_name, "tt_load_glyph_header", 1);
      face.read_simple_glyph = new TTInstanceMethod(class_name, "tt_load_simple_glyph", 1);
      face.read_composite_glyph = new TTInstanceMethod(class_name, "tt_load_composite_glyph", 1);
      face.forget_glyph_frame = new TTInstanceMethod(class_name, "tt_forget_glyph_frame", 1);
    }
 
}

Added ftbase/TTGlyphZoneRec.java.





















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTGlyphZoneRec                                                     */
 /*                                                                       */
  /*  <Description>                                                        */
  /*     A glyph zone is used to load, scale and hint glyph outline        */
  /*     coordinates.                                                      */
  /*                                                                       */
  /*  <Fields>                                                             */
  /*     memory       :: A handle to the memory manager.                   */
  /*                                                                       */
  /*     max_points   :: The maximum size in points of the zone.           */
  /*                                                                       */
  /*     max_contours :: Max size in links contours of the zone.           */
  /*                                                                       */
  /*     n_points     :: The current number of points in the zone.         */
  /*                                                                       */
  /*     n_contours   :: The current number of contours in the zone.       */
  /*                                                                       */
  /*     org          :: The original glyph coordinates (font              */
  /*                     units/scaled).                                    */
  /*                                                                       */
  /*     cur          :: The current glyph coordinates (scaled/hinted).    */
  /*                                                                       */
  /*     tags         :: The point control tags.                           */
  /*                                                                       */
  /*     contours     :: The contours end points.                          */
  /*                                                                       */
  /*     first_point  :: Offset of the current subglyph's first point.     */
  /*                                                                       */
  /* ===================================================================== */

public class TTGlyphZoneRec extends FTDebug {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTGlyphZoneRec";

//    FT_Memory memory;
    public short max_points;
    public short max_contours;
    public short n_points;         /* number of points in zone    */
    public short n_contours;       /* number of contours          */
    public FTVectorRec[] org;  /* original point coordinates  */
    public int org_idx;
    public FTVectorRec[] cur;  /* current point coordinates   */
    public int cur_idx;
    public FTVectorRec[] orus; /* original (unscaled) point coordinates */
    public int orus_idx;
    public byte[] tags;            /* current touch flags         */
    public int tags_idx;
    public short[] contours;       /* contour end points          */
    public int contours_idx;
    public short first_point;      /* offset of first (#0) point  */
    private String init_string = null;

    /* ==================== TTGlyphZoneRec ================================== */
    public TTGlyphZoneRec(String init_str) {
      oid++;
      id = oid;
      init_string = init_str;
      
      max_points = 0;
      max_contours = 0;
      n_points = 0;
      n_contours = 0;
      org = null;
      org_idx = 0;
      cur = null;
      cur_idx = 0;
      orus = null;
      orus_idx = 0;
      tags = null;
      tags_idx = 0;
      contours = null;
      contours_idx = 0;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      str.append("org: "+(Object)org+"\n");
      str.append("cur: "+(Object)cur+"\n");
      str.append("orus: "+(Object)orus);
      return str.toString();
    }
 
    /* =====================================================================
     * copy
     * =====================================================================
     */
    public int copy (TTGlyphZoneRec from) {
      int i;
      
      max_points = from.max_points;
      max_contours = from.max_contours;
      n_points = from.n_points;
      n_contours = from.n_contours;

      org = from.org;
      org_idx = from.org_idx;

      cur = from.cur;
      cur_idx = from.cur_idx;

      orus = from.orus;
      orus_idx = from.orus_idx;

      tags = from.tags;
      tags_idx = from.tags_idx;

      contours = from.contours;
      contours_idx = from.contours_idx;

      first_point = from.first_point;
      return 0;
    }

    /* =====================================================================
     * reset
     * =====================================================================
     */
    public int reset () {
      int i;
      
      max_points = 0;
      max_contours = 0;
      n_points = 0;
      n_contours = 0;

      if (org != null) {
        for (i = 0; i < org.length; i++) {
          org[i].x = 0;
          org[i].y = 0;
        }
      }
      org_idx = 0;

      if (cur != null) {
        for (i = 0; i < cur.length; i++) {
          cur[i].x = 0;
          cur[i].y = 0;
        }
      }
      cur_idx = 0;

      if (orus != null) {
        for (i = 0; i < orus.length; i++) {
          orus[i].x = 0;
          orus[i].y = 0;
        }
      }
      orus_idx = 0;

      if (tags != null) {
        for (i = 0; i < tags.length; i++) {
          tags[i] = 0;
        }
      }
      tags_idx = 0;

      if (contours != null) {
        for (i = 0; i < contours.length; i++) {
          contours[i] = 0;
        }
      }
      contours_idx = 0;

      first_point = 0;
      return 0;
    }

    /* =====================================================================
     *    tt_glyphzone_new
     *
     * <Description>
     *    Allocate a new glyph zone.
     *
     * <Input>
     *    memory      :: A handle to the current memory object.
     *
     *    maxPoints   :: The capacity of glyph zone in points.
     *
     *    maxContours :: The capacity of glyph zone in contours.
     *
     * <Output>
     *    zone        :: A pointer to the target glyph zone record.
     * 
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int tt_glyphzone_new(short maxPoints, short maxContours, FTReference<TTGlyphZoneRec> zone_ref)
  {
      int i;
      int  error = 0;
      TTGlyphZoneRec zone = zone_ref.Get();

      zone.org = new FTVectorRec[maxPoints];
      for (i = 0; i < maxPoints; i++) {
        zone.org[i] = new FTVectorRec();
      }
      zone.cur = new FTVectorRec[maxPoints];
      for (i = 0; i < maxPoints; i++) {
        zone.cur[i] = new FTVectorRec();
      }
      zone.orus = new FTVectorRec[maxPoints];
      for (i = 0; i < maxPoints; i++) {
        zone.orus[i] = new FTVectorRec();
      }
      zone.tags = new byte[maxPoints];
      zone.contours = new short[maxContours];
      zone.max_points = maxPoints;
      zone.max_contours = maxContours;
      zone_ref.Set(zone);
      return error;
    }

    /* =====================================================================
     * tt_prepare_zone
     *
     * =====================================================================
     */
    public static void tt_prepare_zone(FTReference<TTGlyphZoneRec> zone_ref, FTGlyphLoadRec load, int start_point, int start_contour) {
      TTGlyphZoneRec zone = zone_ref.Get();
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_prepare_zone: "+load.extra_points+"!"+load.extra_points_idx+"!"+load.extra_points2+"!"+load.extra_points2_idx+"!");
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_prepare_zone1: "+(load.extra_points == null ? 0 : load.extra_points.length)+"!"+(load.extra_points2 == null ? 0 : load.extra_points2.length)+"!");
      zone.n_points = (short)(load.outline.n_points - start_point);
      zone.n_contours = (short)(load.outline.n_contours - start_contour);
      zone.org = load.extra_points;
      zone.org_idx = load.extra_points_idx + start_point;
      zone.cur = load.outline.points;
      zone.cur_idx = load.outline.points_idx + start_point;
      zone.orus = load.extra_points2;
      zone.orus_idx = load.extra_points2_idx + start_point;
      zone.tags = (byte[])load.outline.tags;
      zone.tags_idx = load.outline.tags_idx + start_point;
      zone.contours = (short[])load.outline.contours;
      zone.contours_idx = load.outline.contours_idx + start_contour;
      zone.first_point = (short)start_point;
Debug(0, DBG_LOAD_GLYPH, TAG, "zone org: "+load.extra_points+"!"+load.extra_points_idx+"!"+load.extra_points2+"!"+load.extra_points2_idx+"!");
      zone_ref.Set(zone);
FTGlyphLoaderRec._showLoaderZone("tt_prepare_zone");
    }

    /* =====================================================================
     * tt_glyphzone_done
     *
     * <Description>
     *    Deallocate a glyph zone.
     *
     * <Input>
     *    zone :: A pointer to the target glyph zone.
     *
     * =====================================================================
     */
    public static int tt_glyphzone_done(TTGlyphZoneRec zone) {
      int error = 0;
      
      zone.contours = null;
      zone.tags = null;
      zone.cur = null;
      zone.org = null;
      zone.orus = null;

      zone.max_points = 0;
      zone.n_points = 0;
      zone.max_contours = 0;
      zone.n_contours = 0;
      return error;
    }

}

Added ftbase/TTGraphicsStateRec.java.

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTGraphicsStateRec                                                    */
  /*                                                                       */
  /* <Struct>                                                              */
  /*    TTGraphicsStateRec                                                    */
  /*                                                                       */
  /* <Description>                                                         */
  /*    The TrueType graphics state used during bytecode interpretation.   */
  /* ===================================================================== */

public class TTGraphicsStateRec extends FTDebug {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTGraphicsStateRec";

    public short rp0;
    public short rp1;
    public short rp2;
    public FTVectorRec dualVector;
    public FTVectorRec projVector;
    public FTVectorRec freeVector;
    public long loop;
    public int minimum_distance;
    public int round_state;
    public boolean auto_flip;
    public int control_value_cutin;
    public int single_width_cutin;
    public int single_width_value;
    public short delta_base;
    public short delta_shift;
    public byte instruct_control;
    /* According to Greg Hitchcock from Microsoft, the `scan_control'     */
    /* variable as documented in the TrueType specification is a 32-bit   */
    /* integer; the high-word part holds the SCANTYPE value, the low-word */
    /* part the SCANCTRL value.  We separate it into two fields.          */
    public boolean scan_control;
    public int scan_type;
    public short gep0;
    public short gep1;
    public short gep2;

    /* ==================== TTGraphicsStateRec ================================== */
    public TTGraphicsStateRec() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTInterpBase.java.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

  /* ===================================================================== */
  /*    TTInterpBase                                                       */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpBase extends FTDebug {
    private static int oid = 0;

    /* =====================================================================
     *
     * Rounding mode constants.
     *
     * =====================================================================
     */
    public final static int TT_Round_To_Half_Grid   = 0;
    public final static int TT_Round_To_Grid        = 1;
    public final static int TT_Round_To_Double_Grid = 2;
    public final static int TT_Round_Down_To_Grid   = 3;
    public final static int TT_Round_Up_To_Grid     = 4;
    public final static int TT_Round_Off            = 5;
    public final static int TT_Round_Super          = 6;
    public final static int TT_Round_Super_45       = 7;

    public final static boolean SUCCESS = false;
    public final static boolean FAILURE = true;
    public final static long MAX_RUNNABLE_OPCODES = 1000000L;
    public final static int TT_INTERPRETER_VERSION_35 = 35;
    
    private int id;
    private static String TAG = "TTInterpBase";
    public static TTExecContextRec cur = new TTExecContextRec();
    public int x = 0;
    protected static byte[] popPushCount = new byte[256];
    protected static String[] opcode_name = {
      "SVTCA y",
      "SVTCA x",
      "SPvTCA y",
      "SPvTCA x",
      "SFvTCA y",
      "SFvTCA x",
      "SPvTL ||",
      "SPvTL +",
      "SFvTL ||",
      "SFvTL +",
      "SPvFS",
      "SFvFS",
      "GPV",
      "GFV",
      "SFvTPv",
      "ISECT",

      "SRP0",
      "SRP1",
      "SRP2",
      "SZP0",
      "SZP1",
      "SZP2",
      "SZPS",
      "SLOOP",
      "RTG",
      "RTHG",
      "SMD",
      "ELSE",
      "JMPR",
      "SCvTCi",
      "SSwCi",
      "SSW",

      "DUP",
      "POP",
      "CLEAR",
      "SWAP",
      "DEPTH",
      "CINDEX",
      "MINDEX",
      "AlignPTS",
      "INS_$28",
      "UTP",
      "LOOPCALL",
      "CALL",
      "FDEF",
      "ENDF",
      "MDAP[0]",
      "MDAP[1]",

      "IUP[0]",
      "IUP[1]",
      "SHP[0]",
      "SHP[1]",
      "SHC[0]",
      "SHC[1]",
      "SHZ[0]",
      "SHZ[1]",
      "SHPIX",
      "IP",
      "MSIRP[0]",
      "MSIRP[1]",
      "AlignRP",
      "RTDG",
      "MIAP[0]",
      "MIAP[1]",

      "NPushB",
      "NPushW",
      "WS",
      "RS",
      "WCvtP",
      "RCvt",
      "GC[0]",
      "GC[1]",
      "SCFS",
      "MD[0]",
      "MD[1]",
      "MPPEM",
      "MPS",
      "FlipON",
      "FlipOFF",
      "DEBUG",

      "LT",
      "LTEQ",
      "GT",
      "GTEQ",
      "EQ",
      "NEQ",
      "ODD",
      "EVEN",
      "IF",
      "EIF",
      "AND",
      "OR",
      "NOT",
      "DeltaP1",
      "SDB",
      "SDS",

      "ADD",
      "SUB",
      "DIV",
      "MUL",
      "ABS",
      "NEG",
      "FLOOR",
      "CEILING",
      "ROUND[0]",
      "ROUND[1]",
      "ROUND[2]",
      "ROUND[3]",
      "NROUND[0]",
      "NROUND[1]",
      "NROUND[2]",
      "NROUND[3]",

      "WCvtF",
      "DeltaP2",
      "DeltaP3",
      "DeltaCn[0]",
      "DeltaCn[1]",
      "DeltaCn[2]",
      "SROUND",
      "S45Round",
      "JROT",
      "JROF",
      "ROFF",
      "INS_$7B",
      "RUTG",
      "RDTG",
      "SANGW",
      "AA",

      "FlipPT",
      "FlipRgON",
      "FlipRgOFF",
      "INS_$83",
      "INS_$84",
      "ScanCTRL",
      "SDVPTL[0]",
      "SDVPTL[1]",
      "GetINFO",
      "IDEF",
      "ROLL",
      "MAX",
      "MIN",
      "ScanTYPE",
      "InstCTRL",
      "INS_$8F",

      "INS_$90",
      "INS_$91",
      "INS_$92",
      "INS_$93",
      "INS_$94",
      "INS_$95",
      "INS_$96",
      "INS_$97",
      "INS_$98",
      "INS_$99",
      "INS_$9A",
      "INS_$9B",
      "INS_$9C",
      "INS_$9D",
      "INS_$9E",
      "INS_$9F",

      "INS_$A0",
      "INS_$A1",
      "INS_$A2",
      "INS_$A3",
      "INS_$A4",
      "INS_$A5",
      "INS_$A6",
      "INS_$A7",
      "INS_$A8",
      "INS_$A9",
      "INS_$AA",
      "INS_$AB",
      "INS_$AC",
      "INS_$AD",
      "INS_$AE",
      "INS_$AF",

      "PushB[0]",
      "PushB[1]",
      "PushB[2]",
      "PushB[3]",
      "PushB[4]",
      "PushB[5]",
      "PushB[6]",
      "PushB[7]",
      "PushW[0]",
      "PushW[1]",
      "PushW[2]",
      "PushW[3]",
      "PushW[4]",
      "PushW[5]",
      "PushW[6]",
      "PushW[7]",

      "MDRP[00]",
      "MDRP[01]",
      "MDRP[02]",
      "MDRP[03]",
      "MDRP[04]",
      "MDRP[05]",
      "MDRP[06]",
      "MDRP[07]",
      "MDRP[08]",
      "MDRP[09]",
      "MDRP[10]",
      "MDRP[11]",
      "MDRP[12]",
      "MDRP[13]",
      "MDRP[14]",
      "MDRP[15]",

      "MDRP[16]",
      "MDRP[17]",
      "MDRP[18]",
      "MDRP[19]",
      "MDRP[20]",
      "MDRP[21]",
      "MDRP[22]",
      "MDRP[23]",
      "MDRP[24]",
      "MDRP[25]",
      "MDRP[26]",
      "MDRP[27]",
      "MDRP[28]",
      "MDRP[29]",
      "MDRP[30]",
      "MDRP[31]",

      "MIRP[00]",
      "MIRP[01]",
      "MIRP[02]",
      "MIRP[03]",
      "MIRP[04]",
      "MIRP[05]",
      "MIRP[06]",
      "MIRP[07]",
      "MIRP[08]",
      "MIRP[09]",
      "MIRP[10]",
      "MIRP[11]",
      "MIRP[12]",
      "MIRP[13]",
      "MIRP[14]",
      "MIRP[15]",

      "MIRP[16]",
      "MIRP[17]",
      "MIRP[18]",
      "MIRP[19]",
      "MIRP[20]",
      "MIRP[21]",
      "MIRP[22]",
      "MIRP[23]",
      "MIRP[24]",
      "MIRP[25]",
      "MIRP[26]",
      "MIRP[27]",
      "MIRP[28]",
      "MIRP[29]",
      "MIRP[30]",
      "MIRP[31]"
    };


    protected static byte[] opcode_length =  {
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,

     -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,

      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,

      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
      1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
    };

    /* ==================== TTInterpBase ================================== */
    public TTInterpBase() {
      oid++;
      id = oid;
    	    /* opcodes are gathered in groups of 16 */
    	    /* please keep the spaces as they are   */
      popPushCount[0] =   /*  SVTCA  y  */  Pack(0, 0);
      popPushCount[1] =   /*  SVTCA  x  */  Pack(0, 0);
      popPushCount[2] =   /*  SPvTCA y  */  Pack(0, 0);
      popPushCount[3] =   /*  SPvTCA x  */  Pack(0, 0);
      popPushCount[4] =   /*  SFvTCA y  */  Pack(0, 0);
      popPushCount[5] =   /*  SFvTCA x  */  Pack(0, 0);
      popPushCount[6] =   /*  SPvTL //  */  Pack(2, 0);
      popPushCount[7] =   /*  SPvTL +   */  Pack(2, 0);
      popPushCount[8] =   /*  SFvTL //  */  Pack(2, 0);
      popPushCount[9] =   /*  SFvTL +   */  Pack(2, 0);
      popPushCount[10] =  /*  SPvFS     */  Pack(2, 0);
      popPushCount[11] =  /*  SFvFS     */  Pack(2, 0);
      popPushCount[12] =  /*  GPV       */  Pack(0, 2);
      popPushCount[13] =  /*  GFV       */  Pack(0, 2);
      popPushCount[14] =  /*  SFvTPv    */  Pack(0, 0);
      popPushCount[15] =  /*  ISECT     */  Pack(5, 0);
 
      popPushCount[16] =  /*  SRP0      */  Pack(1, 0);
      popPushCount[17] =  /*  SRP1      */  Pack(1, 0);
      popPushCount[18] =  /*  SRP2      */  Pack(1, 0);
      popPushCount[19] =  /*  SZP0      */  Pack(1, 0);
      popPushCount[20] =  /*  SZP1      */  Pack(1, 0);
      popPushCount[21] =  /*  SZP2      */  Pack(1, 0);
      popPushCount[22] =  /*  SZPS      */  Pack(1, 0);
      popPushCount[23] =  /*  SLOOP     */  Pack(1, 0);
      popPushCount[24] =  /*  RTG       */  Pack(0, 0);
      popPushCount[25] =  /*  RTHG      */  Pack(0, 0);
      popPushCount[26] =  /*  SMD       */  Pack(1, 0);
      popPushCount[27] =  /*  ELSE      */  Pack(0, 0);
      popPushCount[38] =  /*  JMPR      */  Pack(1, 0);
      popPushCount[29] =  /*  SCvTCi    */  Pack(1, 0);
      popPushCount[30] =  /*  SSwCi     */  Pack(1, 0);
      popPushCount[31] =  /*  SSW       */  Pack(1, 0);
      
      popPushCount[32] =  /*  DUP       */  Pack(1, 2);
      popPushCount[33] =  /*  POP       */  Pack(1, 0);
      popPushCount[34] =  /*  CLEAR     */  Pack(0, 0);
      popPushCount[35] =  /*  SWAP      */  Pack(2, 2);
      popPushCount[36] =  /*  DEPTH     */  Pack(0, 1);
      popPushCount[37] =  /*  CINDEX    */  Pack(1, 1);
      popPushCount[38] =  /*  MINDEX    */  Pack(1, 0);
      popPushCount[39] =  /*  AlignPTS  */  Pack(2, 0);
      popPushCount[40] =  /*  INS_$28   */  Pack(0, 0);
      popPushCount[41] =  /*  UTP       */  Pack(1, 0);
      popPushCount[42] =  /*  LOOPCALL  */  Pack(2, 0);
      popPushCount[43] =  /*  CALL      */  Pack(1, 0);
      popPushCount[44] =  /*  FDEF      */  Pack(1, 0);
      popPushCount[45] =  /*  ENDF      */  Pack(0, 0);
      popPushCount[46] =  /*  MDAP[0]   */  Pack(1, 0);
      popPushCount[47] =  /*  MDAP[1]   */  Pack(1, 0);
      
      popPushCount[48] =  /*  IUP[0]    */  Pack(0, 0);
      popPushCount[49] =  /*  IUP[1]    */  Pack(0, 0);
      popPushCount[50] =  /*  SHP[0]    */  Pack(0, 0);
      popPushCount[51] =  /*  SHP[1]    */  Pack(0, 0);
      popPushCount[52] =  /*  SHC[0]    */  Pack(1, 0);
      popPushCount[53] =  /*  SHC[1]    */  Pack(1, 0);
      popPushCount[54] =  /*  SHZ[0]    */  Pack(1, 0);
      popPushCount[55] =  /*  SHZ[1]    */  Pack(1, 0);
      popPushCount[56] =  /*  SHPIX     */  Pack(1, 0);
      popPushCount[57] =  /*  IP        */  Pack(0, 0);
      popPushCount[58] =  /*  MSIRP[0]  */  Pack(2, 0);
      popPushCount[59] =  /*  MSIRP[1]  */  Pack(2, 0);
      popPushCount[60] =  /*  AlignRP   */  Pack(0, 0);
      popPushCount[61] =  /*  RTDG      */  Pack(0, 0);
      popPushCount[62] =  /*  MIAP[0]   */  Pack(2, 0);
      popPushCount[63] =  /*  MIAP[1]   */  Pack(2, 0);
      
      popPushCount[64] =  /*  NPushB    */  Pack(0, 0);
      popPushCount[65] =  /*  NPushW    */  Pack(0, 0);
      popPushCount[66] =  /*  WS        */  Pack(2, 0);
      popPushCount[67] =  /*  RS        */  Pack(1, 1);
      popPushCount[68] =  /*  WCvtP     */  Pack(2, 0);
      popPushCount[69] =  /*  RCvt      */  Pack(1, 1);
      popPushCount[70] =  /*  GC[0]     */  Pack(1, 1);
      popPushCount[71] =  /*  GC[1]     */  Pack(1, 1);
      popPushCount[72] =  /*  SCFS      */  Pack(2, 0);
      popPushCount[73] =  /*  MD[0]     */  Pack(2, 1);
      popPushCount[74] =  /*  MD[1]     */  Pack(2, 1);
      popPushCount[75] =  /*  MPPEM     */  Pack(0, 1);
      popPushCount[76] =  /*  MPS       */  Pack(0, 1);
      popPushCount[77] =  /*  FlipON    */  Pack(0, 0);
      popPushCount[78] =  /*  FlipOFF   */  Pack(0, 0);
      popPushCount[79] =  /*  DEBUG     */  Pack(1, 0);
      
      popPushCount[80] =  /*  LT        */  Pack(2, 1);
      popPushCount[81] =  /*  LTEQ      */  Pack(2, 1);
      popPushCount[82] =  /*  GT        */  Pack(2, 1);
      popPushCount[83] =  /*  GTEQ      */  Pack(2, 1);
      popPushCount[84] =  /*  EQ        */  Pack(2, 1);
      popPushCount[85] =  /*  NEQ       */  Pack(2, 1);
      popPushCount[86] =  /*  ODD       */  Pack(1, 1);
      popPushCount[87] =  /*  EVEN      */  Pack(1, 1);
      popPushCount[88] =  /*  IF        */  Pack(1, 0);
      popPushCount[89] =  /*  EIF       */  Pack(0, 0);
      popPushCount[90] =  /*  AND       */  Pack(2, 1);
      popPushCount[91] =  /*  OR        */  Pack(2, 1);
      popPushCount[92] =  /*  NOT       */  Pack(1, 1);
      popPushCount[93] =  /*  DeltaP1   */  Pack(1, 0);
      popPushCount[94] =  /*  SDB       */  Pack(1, 0);
      popPushCount[95] =  /*  SDS       */  Pack(1, 0);
      
      popPushCount[96] =  /*  ADD       */  Pack(2, 1);
      popPushCount[97] =  /*  SUB       */  Pack(2, 1);
      popPushCount[98] =  /*  DIV       */  Pack(2, 1);
      popPushCount[99] =  /*  MUL       */  Pack(2, 1);
      popPushCount[100] = /*  ABS       */  Pack(1, 1);
      popPushCount[101] = /*  NEG       */  Pack(1, 1);
      popPushCount[102] = /*  FLOOR     */  Pack(1, 1);
      popPushCount[103] = /*  CEILING   */  Pack(1, 1);
      popPushCount[104] = /*  ROUND[0]  */  Pack(1, 1);
      popPushCount[105] = /*  ROUND[1]  */  Pack(1, 1);
      popPushCount[106] = /*  ROUND[2]  */  Pack(1, 1);
      popPushCount[107] = /*  ROUND[3]  */  Pack(1, 1);
      popPushCount[108] = /*  NROUND[0] */  Pack(1, 1);
      popPushCount[109] = /*  NROUND[1] */  Pack(1, 1);
      popPushCount[110] = /*  NROUND[2] */  Pack(1, 1);
      popPushCount[111] = /*  NROUND[3] */  Pack(1, 1);
      
      popPushCount[112] = /*  WCvtF     */  Pack(2, 0);
      popPushCount[113] = /*  DeltaP2   */  Pack(1, 0);
      popPushCount[114] = /*  DeltaP3   */  Pack(1, 0);
      popPushCount[115] = /*  DeltaCn[0] */ Pack(1, 0);
      popPushCount[116] = /*  DeltaCn[1] */ Pack(1, 0);
      popPushCount[117] = /*  DeltaCn[2] */ Pack(1, 0);
      popPushCount[118] = /*  SROUND    */  Pack(1, 0);
      popPushCount[119] = /*  S45Round  */  Pack(1, 0);
      popPushCount[120] = /*  JROT      */  Pack(2, 0);
      popPushCount[121] = /*  JROF      */  Pack(2, 0);
      popPushCount[122] = /*  ROFF      */  Pack(0, 0);
      popPushCount[123] = /*  INS_$7B   */  Pack(0, 0);
      popPushCount[124] = /*  RUTG      */  Pack(0, 0);
      popPushCount[125] = /*  RDTG      */  Pack(0, 0);
      popPushCount[126] = /*  SANGW     */  Pack(1, 0);
      popPushCount[127] = /*  AA        */  Pack(1, 0);
      
      popPushCount[128] = /*  FlipPT    */  Pack(0, 0);
      popPushCount[129] = /*  FlipRgON  */  Pack(2, 0);
      popPushCount[130] = /*  FlipRgOFF */  Pack(2, 0);
      popPushCount[131] = /*  INS_$83   */  Pack(0, 0);
      popPushCount[132] = /*  INS_$84   */  Pack(0, 0);
      popPushCount[133] = /*  ScanCTRL  */  Pack(1, 0);
      popPushCount[134] = /*  SDPVTL[0] */  Pack(2, 0);
      popPushCount[135] = /*  SDPVTL[1] */  Pack(2, 0);
      popPushCount[136] = /*  GetINFO   */  Pack(1, 1);
      popPushCount[137] = /*  IDEF      */  Pack(1, 0);
      popPushCount[138] = /*  ROLL      */  Pack(3, 3);
      popPushCount[139] = /*  MAX       */  Pack(2, 1);
      popPushCount[140] = /*  MIN       */  Pack(2, 1);
      popPushCount[141] = /*  ScanTYPE  */  Pack(1, 0);
      popPushCount[142] = /*  InstCTRL  */  Pack(2, 0);
      popPushCount[143] = /*  INS_$8F   */  Pack(0, 0);
      
      popPushCount[144] = /*  INS_$90  */   Pack(0, 0);
      popPushCount[145] = /*  INS_$91  */   Pack(0, 0);
      popPushCount[146] = /*  INS_$92  */   Pack(0, 0);
      popPushCount[147] = /*  INS_$93  */   Pack(0, 0);
      popPushCount[148] = /*  INS_$94  */   Pack(0, 0);
      popPushCount[149] = /*  INS_$95  */   Pack(0, 0);
      popPushCount[150] = /*  INS_$96  */   Pack(0, 0);
      popPushCount[151] = /*  INS_$97  */   Pack(0, 0);
      popPushCount[152] = /*  INS_$98  */   Pack(0, 0);
      popPushCount[153] = /*  INS_$99  */   Pack(0, 0);
      popPushCount[154] = /*  INS_$9A  */   Pack(0, 0);
      popPushCount[155] = /*  INS_$9B  */   Pack(0, 0);
      popPushCount[156] = /*  INS_$9C  */   Pack(0, 0);
      popPushCount[157] = /*  INS_$9D  */   Pack(0, 0);
      popPushCount[158] = /*  INS_$9E  */   Pack(0, 0);
      popPushCount[159] = /*  INS_$9F  */   Pack(0, 0);
      
      popPushCount[160] = /*  INS_$A0  */   Pack(0, 0);
      popPushCount[161] = /*  INS_$A1  */   Pack(0, 0);
      popPushCount[162] = /*  INS_$A2  */   Pack(0, 0);
      popPushCount[163] = /*  INS_$A3  */   Pack(0, 0);
      popPushCount[164] = /*  INS_$A4  */   Pack(0, 0);
      popPushCount[165] = /*  INS_$A5  */   Pack(0, 0);
      popPushCount[166] = /*  INS_$A6  */   Pack(0, 0);
      popPushCount[167] = /*  INS_$A7  */   Pack(0, 0);
      popPushCount[168] = /*  INS_$A8  */   Pack(0, 0);
      popPushCount[169] = /*  INS_$A9  */   Pack(0, 0);
      popPushCount[170] = /*  INS_$AA  */   Pack(0, 0);
      popPushCount[171] = /*  INS_$AB  */   Pack(0, 0);
      popPushCount[172] = /*  INS_$AC  */   Pack(0, 0);
      popPushCount[173] = /*  INS_$AD  */   Pack(0, 0);
      popPushCount[174] = /*  INS_$AE  */   Pack(0, 0);
      popPushCount[175] = /*  INS_$AF  */   Pack(0, 0);
      
      popPushCount[176] = /*  PushB[0]  */  Pack(0, 1);
      popPushCount[177] = /*  PushB[1]  */  Pack(0, 2);
      popPushCount[178] = /*  PushB[2]  */  Pack(0, 3);
      popPushCount[179] = /*  PushB[3]  */  Pack(0, 4);
      popPushCount[180] = /*  PushB[4]  */  Pack(0, 5);
      popPushCount[181] = /*  PushB[5]  */  Pack(0, 6);
      popPushCount[182] = /*  PushB[6]  */  Pack(0, 7);
      popPushCount[183] = /*  PushB[7]  */  Pack(0, 8);
      popPushCount[184] = /*  PushW[0]  */  Pack(0, 1);
      popPushCount[185] = /*  PushW[1]  */  Pack(0, 2);
      popPushCount[186] = /*  PushW[2]  */  Pack(0, 3);
      popPushCount[187] = /*  PushW[3]  */  Pack(0, 4);
      popPushCount[188] = /*  PushW[4]  */  Pack(0, 5);
      popPushCount[189] = /*  PushW[5]  */  Pack(0, 6);
      popPushCount[190] = /*  PushW[6]  */  Pack(0, 7);
      popPushCount[191] = /*  PushW[7]  */  Pack(0, 8);
      
      popPushCount[192] = /*  MDRP[00]  */  Pack(1, 0);
      popPushCount[193] = /*  MDRP[01]  */  Pack(1, 0);
      popPushCount[194] = /*  MDRP[02]  */  Pack(1, 0);
      popPushCount[195] = /*  MDRP[03]  */  Pack(1, 0);
      popPushCount[196] = /*  MDRP[04]  */  Pack(1, 0);
      popPushCount[197] = /*  MDRP[05]  */  Pack(1, 0);
      popPushCount[198] = /*  MDRP[06]  */  Pack(1, 0);
      popPushCount[199] = /*  MDRP[07]  */  Pack(1, 0);
      popPushCount[200] = /*  MDRP[08]  */  Pack(1, 0);
      popPushCount[201] = /*  MDRP[09]  */  Pack(1, 0);
      popPushCount[202] = /*  MDRP[10]  */  Pack(1, 0);
      popPushCount[203] = /*  MDRP[11]  */  Pack(1, 0);
      popPushCount[204] = /*  MDRP[12]  */  Pack(1, 0);
      popPushCount[205] = /*  MDRP[13]  */  Pack(1, 0);
      popPushCount[206] = /*  MDRP[14]  */  Pack(1, 0);
      popPushCount[207] = /*  MDRP[15]  */  Pack(1, 0);
      
      popPushCount[208] = /*  MDRP[16]  */  Pack(1, 0);
      popPushCount[209] = /*  MDRP[17]  */  Pack(1, 0);
      popPushCount[210] = /*  MDRP[18]  */  Pack(1, 0);
      popPushCount[211] = /*  MDRP[19]  */  Pack(1, 0);
      popPushCount[212] = /*  MDRP[20]  */  Pack(1, 0);
      popPushCount[213] = /*  MDRP[21]  */  Pack(1, 0);
      popPushCount[214] = /*  MDRP[22]  */  Pack(1, 0);
      popPushCount[215] = /*  MDRP[23]  */  Pack(1, 0);
      popPushCount[216] = /*  MDRP[24]  */  Pack(1, 0);
      popPushCount[217] = /*  MDRP[25]  */  Pack(1, 0);
      popPushCount[218] = /*  MDRP[26]  */  Pack(1, 0);
      popPushCount[219] = /*  MDRP[27]  */  Pack(1, 0);
      popPushCount[220] = /*  MDRP[28]  */  Pack(1, 0);
      popPushCount[221] = /*  MDRP[29]  */  Pack(1, 0);
      popPushCount[222] = /*  MDRP[30]  */  Pack(1, 0);
      popPushCount[223] = /*  MDRP[31]  */  Pack(1, 0);
      
      popPushCount[224] = /*  MIRP[00]  */  Pack(2, 0);
      popPushCount[225] = /*  MIRP[01]  */  Pack(2, 0);
      popPushCount[226] = /*  MIRP[02]  */  Pack(2, 0);
      popPushCount[227] = /*  MIRP[03]  */  Pack(2, 0);
      popPushCount[228] = /*  MIRP[04]  */  Pack(2, 0);
      popPushCount[229] = /*  MIRP[05]  */  Pack(2, 0);
      popPushCount[230] = /*  MIRP[06]  */  Pack(2, 0);
      popPushCount[231] = /*  MIRP[07]  */  Pack(2, 0);
      popPushCount[232] = /*  MIRP[08]  */  Pack(2, 0);
      popPushCount[233] = /*  MIRP[09]  */  Pack(2, 0);
      popPushCount[234] = /*  MIRP[10]  */  Pack(2, 0);
      popPushCount[235] = /*  MIRP[11]  */  Pack(2, 0);
      popPushCount[236] = /*  MIRP[12]  */  Pack(2, 0);
      popPushCount[237] = /*  MIRP[13]  */  Pack(2, 0);
      popPushCount[238] = /*  MIRP[14]  */  Pack(2, 0);
      popPushCount[239] = /*  MIRP[15]  */  Pack(2, 0);
      
      popPushCount[240] = /*  MIRP[16]  */  Pack(2, 0);
      popPushCount[241] = /*  MIRP[17]  */  Pack(2, 0);
      popPushCount[242] = /*  MIRP[18]  */  Pack(2, 0);
      popPushCount[243] = /*  MIRP[19]  */  Pack(2, 0);
      popPushCount[244] = /*  MIRP[20]  */  Pack(2, 0);
      popPushCount[245] = /*  MIRP[21]  */  Pack(2, 0);
      popPushCount[246] = /*  MIRP[22]  */  Pack(2, 0);
      popPushCount[247] = /*  MIRP[23]  */  Pack(2, 0);
      popPushCount[248] = /*  MIRP[24]  */  Pack(2, 0);
      popPushCount[249] = /*  MIRP[25]  */  Pack(2, 0);
      popPushCount[250] = /*  MIRP[26]  */  Pack(2, 0);
      popPushCount[251] = /*  MIRP[27]  */  Pack(2, 0);
      popPushCount[252] = /*  MIRP[28]  */  Pack(2, 0);
      popPushCount[253] = /*  MIRP[29]  */  Pack(2, 0);
      popPushCount[254] = /*  MIRP[30]  */  Pack(2, 0);
      popPushCount[255] = /*  MIRP[31]  */  Pack(2, 0);
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
    
    /* ==================== Pack ===================================== */
    private static byte Pack(int x, int y) {
      byte valx = (byte)x;
      byte valy = (byte)y;
      byte valx_nibble = (byte)(((valx & 0xF) << 4) & 0xFF);
      byte valy_nibble = (byte)((valy & 0xF));

      return (byte)((valx_nibble | valy_nibble) & 0xFF);
    }

    /* =====================================================================
     * <Function>
     *    Init_Context
     *
     * <Description>
     *    Initializes a context object.
     *
     * <Input>
     *    memory :: A handle to the parent memory object.
     *
     * <InOut>
     *    exec   :: A handle to the target execution context.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     * =====================================================================
     */
    public static int InitContext(TTExecContextRec exec) {
      int error = FTError.INTERP_ERR_OK;

      exec.callSize = 32;
      exec.callStack = new TTCallRec[exec.callSize];
      for (int i = 0; i < exec.callSize; i++) {
        exec.callStack[i] = new TTCallRec();
      }
      /* all values in the context are set to 0 already, but this is */
      /* here as a remainder                                         */
      exec.maxPoints = 0;
      exec.maxContours = 0;
      exec.stackSize = 0;
      exec.glyphSize = 0;
      exec.stack = null;
      exec.glyphIns = null;
      exec.face = null;
      exec.size = null;
      return error;
    }

    /* ==================== TTNewContext ===================================== */
    public static TTExecContextRec TTNewContext(TTDriverRec driver) {
      TTExecContextRec exec;

Debug(0, DBG_INTERP, TAG, "TT_New_Context");
      if (driver.context == null) {
        int error;

        /* allocate object */
        exec = new TTExecContextRec();
Debug(0, DBG_INTERP, TAG, "ttexec: exec2: "+exec+"!");
        /* store it into the driver */
        error = InitContext(exec);
        if (error != 0) {
          return null;
        }
        driver.context = exec;
      }
      return driver.context;
    }

    /* ==================== setValueOfCurField ===================================== */
    public void setValueOfCurField(String name, int value) {
      try {
    	Class<?> cls = cur.getClass();
Debug(0, DBG_INTERP, TAG, "S1:"+cur.GS.round_state);
    	name = "GS";
    	Field fld = cls.getDeclaredField(name);
Debug(0, DBG_INTERP, TAG, "fld:"+fld+"!"+cls);
//Class<?> cls4 = fld.getDeclaringClass();
//System.out.println("cls4:"+cls4+"!"+cls4.getName());
    	Class<?> cls2 = fld.getDeclaringClass();
Debug(0, DBG_INTERP, TAG, "cls2:"+cls2+"!"+cls2.getName());

        Class<?> cls3 = Class.forName("org.apwtcl.gles20.truetype.TTGraphicsState");
Debug(0, DBG_INTERP, TAG, "cls3:"+cls3+"!"+cls3.getName());
    	Field fld2 = cls3.getDeclaredField("round_state");
Debug(0, DBG_INTERP, TAG, "fld2:"+fld2);
    	fld2.setInt(cur.GS, 13);
      } catch (NoSuchFieldException x) {
        x.printStackTrace();
      } catch (IllegalAccessException x) {
        x.printStackTrace();
      } catch (ClassNotFoundException x) {
          x.printStackTrace();
      }
Debug(0, DBG_INTERP, TAG, "var:"+name+"!"+cur.GS.round_state+"!");
    }
 
    /* ==================== callCurFunc ===================================== */
    public static int callCurFunc(String name, int value1, int value2) {
      int result;

Debug(0, DBG_INTERP, TAG, "call method:"+name+"!"+value1+"!"+value2+"!");
      try {
    	Class<?> cls = cur.getClass();
    	Method m = cls.getDeclaredMethod(name);
Debug(0, DBG_INTERP, TAG, "m:"+m+"!"+cls);
    	result = (int)m.invoke(cur, value1, value2);
    	return result;
      } catch (InvocationTargetException x) {
          x.printStackTrace();
      } catch (NoSuchMethodException x) {
        x.printStackTrace();
      } catch (IllegalAccessException x) {
        x.printStackTrace();
      }
      return -1;
    }
 
}

Added ftbase/TTInterpFuncs3.java.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

import android.util.Log;
  /* ===================================================================== */
  /*    TTInterpFuncs3                                                        */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpFuncs3 extends FTDebug {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTInterpFuncs3";
    
    /* ==================== TTInterpFuncs3 ================================== */
    public TTInterpFuncs3() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* ==================== _showZp0Zp1OrgCur ================================ */
    public static void _showZp0Zp1OrgCur( String str, TTExecContextRec cur ) {
      Debug(0, DBG_RENDER, TAG, str);
      Debug(0, DBG_RENDER, TAG, "zp0.org: "+(Object)cur.zp0.org);
      Debug(0, DBG_RENDER, TAG, "zp1.org: "+(Object)cur.zp1.org);
      Debug(0, DBG_RENDER, TAG, "zp2.org: "+(Object)cur.zp2.org);
      Debug(0, DBG_RENDER, TAG, "zp0.cur: "+(Object)cur.zp0.cur);
      Debug(0, DBG_RENDER, TAG, "zp1.cur: "+(Object)cur.zp1.cur);
      Debug(0, DBG_RENDER, TAG, "zp2.cur: "+(Object)cur.zp2.cur);
      Debug(0, DBG_RENDER, TAG, "zp0.orus: "+(Object)cur.zp0.orus);
      Debug(0, DBG_RENDER, TAG, "zp1.orus: "+(Object)cur.zp1.orus);
      Debug(0, DBG_RENDER, TAG, "zp2.orus: "+(Object)cur.zp2.orus);
      for( int i = 0; i < 6; i++) {
        Debug(0, DBG_RENDER, TAG, String.format("zp0.org: %d x: %d, y: %d\n", i, cur.zp0.org[cur.zp0.org_idx + i].x, cur.zp0.org[cur.zp0.org_idx + i].y));
        Debug(0, DBG_RENDER, TAG, String.format("zp1.org: %d x: %d, y: %d\n", i, cur.zp1.org[cur.zp1.org_idx + i].x, cur.zp1.org[cur.zp1.org_idx + i].y));
        Debug(0, DBG_RENDER, TAG, String.format("zp0.cur: %d x: %d, y: %d\n", i, cur.zp0.cur[cur.zp0.cur_idx + i].x, cur.zp0.cur[cur.zp0.cur_idx + i].y));
        Debug(0, DBG_RENDER, TAG, String.format("zp1.cur: %d x: %d, y: %d\n", i, cur.zp1.cur[cur.zp1.cur_idx + i].x, cur.zp1.cur[cur.zp1.cur_idx + i].y));
      }
    }

    /* =====================================================================
     * TT_DotFix14
     *
     * compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding
     * =====================================================================
     */
    public static int TT_DotFix14(int ax, int ay, long bx, long by) {
Debug(0, DBG_INTERP, TAG, "TT_DotFix14");
      int m;
      int s;
      int hi1;
      int hi2;
      int hi;
      int l;
      int lo1;
      int lo2;
      int lo;

      /* compute ax*bx as 64-bit value */
      l = (int)((ax & 0xFFFF) * bx);
      m = (ax >> 16) * (int)bx;
      lo1 = l + ((int)m << 16);
      hi1 = (m >> 16) + ((int)l >> 31) + (lo1 < l ? 1 : 0);
      /* compute ay*by as 64-bit value */
      l = (int)((ay & 0xFFFF) * by);
      m = (ay >> 16) * (int)by;
      lo2 = l + ((int)m << 16);
      hi2 = (m >> 16) + ((int)l >> 31) + (lo2 < l ? 1 : 0);
      /* add them */
      lo = lo1 + lo2;
      hi = hi1 + hi2 + (lo < lo1 ? 1 : 0);
      /* divide the result by 2^14 with rounding */
      s = hi >> 31;
      l = lo + (int)s;
      hi += s + (l < lo ? 1 : 0);
      lo  = l;
      l = lo + 0x2000;
      hi += (l < lo ? 1 : 0);
      return (int)(((int)hi << 18) | (l >> 14));
    }

    /* =====================================================================
     * ProjectX
     *
     * <Description>
     *    Computes the projection of the vector given by (v2-v1) along the
     *    horizontal axis.
     *
     * <Input>
     *    v1 :: First input vector.
     *    v2 :: Second input vector.
     *
     * <Return>
     *    The distance in F26dot6 format.
     *
     * =====================================================================
     */
    public static long ProjectX(Object ... args) {
      long dx = (long)args[0];
      long dy = (long)args[1];

Debug(0, DBG_INTERP, TAG, String.format("ProjectX: dx: %d, dy: %d", dx, dy));
      return dx;
    } 
    
    /* =====================================================================
     * ProjectY
     *
     * <Description>
     *    Computes the projection of the vector given by (v2-v1) along the
     *    vertical axis.
     *
     * <Input>
     *    v1 :: First input vector.
     *    v2 :: Second input vector.
     *
     * <Return>
     *    The distance in F26dot6 format.
     *
     * =====================================================================
     */
    public static long ProjectY(Object ... args) {
      long dx = (long)args[0];
      long dy = (long)args[1];
Debug(0, DBG_INTERP, TAG, String.format("ProjectY: dx: %d, dy: %d", dx, dy));

      return dy;
    } 
    
    /* =====================================================================
     * Project
     *
     * <Description>
     *    Computes the projection of vector given by (v2-v1) along the
     *    current projection vector.
     *
     * <Input>
     *    v1 :: First input vector.
     *    v2 :: Second input vector.
     *
     * <Return>
     *    The distance in F26dot6 format.
     *
     * =====================================================================
     */
    public static long Project(Object ... args) {
Debug(0, DBG_INTERP, TAG, "Project");
      long dx = (long)args[0];
      long dy = (long)args[1];
    
      return TT_DotFix14((int)dx, (int)dy, TTInterpRun.cur.GS.projVector.x, TTInterpRun.cur.GS.projVector.y);
    } 
    
    /* =====================================================================
     * DualProject
     *
     * <Description>
     *    Computes the projection of the vector given by (v2-v1) along the
     *    current dual vector.
     *
     * <Input>
     *    v1 :: First input vector.
     *    v2 :: Second input vector.
     *
     * <Return>
     *    The distance in F26dot6 format.
     *
     * =====================================================================
     */
    public static long DualProject(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DualProject");
      long dx = (long)args[0];
      long dy = (long)args[1];

      return (long)TT_DotFix14((int)dx, (int)dy, TTInterpRun.cur.GS.dualVector.x, TTInterpRun.cur.GS.dualVector.y); 
    } 

    /* =====================================================================
     * DirectMove
     *
     * <Description>
     *    Moves a point by a given distance along the freedom vector.  The
     *    point will be `touched'.
     *
     * <Input>
     *    point    :: The index of the point to move.
     *
     *    distance :: The distance to apply.
     *
     * <InOut>
     *    zone     :: The affected glyph zone.
     *
     * =====================================================================
     */
    public static void DirectMove(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DirectMove");
      TTGlyphZoneRec zone = (TTGlyphZoneRec)args[0];
      short point = (short)args[1];
      long distance = (long)args[2];
      long v;

      v = TTInterpRun.cur.GS.freeVector.x;
      if (v != 0) {
        zone.cur[point].x += FTCalc.FT_MulDiv(distance, v, TTInterpRun.cur.F_dot_P);
        zone.tags[point] |= FT_CURVE_TAG_TOUCH_X;
      }
      v = TTInterpRun.cur.GS.freeVector.y;
      if (v != 0) {
        zone.cur[point].y += FTCalc.FT_MulDiv(distance, v, TTInterpRun.cur.F_dot_P );
        zone.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
      }
    } 

    /* =====================================================================
     * DirectMoveOrig
     *
     * =====================================================================
     */
    public static int DirectMoveOrig(Object ... args) {
Log.w(TAG, "DirectMoveOrig not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "DirectMoveOrig");
      Object obj = args[0];
    
      int error = 0;
    
      return error;
    } 
    
    /* =====================================================================
     * DirectMoveX
     *
     * =====================================================================
     */
    public static void DirectMoveX(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DirectMoveX");
      TTGlyphZoneRec zone = (TTGlyphZoneRec)args[0];
      short point = (short)args[1];
      long distance = (long)args[2];

FTGlyphLoaderRec._showLoaderZone("DirectMoveX");
Debug(0, DBG_INTERP, TAG, "zone: "+zone.toDebugString()+"!");
Debug(0, DBG_INTERP, TAG, String.format("Direct_Move_X: point: %d x: %d distance: %d\n", point, zone.cur[zone.cur_idx + point].x, distance));
      zone.cur[zone.cur_idx + point].x += distance;
_showZp0Zp1OrgCur("DirectMoveX", TTInterpBase.cur);
Debug(0, DBG_INTERP, TAG, String.format("Direct_Move_X2: cur_idx: %d point: %d x: %d distance: %d\n",
    zone.cur_idx, point, zone.cur[zone.cur_idx + point].x, distance));
      zone.tags[point] |= FT_CURVE_TAG_TOUCH_X;
    } 

    /* =====================================================================
     * DirectMoveOrigX
     *
     * =====================================================================
     */
    public static void DirectMoveOrigX(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DirectMoveOrigX");
      TTGlyphZoneRec zone = (TTGlyphZoneRec)args[0];
      short point = (short)args[1];
      long distance = (long)args[2];
    
      zone.org[zone.org_idx + point].x += distance;
    } 

    /* =====================================================================
     * DirectMoveY
     *
     * =====================================================================
     */
    public static void DirectMoveY(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DirectMoveY");
      TTGlyphZoneRec zone = (TTGlyphZoneRec)args[0];
      short point = (short)args[1];
      long distance = (long)args[2];

Debug(0, DBG_INTERP, TAG, String.format("Direct_Move_Y: %d %d %d\n", point, zone.cur[zone.cur_idx + point].y, distance));
Debug(0, DBG_INTERP, TAG, String.format("Direct_Move_Y 2: rp1: %d rp2: %d rp3: %d\n", TTInterpRun.cur.GS.rp0, TTInterpRun.cur.GS.rp1, TTInterpRun.cur.GS.rp2));
      zone.cur[zone.cur_idx + point].y += distance;
      zone.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
    } 

    /* =====================================================================
     * DirectMoveOrigY
     *
     * =====================================================================
     */
    public static void DirectMoveOrigY(Object ... args) {
Debug(0, DBG_INTERP, TAG, "DirectMoveOrigY");
      TTGlyphZoneRec zone = (TTGlyphZoneRec)args[0];
      short point = (short)args[1];
      long distance = (long)args[2];
    
      zone.org[zone.org_idx + point].y += distance;
    } 

    /* =====================================================================
     * ReadCVTStretched
     *
     * =====================================================================
     */
    public static int ReadCVTStretched(Object ... args) {
Log.w(TAG, "ReadCVTStretched not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "ReadCVTStretched");
      Object obj = args[0];
    
      int error = 0;
    
      return error;
    } 

    /* =====================================================================
     * WriteCVTStretched
     *
     * =====================================================================
     */
    public static int WriteCVTStretched(Object ... args) {
Log.w(TAG, "WriteCVTStretched not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "WriteCVTStretched");
      Object obj = args[0];
    
      int error = 0;
    
      return error;
    } 
    
    /* =====================================================================
     * MoveCVTStretched
     *
     * =====================================================================
     */
    public static int MoveCVTStretched(Object ... args) {
Log.w(TAG, "MoveCVTStretched not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "MoveCVTStretched");
      Object obj = args[0];
    
      int error = 0;
    
      return error;
    } 
    
    /* =====================================================================
     * ReadCVT
     *
     * =====================================================================
     */
    public static int ReadCVT(Object ... args) {
Debug(0, DBG_INTERP, TAG, "ReadCVT");
      int idx = (int)args[0];

Debug(0, DBG_INTERP, TAG, String.format("ReadCVT2: idx: %d %d", idx, TTInterpRun.cur.cvt[idx]));
if (idx == 145) {
  for (int i = 0; i < 15; i++) {
      Debug(0, DBG_INTERP, TAG, String.format("i: %d  %d %d %d %d %d  %d %d %d %d %d",
        i * 10,
        TTInterpRun.cur.cvt[i*10 + 0],
        TTInterpRun.cur.cvt[i*10 + 1],
        TTInterpRun.cur.cvt[i*10 + 2],
        TTInterpRun.cur.cvt[i*10 + 3],
        TTInterpRun.cur.cvt[i*10 + 4],
        TTInterpRun.cur.cvt[i*10 + 5],
        TTInterpRun.cur.cvt[i*10 + 6],
        TTInterpRun.cur.cvt[i*10 + 7],
        TTInterpRun.cur.cvt[i*10 + 8],
        TTInterpRun.cur.cvt[i*10 + 9]
        ));
  }
  Debug(0, DBG_INTERP, TAG, String.format("145: %d 0x%08x", TTInterpRun.cur.cvt[idx], TTInterpRun.cur.cvt[idx]));
}
      return (int)TTInterpRun.cur.cvt[idx];
    } 
    
    /* =====================================================================
     * WriteCVT
     *
     * =====================================================================
     */
    public static void WriteCVT(Object ... args) {
      int idx = (int)args[0];
      int value = (int)args[1];
Debug(0, DBG_INTERP, TAG, String.format("WriteCVT: idx: %d value: %d", idx, value));

      TTInterpRun.cur.cvt[idx] = (long)value;
    } 
    
    /* =====================================================================
     * MoveCVT
     *
     * =====================================================================
     */
    public static int MoveCVT(Object ... args) {
Log.w(TAG, "MoveCVT not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "MoveCVT");
      Object obj = args[0];
    
      int error = 0;
    
      return error;
    } 

    /* =====================================================================
     * RoundNone
     *
     * =====================================================================
     */
    public static int RoundNone(Object ... args) {
Log.w(TAG, "RoundNone not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundNone");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundToGrid
     *
     * <Description>
     *    Rounds value to grid after adding engine compensation.
     *
     * <Input> 
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    public static long RoundToGrid(Object ... args) {
      long distance = (long)args[0];
      long compensation = (long)args[1];
      long val;
Debug(0, DBG_INTERP, TAG, String.format("RoundToGrid: distance: %d, compensation: %d", distance, compensation));

      if (distance >= 0) {
        val = distance + compensation + 32;
        if (distance != 0 && val > 0) {
          val &= ~63;
        } else {
          val = 0;
        }
      } else {
        val = -FTCalc.FT_PIX_ROUND(compensation - distance);
        if (val > 0) {
          val = 0;
        }
      }
      return  val;
    }

    /* =====================================================================
     * RoundUpToGrid
     *
     * =====================================================================
     */
    public static int RoundUpToGrid(Object ... args) {
Log.w(TAG, "RoundUpToGrid not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundUpToGrid");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundDownToGrid
     *
     * =====================================================================
     */
    public static int RoundDownToGrid(Object ... args) {
Log.w(TAG, "RoundDownToGrid not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundDownToGrid");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundToHalfGrid
     *
     * =====================================================================
     */
    public static int RoundToHalfGrid(Object ... args) {
Log.w(TAG, "RoundToHalfGrid not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundToHalfGrid");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundToDoubleGrid
     *
     * =====================================================================
     */
    public static int RoundToDoubleGrid(Object ... args) {
Log.w(TAG, "RoundToDoubleGrid not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundToDoubleGrid");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundSuper
     *
     * =====================================================================
     */
    public static int RoundSuper(Object ... args) {
Log.w(TAG, "RoundSuper not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundSuper");
      Object obj = args[0];

      int error = 0;

      return error;
    }

    /* =====================================================================
     * RoundSuper45
     *
     * =====================================================================
     */
    public static int RoundSuper45(Object ... args) {
Log.w(TAG, "RoundSuper45 not yet implemented!!");
Debug(0, DBG_INTERP, TAG, "RoundSuper45");
      Object obj = args[0];

      int error = 0;

      return error;
    }

}

Added ftbase/TTInterpInsFuncs1.java.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTInterpInsFuncs1                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpInsFuncs1 extends TTInterpOpcodeFuncs1 {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTInterpInsFuncs1";

    /* ==================== TTInterpInsFuncs1 ================================== */
    public TTInterpInsFuncs1() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* ==================== FT_MulFix ===================================== */
    protected static Long FT_MulFix(Long a, Long b) {
      int s = 1;
      Long c;

      if (a < 0) {
        a = -a;
        s = -1;
      }
      if (b < 0) {
        b = -b;
        s = -s;
      }
      c = (long)((a * b + 0x8000L) >> 16);
      return (s > 0) ? c : -c;
    }

    /* ==================== FT_StackMove ===================================== */
    protected static void FT_StackMove(int offset1, int offset2, int length) {
      int idx1;
      int idx2;
      int i;

      if (offset1 < offset2) {
        idx1 = offset2 + length;
        idx2 = offset1 + length;
        for ( i = length - 1; i >= 0; i--) {
          cur.stack[idx2] = cur.stack[idx1];
          idx2--;
          idx1--;
        }
      } else {
        idx1 = offset1 + length;
        idx2 = offset2 + length;
        for ( i = length - 1; i >= 0; i--) {
          cur.stack[idx1] = cur.stack[idx2];
          idx2--;
          idx1--;
        }
      }
    }

    /* =====================================================================
     * <Function>
     *    GetShortIns
     *
     * <Description>
     *    Returns a short integer taken from the instruction stream at
     *    address IP.
     *
     * <Return>
     *    Short read at code[IP].
     *
     * <Note>
     *    This one could become a macro.
     * =====================================================================
     */

    protected static Short GetShortIns() {
      short val;
      short short1;
      short short2;
      /* Reading a byte stream so there is no endianess (DaveP) */
      cur.IP += 2;
      short1 = (short)((cur.code[cur.IP - 2] & 0xFF) << 8);
      short2 = (short)(cur.code[cur.IP - 1] & 0xFF);
      val = (short)((short1 + short2) & 0xFFFF);
      return val;
//      return (short)(((cur.code[cur.IP - 2]) << 8) + cur.code[cur.IP - 1]);
    }

    /* =====================================================================
     * <Function>
     *    insGotoCodeRange
     *
     * <Description>
     *    Goes to a certain code range in the instruction stream.
     *
     * <Input>
     *    aRange :: The index of the code range.
     *
     *
     *    aIP    :: The new IP address in the code range.
     *
     * <Return>
     *    SUCCESS or FAILURE.
     * =====================================================================
     */
    protected static boolean insGotoCodeRange(int aRange, Long aIP) {
      TTCodeRange range;

      if (aRange < 1 || aRange > 3) {
        cur.error = FTError.INTERP_BAD_ARGUMENT;
        return FAILURE;
      }
      range = cur.codeRangeTable[aRange - 1];
      if (range.base == null) {   /* invalid coderange */
        cur.error = FTError.INTERP_INVALID_CODE_RANGE;
        return FAILURE;
      }
      /* NOTE: Because the last instruction of a program may be a CALL */
      /*       which will return to the first byte *after* the code    */
      /*       range, we test for aIP <= Size, instead of aIP < Size.  */
      if (aIP > range.size) {
        cur.error = FTError.INTERP_CODE_OVERFLOW;
        return FAILURE;
      }
Debug(0, DBG_INTERP, TAG, "insGoto: "+aRange+"!"+range.base+"!"+range.short_base+"!");
      cur.code = range.base;
      cur.cvt_code = range.short_base;
      cur.codeSize = range.size.intValue();
Debug(0, DBG_INTERP, TAG, String.format("insGotoCodeRange: size: %d", cur.codeSize));
      cur.IP = aIP.intValue();
      cur.curRange = aRange;
      return SUCCESS;
    }

    /* =====================================================================
     * MINDEX[]:     Move INDEXed element
     * Opcode range: 0x26
     * Stack:        int32? --> StkElt
     * =====================================================================
     */

    protected static void insMINDEX() {
      int L;
      Long K;

      L = (int)cur.stack[cur.numArgs + 0];
      if (L <= 0 || L > cur.numArgs) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
      } else {
        K = cur.stack[cur.numArgs - L];
        FT_StackMove(cur.numArgs - L, cur.numArgs - L + 1, (L - 1));
        cur.stack[cur.numArgs - 1] = K;
      }
    }

    /* =====================================================================
     * ROLL[]:       ROLL top three elements
     * Opcode range: 0x8A
     * Stack:        3 * StkElt --> 3 * StkElt
     * =====================================================================
     */
    protected static void insROLL() {
      int A;
      int B;
      int C;

      A = (int)cur.stack[cur.numArgs + 2];
      B = (int)cur.stack[cur.numArgs + 1];
      C = (int)cur.stack[cur.numArgs + 0];
      cur.stack[cur.numArgs + 2] = C;
      cur.stack[cur.numArgs + 1] = A;
      cur.stack[cur.numArgs + 0] = B;
    }

    /* =====================================================================
     *
     * MANAGING THE FLOW OF CONTROL
     *
     *   Instructions appear in the specification's order.
     *
     * =====================================================================
     */
    protected static boolean SkipCode() {
      cur.IP += cur.length;
      if ( cur.IP < cur.codeSize ) {
        cur.opcode = (short)(cur.code[cur.IP] & 0xFF);
        cur.length = opcode_length[cur.opcode];
        if (cur.length < 0) {
          if (cur.IP + 1 >= cur.codeSize) {
            cur.error = FTError.INTERP_CODE_OVERFLOW;
            return FAILURE;
          }
          cur.length = 2 - cur.length * (cur.code[cur.IP + 1] & 0xFF);
        }
        if (cur.IP + cur.length <= cur.codeSize) {
          return SUCCESS;
        }
      }
      return FAILURE;
    }
  
    /* =====================================================================
     *
     * IF[]:         IF test
     * Opcode range: 0x58
     * Stack:        StkElt -->
     *
     * =====================================================================
     */
    protected static void insIF() {
      int nIfs;
      boolean Out;

Debug(0, DBG_INTERP, TAG, String.format("insIF: %d\n", cur.stack[cur.numArgs + 0]));
      if (cur.stack[cur.numArgs + 0] != 0) {
        return;
      } 
      nIfs = 1;
      Out = false;
      do {
        if (SkipCode() == FAILURE) {
          return;
        } 
        switch (cur.opcode) {
        case 0x58:      /* IF */
          nIfs++;
          break;
        case 0x1B:      /* ELSE */
          Out = (nIfs == 1);
          break;
        case 0x59:      /* EIF */
          nIfs--;
          Out = (nIfs == 0);
          break;
        }
      } while (Out == false);
    }
  
    /* =====================================================================
     *
     * ELSE[]:       ELSE
     * Opcode range: 0x1B
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insELSE() {
      int nIfs;
  
      nIfs = 1;
      do {
        if (SkipCode() == FAILURE) {
          return;
        } 
        switch (cur.opcode) {
        case 0x58:    /* IF */
          nIfs++;
          break;
        case 0x59:    /* EIF */
          nIfs--;
          break;
        }
      } while (nIfs != 0);
    }
  
    /* =====================================================================
     *
     * DEFINING AND USING FUNCTIONS AND INSTRUCTIONS
     *
     *   Instructions appear in the specification's order.
     *
     * =====================================================================
     */
  
    /* =====================================================================
     *
     * FDEF[]:       Function DEFinition
     * Opcode range: 0x2C
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insFDEF() {
      int n;
//      TTDefRec rec;
      int recIdx;
      int limit;

Debug(0, DBG_INTERP, TAG, "insFDEF");
      /* some font programs are broken enough to redefine functions! */
      /* We will then parse the current table.                       */
      recIdx = 0;
//      rec = cur.FDefs[recIdx];
      limit = recIdx + cur.numFDefs;
      n = (int)cur.stack[cur.numArgs];
Debug(0, DBG_INTERP, TAG, "n: "+n+"!"+cur.numArgs+"!"+cur.stack[cur.numArgs]+"!"+cur.stack[0]+"!");
      for (recIdx = 0; recIdx < limit; recIdx++) {
        if (cur.FDefs[recIdx].opc == n) {
          break;
        }
      }
      if (recIdx == limit) {
        /* check that there is enough room for new functions */
        if (cur.numFDefs >= cur.maxFDefs) {
          cur.error = FTError.INTERP_TOO_MANY_FUNCTION_DEFS;
          return;
        }
        cur.numFDefs++;
      }
Debug(0, DBG_INTERP, TAG, "recIdx1: "+recIdx+"!");
      /* Although FDEF takes unsigned 32-bit integer,  */
      /* func # must be within unsigned 16-bit integer */
      if (n > 0xFFFF) {
        cur.error = FTError.INTERP_TOO_MANY_FUNCTION_DEFS;
        return;
      }
      cur.FDefs[recIdx].range = cur.curRange;
      cur.FDefs[recIdx].opc = n;
      cur.FDefs[recIdx].start = (int)(cur.IP + 1);
      cur.FDefs[recIdx].active = true;
      cur.FDefs[recIdx].inline_delta = false;
      cur.FDefs[recIdx].sph_fdef_flags = 0x0000L;
//      cur.FDefs[recIdx] = rec;
Debug(0, DBG_INTERP, TAG, "recIdx2: "+recIdx+"!"+cur.numFDefs+"!"+limit+"!opc: "+cur.FDefs[recIdx].opc+"!");
for (int j = 0; j < cur.numArgs; j++) {
  Debug(0, DBG_INTERP, TAG, "stack: "+cur.stack[j]+"!");
}
for (int j = 0; j < cur.numArgs; j++) {
  Debug(0, DBG_INTERP, TAG, "args: "+cur.stack[cur.numArgs + j]+"!");
}
Debug(0, DBG_INTERP, TAG, String.format("rec: %d %d %d %b %b", cur.FDefs[recIdx].range, cur.FDefs[recIdx].opc, cur.FDefs[recIdx].start, cur.FDefs[recIdx].active, cur.FDefs[recIdx].inline_delta));
      if (n > cur.maxFunc) {
        cur.maxFunc = n;
      } 
      /* Now skip the whole function definition. */
      /* We don't allow nested IDEFS & FDEFs.    */
      while (SkipCode() == SUCCESS) {
        switch (cur.opcode & 0xFF) {
        case 0x89:    /* IDEF */
        case 0x2C:    /* FDEF */
          cur.error = FTError.INTERP_NESTED_DEFS;
          return;
        case 0x2D:   /* ENDF */
          cur.FDefs[recIdx].end = (int)cur.IP;
          return;
        }
      }
    }
  
    /* =====================================================================
     *
     * ENDF[]:       END Function definition
     * Opcode range: 0x2D
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insENDF() {
      TTCallRec pRec;
  
      if (cur.callTop <= 0) {   /* We encountered an ENDF without a call */
        cur.error = FTError.INTERP_ENDF_IN_EXEC_STREAM;
        return;
      }
      cur.callTop--;
      pRec = cur.callStack[cur.callTop];
      pRec.CurCount--;
      cur.step_ins = false;
      if (pRec.CurCount > 0) {
        cur.callTop++;
        cur.IP = pRec.CurRestart;
      } else {
        /* Loop through the current function */
        insGotoCodeRange(pRec.CallerRange, (long)pRec.CallerIP);
      }
      /* Exit the current call frame.                      */
      /* NOTE: If the last instruction of a program is a   */
      /*       CALL or LOOPCALL, the return address is     */
      /*       always out of the code range.  This is a    */
      /*       valid address, and it is why we do not test */
      /*       the result of Ins_Goto_CodeRange() here!    */
    }
  
    /* =====================================================================
     *
     * CALL[]:       CALL function
     * Opcode range: 0x2B
     * Stack:        uint32? -->
     *
     * =====================================================================
     */
    protected static void insCALL() {
      int F;
//      TTCallRec pCrec;
      TTDefRec def;
      int defIdx = 0;
  
      /* first of all, check the index */
      F = (int)cur.stack[cur.numArgs];
Debug(0, DBG_INTERP, TAG, "insCall: "+F+"!"+cur.maxFunc+"!numArgs: "+cur.numArgs);
      if (BOUNDSL((long)F, (long)(cur.maxFunc + 1))) {
        cur.error = FTError.INTERP_INVALID_REFERENCE;
        return;
      } 
      /* Except for some old Apple fonts, all functions in a TrueType */
      /* font are defined in increasing order, starting from 0.  This */
      /* means that we normally have                                  */
      /*                                                              */
      /*    cur.maxFunc+1 == cur.numFDefs                             */
      /*    cur.FDefs[n].opc == n for n in 0..cur.maxFunc             */
      /*                                                              */
      /* If this isn't true, we need to look up the function table.   */
  
      def = cur.FDefs[F];
      if (cur.maxFunc + 1 != cur.numFDefs || def.opc != F) {
        /* look up the FDefs table */
        int limit;
  
        def = cur.FDefs[defIdx];
        limit = defIdx + cur.numFDefs;
        while (defIdx < limit && def.opc != F) {
          defIdx++;
        } 
        if (defIdx == limit) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
          return;
        }
      }
      /* check that the function is active */
      if (!def.active) {
        cur.error = FTError.INTERP_INVALID_REFERENCE;
        return;
      } 
      /* check the call stack */
      if (cur.callTop >= cur.callSize) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
//      pCrec = cur.callStack[cur.callTop];
      cur.callStack[cur.callTop].CallerRange = cur.curRange;
      cur.callStack[cur.callTop].CallerIP = cur.IP + 1;
      cur.callStack[cur.callTop].CurCount = 1;
      cur.callStack[cur.callTop].CurRestart = def.start;
      cur.callStack[cur.callTop].CurEnd = def.end;
      cur.callTop++;
Debug(0, DBG_INTERP, TAG, "insGotoCodeRange: "+def.range+"!"+def.start+"!");
      insGotoCodeRange(def.range, (long)def.start);
      cur.step_ins = false;
      return;
    }
  
    /* =====================================================================
     *
     * LOOPCALL[]:   LOOP and CALL function
     * Opcode range: 0x2A
     * Stack:        uint32? Eint16? -->
     *
     * =====================================================================
     */
    protected static void insLOOPCALL() {
      int F;
 //     TTCallRec pCrec;
      TTDefRec def;
      int defIdx;
  
      /* first of all, check the index */
      F = (int)cur.stack[cur.numArgs + 1];
      if (BOUNDSL((long)F, (long)(cur.maxFunc + 1))) {
        cur.error = FTError.INTERP_INVALID_REFERENCE;
        return;
      } 
      /* Except for some old Apple fonts, all functions in a TrueType */
      /* font are defined in increasing order, starting from 0.  This */
      /* means that we normally have                                  */
      /*                                                              */
      /*    cur.maxFunc+1 == cur.numFDefs                             */
      /*    cur.FDefs[n].opc == n for n in 0..cur.maxFunc             */
      /*                                                              */
      /* If this isn't true, we need to look up the function table.   */
      def = cur.FDefs[F];
      if ( cur.maxFunc + 1 != cur.numFDefs || def.opc != F ) {
        /* look up the FDefs table */
        int limit;

        defIdx = 0;
        def = cur.FDefs[defIdx];
        limit = defIdx + cur.numFDefs;
        while (defIdx < limit && def.opc != F) {
          defIdx++;
        } 
        if (defIdx == limit) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
          return;
        }
      }
      /* check that the function is active */
      if (!def.active) {
        cur.error = FTError.INTERP_INVALID_REFERENCE;
        return;
      } 
      /* check stack */
      if (cur.callTop >= cur.callSize) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
      if (cur.stack[cur.numArgs + 0] > 0) {
//        pCrec = cur.callStack[cur.callTop];
        cur.callStack[cur.callTop].CallerRange = cur.curRange;
        cur.callStack[cur.callTop].CallerIP = cur.IP + 1;
        cur.callStack[cur.callTop].CurCount = (int)cur.stack[cur.numArgs + 0];
        cur.callStack[cur.callTop].CurRestart = def.start;
        cur.callStack[cur.callTop].CurEnd = def.end;
        cur.callTop++;
        insGotoCodeRange(def.range, (long)def.start);
        cur.step_ins = false;
      }
      return;
    }
  
    /* =====================================================================
     *
     * IDEF[]:       Instruction DEFinition
     * Opcode range: 0x89
     * Stack:        Eint8 -->
     *
     * =====================================================================
     */
    protected static void insIDEF() {
      TTDefRec def;
      int limit;
      int defIdx;
  
      /*  First of all, look for the same function in our table */
      defIdx = 0;
      def = cur.IDefs[defIdx];
      limit = defIdx + cur.numIDefs;
      for (; defIdx < limit; defIdx++) {
        if (def.opc == cur.stack[cur.numArgs + 0]) {
          break;
        }
      } 
      if (defIdx == limit) {
        /* check that there is enough room for a new instruction */
        if (cur.numIDefs >= cur.maxIDefs) {
          cur.error = FTError.INTERP_TOO_MANY_INSTRUCTION_DEFS;
          return;
        }
        cur.numIDefs++;
      }
      /* opcode must be unsigned 8-bit integer */
      if (0 > cur.stack[cur.numArgs + 0] || cur.stack[cur.numArgs + 0] > 0x00FF) {
        cur.error = FTError.INTERP_TOO_MANY_INSTRUCTION_DEFS;
        return;
      }
      def.opc = (int)cur.stack[cur.numArgs + 0];
      def.start = (int)(cur.IP + 1);
      def.range = cur.curRange;
      def.active = true;
      if (cur.stack[cur.numArgs + 0] > cur.maxIns) {
        cur.maxIns = (byte)cur.stack[cur.numArgs + 0];
      } 
      /* Now skip the whole function definition. */
      /* We don't allow nested IDEFs & FDEFs.    */
      while (SkipCode() == SUCCESS) {
        switch (cur.opcode & 0xFF) {
        case 0x89:   /* IDEF */
        case 0x2C:   /* FDEF */
          cur.error = FTError.INTERP_NESTED_DEFS;
          return;
        case 0x2D:   /* ENDF */
          return;
        }
      }
    }
  
    /* =====================================================================
    /*
    /* PUSHING DATA ONTO THE INTERPRETER STACK
    /*
    /*   Instructions appear in the specification's order.
    /*
    /* =====================================================================
  
    /* =====================================================================
     *
     * NPUSHB[]:     PUSH N Bytes
     * Opcode range: 0x40
     * Stack:        --> uint32...
     *
     * =====================================================================
     */
    protected static void insNPUSHB() {
      int L;
      int K;

      L = cur.code[cur.IP + 1] & 0xFF;
Debug(0, DBG_INTERP, TAG, String.format("insNPUSHB: L: %d, cur.IP: %d", L, cur.IP));
      if (BOUNDS(L, cur.stackSize + 1 - cur.top)) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
      for (K = 1; K <= L; K++) {
        cur.stack[cur.numArgs + K - 1] = cur.code[cur.IP + K + 1] & 0xFF;
Debug(0, DBG_INTERP, TAG, String.format("pushb: %d 0x%02x, numArgs: %d", K-1, cur.stack[cur.numArgs + K - 1], cur.numArgs));
      }
      cur.new_top += L;
    }
  
    /* =====================================================================
     *
     * NPUSHW[]:     PUSH N Words
     * Opcode range: 0x41
     * Stack:        --> int32...
     *
     * =====================================================================
     */
    protected static void insNPUSHW() {
      int L;
      int K;
  
      L = cur.code[cur.IP + 1] & 0xFF;
      if (BOUNDS(L, cur.stackSize + 1 - cur.top)) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
      cur.IP += 2;
      for (K = 0; K < L; K++) {
        cur.stack[cur.numArgs + K] = GetShortIns();
      } 
      cur.step_ins = false;
      cur.new_top += L;
    }
  
    /* =====================================================================
     *
     * PUSHB[abc]:   PUSH Bytes
     * Opcode range: 0xB0-0xB7
     * Stack:        --> uint32...
     *
     * =====================================================================
     */
    protected static void insPUSHB() {
      int L;
      int K;
  
      L = (cur.opcode - 0xB0 + 1);
Debug(0, DBG_INTERP, TAG, String.format("insPUSHB numArgs: %d L: %d", cur.numArgs, L));
      if (BOUNDS(L, cur.stackSize + 1 - cur.top)) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
      for (K = 1; K <= L; K++) {
        cur.stack[cur.numArgs + K - 1] = (cur.code[cur.IP + K] & 0xFF);
Debug(0, DBG_INTERP, TAG, String.format("IP: K: %d IP: %d %d %d", K, cur.IP, (cur.code[cur.IP + K] & 0xFF), cur.code[cur.IP + K]));
      }
    }
  
    /* =====================================================================
     *
     * PUSHW[abc]:   PUSH Words
     * Opcode range: 0xB8-0xBF
     * Stack:        --> int32...
     *
     * =====================================================================
     */
    protected static void insPUSHW() {
      int L;
      int K;

Debug(0, DBG_INTERP, TAG, "insPUSHW");
      L = (cur.opcode - 0xB8 + 1);
      if (BOUNDS(L, cur.stackSize + 1 - cur.top)) {
        cur.error = FTError.INTERP_STACK_OVERFLOW;
        return;
      }
      cur.IP++;
      for (K = 0; K < L; K++) {
        cur.stack[cur.numArgs + K] = GetShortIns();
      } 
      cur.step_ins = false;
    }
  
    /* =====================================================================
     *
     * MANAGING THE GRAPHICS STATE
     *
     *  Instructions appear in the specs' order.
     *
     * =====================================================================
     */
  
    /* =====================================================================
     *
     * GC[a]:        Get Coordinate projected onto
     * Opcode range: 0x46-0x47
     * Stack:        uint32 --> f26.6
     *
     * XXX: UNDOCUMENTED: Measures from the original glyph must be taken
     *      along the dual projection vector!
     *
     * =====================================================================
     */
    protected static void insGC() {
      Long L;
      Long R;
  
      L = (long)cur.stack[cur.numArgs + 0];
      if (BOUNDSL(L, (long)cur.zp2.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        R = 0L;
      } else {
        if ((cur.opcode & 1) != 0) {
          R = (long)cur.func_dualproj.callClassMethod(cur.zp2.org[cur.zp2.org_idx + L.intValue()].x - cur.zp2.org[cur.zp2.org_idx + L.intValue()].x,
                  cur.zp2.org[cur.zp2.org_idx + L.intValue()].y - cur.zp2.org[cur.zp2.org_idx + L.intValue()].y);
        } else {
          R = (long)cur.func_project.callClassMethod(cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].x - cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].x,
                  cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].y - cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].y);
        }
      }
      cur.stack[cur.numArgs + 0] = R.intValue();
    }
  
    /* =====================================================================
     *
     * SCFS[]:       Set Coordinate From Stack
     * Opcode range: 0x48
     * Stack:        f26.6 uint32 -->
     *
     * Formula:
     *
     *   OA := OA + ( value - OA.p )/( f.p ) * f
     *
     * =====================================================================
     */
    protected static void insSCFS() {
      Long K;
      Long L;
  
      L = (long)cur.stack[cur.numArgs + 0];
      if (BOUNDS(L.intValue(), (int)cur.zp2.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      K =(long)cur.func_project.callClassMethod(cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].x - cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].x,
              cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].y - cur.zp2.cur[cur.zp2.cur_idx + L.intValue()].y);
      cur.func_move.callClassMethod(cur.zp2, L.intValue(), (int)(cur.stack[cur.numArgs + 1] - K));
      /* UNDOCUMENTED!  The MS rasterizer does that with */
      /* twilight points (confirmed by Greg Hitchcock)   */
      if (cur.GS.gep2 == 0) {
        cur.zp2.org[cur.zp2.org_idx + L.intValue()] = cur.zp2.cur[cur.zp2.cur_idx + L.intValue()];
      }
    }
  
    /* =====================================================================
     *
     * MD[a]:        Measure Distance
     * Opcode range: 0x49-0x4A
     * Stack:        uint32 uint32 --> f26.6
     *
     * XXX: UNDOCUMENTED: Measure taken in the original glyph must be along
     *                    the dual projection vector.
     *
     * XXX: UNDOCUMENTED: Flag attributes are inverted!
     *                      0 => measure distance in original outline
     *                      1 => measure distance in grid-fitted outline
     *
     * XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1!
     *
     * =====================================================================
     */
    protected static void insMD() {
      Short K;
      Short L;
      Long D;
  
      K = (short)cur.stack[cur.numArgs + 1];
      L = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)L, (int)cur.zp0.n_points) || BOUNDS((int)K, (int)cur.zp1.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        D = 0L;
      } else {
        if ((cur.opcode & 1) != 0) {
          D = (long)cur.func_project.callClassMethod(cur.zp0.cur[cur.zp0.cur_idx + L.intValue()].x - cur.zp1.cur[cur.zp0.cur_idx + K.intValue()].x,
                  cur.zp0.cur[cur.zp0.cur_idx + L.intValue()].y - cur.zp1.cur[cur.zp0.cur_idx + K.intValue()].y);
        } else {
          /* XXX: UNDOCUMENTED: twilight zone special case */
          if (cur.GS.gep0 == 0 || cur.GS.gep1 == 0) {
            FTVectorRec vec1 = cur.zp0.org[cur.zp0.org_idx + L];
            FTVectorRec vec2 = cur.zp1.org[cur.zp1.org_idx + K];

            D = (long)cur.func_dualproj.callClassMethod(vec1.x, vec2.y);
          } else {
            FTVectorRec vec1 = cur.zp0.orus[cur.zp0.orus_idx + L];
            FTVectorRec vec2 = cur.zp1.orus[cur.zp1.orus_idx + K];
  
            if (cur.metrics.x_scale == cur.metrics.y_scale) {
              /* this should be faster */
              D = (long)cur.func_dualproj.callClassMethod(vec1.x - vec2.x, vec1.y - vec2.y);
              D = FT_MulFix(D, cur.metrics.x_scale);
            } else {
              FTVectorRec vec = new FTVectorRec();
  
              vec.x = FT_MulFix(vec1.x - vec2.x, cur.metrics.x_scale);
              vec.y = FT_MulFix(vec1.y - vec2.y, cur.metrics.y_scale);
              D = (long)cur.func_dualproj.callClassMethod(vec.x, vec.y);
            }
          }
        }
      }
      cur.stack[cur.numArgs + 0] = D.intValue();
    }
  
    /* =====================================================================
     *
     * SDPVTL[a]:    Set Dual PVector to Line
     * Opcode range: 0x86-0x87
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    protected static void insSDPVTL() {
      Long A;
      Long B;
      Long C;
      Short p1;    /* was FT_Int in pas type ERROR */
      Short p2;    /* was FT_Int in pas type ERROR */
      int aOpc = cur.opcode;
  
      p1 = (short)cur.stack[cur.numArgs + 1];
      p2 = (short)cur.stack[cur.numArgs + 0];
  
      if (BOUNDS((int)p2, (int)cur.zp1.n_points) || BOUNDS((int)p1, (int)cur.zp2.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      {
        FTVectorRec v1 = cur.zp1.org[cur.zp1.org_idx + p2];
        FTVectorRec v2 = cur.zp2.org[cur.zp2.org_idx + p1];
  
        A = v1.x - v2.x;
        B = v1.y - v2.y;
        /* If v1 == v2, SDPVTL behaves the same as */
        /* SVTCA[X], respectively.                 */
        /*                                         */
        /* Confirmed by Greg Hitchcock.            */
        if (A == 0 && B == 0) {
          A = 0x4000L;
          aOpc = 0;
        }
      }
      if ((aOpc & 1) != 0) {
        C = B;   /* counter clockwise rotation */
        B = A;
        A = -C;
      }
      FTReference<FTVectorRec> dualVec_ref = new FTReference<FTVectorRec>();
      dualVec_ref.Set(cur.GS.dualVector);
      Normalize(A, B, dualVec_ref);
      cur.GS.dualVector = dualVec_ref.Get();
      {
        FTVectorRec v1 = cur.zp1.cur[cur.zp1.cur_idx + p2];
        FTVectorRec v2 = cur.zp2.cur[cur.zp2.cur_idx + p1];
  
        A = v1.x - v2.x;
        B = v1.y - v2.y;
        if (A == 0 && B == 0) {
          A = 0x4000L;
          aOpc = 0;
        }
      }
      if ((aOpc & 1) != 0) {
        C = B;   /* counter clockwise rotation */
        B = A;
        A = -C;
      }
      dualVec_ref.Set(cur.GS.projVector);
      Normalize(A, B, dualVec_ref);
      cur.GS.projVector = dualVec_ref.Get();
//      GUESS_VECTOR( freeVector );
      computeFuncs();
    }
  
    /* =====================================================================
     *
     * SZP0[]:       Set Zone Pointer 0
     * Opcode range: 0x13
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSZP0() {
      switch ((int)cur.stack[cur.numArgs + 0]) {
      case 0:
        cur.zp0 = cur.twilight;
        break;
      case 1:
        cur.zp0 = cur.pts;
        break;
      default:
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      cur.GS.gep0 = (short)cur.stack[cur.numArgs + 0];
    }
  
    /* =====================================================================
     *
     * SZP1[]:       Set Zone Pointer 1
     * Opcode range: 0x14
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSZP1() {
      switch ((int)cur.stack[cur.numArgs + 0]) {
      case 0:
        cur.zp1 = cur.twilight;
        break;
      case 1:
        cur.zp1 = cur.pts;
        break;
      default:
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      cur.GS.gep1 = (short)cur.stack[cur.numArgs + 0];
    }

    /* =====================================================================
     *
     * SZP2[]:       Set Zone Pointer 2
     * Opcode range: 0x15
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSZP2() {
      switch ((int)cur.stack[cur.numArgs + 0]) {
      case 0:
        cur.zp2 = cur.twilight;
        break;
      case 1:
        cur.zp2 = cur.pts;
        break;
      default:
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      cur.GS.gep2 = (short)cur.stack[cur.numArgs + 0];
    } 

    /* =====================================================================
     *
     * SZPS[]:       Set Zone PointerS
     * Opcode range: 0x16
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSZPS() {
      switch ((int)cur.stack[cur.numArgs + 0]) {
      case 0:
        cur.zp0 = cur.twilight;
        break;
      case 1:
        cur.zp0 = cur.pts;
        break;
      default:
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      cur.zp1 = cur.zp0;
      cur.zp2 = cur.zp0;
      cur.GS.gep0 = (short)cur.stack[cur.numArgs + 0];
      cur.GS.gep1 = (short)cur.stack[cur.numArgs + 0];
      cur.GS.gep2 = (short)cur.stack[cur.numArgs + 0];
    }

    /* =====================================================================
     *
     * INSTCTRL[]:   INSTruction ConTRoL
     * Opcode range: 0x8e
     * Stack:        int32 int32 -->
     *
     * =====================================================================
     */
    protected static void insINSTCTRL() {
      Long K;
      Long L;
  
      K = (long)cur.stack[cur.numArgs + 1];
      L = (long)cur.stack[cur.numArgs + 0];
      if (K < 1 || K > 2) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
	}
        return;
      }
      if (L != 0) {
        L = K;
      } 
      byte byte1 = (byte)(cur.GS.instruct_control & ~(K.byteValue() & 0xFF));
      byte byte2 = (byte)(L.byteValue() & 0xFF);
      cur.GS.instruct_control = (byte)(byte1 | byte2);
    }
  
    /* =====================================================================
     *
     * SCANCTRL[]:   SCAN ConTRoL
     * Opcode range: 0x85
     * Stack:        uint32? -->
     *
     * =====================================================================
     */
    protected static void insSCANCTRL() {
      int A;
  
      /* Get Threshold */
      A = ((int)cur.stack[cur.numArgs + 0] & 0xFF);
      if (A == 0xFF) {
        cur.GS.scan_control = true;
        return;
      } else {
        if ( A == 0 ) {
          cur.GS.scan_control = false;
          return;
        }
      }
      if ((cur.stack[cur.numArgs + 0] & 0x100) != 0 && cur.tt_metrics.ppem <= A) {
        cur.GS.scan_control = true;
      } 
      if ((cur.stack[cur.numArgs + 0] & 0x200) != 0 && cur.tt_metrics.rotated) {
        cur.GS.scan_control = true;
      } 
      if ((cur.stack[cur.numArgs + 0] & 0x400) != 0 && cur.tt_metrics.stretched) {
        cur.GS.scan_control = true;
      } 
      if ((cur.stack[cur.numArgs + 0] & 0x800) != 0 && cur.tt_metrics.ppem > A) {
        cur.GS.scan_control = false;
      } 
      if ((cur.stack[cur.numArgs + 0] & 0x1000) != 0 && cur.tt_metrics.rotated) {
        cur.GS.scan_control = false;
      } 
      if ((cur.stack[cur.numArgs + 0] & 0x2000) != 0 && cur.tt_metrics.stretched) {
        cur.GS.scan_control = false;
      }
    }

    /* =====================================================================
     *
     * SCANTYPE[]:   SCAN TYPE
     * Opcode range: 0x8D
     * Stack:        uint32? -->
     *
     * =====================================================================
     */
    protected static void insSCANTYPE() {
      if (cur.stack[cur.numArgs + 0] >= 0) {
        cur.GS.scan_type = (int)cur.stack[cur.numArgs + 0];
      }
    }

    /* =====================================================================
     *
     * MANAGING OUTLINES
     *
     *   Instructions appear in the specification's order.
     * 
     * =====================================================================
     */

    /* =====================================================================
     *
     * FLIPPT[]:     FLIP PoinT
     * Opcode range: 0x80
     * Stack:        uint32... -->
     *
     * =====================================================================
     */
    protected static void insFLIPPT() {
      Short point;
  
      if (cur.top < cur.GS.loop) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_TOO_FEW_ARGUMENTS;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
      while (cur.GS.loop > 0) {
        cur.numArgs--;
        point = (short)cur.stack[cur.numArgs];
        if (BOUNDS((int)point, (int)cur.pts.n_points)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
        } else {
          cur.pts.tags[point] ^= FT_CURVE_TAG_ON;
        }
        cur.GS.loop--;
      }
      cur.GS.loop = 1;
      cur.new_top = cur.numArgs;
    }


    /* =====================================================================
     *
     * SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis
     * Opcode range: 0x00-0x01
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insSVTCA() {
        DO_SVTCA();
    }

    /* =====================================================================
     *
     * SPVTCA[a]:    Set PVector to Coordinate Axis
     * Opcode range: 0x02-0x03
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insSPVTCA() {
        DO_SPVTCA();
    }

    /* =====================================================================
     *
     * SFVTCA[a]:    Set FVector to Coordinate Axis
     * Opcode range: 0x04-0x05
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insSFVTCA() {
        DO_SFVTCA();
    }

    /* =====================================================================
     *
     * SPVTL[a]:     Set PVector To Line
     * Opcode range: 0x06-0x07
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    protected static void insSPVTL() {
        DO_SPVTL();
    }

    /* =====================================================================
     *
     * SFVTL[a]:     Set FVector To Line
     * Opcode range: 0x08-0x09
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    protected static void insSFVTL() {
        DO_SFVTL();
    }

    /* =====================================================================
     *
     * SFVTPV[]:     Set FVector To PVector
     * Opcode range: 0x0E
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insSFVTPV() {
        DO_SFVTPV();
    }

    /* =====================================================================
     *
     * SPVFS[]:      Set PVector From Stack
     * Opcode range: 0x0A
     * Stack:        f2.14 f2.14 -->
     *
     * =====================================================================
     */
    protected static void insSPVFS() {
        DO_SPVFS();
    }

    /* =====================================================================
     *
     * SFVFS[]:      Set FVector From Stack
     * Opcode range: 0x0B
     * Stack:        f2.14 f2.14 -->
     *
     * =====================================================================
     */
    protected static void insSFVFS() {
        DO_SFVFS();
    }

    /* =====================================================================
     *
     * GPV[]:        Get Projection Vector
     * Opcode range: 0x0C
     * Stack:        ef2.14 --> ef2.14
     *
     * =====================================================================
     */
    protected static void insGPV() {
        DO_GPV();
    }

    /* =====================================================================
     * GFV[]:        Get Freedom Vector
     * Opcode range: 0x0D
     * Stack:        ef2.14 --> ef2.14
     *
     * =====================================================================
     */
    protected static void insGFV() {
        DO_GFV();
    }

    /* =====================================================================
     *
     * SRP0[]:       Set Reference Point 0
     * Opcode range: 0x10
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSRP0() {
        DO_SRP0();
    }

    /* =====================================================================
     *
     * SRP1[]:       Set Reference Point 1
     * Opcode range: 0x11
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSRP1() {
        DO_SRP1();
    }

    /* =====================================================================
     *
     * SRP2[]:       Set Reference Point 2
     * Opcode range: 0x12
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    protected static void insSRP2() {
        DO_SRP2();
    }

    /* =====================================================================
     *
     * RTHG[]:       Round To Half Grid
     * Opcode range: 0x19
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insRTHG() {
        DO_RTHG();
    }

}

Added ftbase/TTInterpInsFuncs2.java.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTInterpInsFuncs2                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpInsFuncs2 extends TTInterpInsFuncs1 {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTInterpInsFuncs2";

    /* ==================== TTInterpInsFuncs2 ================================== */
    public TTInterpInsFuncs2() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return  TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 

    /* =====================================================================
     *
     * FLIPRGON[]:   FLIP RanGe ON
     * Opcode range: 0x81
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    static void insFLIPRGON() {
      Short I;
      Short K;
      Short L;

      K = (short)cur.stack[cur.numArgs + 1];
      L = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)K, (int)cur.pts.n_points) || BOUNDS((int)L, (int)cur.pts.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      for (I = L; I <= K; I++) {
        cur.pts.tags[I] |= FT_CURVE_TAG_ON;
      }
    }

    /* =====================================================================
     *
     * FLIPRGOFF:    FLIP RanGe OFF
     * Opcode range: 0x82
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    static void insFLIPRGOFF() {
      Short I;
      Short K;
      Short L;

      K = (short)cur.stack[cur.numArgs + 1];
      L = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)K, (int)cur.pts.n_points) || BOUNDS((int)L, (int)cur.pts.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      for (I = L; I <= K; I++) {
        cur.pts.tags[I] &= ~FT_CURVE_TAG_ON;
      }
    }

    private static boolean ComputePointDisplacement(FTReference<Long> x_ref, FTReference<Long> y_ref, FTReference<TTGlyphZoneRec> zone_ref, FTReference<Short> short_ref) {
      TTGlyphZoneRec zp;
      Short p;
      long d;
      Long x;
      Long y;

      if ((cur.opcode & 1) != 0) {
        zp = cur.zp0;
        p  = cur.GS.rp1;
      } else {
        zp = cur.zp1;
        p  = cur.GS.rp2;
      }
      if (BOUNDS((int)p, (int)zp.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        short_ref.Set((short)0);
        return FAILURE;
      }
      zone_ref.Set(zp);
      short_ref.Set(p);
      d = (long)cur.func_project.callClassMethod(zp.cur[zp.cur_idx + p].x - zp.org[zp.org_idx + p].x,
              zp.cur[zp.cur_idx + p].y - zp.org[zp.org_idx + p].y);
      x = FTCalc.FT_MulDiv(d, cur.GS.freeVector.x, cur.F_dot_P);
      x_ref.Set(x);
      y = FTCalc.FT_MulDiv(d, cur.GS.freeVector.y, cur.F_dot_P);
      y_ref.Set(y);
      return SUCCESS;
    }

    static void MoveZp2Point(Short point, Long dx, Long dy, boolean touch ) {
      if (cur.GS.freeVector.x != 0) {
        cur.zp2.cur[cur.zp2.cur_idx + point].x = (cur.zp2.cur[cur.zp2.cur_idx + point].x + dx);
        if (touch) {
          cur.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
        }
      }
      if (cur.GS.freeVector.y != 0) {
        cur.zp2.cur[cur.zp2.cur_idx + point].y = (cur.zp2.cur[cur.zp2.cur_idx + point].y + dy);
        if (touch) {
          cur.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
        }
      }
    }

    /* =====================================================================
     *
     * SHP[a]:       SHift Point by the last point
     * Opcode range: 0x32-0x33
     * Stack:        uint32... -->
     *
     * =====================================================================
     */
    static void insSHP() {
      TTGlyphZoneRec zp;
      Short ref;
      Long dx;
      Long dy;
      Short point;
      FTReference<Long> dx_ref = new FTReference<Long>();  
      FTReference<Long> dy_ref = new FTReference<Long>();  
      FTReference<TTGlyphZoneRec> zp_ref = new FTReference<TTGlyphZoneRec>();  
      FTReference<Short> short_ref = new FTReference<Short>();  

      if (cur.top < cur.GS.loop) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
      if (ComputePointDisplacement(dx_ref, dy_ref, zp_ref, short_ref)) {
        return;
      }
      dx = dx_ref.Get();
      dy = dy_ref.Get();
      while (cur.GS.loop > 0) {
        cur.numArgs--;
        point = (short)cur.stack[cur.numArgs];
        if (BOUNDS((int)point, (int)cur.zp2.n_points)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
        } else {
          MoveZp2Point(point, dx, dy, true);
        }
        cur.GS.loop--;
      }
      cur.GS.loop = 1;
      cur.new_top = cur.numArgs;
    }

    /* =====================================================================
     *
     * SHC[a]:       SHift Contour
     * Opcode range: 0x34-35
     * Stack:        uint32 -->
     *
     * UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual)
     *               contour in the twilight zone, namely contour number
     *               zero which includes all points of it.
     *
     * =====================================================================
     */
    static void insSHC() {
      TTGlyphZoneRec zp;
      Short ref;
      Long dx;
      Long dy;
      Short contour;
      Short bounds;
      Short start;
      int limit;
      int i;
      FTReference<Long> dx_ref = new FTReference<Long>();  
      FTReference<Long> dy_ref = new FTReference<Long>();  
      FTReference<TTGlyphZoneRec> zp_ref = new FTReference<TTGlyphZoneRec>();  
      FTReference<Short> short_ref = new FTReference<Short>();  

      contour = (short)cur.stack[cur.numArgs + 0];
      bounds  = (cur.GS.gep2 == 0) ? 1 : cur.zp2.n_contours;
      if (BOUNDS((int)contour, (int)bounds)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      if (ComputePointDisplacement(dx_ref, dy_ref, zp_ref, short_ref)) {
        return;
      }
      dx = dx_ref.Get();
      dy = dy_ref.Get();
      zp = zp_ref.Get();
      ref = short_ref.Get();
      if (contour == 0) {
        start = 0;
      } else {
        start = (short)(cur.zp2.contours[contour - 1] + 1 - cur.zp2.first_point);
      }
      /* we use the number of points if in the twilight zone */
      if (cur.GS.gep2 == 0) {
        limit = cur.zp2.n_points;
      } else {
        limit = (short)(cur.zp2.contours[contour] - cur.zp2.first_point + 1);
      }
      for (i = start; i < limit; i++) {
        if (zp.cur != cur.zp2.cur || ref != i) {
          MoveZp2Point((short)i, dx, dy, true);
        }
      }
    }

    /* =====================================================================
     *
     * SHZ[a]:       SHift Zone
     * Opcode range: 0x36-37
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    static void insSHZ() {
      TTGlyphZoneRec zp;
      Short ref;
      Long dx;
      Long dy;
      int limit;
      int i;
      FTReference<Long> dx_ref = new FTReference<Long>();  
      FTReference<Long> dy_ref = new FTReference<Long>();  
      FTReference<TTGlyphZoneRec> zp_ref = new FTReference<TTGlyphZoneRec>();  
      FTReference<Short> short_ref = new FTReference<Short>();  

      if (BOUNDS((int)cur.stack[cur.numArgs + 0], 2)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      if (ComputePointDisplacement(dx_ref, dy_ref, zp_ref, short_ref)) {
        return;
      }
      dx = dx_ref.Get();
      dy = dy_ref.Get();
      zp = zp_ref.Get();
      ref = short_ref.Get();
      /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.     */
      /*      Twilight zone has no real contours, so use `n_points'. */
      /*      Normal zone's `n_points' includes phantoms, so must    */
      /*      use end of last contour.                               */
      if (cur.GS.gep2 == 0) {
        limit = (short)cur.zp2.n_points;
      } else {
        if (cur.GS.gep2 == 1 && cur.zp2.n_contours > 0) {
          limit = (short)(cur.zp2.contours[cur.zp2.n_contours - 1] + 1);
        } else {
          limit = 0;
        }
      }
      /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
      for (i = 0; i < limit; i++) {
        if (zp.cur != cur.zp2.cur || ref != i) {
          MoveZp2Point((short)i, dx, dy, false);
        }
      }
    }

    /* =====================================================================
     *
     * SHPIX[]:      SHift points by a PIXel amount
     * Opcode range: 0x38
     * Stack:        f26.6 uint32... -->
     *
     * =====================================================================
     */
    static void insSHPIX() {
      Long dx;
      Long dy;
      Short point;

      if (cur.top < cur.GS.loop + 1) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
      dx = TT_MulFix14((long)cur.stack[cur.numArgs + 0], (long)cur.GS.freeVector.x);
      dy = TT_MulFix14((long)cur.stack[cur.numArgs + 0], (long)cur.GS.freeVector.y);
      while (cur.GS.loop > 0) {
        cur.numArgs--;
        point = (short)cur.stack[cur.numArgs];
        if (BOUNDS((int)point, (int)cur.zp2.n_points)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
        } else {
          MoveZp2Point(point, dx, dy, true);
        }
        cur.GS.loop--;
      }
      cur.GS.loop = 1;
      cur.new_top = cur.numArgs;
    }

    /* =====================================================================
     *
     * MSIRP[a]:     Move Stack Indirect Relative Position
     * Opcode range: 0x3A-0x3B
     * Stack:        f26.6 uint32 -->
     *
     * =====================================================================
     */
    static void insMSIRP() {
      Short point;
      Long distance;

      point = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)point, (int)cur.zp1.n_points) || BOUNDS((int)cur.GS.rp0, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      /* UNDOCUMENTED!  The MS rasterizer does that with */
      /* twilight points (confirmed by Greg Hitchcock)   */
      if (cur.GS.gep1 == 0) {
        cur.zp1.org[cur.zp1.org_idx + point] = cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0];
        cur.func_move_orig.callClassMethod(cur.zp1, point, (long)cur.stack[cur.numArgs + 1]);
        cur.zp1.cur[cur.zp1.cur_idx + point] = cur.zp1.org[cur.zp1.org_idx + point];
      }
      distance = (long)cur.func_project.callClassMethod(cur.zp1.cur[cur.zp1.cur_idx + point].x - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].x,
              cur.zp1.cur[cur.zp1.cur_idx + point].y - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].y);
      cur.func_move.callClassMethod(cur.zp1, point, (long)(cur.stack[cur.numArgs + 1] - distance));
      cur.GS.rp1 = cur.GS.rp0;
      cur.GS.rp2 = point;
      if ((cur.opcode & 1) != 0) {
        cur.GS.rp0 = point;
      }
    }

    /* =====================================================================
     *
     * MDAP[a]:      Move Direct Absolute Point
     * Opcode range: 0x2E-0x2F
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    static void insMDAP() {
      Short  point;
      long cur_dist;
      long distance;

Debug(0, DBG_INTERP, TAG, String.format("insMDAP: cur.GS.gep0: %d, cur.GS.gep1: %d", cur.GS.gep0, cur.GS.gep1));
      point = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)point, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      if ((cur.opcode & 1) != 0) {
        cur_dist = ((Long)cur.func_project.callClassMethod(cur.zp0.cur[cur.zp0.cur_idx + point].x,
                cur.zp0.cur[cur.zp0.cur_idx + point].y));
        distance = (((Long)cur.func_round.callClassMethod(cur_dist, (long)cur.tt_metrics.compensations[0])) - cur_dist);
Debug(0, DBG_INTERP, TAG, String.format("cur_dist: %d, distance: %d comp: %d \n", cur_dist, distance, cur.tt_metrics.compensations[0]));
      } else {
        distance = 0;
      }
      cur.func_move.callClassMethod(cur.zp0, (short)point, distance);
      cur.GS.rp0 = point;
      cur.GS.rp1 = point;
Debug(0, DBG_INTERP, TAG, String.format("insMDAP end: point: %d distance: %d, cur.GS.rp0: %d, cur.GS.rp1: %d\n", point, distance, cur.GS.rp0, cur.GS.rp1));
    }

    /* =====================================================================
     *
     * MIAP[a]:      Move Indirect Absolute Point
     * Opcode range: 0x3E-0x3F
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    static void insMIAP() {
      Long cvtEntry;
      Short point;
      int distance;
      int org_dist;
      Long control_value_cutin;

      control_value_cutin = (long)cur.GS.control_value_cutin;
      cvtEntry = (long)cur.stack[cur.numArgs + 1];
      point = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)point, (int)cur.zp0.n_points) || BOUNDSL((long)cvtEntry, (long)cur.cvtSize)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.rp0 = point;
        cur.GS.rp1 = point;
        return;
      }
      /* UNDOCUMENTED!                                                      */
      /*                                                                    */
      /* The behaviour of an MIAP instruction is quite different when used  */
      /* in the twilight zone.                                              */
      /*                                                                    */
      /* First, no control value cut-in test is performed as it would fail  */
      /* anyway.  Second, the original point, i.e. (org_x,org_y) of         */
      /* zp0.point, is set to the absolute, unrounded distance found in the */
      /* CVT.                                                               */
      /*                                                                    */
      /* This is used in the CVT programs of the Microsoft fonts Arial,     */
      /* Times, etc., in order to re-adjust some key font heights.  It      */
      /* allows the use of the IP instruction in the twilight zone, which   */
      /* otherwise would be invalid according to the specification.         */
      /*                                                                    */
      /* We implement it with a special sequence for the twilight zone.     */
      /* This is a bad hack, but it seems to work.                          */
      /*                                                                    */
      /* Confirmed by Greg Hitchcock.                                       */
      distance = (int)cur.func_read_cvt.callClassMethod(cvtEntry.intValue(), 0);
      if (cur.GS.gep0 == 0) {  /* If in twilight zone */
        cur.zp0.org[cur.zp0.org_idx + point].x = (TT_MulFix14((long)distance, cur.GS.freeVector.x));
        cur.zp0.org[cur.zp0.org_idx + point].y = (TT_MulFix14((long)distance, cur.GS.freeVector.y));
        cur.zp0.cur[cur.zp0.cur_idx + point] = cur.zp0.org[cur.zp0.org_idx + point];
      }
      org_dist = (int)cur.func_project.callClassMethod(cur.zp0.cur[cur.zp0.cur_idx + point].x - cur.zp0.cur[cur.zp0.cur_idx + point].x,
              cur.zp0.cur[cur.zp0.cur_idx + point].y - cur.zp0.cur[cur.zp0.cur_idx + point].y);
      if ((cur.opcode & 1) != 0) {  /* rounding and control cut-in flag */
        if (FTCalc.FT_ABS((long)(distance - org_dist)) > control_value_cutin) {
          distance = org_dist;
        }
        distance = (int)cur.func_round.callClassMethod(distance, cur.tt_metrics.compensations[0]);
      }
      cur.func_move.callClassMethod(cur.zp0, point, distance - org_dist);
      cur.GS.rp0 = point;
      cur.GS.rp1 = point;
    }

    /* =====================================================================
     *
     * MDRP[abcde]:  Move Direct Relative Point
     * Opcode range: 0xC0-0xDF
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    static void insMDRP() {
      short point;
      long org_dist;
      long distance;
      long minimum_distance;

Debug(0, DBG_INTERP, TAG, String.format("insMDRP: cur.GS.gep0: %d, cur.GS.gep1: %d", cur.GS.gep0, cur.GS.gep1));
      minimum_distance = cur.GS.minimum_distance;
      point = (short)cur.stack[cur.numArgs + 0];
Debug(0, DBG_INTERP, TAG, String.format("insMDRP: minimum_distance: %d point: %d rp0: %d",  minimum_distance, point, cur.GS.rp0));
      if (BOUNDS((int)point, (int)cur.zp1.n_points ) || BOUNDS((int)cur.GS.rp0, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.rp1 = cur.GS.rp0;
        cur.GS.rp2 = point;
        if ((cur.opcode & 16) != 0) {
          cur.GS.rp0 = point;
        }
        return;
      }
      /* XXX: Is there some undocumented feature while in the */
      /*      twilight zone?                                  */
      /* XXX: UNDOCUMENTED: twilight zone special case */
Debug(0, DBG_INTERP, TAG, String.format("cur.GS.gep0: %d, cur.GS.gep1: %d\n", cur.GS.gep0, cur.GS.gep1));
      if (cur.GS.gep0 == 0 || cur.GS.gep1 == 0) {
        FTVectorRec vec1 = cur.zp1.org[cur.zp1.org_idx + point];
        FTVectorRec vec2 = cur.zp0.org[cur.zp1.org_idx + cur.GS.rp0];

        org_dist = (long)cur.func_dualproj.callClassMethod(vec1.x - vec2.x, vec1.y - vec2.y);
      } else {
        FTVectorRec vec1 = cur.zp1.orus[cur.zp1.orus_idx + point];
        FTVectorRec vec2 = cur.zp0.orus[cur.zp1.orus_idx + cur.GS.rp0];

Debug(0, DBG_INTERP, TAG, String.format("vec1: %d %d, vec2: %d %d\n", vec1.x, vec1.y, vec2.x, vec2.y));
Debug(0, DBG_INTERP, TAG, String.format("x_scale: %d y_scale: %d", cur.metrics.x_scale, cur.metrics.y_scale));
        if (cur.metrics.x_scale == cur.metrics.y_scale) {
          /* this should be faster */
          org_dist = (long)cur.func_dualproj.callClassMethod(vec1.x - vec2.x, vec1.y - vec2.y);
Debug(0, DBG_INTERP, TAG, String.format("d1: %d", org_dist));
          org_dist = FT_MulFix(org_dist, cur.metrics.x_scale);
Debug(0, DBG_INTERP, TAG, String.format("d2: %d", org_dist));
        } else {
          FTVectorRec vec = new FTVectorRec();

          vec.x = FT_MulFix(vec1.x - vec2.x, cur.metrics.x_scale);
          vec.y = FT_MulFix(vec1.y - vec2.y, cur.metrics.y_scale);
          org_dist = (long)cur.func_dualproj.callClassMethod(vec.x, vec.y);
        }
      }
Debug(0, DBG_INTERP, TAG, "org_dist1: "+org_dist);
      /* single width cut-in test */
      if (FTCalc.FT_ABS(org_dist - cur.GS.single_width_value) < cur.GS.single_width_cutin) {
        if (org_dist >= 0) {
          org_dist = (long)cur.GS.single_width_value;
        } else {
          org_dist = -(long)cur.GS.single_width_value;
        }
      }
Debug(0, DBG_INTERP, TAG, "org_dist2: "+org_dist);
      /* round flag */
      if ((cur.opcode & 4) != 0) {
        distance = (long)cur.func_round.callClassMethod(org_dist, (long)(cur.tt_metrics.compensations[cur.opcode & 3]));
      } else {
        distance = RoundNone(org_dist, (long)(cur.tt_metrics.compensations[cur.opcode & 3])).intValue();
      }
Debug(0, DBG_INTERP, TAG, "distance1: "+distance);
      /* minimum distance flag */
      if ((cur.opcode & 8) != 0) {
        if (org_dist >= 0) {
          if (distance < minimum_distance) {
            distance = minimum_distance;
          }
        } else {
          if (distance > -minimum_distance) {
            distance = -minimum_distance;
          }
        }
      }
Debug(0, DBG_INTERP, TAG, "distance2: "+distance);
Debug(0, DBG_INTERP, TAG, String.format("insMDRP 3: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.gep0: %d, cur.GS.gep1: %d", cur.GS.rp0, cur.GS.rp1, cur.GS.gep0, cur.GS.gep1));
      /* now move the point */
      org_dist = (long)cur.func_project.callClassMethod(cur.zp1.cur[cur.zp1.cur_idx + point].x - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].x,
              cur.zp1.cur[cur.zp1.cur_idx + point].y - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].y);
Debug(0, DBG_INTERP, TAG, "org_dist3: "+org_dist);
      cur.func_move.callClassMethod(cur.zp1 , point,(long)(distance - org_dist));

Debug(0, DBG_INTERP, TAG, String.format("insMDRP 5: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.rp2: %d", cur.GS.rp0, cur.GS.rp1, cur.GS.rp2));
      cur.GS.rp1 = cur.GS.rp0;
      cur.GS.rp2 = point;
Debug(0, DBG_INTERP, TAG, String.format("insMDRP 6: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.rp2: %d opcode: 0x%04x", cur.GS.rp0, cur.GS.rp1, cur.GS.rp2, cur.opcode));
      if ((cur.opcode & 16) != 0) {
Debug(0, DBG_INTERP, TAG, String.format("insMDRP 7: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.rp2: %d", cur.GS.rp0, cur.GS.rp1, cur.GS.rp2));
        cur.GS.rp0 = point;
      }
Debug(0, DBG_INTERP, TAG, String.format("insMDRP end: cur.GS.rp0: %d, cur.GS.rp1: %d", cur.GS.rp0, cur.GS.rp1));
    }

    /* =====================================================================
     *
     * MIRP[abcde]:  Move Indirect Relative Point
     * Opcode range: 0xE0-0xFF
     * Stack:        int32? uint32 -->
     *
     * =====================================================================
     */
    static void insMIRP() {
      short point;
      long cvtEntry;
      long cvt_dist;
      long distance;
      long cur_dist;
      long org_dist;
      int control_value_cutin;
      long minimum_distance;

Debug(0, DBG_INTERP, TAG, String.format("Ins_MIRP: cur.GS.rp0: %d, cur.GS.rp1: %d", cur.GS.rp0, cur.GS.rp1));
      minimum_distance = cur.GS.minimum_distance;
      control_value_cutin = cur.GS.control_value_cutin;
      point = (short)cur.stack[cur.numArgs + 0];
      cvtEntry = (long)(cur.stack[cur.numArgs + 1] + 1);
Debug(0, DBG_INTERP, TAG, String.format("Ins_MIRP: minimum_distance: %d, control_value_cutin: %d, point: %d, cvtEntry: %d", minimum_distance, control_value_cutin, point, cvtEntry));
      /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
      if (BOUNDS((int)point, (int)cur.zp1.n_points) ||
           BOUNDSL((long)cvtEntry, (long)cur.cvtSize + 1) ||
           BOUNDS((int)cur.GS.rp0, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.rp1 = cur.GS.rp0;
        if ((cur.opcode & 16) != 0) {
          cur.GS.rp0 = point;
        }
        cur.GS.rp2 = point;
        return;
      }
      if (cvtEntry == 0) {
        cvt_dist = 0L;
      } else {
        cvt_dist = (long)((int)cur.func_read_cvt.callClassMethod((int)(cvtEntry - 1), 0));
      }
Debug(0, DBG_INTERP, TAG, String.format("cvtEntry: %d, cvt_dist: %d", cvtEntry, cvt_dist));
      /* single width test */
      if (FTCalc.FT_ABS(cvt_dist - cur.GS.single_width_value) < cur.GS.single_width_cutin) {
        if (cvt_dist >= 0) {
          cvt_dist = (long)cur.GS.single_width_value;
        } else {
          cvt_dist = -(long)cur.GS.single_width_value;
        }
      }
Debug(0, DBG_INTERP, TAG, String.format("cvt_dist: %d, cur.GS.gep0: %d, cur.GS.gep1: %d", cvt_dist, cur.GS.gep0, cur.GS.gep1));
      /* UNDOCUMENTED!  The MS rasterizer does that with */
      /* twilight points (confirmed by Greg Hitchcock)   */
      if (cur.GS.gep1 == 0) {
        cur.zp1.org[cur.zp1.org_idx + point].x = (cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].x + TT_MulFix14(cvt_dist, cur.GS.freeVector.x));
        cur.zp1.org[cur.zp1.org_idx + point].y = (cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].y + TT_MulFix14(cvt_dist, cur.GS.freeVector.y));
        cur.zp1.cur[cur.zp1.cur_idx + point] = cur.zp1.org[cur.zp1.org_idx + point];
      }
Debug(0, DBG_INTERP, TAG, String.format("dualproj: point: %d, GS.rp0: %d, zp1.org[point].x: %d, zp1.org[point].y: %d, zp0.org[GS.rp0].x: %d, zp0.org[GS.rp0].y: %d", point, cur.GS.rp0, cur.zp1.org[cur.zp1.org_idx + point].x, cur.zp1.org[cur.zp1.org_idx + point].y, cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].x, cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].y));
      org_dist = (long)cur.func_dualproj.callClassMethod(cur.zp1.org[cur.zp1.org_idx + point].x - cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].x,
              cur.zp1.org[cur.zp1.org_idx + point].y - cur.zp0.org[cur.zp0.org_idx + cur.GS.rp0].y);
      cur_dist = (long)cur.func_project.callClassMethod(cur.zp1.cur[cur.zp1.cur_idx + point].x - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].x,
              cur.zp1.cur[cur.zp1.cur_idx + point].y - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].y);
      /* auto-flip test */
      if (cur.GS.auto_flip) {
        if ((org_dist ^ cvt_dist) < 0) {
          cvt_dist = -cvt_dist;
        }
      }
      /* control value cut-in and round */
      if ((cur.opcode & 4) != 0) {
        /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
        /*      refer to the same zone.                                  */
        if (cur.GS.gep0 == cur.GS.gep1) {
          /* XXX: According to Greg Hitchcock, the following wording is */
          /*      the right one:                                        */
          /*                                                            */
          /*        When the absolute difference between the value in   */
          /*        the table [CVT] and the measurement directly from   */
          /*        the outline is _greater_ than the cut_in value, the */
          /*        outline measurement is used.                        */
          /*                                                            */
          /*      This is from `instgly.doc'.  The description in       */
          /*      `ttinst2.doc', version 1.66, is thus incorrect since  */
          /*      it implies `>=' instead of `>'.                       */
          if (FTCalc.FT_ABS(cvt_dist - org_dist) > control_value_cutin) {
            cvt_dist = (long)org_dist;
          }
        }
        distance = (long)cur.func_round.callClassMethod(cvt_dist, (long)cur.tt_metrics.compensations[cur.opcode & 3]);
      } else {
        distance = RoundNone(cvt_dist, (long)(cur.tt_metrics.compensations[cur.opcode & 3])).intValue();
      }
      /* minimum distance test */
      if ((cur.opcode & 8) != 0) {
        if (org_dist >= 0) {
          if (distance < minimum_distance) {
            distance = minimum_distance;
          }
        } else {
          if (distance > -minimum_distance) {
            distance = -minimum_distance;
          }
        }
      }
      cur.func_move.callClassMethod(cur.zp1, point, (long)(distance - cur_dist));
      cur.GS.rp1 = cur.GS.rp0;
      if ((cur.opcode & 16) != 0) {
        cur.GS.rp0 = point;
      }
      cur.GS.rp2 = point;
    }

    /* =====================================================================
     *
     * ALIGNRP[]:    ALIGN Relative Point
     * Opcode range: 0x3C
     * Stack:        uint32 uint32... -->
     *
     * =====================================================================
     */
    static void insALIGNRP() {
      short point;
      long  distance;

      if (cur.top < cur.GS.loop || BOUNDS((int)cur.GS.rp0, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
      while (cur.GS.loop > 0) {
        cur.numArgs--;
        point = (short)cur.stack[cur.numArgs];
        if (BOUNDS((int)point, (int)cur.zp1.n_points)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
        } else {
          distance = (long)cur.func_project.callClassMethod(cur.zp1.cur[cur.zp1.cur_idx + point].x - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].x,
                  cur.zp1.cur[cur.zp1.cur_idx + point].y - cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].y);
Debug(0, DBG_INTERP, TAG, String.format("distance: %d, zp1.cur[point].x: %d, zp1.cur[point].x: %d, zp0.cur[rp0].x: %d, zp0.cur[rp0].y: %d", distance, cur.zp1.cur[cur.zp1.cur_idx + point].x, cur.zp1.cur[cur.zp1.cur_idx + point].y, cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].x, cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp0].y));
          cur.func_move.callClassMethod(cur.zp1, point, -distance);
        }
        cur.GS.loop--;
      }
      cur.GS.loop = 1;
      cur.new_top = cur.numArgs;
    }

    /* =====================================================================
     *
     * ISECT[]:      moves point to InterSECTion
     * Opcode range: 0x0F
     * Stack:        5 * uint32 -->
     *
     * =====================================================================
     */
    static void insISECT() {
      Short point;
      Short a0;
      Short a1;
      Short b0;
      Short b1;
      Long discriminant;
      Long dotproduct;

      int dx;
      int dy;
      int dax;
      int day;
      int dbx;
      int dby;
      Long val;
      FTVectorRec R = new FTVectorRec();

      point = (short)cur.stack[cur.numArgs + 0];
      a0 = (short)cur.stack[cur.numArgs + 1];
      a1 = (short)cur.stack[cur.numArgs + 2];
      b0 = (short)cur.stack[cur.numArgs + 3];
      b1 = (short)cur.stack[cur.numArgs + 4];

      if (BOUNDS((int)b0, (int)cur.zp0.n_points) ||
           BOUNDS((int)b1, (int)cur.zp0.n_points) ||
           BOUNDS((int)a0, (int)cur.zp1.n_points) ||
           BOUNDS((int)a1, (int)cur.zp1.n_points) ||
           BOUNDS((int)point, (int)cur.zp2.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
	}
        return;
      }
      /* Cramer's rule */
      dbx = (int)(cur.zp0.cur[cur.zp0.cur_idx + b1].x - cur.zp0.cur[cur.zp0.cur_idx + b0].x);
      dby = (int)(cur.zp0.cur[cur.zp0.cur_idx + b1].y - cur.zp0.cur[cur.zp0.cur_idx + b0].y);
      dax = (int)(cur.zp1.cur[cur.zp1.cur_idx + a1].x - cur.zp1.cur[cur.zp1.cur_idx + a0].x);
      day = (int)(cur.zp1.cur[cur.zp1.cur_idx + a1].y - cur.zp1.cur[cur.zp1.cur_idx + a0].y);
      dx = (int)(cur.zp0.cur[cur.zp0.cur_idx + b0].x - cur.zp1.cur[cur.zp1.cur_idx + a0].x);
      dy = (int)(cur.zp0.cur[cur.zp0.cur_idx + b0].y - cur.zp1.cur[cur.zp1.cur_idx + a0].y);
      cur.zp2.tags[point] |= (FT_CURVE_TAG_TOUCH_X | FT_CURVE_TAG_TOUCH_Y);
      discriminant = FTCalc.FT_MulDiv((long)dax, -(long)dby, 0x40L) + FTCalc.FT_MulDiv((long)day, (long)dbx, 0x40L);
      dotproduct = FTCalc.FT_MulDiv((long)dax, (long)dbx, 0x40L) + FTCalc.FT_MulDiv((long)day, (long)dby, 0x40L);
      /* The discriminant above is actually a cross product of vectors     */
      /* da and db. Together with the dot product, they can be used as     */
      /* surrogates for sine and cosine of the angle between the vectors.  */
      /* Indeed,                                                           */
      /*       dotproduct   = |da||db|cos(angle)                           */
      /*       discriminant = |da||db|sin(angle)     .                     */
      /* We use these equations to reject grazing intersections by         */
      /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
      if (19 * FTCalc.FT_ABS(discriminant) > FTCalc.FT_ABS(dotproduct)) {
        val = FTCalc.FT_MulDiv((long)dx, -(long)dby, 0x40L) + FTCalc.FT_MulDiv((long)dy, (long)dbx, 0x40L);
        R.x = FTCalc.FT_MulDiv(val, (long)dax, discriminant);
        R.y = FTCalc.FT_MulDiv(val, (long)day, discriminant);
        cur.zp2.cur[cur.zp2.cur_idx + point].x = (cur.zp1.cur[cur.zp1.cur_idx + a0].x + R.x);
        cur.zp2.cur[cur.zp2.cur_idx + point].y = (cur.zp1.cur[cur.zp1.cur_idx + a0].y + R.y);
      } else {
        /* else, take the middle of the middles of A and B */
        cur.zp2.cur[cur.zp2.cur_idx + point].x = ((cur.zp1.cur[cur.zp1.cur_idx + a0].x + cur.zp1.cur[cur.zp1.cur_idx + a1].x +
                                 cur.zp0.cur[cur.zp0.cur_idx + b0].x + cur.zp0.cur[cur.zp0.cur_idx + b1].x) / 4);
        cur.zp2.cur[cur.zp2.cur_idx + point].y = ((cur.zp1.cur[cur.zp1.cur_idx + a0].y + cur.zp1.cur[cur.zp1.cur_idx + a1].y +
                                 cur.zp0.cur[cur.zp0.cur_idx + b0].y + cur.zp0.cur[cur.zp0.cur_idx + b1].y) / 4);
      }
    }

    /* =====================================================================
     *
     * ALIGNPTS[]:   ALIGN PoinTS
     * Opcode range: 0x27
     * Stack:        uint32 uint32 -->
     *
     * =====================================================================
     */
    static void insALIGNPTS() {
      short p1;
      short p2;
      long distance;

      p1 = (short)cur.stack[cur.numArgs + 0];
      p2 = (short)cur.stack[cur.numArgs + 1];
      if (BOUNDS((int)p1, (int)cur.zp1.n_points) || BOUNDS((int)p2, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
	}
        return;
      }
      distance = (int)cur.func_project.callClassMethod(cur.zp0.cur[cur.zp0.cur_idx + p2].x - cur.zp1.cur[cur.zp1.cur_idx + p1].x,
              cur.zp0.cur[cur.zp0.cur_idx + p2].y - cur.zp1.cur[cur.zp1.cur_idx + p1].y) / 2;
      cur.func_move.callClassMethod(cur.zp1, p1, distance);
      cur.func_move.callClassMethod(cur.zp0, p2, -distance);
    }

    /* =====================================================================
     *
     * IP[]:         Interpolate Point
     * Opcode range: 0x39
     * Stack:        uint32... -->
     *
     * SOMETIMES, DUMBER CODE IS BETTER CODE
     * =====================================================================
     */
    static void insIP() {
      long old_range;
      long cur_range;
      FTVectorRec orus_base;
      FTVectorRec cur_base;
      boolean twilight;

      if (cur.top < cur.GS.loop) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
      /*
       * We need to deal in a special way with the twilight zone.
       * Otherwise, by definition, the value of cur.twilight.orus[n] is (0,0),
       * for every n.
       */
      twilight = cur.GS.gep0 == 0 || cur.GS.gep1 == 0 || cur.GS.gep2 == 0;

      if (BOUNDS((int)cur.GS.rp1, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        cur.GS.loop = 1;
        cur.new_top = cur.numArgs;
        return;
      }
Debug(0, DBG_INTERP, TAG, String.format("twilight: %b, rp1: %d", twilight, cur.GS.rp1));
      if (twilight) {
        orus_base = cur.zp0.org[cur.zp0.org_idx + cur.GS.rp1];
      } else {
        orus_base = cur.zp0.orus[cur.zp0.orus_idx + cur.GS.rp1];
Debug(0, DBG_INTERP, TAG, String.format("orus.x: %d, orus.y: %d", orus_base.x,orus_base.y));
Debug(0, DBG_INTERP, TAG, String.format("orus2.x: %d, orus2.y: %d", cur.zp0.orus[cur.zp0.orus_idx + 1].x, cur.zp0.orus[cur.zp0.orus_idx + 1].y));
      }
      cur_base = cur.zp0.cur[cur.zp0.cur_idx + cur.GS.rp1];
      /* XXX: There are some glyphs in some braindead but popular */
      /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
      /*      calling IP[] with bad values of rp[12].             */
      /*      Do something sane when this odd thing happens.      */
      if (BOUNDS((int)cur.GS.rp1, (int)cur.zp0.n_points) || BOUNDS((int)cur.GS.rp2, (int)cur.zp1.n_points)) {
        old_range = 0;
        cur_range = 0;
      } else {
        if (twilight) {
          old_range = (long)cur.func_dualproj.callClassMethod(cur.zp1.org[cur.zp1.org_idx + cur.GS.rp2].x - orus_base.x,
                  cur.zp1.org[cur.zp1.org_idx + cur.GS.rp2].y - orus_base.y);
        } else {
        System.out.println(String.format("x_scale: %d,  y_scale:%d", cur.metrics.x_scale, cur.metrics.y_scale));
          if (cur.metrics.x_scale == cur.metrics.y_scale) {
Debug(0, DBG_INTERP, TAG, String.format("rp2: %d, zp1.orus.x: %d, x: %d, zp1.orus.y: %d, y: %d", cur.GS.rp2, cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].x, orus_base.x,
cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].y, orus_base.y));            
            old_range = (long)cur.func_dualproj.callClassMethod(cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].x - orus_base.x,
                    cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].y - orus_base.y);
Debug(0, DBG_INTERP, TAG, String.format("old_range: %d, rp2.x: %d, rp2.y: %d, orus.x: %d, orus.y: %d", old_range, cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].x, cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].y, orus_base.x, orus_base.y));
          } else {
            FTVectorRec vec = new FTVectorRec();

            vec.x = FT_MulFix(cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].x - orus_base.x, cur.metrics.x_scale);
            vec.y = FT_MulFix(cur.zp1.orus[cur.zp1.orus_idx + cur.GS.rp2].y - orus_base.y, cur.metrics.y_scale);
            old_range = (int)cur.func_dualproj.callClassMethod(vec.x, vec.y);
          }
        }
        cur_range = (long)cur.func_project.callClassMethod(cur.zp1.cur[cur.zp1.cur_idx + cur.GS.rp2].x - cur_base.x,
                cur.zp1.cur[cur.zp1.cur_idx + cur.GS.rp2].y - cur_base.y);
      }
Debug(0, DBG_INTERP, TAG, String.format("old_range:%d cur_range: %d", old_range, cur_range));
      for (; cur.GS.loop > 0; --cur.GS.loop) {
        short point = (short)cur.stack[--cur.numArgs];
        long org_dist;
        long cur_dist;
        long new_dist;

        /* check point bounds */
        if (BOUNDS((int)point, (int)cur.zp2.n_points)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
          continue;
        }
        if (twilight) {
          org_dist = (long)cur.func_dualproj.callClassMethod(cur.zp2.org[cur.zp2.org_idx + point].x - orus_base.x,
                  cur.zp2.org[cur.zp2.org_idx + point].y - orus_base.y);
        } else {
       	  if (cur.metrics.x_scale == cur.metrics.y_scale) {
            org_dist = (long)cur.func_dualproj.callClassMethod(cur.zp2.orus[cur.zp2.orus_idx + point].x - orus_base.x,
                    cur.zp2.orus[cur.zp2.orus_idx + point].y - orus_base.y);
          } else {
            FTVectorRec vec = new FTVectorRec();

            vec.x = FT_MulFix(cur.zp2.orus[cur.zp2.orus_idx + point].x - orus_base.x,
                               cur.metrics.x_scale);
            vec.y = FT_MulFix( cur.zp2.orus[cur.zp2.orus_idx + point].y - orus_base.y,
                               cur.metrics.y_scale);
            org_dist = (long)cur.func_dualproj.callClassMethod(vec.x, vec.y);
          }
        }
        cur_dist = (long)cur.func_project.callClassMethod(cur.zp2.cur[cur.zp2.cur_idx + point].x - cur_base.x,
                cur.zp2.cur[cur.zp2.cur_idx + point].y - cur_base.y);
        if (org_dist != 0) {
          if (old_range != 0) {
            new_dist = FTCalc.FT_MulDiv((long)org_dist, (long)cur_range, (long)old_range);
          } else {
            /* This is the same as what MS does for the invalid case:  */
            /*                                                         */
            /*   delta = (Original_Pt - Original_RP1) -                */
            /*           (Current_Pt - Current_RP1)                    */
            /*                                                         */
            /* In FreeType speak:                                      */
            /*                                                         */
            /*   new_dist = cur_dist -                                 */
            /*              org_dist - cur_dist;                       */
            new_dist = -org_dist;
          }
        } else {
          new_dist = 0;
        }
        cur.func_move.callClassMethod(cur.zp2, point, new_dist - cur_dist);
      }
      cur.GS.loop = 1;
      cur.new_top = cur.numArgs;
    }

    /* =====================================================================
     *
     * UTP[a]:       UnTouch Point
     * Opcode range: 0x29
     * Stack:        uint32 -->
     *
     * =====================================================================
     */
    static void insUTP() {
      Short point;
      byte mask;

      point = (short)cur.stack[cur.numArgs + 0];
      if (BOUNDS((int)point, (int)cur.zp0.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.INTERP_INVALID_REFERENCE;
        }
        return;
      }
      mask = (byte)0xFF;
      if (cur.GS.freeVector.x != 0) {
        mask &= ~FT_CURVE_TAG_TOUCH_X;
      }
      if (cur.GS.freeVector.y != 0) {
        mask &= ~FT_CURVE_TAG_TOUCH_Y;
      }
      cur.zp0.tags[point] &= mask;
    }

    /* ======================== insUNKNOWN ============================== */
    protected static void insUNKNOWN() {
      TTDefRec def = cur.IDefs[0];
      int limit = cur.numIDefs;
      int defIdx;

      for (defIdx = 0; defIdx < limit; defIdx++) {
        if (def.opc == cur.opcode && def.active) {
          TTCallRec call;

          if (cur.callTop >= cur.callSize) {
            cur.error = FTError.INTERP_STACK_OVERFLOW;
            return;
          }
          call = cur.callStack[cur.callTop++];
          call.CallerRange = cur.curRange;
          call.CallerIP = cur.IP + 1;
          call.CurCount = 1;
          call.CurRestart = def.start;
          call.CurEnd = def.end;
          insGotoCodeRange(def.range, (long)def.start);
          cur.step_ins = false;
          return;
        }
      }
      cur.error = FTError.INTERP_INVALID_OPCODE;
    }

    /* =====================================================================
     * _iup_worker_shift
     * =====================================================================
     */
    private static void _iup_worker_shift(FTReference<IUPWorkerRec> worker_ref, Integer p1, Integer p2, Integer p, boolean useX) {
      int i;
      long dx;
      IUPWorkerRec worker = worker_ref.Get();

      if (useX) {
        dx = worker.curs[worker.cur_idx + p].x - worker.orgs[worker.org_idx + p].x;
      } else {
        dx = worker.curs[worker.cur_idx + p].y - worker.orgs[worker.org_idx + p].y;        
      }
      if (dx != 0) {
        for (i = p1; i < p; i++) {
          if (useX) {
            worker.curs[worker.cur_idx + i].x = worker.curs[worker.cur_idx + i].x + dx;
          } else {
            worker.curs[worker.cur_idx + i].y = worker.curs[worker.cur_idx + i].y + dx;            
          }
        }
        for (i = p + 1; i <= p2; i++) {
          if (useX) {
            worker.curs[worker.cur_idx + i].x = worker.curs[worker.cur_idx + i].x + dx;
          } else {
            worker.curs[worker.cur_idx + i].y = worker.curs[worker.cur_idx + i].y + dx;            
          }
        }
      }
      worker_ref.Set(worker);
    }

    /* =====================================================================
     * _iup_worker_interpolate
     * =====================================================================
     */
    private static void _iup_worker_interpolate(FTReference<IUPWorkerRec> worker_ref, int p1, int p2,
           int ref1, int ref2, boolean useX) {
      IUPWorkerRec worker = worker_ref.Get();
      int i;
      long orus1;
      long orus2;
      long org1;
      long org2;
      long delta1;
      long delta2;

Debug(0, DBG_INTERP, TAG, String.format("_iup_worker_interpolate: p1: %d, p2: %d, ref1: %d ref2: %d", p1, p2, ref1, ref2));
      if (p1 > p2) {
        return;
      }
      if (BOUNDS((int)ref1, (int)worker.max_points) ||
           BOUNDS((int)ref2, (int)worker.max_points)) {
        return;
      }
      if (useX) {
        orus1 = worker.orus[worker.orus_idx + ref1].x;
        orus2 = worker.orus[worker.orus_idx + ref2].x;
      } else {
        orus1 = worker.orus[worker.orus_idx + ref1].y;
        orus2 = worker.orus[worker.orus_idx + ref2].y;        
      }
      if (orus1 > orus2) {
        long tmp_o;
        int tmp_r;

        tmp_o = orus1;
        orus1 = orus2;
        orus2 = tmp_o;
        tmp_r = ref1;
        ref1  = ref2;
        ref2  = tmp_r;
      }
      if (useX) {
        org1   = worker.orgs[worker.org_idx + ref1].x;
        org2   = worker.orgs[worker.org_idx + ref2].x;
        delta1 = worker.curs[worker.cur_idx + ref1].x - org1;
        delta2 = worker.curs[worker.org_idx + ref2].x - org2;
      } else {
        org1   = worker.orgs[worker.org_idx + ref1].y;
        org2   = worker.orgs[worker.org_idx + ref2].y;
        delta1 = worker.curs[worker.cur_idx + ref1].y - org1;
        delta2 = worker.curs[worker.org_idx + ref2].y - org2;
      }
Debug(0, DBG_INTERP, TAG, String.format("org1: %d,  org2: %d, delta1: %d, delta2: %d, orus1. %d, orus2: %d", org1, org2, delta1, delta2, orus1, orus2));
      if (orus1 == orus2) {
        /* simple shift of untouched points */
        for (i = p1; i <= p2; i++) {
          long x;

          if (useX) {
            x = worker.orgs[worker.org_idx + i].x;
          } else {
            x = worker.orgs[worker.org_idx + i].y;            
          }
          if (x <= org1) {
            x += delta1;
          } else {
            x += delta2;
          }
Debug(0, DBG_INTERP, TAG, String.format("i: %d curs[i].x: %d x: %d",  i, useX ? worker.curs[worker.cur_idx + i].x : worker.curs[worker.cur_idx + i].y, x));
          if (useX) {
            worker.curs[worker.cur_idx + i].x = x;
          } else {
            worker.curs[worker.cur_idx + i].y = x;            
          }
        }
      } else {
        long scale = 0L;
        boolean scale_valid = false;

Debug(0, DBG_INTERP, TAG, String.format("p1: %d, p2: %d", p1, p2));
        /* interpolation */
        for (i = p1; i <= p2; i++) {
          long x;

          if (useX) {
            x = worker.orgs[worker.org_idx + i].x;
          } else {
            x = worker.orgs[worker.org_idx + i].y;            
          }
Debug(0, DBG_INTERP, TAG, String.format("x: %d org1: %d, org2: %d, delta1: %d", x, org1, org2, delta1));
          if (x <= org1) {
            x += delta1;
          } else {
            if (x >= org2) {
              x += delta2;
            } else {
              if (!scale_valid) {
                scale_valid = true;
                scale = FTCalc.FTDivFix(org2 + delta2 - (org1 + delta1), orus2 - orus1);
              }
Debug(0, DBG_INTERP, TAG, String.format("scale: %d, org1: %d, delta1: %d, worker.orus[i].x: %d, orus1: %d", scale, org1, delta1, useX ?  worker.orus[worker.orus_idx + i].x :  worker.orus[worker.orus_idx + i].y, orus1));
              if (useX) {
                x = (org1 + delta1) + FT_MulFix(worker.orus[worker.orus_idx + i].x - orus1, scale);
              } else {
                x = (org1 + delta1) + FT_MulFix(worker.orus[worker.orus_idx + i].y - orus1, scale);              
              }
Debug(0, DBG_INTERP, TAG, String.format("x: %d", x));
            }
          }
          if (useX) {
            worker.curs[worker.cur_idx + i].x = x;
          } else {
            worker.curs[worker.cur_idx + i].y = x;            
          }
        }
      }
//FTGlyphLoaderRec._showLoaderZone("_iup_worker_interpolate end");
      worker_ref.Set(worker);
    }

    /* =====================================================================
     *
     * IUP[a]:       Interpolate Untouched Points
     * Opcode range: 0x30-0x31
     * Stack:        -->
     *
     * =====================================================================
     */
    protected static void insIUP() {
      IUPWorkerRec V = new IUPWorkerRec();
      FTReference<IUPWorkerRec> worker_ref;
      byte mask;
      int first_point;   /* first point of contour        */
      int end_point;     /* end point (last+1) of contour */
      int first_touched; /* first touched point in contour   */
      int cur_touched;   /* current touched point in contour */
      int point;         /* current point   */
      short contour;     /* current contour */
      boolean useX = true;

Debug(0, DBG_INTERP, TAG, "insIUP");
      /* ignore empty outlines */
      if (cur.pts.n_contours == 0) {
        return;
      }
//FTGlyphLoaderRec._showLoaderZone("insIUP");
      if ((cur.opcode & 1) != 0) {
        useX = true;
        mask = FT_CURVE_TAG_TOUCH_X;
        V.orgs = cur.pts.org;
        V.org_idx = cur.pts.org_idx + 0;
        V.curs = cur.pts.cur;
        V.cur_idx = cur.pts.cur_idx + 0;
        V.orus = cur.pts.orus;
        V.orus_idx = cur.pts.orus_idx + 0;
      } else {
        useX = false;
        mask = FT_CURVE_TAG_TOUCH_Y;
        V.orgs = cur.pts.org;
//        V.org_idx = cur.pts.org_idx + 1;
        V.org_idx = cur.pts.org_idx + 0;
        V.curs = cur.pts.cur;
//        V.cur_idx = cur.pts.cur_idx + 1;
        V.cur_idx = cur.pts.cur_idx + 0;
        V.orus = cur.pts.orus;
//        V.orus_idx = cur.pts.orus_idx + 1;
        V.orus_idx = cur.pts.orus_idx + 0;
      }
      V.max_points = (int)cur.pts.n_points;
      contour = 0;
      point = 0;
      do {
        end_point = cur.pts.contours[contour] - cur.pts.first_point;
        first_point = point;
        if (BOUNDS((int)end_point, (int)cur.pts.n_points)) {
          end_point = cur.pts.n_points - 1;
        }
        while (point <= end_point && (cur.pts.tags[point] & mask) == 0) {
          point++;
        }
        worker_ref = new FTReference<IUPWorkerRec>();
        worker_ref.Set(V);
        if (point <= end_point) {
          first_touched = point;
          cur_touched   = point;
          point++;
          while (point <= end_point) {
            if ((cur.pts.tags[point] & mask) != 0) {
              _iup_worker_interpolate(worker_ref, cur_touched + 1, point - 1, cur_touched, point, useX);
              cur_touched = point;
            }
            point++;
          }
          if (cur_touched == first_touched) {
            _iup_worker_shift(worker_ref, first_point, end_point, cur_touched, useX);
          } else {
            _iup_worker_interpolate(worker_ref, (cur_touched + 1), end_point, 
                    cur_touched, first_touched, useX);
            if (first_touched > 0) {
              _iup_worker_interpolate(worker_ref, first_point, first_touched - 1,
                      cur_touched, first_touched, useX);
            }
          }
          V = worker_ref.Get();            
        }
        contour++;
      } while (contour < cur.pts.n_contours);
//FTGlyphLoaderRec._showLoaderZone("insIUP END");
    }

    /* =====================================================================
     *
     * DELTAPn[]:    DELTA exceptions P1, P2, P3
     * Opcode range: 0x5D,0x71,0x72
     * Stack:        uint32 (2 * uint32)... -->
     *
     * =====================================================================
     */
    protected static void insDELTAP() {
      Long k;
      Long nump;
      Short A;
      Long C;
      Long B;

Debug(0, DBG_INTERP, TAG, "insDELTAP");
      nump = (long)cur.stack[cur.numArgs + 0];   /* some points theoretically may occur more
                                     than once, thus UShort isn't enough */
      for (k = 1L; k <= nump; k++) {
        if (cur.numArgs < 2) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_TOO_FEW_ARGUMENTS;
          }
          cur.numArgs = 0;
          cur.new_top = cur.numArgs;
Debug(0, DBG_INTERP, TAG, "insDELTAP end 0");
          return;
        }
        cur.numArgs -= 2;
        A = (short)cur.stack[cur.numArgs + 1];
        B = cur.stack[cur.numArgs];
        /* XXX: Because some popular fonts contain some invalid DeltaP */
        /*      instructions, we simply ignore them when the stacked   */
        /*      point reference is off limit, rather than returning an */
        /*      error.  As a delta instruction doesn't change a glyph  */
        /*      in great ways, this shouldn't be a problem.            */
        if (!BOUNDS((int)A, (int)cur.zp0.n_points)) {
          C = ((long)B & 0xF0) >> 4;
          switch (cur.opcode) {
          case 0x5D:
            break;
          case 0x71:
            C += 16;
            break;
          case 0x72:
            C += 32;
            break;
          }
          C += cur.GS.delta_base;
          if (CurrentPpem() == (long)C) {
            B = ((long)B & 0xF) - 8;
            if (B >= 0) {
              B++;
            }
            B = B * 64 / (1L << cur.GS.delta_shift);
            cur.func_move.callClassMethod(cur.zp0, A.shortValue(), B.longValue());
          }
        } else {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
          }
        }
      }
Debug(0, DBG_INTERP, TAG, "insDELTAP end 1");
      cur.new_top = cur.numArgs;
Debug(0, DBG_INTERP, TAG, "insDELTAP end 2");
    }

    /* =====================================================================
     *
     * DELTACn[]:    DELTA exceptions C1, C2, C3
     * Opcode range: 0x73,0x74,0x75
     * Stack:        uint32 (2 * uint32)... -->
     *
     * =====================================================================
     */
    protected static void insDELTAC() {
      Long nump;
      Long k;
      Long A;
      Long C;
      Long B;

      nump = (long)cur.stack[cur.numArgs + 0];
      for (k = 1L; k <= nump; k++) {
        if (cur.numArgs < 2) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_TOO_FEW_ARGUMENTS;
          }
          cur.numArgs = 0;
          cur.new_top = cur.numArgs;
          return;
        }
        cur.numArgs -= 2;
        A = (long)cur.stack[cur.numArgs + 1];
        B = cur.stack[cur.numArgs];
        if (BOUNDSL(A, (long)cur.cvtSize)) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_INVALID_REFERENCE;
            return;
          }
        } else {
          C = ((long)B & 0xF0) >> 4;
          switch (cur.opcode) {
          case 0x73:
            break;
          case 0x74:
            C += 16;
            break;
          case 0x75:
            C += 32;
            break;
          }
          C += cur.GS.delta_base;
          if (CurrentPpem() == (long)C) {
            B = ((long)B & 0xF) - 8;
            if (B >= 0) {
              B++;
            }
            B = B * 64 / (1L << cur.GS.delta_shift);
            cur.func_move_cvt.callClassMethod(A.intValue(), B.intValue());
          }
        }
      }
      cur.new_top = cur.numArgs;
    }

    /* =====================================================================
     *
     * MISC. INSTRUCTIONS
     *
     * =====================================================================
     */

    /* =====================================================================
     *
     * GETINFO[]:    GET INFOrmation
     * Opcode range: 0x88
     * Stack:        uint32 --> uint32
     *
     * =====================================================================
     */
    protected static void insGETINFO() {
      Long K;

      K = 0L;
      if ((cur.stack[cur.numArgs + 0] & 1) != 0) {
          K = (long)TT_INTERPRETER_VERSION_35;
      }
      /********************************/
      /* GLYPH ROTATED                */
      /* Selector Bit:  1             */
      /* Return Bit(s): 8             */
      /*                              */
      if ((cur.stack[cur.numArgs + 0] & 2) != 0 && cur.tt_metrics.rotated) {
        K |= 0x80;
      }
      /********************************/
      /* GLYPH STRETCHED              */
      /* Selector Bit:  2             */
      /* Return Bit(s): 9             */
      /*                              */
      if ((cur.stack[cur.numArgs + 0] & 4) != 0 && cur.tt_metrics.stretched) {
        K |= 1 << 8;
      }
      /********************************/
      /* HINTING FOR GRAYSCALE        */
      /* Selector Bit:  5             */
      /* Return Bit(s): 12            */
      /*                              */
      if (((cur.stack[cur.numArgs + 0] & 32) != 0) && cur.grayscale) {
        K |= 1 << 12;
      }
      cur.stack[cur.numArgs + 0] = K.intValue();
    }
}

Added ftbase/TTInterpOpcodeFuncs1.java.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTInterpOpcodeFuncs1                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpOpcodeFuncs1 extends TTInterpBase {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTInterpOpcodeFuncs1";

    /* ==================== TTInterpOpcodeFuncs1 ================================== */
    public TTInterpOpcodeFuncs1() {
      super();
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* ===================================================================== */
    /* When not using the big switch statements, the interpreter uses a */
    /* call table defined later below in this source.  Each opcode must */
    /* thus have a corresponding function, even trivial ones.           */
    /*                                                                  */
    /* They are all defined there.                                      */
    /* ===================================================================== */

    /* ==================== Normalize =====================================
     * 
     * <Function>
     *    Normalize
     *
     * <Description>
     *    Norms a vector.
     *
     * <Input>
     *    Vx :: The horizontal input vector coordinate.
     *    Vy :: The vertical input vector coordinate.
     *
     * <Output>
     *    R  :: The normed unit vector.
     *
     * <Return>
     *    Returns FAILURE if a vector parameter is zero.
     *
     * <Note>
     *    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and
     *    R is undefined.
     * ====================================================================
     */
    public static boolean Normalize(Long Vx, Long Vy, FTReference<FTVectorRec>  R_ref) {
      Long  W;
      FTVectorRec R = R_ref.Get();

Debug(0, DBG_INTERP, TAG, String.format("Normalize: Vx: %d, vy: %d", Vx, Vy));
      if (FTCalc.FT_ABS(Vx) < 0x4000L && FTCalc.FT_ABS(Vy) < 0x4000L) {
        if (Vx == 0 && Vy == 0) {
          /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
          /*      to normalize the vector (0,0).  Return immediately. */
          return SUCCESS;
        }
        Vx *= 0x4000;
        Vy *= 0x4000;
Debug(0, DBG_INTERP, TAG, String.format("Normalize2: Vx: %d, vy: %d", Vx, Vy));
      }
Debug(0, DBG_INTERP, TAG, String.format("Normalize2: Vx: %d, vy: %d", Vx, Vy));
      W = FTCalc.FTHypot(Vx, Vy);
Debug(0, DBG_INTERP, TAG, String.format("W: %d 0x%x",  W, W));
      R.x = FTCalc.FTDivFix(Vx, W << 2);
      R.y = FTCalc.FTDivFix(Vy, W << 2);
Debug(0, DBG_INTERP, TAG, String.format("R.x: %d, R.y: %d", R.x, R.y));
      R_ref.Set(R);
      return SUCCESS;
    }

    /* ====================================================================
     * <Function>
     *    SetSuperRound
     *
     * <Description>
     *    Sets Super Round parameters.
     *
     * <Input>
     *    GridPeriod :: The grid period.
     *
     *    selector   :: The SROUND opcode.
     * ====================================================================
     */
    protected static void SetSuperRound(int GridPeriod, int selector) {
      switch (selector & 0xC0) {
      case 0:
        cur.period = GridPeriod / 2;
        break;
      case 0x40:
        cur.period = GridPeriod;
        break;
      case 0x80:
        cur.period = GridPeriod * 2;
        break;
      /* This opcode is reserved, but... */
      case 0xC0:
        cur.period = GridPeriod;
        break;
      }
      switch (selector & 0x30) {
      case 0:
        cur.phase = 0;
        break;
      case 0x10:
        cur.phase = cur.period / 4;
        break;
      case 0x20:
        cur.phase = cur.period / 2;
        break;
      case 0x30:
        cur.phase = cur.period * 3 / 4;
        break;
      }
      if ((selector & 0x0F) == 0) {
        cur.threshold = cur.period - 1;
      } else {
        cur.threshold = ((selector & 0x0F) - 4) * cur.period / 8;
      }
      cur.period    /= 256;
      cur.phase     /= 256;
      cur.threshold /= 256;
    }

    /* ==================== TT_MulFix14 ===================================== */
    protected static Long TT_MulFix14(Long a, Long b) {
      int   sign;
      Long ah;
      Long al;
      Long mid;
      Long lo;
      Long hi;

      sign = (int)(a ^ b);
      if (a < 0) {
        a = -a;
      }
      if (b < 0) {
        b = -b;
      }
      ah = (long)((a >> 16) & 0xFFFF);
      al = (long)(a & 0xFFFF);
      lo = al * b;
      mid = ah * b;
      hi = mid >> 16;
      mid = (mid << 16) + (1 << 13); /* rounding */
      lo += mid;
      if (lo < mid) {
        hi += 1;
      }
      mid = (long)((lo >> 14) | (hi << 18));
      return sign >= 0 ? mid : -mid;
    }

    /* ====================================================================
     * <Function>
     *    RoundNone
     *
     * <Description>
     *    Does not round, but adds engine compensation.
     *
     * <Input>
     *    distance     :: The distance (not) to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    The compensated distance.
     *
     * <Note>
     *    The TrueType specification says very few about the relationship
     *    between rounding and engine compensation.  However, it seems from
     *    the description of super round that we should add the compensation
     *    before rounding.
     * ====================================================================
     */
    protected static Long RoundNone(Long distance, Long compensation) {
      Long val;

      if (distance >= 0) {
        val = distance + compensation;
        if (distance != 0 && val < 0) {
          val = 0L;
        }
      } else {
        val = distance - compensation;
        if (val > 0) {
          val = 0L;
        }
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundToGrid
     *
     * <Description>
     *    Rounds value to grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    protected static Long RoundToGrid(Long distance, Long compensation) {
      Long val;

      if (distance >= 0) {
        val = distance + compensation + 32;
        if (distance != 0 && val > 0) {
          val &= ~63;
        } else {
          val = 0L;
        }
      } else {
        val = -FTCalc.FT_PIX_ROUND(compensation - distance);
        if (val > 0) {
          val = 0L;
        }
      }
      return  val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundToHalfGrid
     *
     * <Description>
     *    Rounds value to half grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    protected static Long RoundToHalfGrid(Long distance, Long compensation) {
      Long val;

      if (distance >= 0) {
        val = FTCalc.FT_PIX_FLOOR(distance + compensation) + 32;
        if (distance != 0 && val < 0) {
          val = 0L;
        }
      } else {
        val = -(FTCalc.FT_PIX_FLOOR(compensation - distance) + 32);
        if (val > 0) {
          val = 0L;
        }
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundDownToGrid
     *
     * <Description>
     *    Rounds value down to grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    protected static Long RoundDownToGrid(Long distance, Long compensation) {
      Long  val;

      if (distance >= 0) {
        val = distance + compensation;
        if (distance != 0 && val > 0) {
          val &= ~63;
        } else {
          val = 0L;
        }
      } else {
        val = -((compensation - distance) & -64);
        if (val > 0) {
          val = 0L;
        }
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundUpToGrid
     *
     * <Description>
     *    Rounds value up to grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    protected static Long RoundUpToGrid(Long distance, Long compensation) {
      Long  val;

      if (distance >= 0) {
        val = distance + compensation + 63;
        if (distance != 0 && val > 0) {
          val &= ~63;
        } else {
          val = 0L;
        }
      } else {
        val = -FTCalc.FT_PIX_CEIL(compensation - distance);
        if (val > 0) {
          val = 0L;
        }
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundToDoubleGrid
     *
     * <Description>
     *    Rounds value to double grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * =====================================================================
     */
    protected static Long RoundToDoubleGrid(Long distance, Long compensation) {
      Long val;

      if (distance >= 0) {
        val = distance + compensation + 16;
        if (distance != 0 && val > 0) {
          val &= ~31;
        } else {
          val = 0L;
        }
      } else {
        val = -FTCalc.FT_PAD_ROUND(compensation - distance, 32);
        if (val > 0) {
          val = 0L;
        }
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundSuper
     *
     * <Description>
     *    Super-rounds value to grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * <Note>
     *    The TrueType specification says very few about the relationship
     *    between rounding and engine compensation.  However, it seems from
     *    the description of super round that we should add the compensation
     *    before rounding.
     *
     * =====================================================================
     */
    protected static Long RoundSuper(Long distance, Long compensation) {
      Long  val;

      if (distance >= 0) {
        val = (distance - cur.phase + cur.threshold + compensation) & -cur.period;
        if (distance != 0 && val < 0) {
          val = 0L;
        }
        val += cur.phase;
      } else {
        val = -((cur.threshold - cur.phase - distance + compensation) & -cur.period );
        if (val > 0) {
          val = 0L;
        }
        val -= cur.phase;
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    RoundSuper45
     *
     * <Description>
     *    Super-rounds value to grid after adding engine compensation.
     *
     * <Input>
     *    distance     :: The distance to round.
     *
     *    compensation :: The engine compensation.
     *
     * <Return>
     *    Rounded distance.
     *
     * <Note>
     *    There is a separate function for RoundSuper45() as we may need
     *    greater precision.
     *
     * =====================================================================
     */
    protected static Long RoundSuper45(Long distance, Long compensation) {
      Long val;

      if (distance >= 0) {
        val = ((distance - cur.phase + cur.threshold + compensation) /
                  cur.period ) * cur.period;
        if (distance != 0 && val < 0) {
          val = 0L;
        }
        val += cur.phase;
      } else {
        val = -(((cur.threshold - cur.phase - distance + compensation) /
                     cur.period) * cur.period);
        if (val > 0) {
          val = 0L;
        }
        val -= cur.phase;
      }
      return val;
    }

    /* =====================================================================
     *
     * <Function>
     *    ComputeRound
     *
     * <Description>
     *    Sets the rounding mode.
     *
     * <Input>
     *    round_mode :: The rounding mode to be used.
     *
     * =====================================================================
     */
    protected static void ComputeRound(byte round_mode) {
if (TTInterpRun.debug > 0) {
System.out.println("ComputeRound");
}
      switch (round_mode) {
      case TT_Round_Off:
        cur.func_round = TTInterpRun.RoundNone;
if (TTInterpRun.debug > 0) {
System.out.println("RoundNone");
}
        break;
      case TT_Round_To_Grid:
        cur.func_round = TTInterpRun.RoundToGrid;
if (TTInterpRun.debug > 0) {
System.out.println("RoundToGrid");
}
        break;
      case TT_Round_Up_To_Grid:
        cur.func_round = TTInterpRun.RoundUpToGrid;
if (TTInterpRun.debug > 0) {
System.out.println("RoundUpToGrid");
}
        break;
      case TT_Round_Down_To_Grid:
        cur.func_round = TTInterpRun.RoundDownToGrid;
if (TTInterpRun.debug > 0) {
System.out.println("RoundDownToGrid");
}
        break;
      case TT_Round_To_Half_Grid:
        cur.func_round = TTInterpRun.RoundToHalfGrid;
if (TTInterpRun.debug > 0) {
System.out.println("RoundToHalfGrid");
}
        break;
      case TT_Round_To_Double_Grid:
        cur.func_round = TTInterpRun.RoundToDoubleGrid;
if (TTInterpRun.debug > 0) {
System.out.println("RoundToDoubleGrid");
}
        break;
      case TT_Round_Super:
        cur.func_round = TTInterpRun.RoundSuper;
if (TTInterpRun.debug > 0) {
System.out.println("RoundSuper");
}
        break;
      case TT_Round_Super_45:
        cur.func_round = TTInterpRun.RoundSuper45;
if (TTInterpRun.debug > 0) {
System.out.println("RoundSuper45");
}
        break;
      }
    }

    /* ====================================================================
     * <Function>
     *    CurrentRatio
     *
     * <Description>
     *    Returns the current aspect ratio scaling factor depending on the
     *    projection vector's state and device resolutions.
     *
     * <Return>
     *    The aspect ratio in 16.16 format, always <= 1.0 .
     *
     * ====================================================================
     */
    protected static Long CurrentRatio() {
      if (cur.tt_metrics.ratio == 0) {
        if (cur.GS.projVector.getY() == 0) {
          cur.tt_metrics.ratio = cur.tt_metrics.x_ratio;
        } else {
          if (cur.GS.projVector.getX() == 0) {
            cur.tt_metrics.ratio = cur.tt_metrics.y_ratio;
          } else {
            Long x;
            Long y;

            x = TT_MulFix14(cur.tt_metrics.x_ratio, cur.GS.projVector.getX() << 2);
            y = TT_MulFix14(cur.tt_metrics.y_ratio, cur.GS.projVector.getY() << 2);
            cur.tt_metrics.ratio = FTCalc.FTHypot(x, y);
          }
        }
      }
      return cur.tt_metrics.ratio;
    }

    /* ==================== currentPpem ===================================== */
    protected static Long CurrentPpem() {
      return FTCalc.FTMulFix((long)cur.tt_metrics.ppem, CurrentRatio());
    }

    /* ==================== BOUNDS ===================================== */
    protected static boolean  BOUNDS(Integer x, Integer n) {
      return (x  >= n);
    }

    /* ==================== BOUNDSL ===================================== */
    protected static boolean  BOUNDSL(Long x, Long n) {
      return (x  >= n);
    }

    /* ==================== insSxVTL ===================================== */
    protected static boolean insSxVTL(short aIdx1, short aIdx2, int aOpc, FTReference<FTUnitVectorRec> vec_ref) {
      long A;
      long B;
      long C;
      FTUnitVectorRec p1;
      FTUnitVectorRec p2;

if (TTInterpRun.debug > 0) {
System.out.println(String.format("insSxVTL: aIdx1: %d, aIdx2: %d, aOpc: 0x%04x", aIdx1, aIdx2, aOpc));
}
      if (((int)aIdx1 >= (int)cur.zp2.n_points) || ((int)aIdx2 >= (int)cur.zp1.n_points)) {
        if (cur.pedantic_hinting) {
          cur.error = FT_Error.INTERP_INVALID_REFERENCE;
        }
        return FAILURE;
      }
      p1 = cur.zp1.cur[cur.zp1.cur_idx + aIdx2];
      p2 = cur.zp2.cur[cur.zp2.cur_idx + aIdx1];
      A = p1.x - p2.x;
      B = p1.y - p2.y;
if (TTInterpRun.debug > 0) {
System.out.println(String.format("1: A: %d B: %d", A, B));      
}
      /* If p1 == p2, SPVTL and SFVTL behave the same as */
      /* SPVTCA[X] and SFVTCA[X], respectively.          */
      /*                                                 */
      /* Confirmed by Greg Hitchcock.                    */
      if (A == 0 && B == 0) {
        A = 0x4000;
        aOpc = 0;
      }
      if ((aOpc & 1) != 0) {
        C = B;   /* counter clockwise rotation */
        B = A;
        A = -C;
      }
if (TTInterpRun.debug > 0) {
System.out.println(String.format("2: A: %d B: %d", A, B));      
}
      Normalize(A, B, vec_ref);
FTUnitVectorRec vec = vec_ref.Get();
if (TTInterpRun.debug > 0) {
System.out.println(String.format("vec: %d %d", vec.x, vec.y));      
}
      return SUCCESS;
    }

    /* ==================== DO_SVTCA ===================================== */
    protected static void DO_SVTCA() {
      short A;
      short B;

      A = (short)((cur.opcode & 1) << 14); 
      B = (short)(A ^ (short)0x4000);
      cur.GS.freeVector.setX((long)A);
      cur.GS.projVector.setX((long)A);
      cur.GS.dualVector.setX((long)A);
      cur.GS.freeVector.setY((long)B);
      cur.GS.projVector.setY((long)B);
      cur.GS.dualVector.setY((long)B);
      computeFuncs();
    }

    /* ==================== DO_SPVTCA ===================================== */
    protected static void DO_SPVTCA() {
      short A;
      short B;

      A = (short)((cur.opcode & 1) << 14);
      B = (short)(A ^ (short)0x4000);
      cur.GS.projVector.setX((long)A);
      cur.GS.dualVector.setX((long)A);
      cur.GS.projVector.setY((long)B);
      cur.GS.dualVector.setY((long)B);
      computeFuncs();
    }

    /* ==================== DO_SFVTCA ===================================== */
    protected static void DO_SFVTCA() {
      short A;
      short B;

      A = (short)((cur.opcode & 1) << 14);
      B = (short)(A ^ (short)0x4000);
      cur.GS.freeVector.setX((long)A);
      cur.GS.freeVector.setY((long)B);
      computeFuncs();
    }

    /* ==================== DO_SPVTL ===================================== */
    protected static void DO_SPVTL() {
      FTReference<FTUnitVectorRec> ft_unit_ref = new FTReference<FTUnitVectorRec>();

      ft_unit_ref.Set(cur.GS.projVector);
if (TTInterpRun.debug > 0) {
System.out.println(String.format("DO_SPVTL: %d, %d", cur.stack[cur.numArgs + 1], cur.stack[cur.numArgs + 0]));      
}
      if (insSxVTL((short)cur.stack[cur.numArgs + 1], (short)cur.stack[cur.numArgs + 0], cur.opcode, ft_unit_ref) == SUCCESS) {
        cur.GS.projVector = ft_unit_ref.Get();
        cur.GS.dualVector = ft_unit_ref.Get();
        computeFuncs();
      }
    }

    /* ==================== DO_SFVTL ===================================== */
    protected static void DO_SFVTL() {
      FTReference<FTUnitVectorRec> ft_unit_ref = new FTReference<FTUnitVectorRec>();

      ft_unit_ref.Set(cur.GS.freeVector);
      if (insSxVTL((short)cur.stack[cur.numArgs + 1], (short)cur.stack[cur.numArgs + 0], cur.opcode, ft_unit_ref) == SUCCESS) {
        cur.GS.freeVector = ft_unit_ref.Get();
        computeFuncs();
      }
    }

    /* ==================== DO_SFVTPV ===================================== */
    protected static void DO_SFVTPV() {
      cur.GS.freeVector = cur.GS.projVector;
      computeFuncs();
    }

    /* ==================== DO_SPVFS ===================================== */
    protected static void DO_SPVFS () {
      short S;
      long X;
      long Y;
      FTReference<FTUnitVectorRec> ft_unit_ref = new FTReference<FTUnitVectorRec>();

      ft_unit_ref.Set(cur.GS.projVector);
      // Only use low 16bits, then sign extend
      S = (short)cur.stack[cur.numArgs + 1];
      Y = (long)S;
      S = (short)cur.stack[cur.numArgs + 0];
      X = (long)S;
      Normalize(X, Y, ft_unit_ref);
      cur.GS.projVector = ft_unit_ref.Get();
      cur.GS.dualVector = cur.GS.projVector;
      computeFuncs();
    }

    /* ==================== DO_SFVFS ===================================== */
    protected static void DO_SFVFS () {
      short S;
      long X;
      long Y;
      FTReference<FTUnitVectorRec> ft_unit_ref = new FTReference<FTUnitVectorRec>();

      ft_unit_ref.Set(cur.GS.freeVector);
      // Only use low 16bits, then sign extend
      S = (short)cur.stack[cur.numArgs + 1];
      Y = (long)S;
      S = (short)cur.stack[cur.numArgs + 0];
      X = S;
      Normalize(X, Y, ft_unit_ref);
      cur.GS.freeVector = ft_unit_ref.Get();
      computeFuncs();
    }


    /* ==================== DO_GPV ===================================== */
    protected static void DO_GPV() {
      cur.stack[cur.numArgs + 0] = (int)(cur.GS.projVector.getX() & 0xFFFF);
      cur.stack[cur.numArgs + 1] = (int)(cur.GS.projVector.getY() & 0xFFFF);
    }

    /* ==================== DO_GFV ===================================== */
    protected static void DO_GFV() {
      cur.stack[cur.numArgs + 0] = (int)(cur.GS.freeVector.getX() & 0xFFFF);
      cur.stack[cur.numArgs + 1] = (int)(cur.GS.freeVector.getY() & 0xFFFF);
    }

    /* ==================== DO_SRP0 ===================================== */
    protected static void DO_SRP0() {
      cur.GS.rp0 = (short)cur.stack[cur.numArgs + 0];
if (TTInterpRun.debug > 0) {
System.out.println(String.format("DO_SRP0: cur.GS.rp0: %d cur.numArgs: %d", cur.GS.rp0, cur.numArgs));      
}
    }

    /* ==================== DO_SRP1 ===================================== */
    protected static void DO_SRP1() {
      cur.GS.rp1 = (short)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_SRP" ===================================== */
    protected static void DO_SRP2() {
      cur.GS.rp2 = (short)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_RTHG ===================================== */
    protected static void DO_RTHG() {
      cur.GS.round_state = TT_Round_To_Half_Grid;
      cur.func_round = TTInterpRun.RoundToHalfGrid;
    }

    /* ==================== DO_RTG ===================================== */
    protected static void DO_RTG() {
      cur.GS.round_state = TT_Round_To_Grid;
      cur.func_round = TTInterpRun.RoundToGrid;
    }

    /* ==================== DO_RTDG ===================================== */
    protected static void DO_RTDG() {
      cur.GS.round_state = TT_Round_To_Double_Grid;
      cur.func_round = TTInterpRun.RoundToDoubleGrid;
    }

    /* ==================== DO_RUTG ===================================== */
    protected static void DO_RUTG() {
      cur.GS.round_state = TT_Round_Up_To_Grid;
      cur.func_round = TTInterpRun.RoundUpToGrid;
    }

    /* ==================== DO_RDTG ===================================== */
    protected static void DO_RDTG() {
      cur.GS.round_state = TT_Round_Down_To_Grid;
      cur.func_round = TTInterpRun.RoundDownToGrid;
    }

    /* ==================== DO_ROFF ===================================== */
    protected static void DO_ROFF() {
      cur.GS.round_state = TT_Round_Off;
      cur.func_round = TTInterpRun.RoundNone;
    }

    /* ==================== DO_SROUND ===================================== */
    protected static void DO_SROUND() {
      SetSuperRound(0x4000, (int)cur.stack[cur.numArgs + 0]);
      cur.GS.round_state = TT_Round_Super;
      cur.func_round = TTInterpRun.RoundSuper;
    }

    /* ==================== DO_S45ROUND ===================================== */
    protected static void DO_S45ROUND() {
      SetSuperRound(0x2D41, (int)cur.stack[cur.numArgs + 0]);
      cur.GS.round_state = TT_Round_Super_45;
      cur.func_round = TTInterpRun.RoundSuper45;
    }

    /* ==================== DO_SLOOP ===================================== */
    protected static void DO_SLOOP() {
      if (cur.stack[cur.numArgs + 0] < 0) {
        cur.error = FT_Error.INTERP_BAD_ARGUMENT;
      } else {
        cur.GS.loop = cur.stack[cur.numArgs + 0];
      }
    }

    /* ==================== DO_SMD ===================================== */
    protected static void DO_SMD() {
      cur.GS.minimum_distance = (int)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_SCVTCI ===================================== */
    protected static void DO_SCVTCI() {
      cur.GS.control_value_cutin = (int)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_SSWCI ===================================== */
    protected static void DO_SSWCI() {
      cur.GS.single_width_cutin = (int)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_SSW ===================================== */
    protected static void DO_SSW() {
      cur.GS.single_width_value = (int)FTCalc.FTMulFix((long)cur.stack[cur.numArgs + 0], (long)cur.tt_metrics.scale);
    }

    /* ==================== DO_FLIPON ===================================== */
    protected static void DO_FLIPON() {
      cur.GS.auto_flip = true;
    }

    /* ==================== DO_FLIPPOFF ===================================== */
    protected static void DO_FLIPOFF() {
      cur.GS.auto_flip = false;
    }

    /* ==================== DO_SDB ===================================== */
    protected static void DO_SDB() {
      cur.GS.delta_base = (short)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_cwSDSFLIPPOFF ===================================== */
    protected static void DO_SDS() {
      cur.GS.delta_shift = (short)cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_MD ===================================== */
    protected static void DO_MD() {  // nothing
    }

    /* ==================== DO_MPPEM ===================================== */
    protected static void DO_MPPEM() {
if (TTInterpRun.debug > 0) {
System.out.println(String.format("DO_MPPEM: %d", CurrentPpem().intValue()));      
}
      cur.stack[cur.numArgs + 0] = CurrentPpem().intValue();
    }

  // Note: The pointSize should be irrelevant in a given font program; 
  //       we thus decide to return only the ppem.
    /* ==================== DO_FMPS ===================================== */
    protected static void DO_MPS() {
      cur.stack[cur.numArgs + 0] = CurrentPpem().intValue();
    }

    /* ==================== DO_DUP ===================================== */
    protected static void DO_DUP() {
      cur.stack[cur.numArgs + 1] = cur.stack[cur.numArgs + 0];
if (TTInterpRun.debug > 0) {
System.out.println(String.format("DO_DUP: %d %d", cur.stack[cur.numArgs + 1], cur.stack[cur.numArgs + 0]));     
}
    }

    /* ==================== DO_CLEAR ===================================== */
    protected static void DO_CLEAR() {
      cur.new_top = 0;
    }

    /* ==================== DO_SWAP ===================================== */
    protected static void DO_SWAP() {
      long L;

      L = cur.stack[cur.numArgs + 0];
      cur.stack[cur.numArgs + 0] = cur.stack[cur.numArgs + 1];
      cur.stack[cur.numArgs + 1] = (int)L;
    }

    /* ==================== DO_DEPTH ===================================== */
    protected static void DO_DEPTH() {
      cur.stack[cur.numArgs + 0] = cur.top;
    }

    /* ==================== DO_CINDEX ===================================== */
    protected static void DO_CINDEX() {
      int L;

      L = (int)cur.stack[cur.numArgs + 0];
      if (L <= 0 || L > cur.numArgs) {
        if (cur.pedantic_hinting) {
          cur.error = FT_Error.INTERP_INVALID_REFERENCE;
        }
        cur.stack[cur.numArgs + 0] = 0;
      } else {
        cur.stack[cur.numArgs + 0] = (int)cur.stack[(cur.numArgs - L)];
      }
    }

    /* ==================== DO_JROT ===================================== */
    protected static void DO_JROT() {
      if (cur.stack[cur.numArgs + 1] != 0) {
        if (cur.stack[cur.numArgs + 0] == 0 && cur.numArgs == 0) {
          cur.error = FT_Error.INTERP_BAD_ARGUMENT;
        }
        cur.IP += cur.stack[cur.numArgs + 0];
        if ( cur.IP < 0 ||
                (cur.callTop > 0 && cur.IP > cur.callStack[cur.callTop - 1].CurEnd)) {
          cur.error = FT_Error.INTERP_BAD_ARGUMENT;
        }
        cur.step_ins = false;
      }
    }

    /* ==================== DO_JMPR ===================================== */
    protected static void DO_JMPR() {
      if (cur.stack[cur.numArgs + 0] == 0 && cur.numArgs == 0) {
        cur.error = FT_Error.INTERP_BAD_ARGUMENT;
      }
      cur.IP += cur.stack[cur.numArgs + 0];
      if (cur.IP < 0 ||
              (cur.callTop > 0 && cur.IP > cur.callStack[cur.callTop - 1].CurEnd)) {
        cur.error = FT_Error.INTERP_BAD_ARGUMENT;
      }
      cur.step_ins = false;
    }

    /* ==================== DO_JROF ===================================== */
    protected static void DO_JROF() {
      if (cur.stack[cur.numArgs + 1] == 0) {
        if (cur.stack[cur.numArgs + 0] == 0 && cur.numArgs == 0) {
          cur.error = FT_Error.INTERP_BAD_ARGUMENT;
        }
        cur.IP += cur.stack[cur.numArgs + 0];
        if (cur.IP < 0  ||
             (cur.callTop > 0 && cur.IP > cur.callStack[cur.callTop - 1].CurEnd)) {
          cur.error = FT_Error.INTERP_BAD_ARGUMENT;
        }
        cur.step_ins = false;
      }
    }

    /* ==================== DO_LT ===================================== */
    protected static void DO_LT() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] < cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_LTEQ ===================================== */
    protected static void DO_LTEQ() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] <= cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_GT ===================================== */
    protected static void DO_GT() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] > cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_GTEQ ===================================== */
    protected static void DO_GTEQ() {
if (TTInterpRun.debug > 0) {
System.out.println(String.format("DO_GTEQ: %d >= %d", cur.stack[cur.numArgs + 0], cur.stack[cur.numArgs + 1]));      
}
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] >= cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_EQ ===================================== */
    protected static void DO_EQ() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] == cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_NEQ ===================================== */
    protected static void DO_NEQ() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] != cur.stack[cur.numArgs + 1]) ? 1 : 0;
    }

    /* ==================== DO_ODD ===================================== */
    protected static void DO_ODD() {
      cur.stack[cur.numArgs + 0] = ((int)cur.func_round.callClassMethod((int)cur.stack[cur.numArgs + 0], 0) & 127) == 64 ? 1 : 0;
    }

    /* ==================== DO_EVEN ===================================== */
    protected static void DO_EVEN() {
      cur.stack[cur.numArgs + 0] = ((int)cur.func_round.callClassMethod((int)cur.stack[cur.numArgs + 0], 0) & 127) == 0 ? 1 : 0;
    }

    /* ==================== DO_AND ===================================== */
    protected static void DO_AND() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] != 0 && cur.stack[cur.numArgs + 1] != 0) ? 1 : 0;
    }

    /* ==================== DO_OR ===================================== */
    protected static void DO_OR() {
      cur.stack[cur.numArgs + 0] = (cur.stack[cur.numArgs + 0] != 0 || cur.stack[cur.numArgs + 1] != 0) ? 1 : 0;
    }

    /* ==================== DO_NOT ===================================== */
    protected static void DO_NOT() {
      cur.stack[cur.numArgs + 0] = cur.stack[cur.numArgs + 0] == 0  ? 1 : 0;
    }

    /* ==================== DO_ADD ===================================== */
    protected static void DO_ADD() {
      cur.stack[cur.numArgs + 0] += cur.stack[cur.numArgs + 1];
    }

    /* ==================== DO_SUB ===================================== */
    protected static void DO_SUB() {
      cur.stack[cur.numArgs + 0] -= cur.stack[cur.numArgs + 1];
    }

    /* ==================== DO_DIV ===================================== */
    protected static void DO_DIV() {
      if (cur.stack[cur.numArgs + 1] == 0) {
        cur.error = FT_Error.INTERP_DIVIDE_BY_ZERO;
      } else {
        cur.stack[cur.numArgs + 0] = FTCalc.FT_MulDivNoRound((long)cur.stack[cur.numArgs + 0], 64L, (long)cur.stack[cur.numArgs + 1]);
      }
    }

    /* ==================== DO_MUL ===================================== */
    protected static void DO_MUL() {
      cur.stack[cur.numArgs + 0] = FTCalc.FT_MulDiv((long)cur.stack[cur.numArgs + 0], (long)cur.stack[cur.numArgs + 1], 64L);
    }

    /* ==================== DO_ABS ===================================== */
    protected static void DO_ABS() {
      cur.stack[cur.numArgs + 0] = (int)(FTCalc.FT_ABS((long)cur.stack[cur.numArgs + 0]) & 0xFFFF);
    }

    /* ==================== DO_NEG ===================================== */
    protected static void DO_NEG() {
      cur.stack[cur.numArgs + 0] = -cur.stack[cur.numArgs + 0];
    }

    /* ==================== DO_FLOOR ===================================== */
    protected static void DO_FLOOR() {
      cur.stack[cur.numArgs + 0] = FTCalc.FT_PIX_FLOOR((long)cur.stack[cur.numArgs + 0]);
    }

    /* ==================== DO_CEILING ===================================== */
    protected static void DO_CEILING() {
      cur.stack[cur.numArgs + 0] = FTCalc.FT_PIX_CEIL((long)cur.stack[cur.numArgs + 0]);
    }

    /* ==================== DO_RS ===================================== */
    protected static void DO_RS() {
      int I = (int)cur.stack[cur.numArgs + 0];

      if (BOUNDSL((long)I, (long)cur.storeSize)) {
        if (cur.pedantic_hinting ) {
          cur.error = FT_Error.INTERP_ARRAY_BOUND_ERROR;
        } else {
          cur.stack[cur.numArgs + 0] = 0;
        }
      } else {
        cur.stack[cur.numArgs + 0] = cur.storage[I];
      }
    }

    /* ==================== DO_WS ===================================== */
    protected static void DO_WS() {
      int I = (int)cur.stack[cur.numArgs + 0];

      if (BOUNDSL((long)I, (long)cur.storeSize)) {
        if (cur.pedantic_hinting) {
        	cur.error = FT_Error.INTERP_ARRAY_BOUND_ERROR;
        }
      } else {
        cur.storage[I] = (long)cur.stack[cur.numArgs + 1];
      }
    }

    /* ==================== DO_RCVT ===================================== */
    protected static void DO_RCVT() {
      int I = (int)cur.stack[cur.numArgs + 0];

      if (BOUNDSL((long)I, (long)cur.cvtSize)) {
        if (cur.pedantic_hinting) {
        	cur.error = FT_Error.INTERP_ARRAY_BOUND_ERROR;
        } else {
          cur.stack[cur.numArgs + 0] = 0;
        }
      } else {
        int val = (int)cur.func_read_cvt.callClassMethod(I, 0) & 0xFFFF;
        cur.stack[cur.numArgs + 0] = val;
      }
    }

    /* ==================== DO_WCVTP ===================================== */
    protected static void DO_WCVTP() {
      int I = (int)cur.stack[cur.numArgs + 0];


      if (BOUNDSL((long)I, (long)cur.cvtSize)) {
        if (cur.pedantic_hinting) {
        	cur.error = FT_Error.INTERP_ARRAY_BOUND_ERROR;
        }
      } else {
        cur.func_write_cvt.callClassMethod(I, (int)cur.stack[cur.numArgs + 1]);
      }
    }

    /* ==================== DO_WCVTF ===================================== */
    protected static void DO_WCVTF() {
      int I = (int)cur.stack[cur.numArgs + 0];

      if (BOUNDSL((long)I, (long)cur.cvtSize)) {
        if (cur.pedantic_hinting) {
        	cur.error = FT_Error.INTERP_ARRAY_BOUND_ERROR;
        }
      } else {
        cur.cvt[I] = FTCalc.FTMulFix((long)cur.stack[cur.numArgs + 1], cur.tt_metrics.scale);
      }
    }

    /* ==================== DO_DEBUG ===================================== */
    protected static void DO_DEBUG() {
      cur.error = FT_Error.INTERP_DEBUG_OPCODE;
    }

    /* ==================== DO_ROUND ===================================== */
    protected static void DO_ROUND() {
      cur.stack[cur.numArgs + 0] = (int)cur.func_round.callClassMethod((int)cur.stack[cur.numArgs + 0], cur.tt_metrics.compensations[cur.opcode - 0x68]);
    }

    /* ==================== DO_NROUND ===================================== */
    protected static void DO_NROUND() {
      cur.stack[cur.numArgs + 0] = RoundNone((long)cur.stack[cur.numArgs + 0], (long)cur.tt_metrics.compensations[cur.opcode - 0x6C]).intValue();
    }

    /* ==================== DO_NROUND ===================================== */
    protected static void DO_MAX() {
      if (cur.stack[cur.numArgs + 1] > cur.stack[cur.numArgs + 0]) {
        cur.stack[cur.numArgs + 0] = cur.stack[cur.numArgs + 1];
      }
    }

    /* ==================== DO_NROUND ===================================== */
    protected static void DO_MIN() {
      if (cur.stack[cur.numArgs + 1] < cur.stack[cur.numArgs + 0]) {
        cur.stack[cur.numArgs + 0] = cur.stack[cur.numArgs + 1];
      }
    }

    /* ==================== ARRAY_BOUND_ERROR ===================================== */
    protected static void ARRAY_BOUND_ERROR() {
      cur.error = FT_Error.INTERP_INVALID_REFERENCE;
    }

    /* =====================================================================
     *
     * <Function>
     *    computeFuncs
     *
     * <Description>
     *    Computes the projection and movement function pointers according
     *    to the current graphics state.
     *
     * =====================================================================
     */
    protected static void computeFuncs() {
//System.out.println(String.format("computeFuncs"));
//System.out.println(String.format("cur.GS.freeVector.x/y: 0x%08x 0x%08x", cur.GS.freeVector.x, cur.GS.freeVector.y));
      if (cur.GS.freeVector.x == 0x4000) {
        cur.F_dot_P = cur.GS.projVector.x;
      } else {
        if (cur.GS.freeVector.y == 0x4000) {
          cur.F_dot_P = cur.GS.projVector.y;
        } else {
          cur.F_dot_P = ((int)cur.GS.projVector.getX().intValue() * cur.GS.freeVector.x +
                        (int)cur.GS.projVector.getY().intValue() * cur.GS.freeVector.y) >> 14;
        }
      }
//System.out.println(String.format("cur.GS.projVector.x/y: 0x%08x 0x%08x", cur.GS.projVector.x, cur.GS.projVector.y));
      if (cur.GS.projVector.x == 0x4000L) {
        cur.func_project = TTInterpRun.ProjectX;
//System.out.println("func_proj ProjectX");
      } else {
        if (cur.GS.projVector.y == 0x4000L) {
          cur.func_project = TTInterpRun.ProjectY;
//System.out.println("func_proj ProjectY");
        } else {
          cur.func_project = TTInterpRun.Project;
//System.out.println("func_proj Project");
        }
      }
//System.out.println(String.format("cur.GS.dualVector.x/y: 0x%08x 0x%08x", cur.GS.dualVector.x, cur.GS.dualVector.y));
      if (cur.GS.dualVector.x == 0x4000L) {
        cur.func_dualproj = TTInterpRun.ProjectX;
//System.out.println("func_dualproj ProjectX");
      } else {
        if (cur.GS.dualVector.y == 0x4000L) {
          cur.func_dualproj = TTInterpRun.ProjectY;
//System.out.println("func_dualproj ProjectY");
        } else {
          cur.func_dualproj = TTInterpRun.DualProject;
//System.out.println("func_dualproj DualProject");
        }
      }
      cur.func_move = TTInterpRun.DirectMove;
      cur.func_move_orig = TTInterpRun.DirectMoveOrig;
//System.out.println(String.format("cur.F_dot_P: 0x%08x", cur.F_dot_P));
      if (cur.F_dot_P == 0x4000L) {
        if (cur.GS.freeVector.x == 0x4000L) {
          cur.func_move = TTInterpRun.DirectMoveX;
          cur.func_move_orig = TTInterpRun.DirectMoveOrigX;
//System.out.println("func_move DirectMoveX");
        } else {
          if (cur.GS.freeVector.y == 0x4000L) {
            cur.func_move = TTInterpRun.DirectMoveY;
            cur.func_move_orig = TTInterpRun.DirectMoveOrigY;
//System.out.println("func_move DirectMoveY");
          }
        }
      }
      /* at small sizes, F_dot_P can become too small, resulting   */
      /* in overflows and `spikes' in a number of glyphs like `w'. */
      if (FTCalc.FT_ABS( cur.F_dot_P) < 0x400L) {
        cur.F_dot_P = 0x4000L;
      }
      /* Disable cached aspect ratio */
      cur.tt_metrics.ratio = 0;
    }

}

Added ftbase/TTInterpRun.java.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTInterpRun                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTInterpRun extends TTInterpInsFuncs2 {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTInterpRun";

    public static int numInstructions = 0;
    public static int debug = 0;

    protected static FTInstanceMethod ProjectX = null;
    protected static FTInstanceMethod ProjectY = null;
    protected static FTInstanceMethod Project = null;
    protected static FTInstanceMethod DualProject = null;
    protected static FTInstanceMethod DirectMove = null;
    protected static FTInstanceMethod DirectMoveOrig = null;
    protected static FTInstanceMethod DirectMoveX = null;
    protected static FTInstanceMethod DirectMoveOrigX = null;
    protected static FTInstanceMethod DirectMoveY = null;
    protected static FTInstanceMethod DirectMoveOrigY = null;
    protected static FTInstanceMethod ReadCVTStretched = null;
    protected static FTInstanceMethod WriteCVTStretched = null;
    protected static FTInstanceMethod MoveCVTStretched = null;
    protected static FTInstanceMethod ReadCVT = null;
    protected static FTInstanceMethod WriteCVT = null;
    protected static FTInstanceMethod MoveCVT = null;
    protected static FTInstanceMethod RoundNone = null;
    protected static FTInstanceMethod RoundToGrid = null;
    protected static FTInstanceMethod RoundUpToGrid = null;
    protected static FTInstanceMethod RoundDownToGrid = null;
    protected static FTInstanceMethod RoundToHalfGrid = null;
    protected static FTInstanceMethod RoundToDoubleGrid = null;
    protected static FTInstanceMethod RoundSuper = null;
    protected static FTInstanceMethod RoundSuper45 = null;
    
    public static boolean doInterpDebug = false;

    /* ==================== TTInterpRun ================================== */
    public TTInterpRun() {
      super();
      oid++;
      id = oid;
      String class_name = "org.apwtcl.gles20.truetype.TTInterpFuncs3";
      ProjectX          = new FTInstanceMethod(class_name, "ProjectX", 1);
      ProjectY          = new FTInstanceMethod(class_name, "ProjectY", 1);
      Project           = new FTInstanceMethod(class_name, "Project", 1);
      DualProject       = new FTInstanceMethod(class_name, "DualProject", 1);
      DirectMove        = new FTInstanceMethod(class_name, "DirectMove", 1);
      DirectMoveOrig    = new FTInstanceMethod(class_name, "DirectMoveOrig", 1);
      DirectMoveX       = new FTInstanceMethod(class_name, "DirectMoveX", 1);
      DirectMoveOrigX   = new FTInstanceMethod(class_name, "DirectMoveOrigX", 1);
      DirectMoveY       = new FTInstanceMethod(class_name, "DirectMoveY", 1);
      DirectMoveOrigY   = new FTInstanceMethod(class_name, "DirectMoveOrigY", 1);
      ReadCVTStretched  = new FTInstanceMethod(class_name, "ReadCVTStretched", 1);
      WriteCVTStretched = new FTInstanceMethod(class_name, "WriteCVTStretched", 1);
      MoveCVTStretched  = new FTInstanceMethod(class_name, "MoveCVTStretched", 1);
      ReadCVT           = new FTInstanceMethod(class_name, "ReadCVT", 1);
      WriteCVT          = new FTInstanceMethod(class_name, "WriteCVT", 1);
      MoveCVT           = new FTInstanceMethod(class_name, "MoveCVT", 1);
      RoundNone         = new FTInstanceMethod(class_name, "RoundNone", 1);
      RoundToGrid       = new FTInstanceMethod(class_name, "RoundToGrid", 1);
      RoundUpToGrid     = new FTInstanceMethod(class_name, "RoundUpToGrid", 1);
      RoundDownToGrid   = new FTInstanceMethod(class_name, "RoundDownToGrid", 1);
      RoundToHalfGrid   = new FTInstanceMethod(class_name, "RoundToHalfGrid", 1);
      RoundToDoubleGrid = new FTInstanceMethod(class_name, "RoundToDoubleGrid", 1);
      RoundSuper        = new FTInstanceMethod(class_name, "RoundSuper", 1);
      RoundSuper45      = new FTInstanceMethod(class_name, "RoundSuper45", 1);
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }

    /* ==================== TTInsRun =====================================
     *
     * RUN
     *
     *  This function executes a run of opcodes.  It will exit in the
     *  following cases:
     *
     *  - Errors (in which case it returns FALSE).
     *
     *  - Reaching the end of the main code range (returns TRUE).
     *    Reaching the end of a code range within a function call is an
     *    error.
     *
     *  - After executing one single opcode, if the flag `Instruction_Trap'
     *    is set to TRUE (returns TRUE).
     *
     *  On exit with TRUE, test IP < CodeSize to know whether it comes from
     *  an instruction trap or a normal termination.
     *
     *
     *  Note: The documented DEBUG opcode pops a value from the stack.  This
     *        behaviour is unsupported; here a DEBUG opcode is always an
     *        error.
     *
     *
     * THIS IS THE INTERPRETER'S MAIN LOOP.
     *
     *  Instructions appear in the specification's order.
     *
     * =====================================================================
     */

    /* documentation is in ttinterp.h */

    public int TTRunIns(Object ... args) {
      TTExecContextRec exec = (TTExecContextRec)args[0];
      byte[] insts = exec.code;
      int ins_counter = 0;  /* executed instructions counter */
      short i;

Debug(0, DBG_INTERP, TAG, "TTRunIns");
//System.out.println("TT_RunIns: stackinfo: "+exec.stackSize+"!"+exec.top+"!"+exec.new_top+"!");
//Log.w(TAG, "Scur"+exec+"!");
      cur = exec;
//      cur.code = insts;
//      cur.codeSize = insts.length;
      
      /* set CVT functions */
      cur.tt_metrics.ratio = 0;
      if (cur.metrics.x_ppem != cur.metrics.y_ppem) {
        /* non-square pixels, use the stretched routines */
        cur.func_read_cvt = TTInterpRun.ReadCVTStretched;
        cur.func_write_cvt = TTInterpRun.WriteCVTStretched;
        cur.func_move_cvt = TTInterpRun.MoveCVTStretched;
      } else {
        /* square pixels, use normal routines */
        cur.func_read_cvt = TTInterpRun.ReadCVT;
        cur.func_write_cvt = TTInterpRun.WriteCVT;
        cur.func_move_cvt = TTInterpRun.MoveCVT;
      }
      computeFuncs();
      ComputeRound((byte)cur.GS.round_state);
//Debug(0, DBG_INTERP, TAG,  "cur.IP: "+cur.IP+"!"+cur.length);
      do {
        cur.opcode = (short)(cur.code[cur.IP] & 0xFF);
	numInstructions++;
if (numInstructions > 500000) {
  doInterpDebug = true;
}
	
        FTTrace.Trace(7, TAG, String.format("opcode: 0x%02x cur.IP: %d %s instr: %d", cur.opcode & 0xFF, cur.IP, opcode_name[cur.opcode], numInstructions));
//FTGlyphLoaderRec._showLoaderZone2("interp_opcode");
        //FT_TRACE7(( "  " ));
//        FT_Trace.Trace(7, TAG, opcode_name[cur.opcode]);
        //FT_TRACE7(( "\n" ));
        cur.length = opcode_length[cur.opcode];
        if (cur.length < 0 ) {
          if (cur.IP + 1 >= cur.codeSize) {
            return LErrorCodeOverflow();
          }
          cur.length = 2 - cur.length * (cur.code[cur.IP + 1] & 0xFF);
        }
        if (cur.IP + cur.length > cur.codeSize) {
          return LErrorCodeOverflow();
        }
        /* First, let's check for empty stack and overflow */
        cur.numArgs = cur.top - (popPushCount[cur.opcode] >> 4);
Debug(0, DBG_INTERP, TAG, String.format("numArgs: %d top: %d stack[numArgs]: %d", cur.numArgs, cur.top, cur.stack[cur.numArgs]));
        /* `args' is the top of the stack once arguments have been popped. */
        /* One can also interpret it as the index of the last argument.    */
        if (cur.numArgs < 0) {
          if (cur.pedantic_hinting) {
            cur.error = FTError.INTERP_TOO_FEW_ARGUMENTS;
            return LError();
          }
          /* push zeroes onto the stack */
          for (i = 0; i < popPushCount[cur.opcode] >> 4; i++) {
            cur.stack[i] = 0;
          }
          cur.numArgs = 0;
        }
        cur.new_top = cur.numArgs + (popPushCount[cur.opcode] & 15);
        /* `new_top' is the new top of the stack, after the instruction's */
        /* execution.  `top' will be set to `new_top' after the `switch'  */
        /* statement.                                                     */
//Debug(0, DBG_INTERP, TAG, "Stack: "+cur.new_top+"!"+cur.stackSize+"!");
        if (cur.new_top > cur.stackSize) {
          cur.error = FTError.INTERP_STACK_OVERFLOW;
          return LError();
        }
        cur.step_ins = true;
        cur.error = FTError.INTERP_ERR_OK;
        {
          short opcode = cur.opcode;
          switch (opcode & 0xFF) {
          case 0x00:  /* SVTCA y  */
          case 0x01:  /* SVTCA x  */
          case 0x02:  /* SPvTCA y */
          case 0x03:  /* SPvTCA x */
          case 0x04:  /* SFvTCA y */
          case 0x05:  /* SFvTCA x */
          {
            short AA;
            short BB;

            AA = (short)((opcode & 1) << 14);
            BB = (short)(AA ^ 0x4000);
            if (opcode < 4) {
              cur.GS.projVector.x = (long)AA;
              cur.GS.projVector.y = (long)BB;
              cur.GS.dualVector.x = (long)AA;
              cur.GS.dualVector.y = (long)BB;
            }
            if ((opcode & 2) == 0) {
              cur.GS.freeVector.x = (long)AA;
              cur.GS.freeVector.y = (long)BB;
            } else {
//              GUESS_VECTOR( freeVector );
            }
            computeFuncs();
            break;
          }
          case 0x06:  /* SPvTL // */
          case 0x07:  /* SPvTL +  */
            DO_SPVTL();
            break;
          case 0x08:  /* SFvTL // */
          case 0x09:  /* SFvTL +  */
            DO_SFVTL();
            break;
          case 0x0A:  /* SPvFS */
            DO_SPVFS();
            break;
          case 0x0B:  /* SFvFS */
            DO_SFVFS();
            break;
          case 0x0C:  /* GPV */
            DO_GPV();
            break;
          case 0x0D:  /* GFV */
            DO_GFV();
            break;
          case 0x0E:  /* SFvTPv */
            DO_SFVTPV();
            break;
          case 0x0F:  /* ISECT  */
            insISECT();
            break;
          case 0x10:  /* SRP0 */
            DO_SRP0();
            break;
          case 0x11:  /* SRP1 */
            DO_SRP1();
            break;
          case 0x12:  /* SRP2 */
            DO_SRP2();
            break;
          case 0x13:  /* SZP0 */
            insSZP0();
            break;
          case 0x14:  /* SZP1 */
            insSZP1();
            break;
          case 0x15:  /* SZP2 */
            insSZP2();
            break;
          case 0x16:  /* SZPS */
            insSZPS();
            break;
          case 0x17:  /* SLOOP */
            DO_SLOOP();
            break;
          case 0x18:  /* RTG */
            DO_RTG();
            break;
          case 0x19:  /* RTHG */
            DO_RTHG();
            break;
          case 0x1A:  /* SMD */
            DO_SMD();
            break;
          case 0x1B:  /* ELSE */
            insELSE();
            break;
          case 0x1C:  /* JMPR */
            DO_JMPR();
            break;
          case 0x1D:  /* SCVTCI */
            DO_SCVTCI();
            break;
          case 0x1E:  /* SSWCI */
            DO_SSWCI();
            break;
          case 0x1F:  /* SSW */
            DO_SSW();
            break;
          case 0x20:  /* DUP */
            DO_DUP();
            break;
          case 0x21:  /* POP */
            /* nothing :-) */
            break;
          case 0x22:  /* CLEAR */
            DO_CLEAR();
            break;
          case 0x23:  /* SWAP */
            DO_SWAP();
            break;
          case 0x24:  /* DEPTH */
            DO_DEPTH();
            break;
          case 0x25:  /* CINDEX */
            DO_CINDEX();
            break;
          case 0x26:  /* MINDEX */
            insMINDEX();
            break;
          case 0x27:  /* ALIGNPTS */
            insALIGNPTS();
            break;
          case 0x28:  /* ???? */
            insUNKNOWN();
            break;
          case 0x29:  /* UTP */
            insUTP();
            break;
          case 0x2A:  /* LOOPCALL */
            insLOOPCALL();
            break;
          case 0x2B:  /* CALL */
            insCALL();
            break;
          case 0x2C:  /* FDEF */
            insFDEF();
            break;
          case 0x2D:  /* ENDF */
            insENDF();
            break;
          case 0x2E:  /* MDAP */
          case 0x2F:  /* MDAP */
            insMDAP();
            break;
          case 0x30:  /* IUP */
          case 0x31:  /* IUP */
            insIUP();
            break;
          case 0x32:  /* SHP */
          case 0x33:  /* SHP */
            insSHP();
            break;
          case 0x34:  /* SHC */
          case 0x35:  /* SHC */
            insSHC();
            break;
          case 0x36:  /* SHZ */
          case 0x37:  /* SHZ */
            insSHZ();
            break;
          case 0x38:  /* SHPIX */
            insSHPIX();
            break;
          case 0x39:  /* IP    */
            insIP();
            break;
          case 0x3A:  /* MSIRP */
          case 0x3B:  /* MSIRP */
            insMSIRP();
            break;
          case 0x3C:  /* AlignRP */
            insALIGNRP();
            break;
          case 0x3D:  /* RTDG */
            DO_RTDG();
            break;
          case 0x3E:  /* MIAP */
          case 0x3F:  /* MIAP */
            insMIAP();
            break;
          case 0x40:  /* NPUSHB */
            insNPUSHB();
            break;
          case 0x41:  /* NPUSHW */
            insNPUSHW();
            break;
          case 0x42:  /* WS */
            DO_WS();
            break;
  //  Set_Invalid_Ref:
  //            cur.error = FT_Error.INTERP_INVALID_REFERENCE;
  //          break;
          case 0x43:  /* RS */
            DO_RS();
            break;
          case 0x44:  /* WCVTP */
            DO_WCVTP();
            break;
          case 0x45:  /* RCVT */
            DO_RCVT();
            break;
          case 0x46:  /* GC */
          case 0x47:  /* GC */
            insGC();
            break;
          case 0x48:  /* SCFS */
            insSCFS();
            break;
          case 0x49:  /* MD */
          case 0x4A:  /* MD */
            insMD();
            break;
          case 0x4B:  /* MPPEM */
            DO_MPPEM();
            break;
          case 0x4C:  /* MPS */
            DO_MPS();
            break;
          case 0x4D:  /* FLIPON */
            DO_FLIPON();
            break;
          case 0x4E:  /* FLIPOFF */
            DO_FLIPOFF();
            break;
          case 0x4F:  /* DEBUG */
            DO_DEBUG();
            break;
          case 0x50:  /* LT */
            DO_LT();
            break;
          case 0x51:  /* LTEQ */
            DO_LTEQ();
            break;
          case 0x52:  /* GT */
            DO_GT();
            break;
          case 0x53:  /* GTEQ */
            DO_GTEQ();
            break;
          case 0x54:  /* EQ */
            DO_EQ();
            break;
          case 0x55:  /* NEQ */
            DO_NEQ();
            break;
          case 0x56:  /* ODD */
            DO_ODD();
          case 0x57:  /* EVEN */
            DO_EVEN();
            break;
          case 0x58:  /* IF */
            insIF();
            break;
          case 0x59:  /* EIF */
            /* do nothing */
            break;
          case 0x5A:  /* AND */
            DO_AND();
            break;
          case 0x5B:  /* OR */
            DO_OR();
            break;
          case 0x5C:  /* NOT */
            DO_NOT();
            break;
          case 0x5D:  /* DELTAP1 */
            insDELTAP();
            break;
          case 0x5E:  /* SDB */
            DO_SDB();
            break;
          case 0x5F:  /* SDS */
            DO_SDS();
            break;
          case 0x60:  /* ADD */
            DO_ADD();
            break;
          case 0x61:  /* SUB */
            DO_SUB();
            break;
          case 0x62:  /* DIV */
            DO_DIV();
            break;
          case 0x63:  /* MUL */
            DO_MUL();
            break;
          case 0x64:  /* ABS */
            DO_ABS();
            break;
          case 0x65:  /* NEG */
            DO_NEG();
            break;
          case 0x66:  /* FLOOR */
            DO_FLOOR();
            break;
          case 0x67:  /* CEILING */
            DO_CEILING();
            break;
          case 0x68:  /* ROUND */
          case 0x69:  /* ROUND */
          case 0x6A:  /* ROUND */
          case 0x6B:  /* ROUND */
            DO_ROUND();
            break;
          case 0x6C:  /* NROUND */
          case 0x6D:  /* NROUND */
          case 0x6E:  /* NRRUND */
          case 0x6F:  /* NROUND */
            DO_NROUND();
            break;
          case 0x70:  /* WCVTF */
            DO_WCVTF();
            break;
          case 0x71:  /* DELTAP2 */
          case 0x72:  /* DELTAP3 */
            insDELTAP();
            break;
          case 0x73:  /* DELTAC0 */
          case 0x74:  /* DELTAC1 */
          case 0x75:  /* DELTAC2 */
            insDELTAC();
            break;
          case 0x76:  /* SROUND */
            DO_SROUND();
            break;
          case 0x77:  /* S45Round */
            DO_S45ROUND();
            break;
          case 0x78:  /* JROT */
            DO_JROT();
            break;
          case 0x79:  /* JROF */
            DO_JROF();
            break;
          case 0x7A:  /* ROFF */
            DO_ROFF();
            break;
          case 0x7B:  /* ???? */
            insUNKNOWN();
            break;
          case 0x7C:  /* RUTG */
            DO_RUTG();
            break;
          case 0x7D:  /* RDTG */
            DO_RDTG();
            break;
          case 0x7E:  /* SANGW */
          case 0x7F:  /* AA    */
            /* nothing - obsolete */
            break;
          case 0x80:  /* FLIPPT */
            insFLIPPT();
            break;
          case 0x81:  /* FLIPRGON */
            insFLIPRGON();
            break;
          case 0x82:  /* FLIPRGOFF */
            insFLIPRGOFF();
            break;
          case 0x83:  /* UNKNOWN */
          case 0x84:  /* UNKNOWN */
            insUNKNOWN();
            break;
          case 0x85:  /* SCANCTRL */
            insSCANCTRL();
            break;
          case 0x86:  /* SDPVTL */
          case 0x87:  /* SDPVTL */
            insSDPVTL();
            break;
          case 0x88:  /* GETINFO */
            insGETINFO();
            break;
          case 0x89:  /* IDEF */
            insIDEF();
            break;
          case 0x8A:  /* ROLL */
            insROLL();
            break;
          case 0x8B:  /* MAX */
            DO_MAX();
            break;
          case 0x8C:  /* MIN */
            DO_MIN();
            break;
          case 0x8D:  /* SCANTYPE */
            insSCANTYPE();
            break;
          case 0x8E:  /* INSTCTRL */
            insINSTCTRL();
            break;
          case 0x8F:
            insUNKNOWN();
            break;
          default:
            if (opcode >= 0xE0) {
              insMIRP();
            } else {
              if (opcode >= 0xC0) {
                insMDRP();
              } else {
                if ( opcode >= 0xB8 ) {
                  insPUSHW();
                } else {
                  if (opcode >= 0xB0) {
                    insPUSHB();
                  } else {
                    insUNKNOWN();
                  }
                }
              }
            }
          }
          boolean useSuiteLabel = false;
          if (cur.error != 0) {
            switch (cur.error) {
              /* looking for redefined instructions */
            case FT_Error.INTERP_INVALID_OPCODE:
            {
              int defIdx = 0;
              TTDefRec def = cur.IDefs[defIdx];
              int limit = defIdx + cur.numIDefs;

              for (defIdx = 0; defIdx < limit; defIdx++) {
                def = cur.IDefs[defIdx];
                if (def.active && cur.opcode == def.opc) {
                  TTCallRec callrec;
  
                  if (cur.callTop >= cur.callSize) {
                    cur.error = FT_Error.INTERP_INVALID_REFERENCE;
                    return LError();
                  }
                  callrec = cur.callStack[cur.callTop];
                  callrec.CallerRange = cur.curRange;
                  callrec.CallerIP = cur.IP + 1;
                  callrec.CurCount = 1;
                  callrec.CurRestart = def.start;
                  callrec.CurEnd = def.end;
                  if (insGotoCodeRange(def.range, (long)def.start) == FAILURE) {
                    return LError();
                  }
                  useSuiteLabel = true;
                  break;
                }
              }
            }
            if (!useSuiteLabel) {
              cur.error = FT_Error.INTERP_INVALID_OPCODE;
              return LError();
            }
            default: 
              return LError();
            }
          }
          if (!useSuiteLabel) {
            cur.top = cur.new_top;
            if (cur.step_ins) {
              cur.IP += cur.length;
            }
            /* increment instruction counter and check if we didn't */
            /* run this program for too long (e.g. infinite loops). */
            if (++ins_counter > MAX_RUNNABLE_OPCODES) {
              return FTError.INTERP_EXECUTION_TOO_LONG;
            }
          }
//Debug(0, DBG_INTERP, TAG, String.format("ll4: %d %d", cur.IP, cur.codeSize));
FTGlyphLoaderRec._showLoaderZone("interp ll4");
          if (cur.IP >= cur.codeSize) {
            if (cur.callTop > 0) {
              cur.error = FTError.INTERP_CODE_OVERFLOW;
              return LError();
            } else {
        	  return FTError.INTERP_ERR_OK;
            }
          }
        }
      } while (!cur.instruction_trap);
      return 1;
    }
    
    private int LErrorCodeOverflow() {
      cur.error = FTError.INTERP_CODE_OVERFLOW;
      return LError();  
    }
  
    private int LError() {
      /* If any errors have occurred, function tables may be broken. */
      /* Force a re-execution of `prep' and `fpgm' tables if no      */
      /* bytecode debugger is run.                                   */
      if (cur.error != FTError.RASTER_ERR_NONE && !cur.instruction_trap) {
//        FT_TRACE1(( "  The interpreter returned error 0x%x\n", cur.error ));
//        exc.size.cvt_ready = false;
      }
      return cur.error;
    }

    /* =====================================================================
     * TTRunContext
     * =====================================================================
     */

    public static int TTRunContext(TTExecContextRec exec, boolean debug) {
      int error = 0;
Debug(0, DBG_INTERP, TAG, String.format("TT_Run_Context %d", TTCodeRange.TT_CODERANGE_GLYPH)+" zp0.cur: "+(Object)exec.zp0.cur+"\n zp1.cur: "+(Object)exec.zp1.cur);
      FTReference<TTExecContextRec> exec_ref = new FTReference<TTExecContextRec>();
      
      exec_ref.Set(exec);
      if ((error = TTSizeFuncs.TTGotoCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_GLYPH, 0L)) != FTError.INTERP_ERR_OK) {
        return error;
      }
      exec = exec_ref.Get();
      exec.zp0 = exec.pts;
      exec.zp1 = exec.pts;
      exec.zp2 = exec.pts;
Debug(0, DBG_INTERP, TAG, "TT_Run_Context2 zp0.cur: "+(Object)exec.zp0.cur+" \nzp1.cur: "+(Object)exec.zp1.cur);
for( int i = 0; i < 6; i++) {
  Debug(0, DBG_INTERP, TAG, String.format("zp1.org: %d x: %d, y: %d\n", i, cur.zp1.org[i].x, cur.zp1.org[i].y));
  Debug(0, DBG_INTERP, TAG, String.format("zp0.org: %d x: %d, y: %d\n", i, cur.zp0.org[i].x, cur.zp0.org[i].y));
}
      exec.GS.gep0 = 1;
      exec.GS.gep1 = 1;
      exec.GS.gep2 = 1;
      exec.GS.projVector.x = 0x4000;
      exec.GS.projVector.y = 0x0000;
      exec.GS.freeVector.x = exec.GS.projVector.x;
      exec.GS.freeVector.y = exec.GS.projVector.y;
      exec.GS.dualVector.x = exec.GS.projVector.x;
      exec.GS.dualVector.y = exec.GS.projVector.y;
      exec.GS.round_state = 1;
      exec.GS.loop = 1;
      /* some glyphs leave something on the stack. so we clean it */
      /* before a new execution.                                  */
      exec.top = 0;
      exec.callTop = 0;
      return (int)exec.face.interpreter.callClassMethod(exec);
    }
}

Added ftbase/TTMaxProfile.java.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// ----------------------------------------------------------------
// TTMaxProfile.java --
//
// Copyright (c) 2014 by Arnulf P. Wiedemann
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//------------------------------------------------------------------------

package ftbase;

//import android.util.Log;

/* ======================================================================= */
/*  This Java implementation is derived from the Freetype code             */
/*  and has been implemented to work together with the Apache batik code   */
/*  for reading .ttf font files                                             */
/*                                                                         */
/*  Copyright (C) of the Java implementation 2014                          */
/*  Arnulf Wiedemann                                                       */
/*                                                                         */
/*  See the file "license.terms" for information on usage and              */
/*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.   */
/*                                                                         */
/*  in this directory the truetype opcode interpreter is ported to Java    */
/*                                                                         */
/*  the next blocks are taken from the original source code                */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
/*            2010 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/* ======================================================================= */

  /* ===================================================================== */
  /*    TTMaxProfile                                                       */
  /*                                                                       */
  /* <Description>                                                         */
  /*    The maximum profile is a table containing many max values which    */
  /*    can be used to pre-allocate arrays.  This ensures that no memory   */
  /*    allocation occurs during a glyph load.                             */
  /*                                                                       */
  /* <Fields>                                                              */
  /*    version               :: The version number.                       */
  /*                                                                       */
  /*    numGlyphs             :: The number of glyphs in this TrueType     */
  /*                             font.                                     */
  /*                                                                       */
  /*    maxPoints             :: The maximum number of points in a         */
  /*                             non-composite TrueType glyph.  See also   */
  /*                             the structure element                     */
  /*                             `maxCompositePoints'.                     */
  /*                                                                       */
  /*    maxContours           :: The maximum number of contours in a       */
  /*                             non-composite TrueType glyph.  See also   */
  /*                             the structure element                     */
  /*                             `maxCompositeContours'.                   */
  /*                                                                       */
  /*    maxCompositePoints    :: The maximum number of points in a         */
  /*                             composite TrueType glyph.  See also the   */
  /*                             structure element `maxPoints'.            */
  /*                                                                       */
  /*    maxCompositeContours  :: The maximum number of contours in a       */
  /*                             composite TrueType glyph.  See also the   */
  /*                             structure element `maxContours'.          */
  /*                                                                       */
  /*    maxZones              :: The maximum number of zones used for      */
  /*                             glyph hinting.                            */
  /*                                                                       */
  /*    maxTwilightPoints     :: The maximum number of points in the       */
  /*                             twilight zone used for glyph hinting.     */
  /*                                                                       */
  /*    maxStorage            :: The maximum number of elements in the     */
  /*                             storage area used for glyph hinting.      */
  /*                                                                       */
  /*    maxFunctionDefs       :: The maximum number of function            */
  /*                             definitions in the TrueType bytecode for  */
  /*                             this font.                                */
  /*                                                                       */
  /*    maxInstructionDefs    :: The maximum number of instruction         */
  /*                             definitions in the TrueType bytecode for  */
  /*                             this font.                                */
  /*                                                                       */
  /*    maxStackElements      :: The maximum number of stack elements used */
  /*                             during bytecode interpretation.           */
  /*                                                                       */
  /*    maxSizeOfInstructions :: The maximum number of TrueType opcodes    */
  /*                             used for glyph hinting.                   */
  /*                                                                       */
  /*    maxComponentElements  :: The maximum number of simple (i.e., non-  */
  /*                             composite) glyphs in a composite glyph.   */
  /*                                                                       */
  /*    maxComponentDepth     :: The maximum nesting depth of composite    */
  /*                             glyphs.                                   */
  /*                                                                       */
  /* <Note>                                                                */
  /*    This structure is only used during font loading.                   */
  /*                                                                       */
  /* ===================================================================== */

public class TTMaxProfile extends FTFrameRead {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTMaxProfile";

    public Long version = 0L;
    public Short numGlyphs = 0;

    public Short maxPoints = 0;
    public Short maxContours = 0;
    public Short maxCompositePoints = 0;
    public Short maxCompositeContours = 0;
    public Short maxZones = 0;
    public Short maxTwilightPoints = 0;
    public Short maxStorage = 0;
    public Short maxFunctionDefs = 0;
    public Short maxInstructionDefs = 0;
    public Short maxStackElements = 0;
    public Short maxSizeOfInstructions = 0;
    public Short maxComponentElements = 0;
    public Short maxComponentDepth = 0;

    /* ==================== TTMaxProfile ================================== */
    public TTMaxProfile() {
      super(null);
    }
    
    /* ==================== TTMaxProfile ================================== */
    public TTMaxProfile(FTStreamRec stream) {
      super(stream);
      oid++;
      id = oid;
      my_class_name = "org.apwtcl.gles20.truetype.TTMaxProfile";
      if (frame_info.size() == 0) {
//        va = new TTInstanceVariable(my_class_name, this, "format_tag", 1);
//        frame_info.add(new FTFrameEntry("format_tag", va, readInt, VAR_IS_INT));
      }
//      fillVariables();
if (FTInit.initDebug > 2) {
System.out.println("TTMaxProfile offset: "+String.format("0x%08x", stream.pos()));
}
      version = (long)stream.readInt(stream);
      numGlyphs = stream.readShort(stream);

    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * =====================================================================
     */
    public int readExtraFields(FTStreamRec stream) {
      maxPoints = stream.readShort(stream);
      maxContours = stream.readShort(stream);
      maxCompositePoints = stream.readShort(stream);
      maxCompositeContours = stream.readShort(stream);
      maxZones = stream.readShort(stream);
      maxTwilightPoints = stream.readShort(stream);
      maxStorage = stream.readShort(stream);
      maxFunctionDefs = stream.readShort(stream);
      maxInstructionDefs = stream.readShort(stream);
      maxStackElements = stream.readShort(stream);
      maxSizeOfInstructions = stream.readShort(stream);
      maxComponentElements = stream.readShort(stream);
      maxComponentDepth = stream.readShort(stream);
      return 0;
    }

}

Added ftbase/TTNameEntryRec.java.









































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTNameEntryRec                                                     */
  /*                                                                       */
  /* <Description>                                                         */
  /*    A structure modeling TrueType name records.  Name records are used */
  /*    to store important strings like family name, style name,           */
  /*    copyright, etc. in _localized_ versions (i.e., language, encoding, */
  /*    etc).                                                              */
  /*                                                                       */
  /* <Fields>                                                              */
  /*    platformID   :: The ID of the name's encoding platform.            */
  /*                                                                       */
  /*    encodingID   :: The platform-specific ID for the name's encoding.  */
  /*                                                                       */
  /*    languageID   :: The platform-specific ID for the name's language.  */
  /*                                                                       */
  /*    nameID       :: The ID specifying what kind of name this is.       */
  /*                                                                       */
  /*    stringLength :: The length of the string in bytes.                 */
  /*                                                                       */
  /*    stringOffset :: The offset to the string in the `name' table.      */
  /*                                                                       */
  /*    string       :: A pointer to the string's bytes.  Note that these  */
  /*                    are usually UTF-16 encoded characters.             */
  /*                                                                       */
  /* ===================================================================== */

public class TTNameEntryRec extends FTFrameRead {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTNameEntryRec";

    public Short platformID = 0;
    public Short encodingID = 0;
    public Short languageID = 0;
    public Short nameID = 0;
    public Short stringLength = 0;
    public Long stringOffset = 0L;
    /* this last field is not defined in the spec */
    /* but used by the FreeType engine            */
    public byte[] string = null;

    /* ==================== TTNameEntryRec ================================== */
    public TTNameEntryRec() {
      super(null);
    }
    
    /* ==================== TTNameEntryRec ================================== */
    public TTNameEntryRec(FTStreamRec stream) {
      super(stream);
      oid++;
      id = oid;
      my_class_name = "org.apwtcl.gles20.truetype.TTNameEntryRec";
      if (frame_info.size() == 0) {
//        va = new FTInstanceVariable(my_class_name, this, "format_tag", 1);
//        frame_info.add(new FTFrameEntry("format_tag", va, readInt, VAR_IS_INT));
      }
//      fillVariables();
Debug(0, DBG_INIT, TAG, "TTNameEntryRec offset: "+String.format("0x%08x", stream.pos()));
      platformID = stream.readShort(stream);
      encodingID = stream.readShort(stream);
      languageID = stream.readShort(stream);
      nameID = stream.readShort(stream);
      stringLength = stream.readShort(stream);
      stringOffset = (long)stream.readInt(stream);
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTNameTableRec.java.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

import android.util.Log;

  /* ===================================================================== */
  /*    TTNameTableRec                                                     */
  /*                                                                       */
  /* <Description>                                                         */
  /*    A structure modeling the TrueType name table.                      */
  /*                                                                       */
  /* <Fields>                                                              */
  /*    format         :: The format of the name table.                    */
  /*                                                                       */
  /*    numNameRecords :: The number of names in table.                    */
  /*                                                                       */
  /*    storageOffset  :: The offset of the name table in the `name'       */
  /*                      TrueType table.                                  */
  /*                                                                       */
  /*    names          :: An array of name records.                        */
  /*                                                                       */
  /*    stream         :: the file's input stream.                         */
  /*                                                                       */
  /* ===================================================================== */

public class TTNameTableRec extends FTFrameRead {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTNameTableRec";

    /* =========================================================================
     *
     * @enum:
     *   TT_PLATFORM_XXX
     *
     * @description:
     *   A list of valid values for the `platform_id' identifier code in
     *   @FT_CharMapRec and @FT_SfntName structures.
     *
     * @values:
     *   TT_PLATFORM_APPLE_UNICODE ::
     *     Used by Apple to indicate a Unicode character map and/or name entry.
     *     See @TT_APPLE_ID_XXX for corresponding `encoding_id' values.  Note
     *     that name entries in this format are coded as big-endian UCS-2
     *     character codes _only_.
     *
     *   TT_PLATFORM_MACINTOSH ::
     *     Used by Apple to indicate a MacOS-specific charmap and/or name entry.
     *     See @TT_MAC_ID_XXX for corresponding `encoding_id' values.  Note that
     *     most TrueType fonts contain an Apple roman charmap to be usable on
     *     MacOS systems (even if they contain a Microsoft charmap as well).
     *
     *   TT_PLATFORM_ISO ::
     *     This value was used to specify ISO/IEC 10646 charmaps.  It is however
     *     now deprecated.  See @TT_ISO_ID_XXX for a list of corresponding
     *     `encoding_id' values.
     *
     *   TT_PLATFORM_MICROSOFT ::
     *     Used by Microsoft to indicate Windows-specific charmaps.  See
     *     @TT_MS_ID_XXX for a list of corresponding `encoding_id' values.
     *     Note that most fonts contain a Unicode charmap using
     *     (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS).
     *
     *   TT_PLATFORM_CUSTOM ::
     *     Used to indicate application-specific charmaps.
     *
     *   TT_PLATFORM_ADOBE ::
     *     This value isn't part of any font format specification, but is used
     *     by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec
     *     structure.  See @TT_ADOBE_ID_XXX.
     * =========================================================================
     */

    public final static int TT_PLATFORM_APPLE_UNICODE = 0;
    public final static int TT_PLATFORM_MACINTOSH     = 1;
    public final static int TT_PLATFORM_ISO           = 2; /* deprecated */
    public final static int TT_PLATFORM_MICROSOFT     = 3;
    public final static int TT_PLATFORM_CUSTOM        = 4;
    public final static int TT_PLATFORM_ADOBE         = 7; /* artificial */

    /* =========================================================================
     *
     * @enum:
     *   TT_APPLE_ID_XXX
     *
     * @description:
     *   A list of valid values for the `encoding_id' for
     *   @TT_PLATFORM_APPLE_UNICODE charmaps and name entries.
     *
     * @values:
     *   TT_APPLE_ID_DEFAULT ::
     *     Unicode version 1.0.
     *
     *   TT_APPLE_ID_UNICODE_1_1 ::
     *     Unicode 1.1; specifies Hangul characters starting at U+34xx.
     *
     *   TT_APPLE_ID_ISO_10646 ::
     *     Deprecated (identical to preceding).
     *
     *   TT_APPLE_ID_UNICODE_2_0 ::
     *     Unicode 2.0 and beyond (UTF-16 BMP only).
     *
     *   TT_APPLE_ID_UNICODE_32 ::
     *     Unicode 3.1 and beyond, using UTF-32.
     *
     *   TT_APPLE_ID_VARIANT_SELECTOR ::
     *     From Adobe, not Apple.  Not a normal cmap.  Specifies variations
     *     on a real cmap.
     * =========================================================================
     */
  
    public final static int TT_APPLE_ID_DEFAULT           = 0; /* Unicode 1.0 */
    public final static int TT_APPLE_ID_UNICODE_1_1       = 1; /* specify Hangul at U+34xx */
    public final static int TT_APPLE_ID_ISO_10646         = 2; /* deprecated */
    public final static int TT_APPLE_ID_UNICODE_2_0       = 3; /* or later */
    public final static int TT_APPLE_ID_UNICODE_32        = 4; /* 2.0 or later, full repertoire */
    public final static int TT_APPLE_ID_VARIANT_SELECTOR  = 5; /* variation selector data */

    /* =========================================================================
     *
     * @enum:
     *   TT_MAC_ID_XXX
     *
     * @description:
     *   A list of valid values for the `encoding_id' for
     *   @TT_PLATFORM_MACINTOSH charmaps and name entries.
     *
     * @values:
     *   TT_MAC_ID_ROMAN ::
     *   TT_MAC_ID_JAPANESE ::
     *   TT_MAC_ID_TRADITIONAL_CHINESE ::
     *   TT_MAC_ID_KOREAN ::
     *   TT_MAC_ID_ARABIC ::
     *   TT_MAC_ID_HEBREW ::
     *   TT_MAC_ID_GREEK ::
     *   TT_MAC_ID_RUSSIAN ::
     *   TT_MAC_ID_RSYMBOL ::
     *   TT_MAC_ID_DEVANAGARI ::
     *   TT_MAC_ID_GURMUKHI ::
     *   TT_MAC_ID_GUJARATI ::
     *   TT_MAC_ID_ORIYA ::
     *   TT_MAC_ID_BENGALI ::
     *   TT_MAC_ID_TAMIL ::
     *   TT_MAC_ID_TELUGU ::
     *   TT_MAC_ID_KANNADA ::
     *   TT_MAC_ID_MALAYALAM ::
     *   TT_MAC_ID_SINHALESE ::
     *   TT_MAC_ID_BURMESE ::
     *   TT_MAC_ID_KHMER ::
     *   TT_MAC_ID_THAI ::
     *   TT_MAC_ID_LAOTIAN ::
     *   TT_MAC_ID_GEORGIAN ::
     *   TT_MAC_ID_ARMENIAN ::
     *   TT_MAC_ID_MALDIVIAN ::
     *   TT_MAC_ID_SIMPLIFIED_CHINESE ::
     *   TT_MAC_ID_TIBETAN ::
     *   TT_MAC_ID_MONGOLIAN ::
     *   TT_MAC_ID_GEEZ ::
     *   TT_MAC_ID_SLAVIC ::
     *   TT_MAC_ID_VIETNAMESE ::
     *   TT_MAC_ID_SINDHI ::
     *   TT_MAC_ID_UNINTERP ::
     * =========================================================================
     */
  
    public final static int TT_MAC_ID_ROMAN              =  0;
    public final static int TT_MAC_ID_JAPANESE           =  1;
    public final static int TT_MAC_ID_TRADITIONAL_CHINESE=  2;
    public final static int TT_MAC_ID_KOREAN             =  3;
    public final static int TT_MAC_ID_ARABIC             =  4;
    public final static int TT_MAC_ID_HEBREW             =  5;
    public final static int TT_MAC_ID_GREEK              =  6;
    public final static int TT_MAC_ID_RUSSIAN            =  7;
    public final static int TT_MAC_ID_RSYMBOL            =  8;
    public final static int TT_MAC_ID_DEVANAGARI         =  9;
    public final static int TT_MAC_ID_GURMUKHI           = 10;
    public final static int TT_MAC_ID_GUJARATI           = 11;
    public final static int TT_MAC_ID_ORIYA              = 12;
    public final static int TT_MAC_ID_BENGALI            = 13;
    public final static int TT_MAC_ID_TAMIL              = 14;
    public final static int TT_MAC_ID_TELUGU             = 15;
    public final static int TT_MAC_ID_KANNADA            = 16;
    public final static int TT_MAC_ID_MALAYALAM          = 17;
    public final static int TT_MAC_ID_SINHALESE          = 18;
    public final static int TT_MAC_ID_BURMESE            = 19;
    public final static int TT_MAC_ID_KHMER              = 20;
    public final static int TT_MAC_ID_THAI               = 21;
    public final static int TT_MAC_ID_LAOTIAN            = 22;
    public final static int TT_MAC_ID_GEORGIAN           = 23;
    public final static int TT_MAC_ID_ARMENIAN           = 24;
    public final static int TT_MAC_ID_MALDIVIAN          = 25;
    public final static int TT_MAC_ID_SIMPLIFIED_CHINESE = 25;
    public final static int TT_MAC_ID_TIBETAN            = 26;
    public final static int TT_MAC_ID_MONGOLIAN          = 27;
    public final static int TT_MAC_ID_GEEZ               = 28;
    public final static int TT_MAC_ID_SLAVIC             = 29;
    public final static int TT_MAC_ID_VIETNAMESE         = 30;
    public final static int TT_MAC_ID_SINDHI             = 31;
    public final static int TT_MAC_ID_UNINTERP           = 32;

    /* =========================================================================
     *
     * @enum:
     *   TT_ISO_ID_XXX
     *
     * @description:
     *   A list of valid values for the `encoding_id' for
     *   @TT_PLATFORM_ISO charmaps and name entries.
     *
     *   Their use is now deprecated.
     *
     * @values:
     *   TT_ISO_ID_7BIT_ASCII ::
     *     ASCII.
     *   TT_ISO_ID_10646 ::
     *     ISO/10646.
     *   TT_ISO_ID_8859_1 ::
     *     Also known as Latin-1.
     * =========================================================================
     */
    public final static int TT_ISO_ID_7BIT_ASCII = 0;
    public final static int TT_ISO_ID_10646      = 1;
    public final static int TT_ISO_ID_8859_1     = 2;

    /* =========================================================================
     *
     * @enum:
     *   TT_MS_ID_XXX
     *
     * @description:
     *   A list of valid values for the `encoding_id' for
     *   @TT_PLATFORM_MICROSOFT charmaps and name entries.
     *
     * @values:
     *   TT_MS_ID_SYMBOL_CS ::
     *     Corresponds to Microsoft symbol encoding. See
     *     @FT_ENCODING_MS_SYMBOL.
     *
     *   TT_MS_ID_UNICODE_CS ::
     *     Corresponds to a Microsoft WGL4 charmap, matching Unicode.  See
     *     @FT_ENCODING_UNICODE.
     *
     *   TT_MS_ID_SJIS ::
     *     Corresponds to SJIS Japanese encoding.  See @FT_ENCODING_SJIS.
     *
     *   TT_MS_ID_GB2312 ::
     *     Corresponds to Simplified Chinese as used in Mainland China.  See
     *     @FT_ENCODING_GB2312.
     *
     *   TT_MS_ID_BIG_5 ::
     *     Corresponds to Traditional Chinese as used in Taiwan and Hong Kong.
     *     See @FT_ENCODING_BIG5.
     *
     *   TT_MS_ID_WANSUNG ::
     *     Corresponds to Korean Wansung encoding.  See @FT_ENCODING_WANSUNG.
     *
     *   TT_MS_ID_JOHAB ::
     *     Corresponds to Johab encoding.  See @FT_ENCODING_JOHAB.
     *
     *   TT_MS_ID_UCS_4 ::
     *     Corresponds to UCS-4 or UTF-32 charmaps.  This has been added to
     *     the OpenType specification version 1.4 (mid-2001.)
     * =========================================================================
     */
    public final static int TT_MS_ID_SYMBOL_CS  =  0;
    public final static int TT_MS_ID_UNICODE_CS =  1;
    public final static int TT_MS_ID_SJIS       =  2;
    public final static int TT_MS_ID_GB2312     =  3;
    public final static int TT_MS_ID_BIG_5      =  4;
    public final static int TT_MS_ID_WANSUNG    =  5;
    public final static int TT_MS_ID_JOHAB      =  6;
    public final static int TT_MS_ID_UCS_4      = 10;

    /* =========================================================================
     *
     * @enum:
     *   TT_ADOBE_ID_XXX
     *
     * @description:
     *   A list of valid values for the `encoding_id' for
     *   @TT_PLATFORM_ADOBE charmaps.  This is a FreeType-specific extension!
     *
     * @values:
     *   TT_ADOBE_ID_STANDARD ::
     *     Adobe standard encoding.
     *   TT_ADOBE_ID_EXPERT ::
     *     Adobe expert encoding.
     *   TT_ADOBE_ID_CUSTOM ::
     *     Adobe custom encoding.
     *   TT_ADOBE_ID_LATIN_1 ::
     *     Adobe Latin~1 encoding.
     * =========================================================================
     */
    public final static int TT_ADOBE_ID_STANDARD = 0;
    public final static int TT_ADOBE_ID_EXPERT   = 1;
    public final static int TT_ADOBE_ID_CUSTOM   = 2;
    public final static int TT_ADOBE_ID_LATIN_1  = 3;

    /* =========================================================================
     *
     * Possible values of the language identifier field in the name records
     * of the TTF `name' table if the `platform' identifier code is
     * TT_PLATFORM_MACINTOSH.  These values are also used as return values
     * for function @FT_Get_CMap_Language_ID.
     *
     * The canonical source for the Apple assigned Language ID's is at
     *
     *   https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html
     *
     * =========================================================================
     */
    public final static int TT_MAC_LANGID_ENGLISH                     =   0;
    public final static int TT_MAC_LANGID_FRENCH                      =   1;
    public final static int TT_MAC_LANGID_GERMAN                      =   2;
    public final static int TT_MAC_LANGID_ITALIAN                     =   3;
    public final static int TT_MAC_LANGID_DUTCH                       =   4;
    public final static int TT_MAC_LANGID_SWEDISH                     =   5;
    public final static int TT_MAC_LANGID_SPANISH                     =   6;
    public final static int TT_MAC_LANGID_DANISH                      =   7;
    public final static int TT_MAC_LANGID_PORTUGUESE                  =   8;
    public final static int TT_MAC_LANGID_NORWEGIAN                   =   9;
    public final static int TT_MAC_LANGID_HEBREW                      =  10;
    public final static int TT_MAC_LANGID_JAPANESE                    =  11;
    public final static int TT_MAC_LANGID_ARABIC                      =  12;
    public final static int TT_MAC_LANGID_FINNISH                     =  13;
    public final static int TT_MAC_LANGID_GREEK                       =  14;
    public final static int TT_MAC_LANGID_ICELANDIC                   =  15;
    public final static int TT_MAC_LANGID_MALTESE                     =  16;
    public final static int TT_MAC_LANGID_TURKISH                     =  17;
    public final static int TT_MAC_LANGID_CROATIAN                    =  18;
    public final static int TT_MAC_LANGID_CHINESE_TRADITIONAL         =  19;
    public final static int TT_MAC_LANGID_URDU                        =  20;
    public final static int TT_MAC_LANGID_HINDI                       =  21;
    public final static int TT_MAC_LANGID_THAI                        =  22;
    public final static int TT_MAC_LANGID_KOREAN                      =  23;
    public final static int TT_MAC_LANGID_LITHUANIAN                  =  24;
    public final static int TT_MAC_LANGID_POLISH                      =  25;
    public final static int TT_MAC_LANGID_HUNGARIAN                   =  26;
    public final static int TT_MAC_LANGID_ESTONIAN                    =  27;
    public final static int TT_MAC_LANGID_LETTISH                     =  28;
    public final static int TT_MAC_LANGID_SAAMISK                     =  29;
    public final static int TT_MAC_LANGID_FAEROESE                    =  30;
    public final static int TT_MAC_LANGID_FARSI                       =  31;
    public final static int TT_MAC_LANGID_RUSSIAN                     =  32;
    public final static int TT_MAC_LANGID_CHINESE_SIMPLIFIED          =  33;
    public final static int TT_MAC_LANGID_FLEMISH                     =  34;
    public final static int TT_MAC_LANGID_IRISH                       =  35;
    public final static int TT_MAC_LANGID_ALBANIAN                    =  36;
    public final static int TT_MAC_LANGID_ROMANIAN                    =  37;
    public final static int TT_MAC_LANGID_CZECH                       =  38;
    public final static int TT_MAC_LANGID_SLOVAK                      =  39;
    public final static int TT_MAC_LANGID_SLOVENIAN                   =  40;
    public final static int TT_MAC_LANGID_YIDDISH                     =  41;
    public final static int TT_MAC_LANGID_SERBIAN                     =  42;
    public final static int TT_MAC_LANGID_MACEDONIAN                  =  43;
    public final static int TT_MAC_LANGID_BULGARIAN                   =  44;
    public final static int TT_MAC_LANGID_UKRAINIAN                   =  45;
    public final static int TT_MAC_LANGID_BYELORUSSIAN                =  46;
    public final static int TT_MAC_LANGID_UZBEK                       =  47;
    public final static int TT_MAC_LANGID_KAZAKH                      =  48;
    public final static int TT_MAC_LANGID_AZERBAIJANI                 =  49;
    public final static int TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT =  49;
    public final static int TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT   =  50;
    public final static int TT_MAC_LANGID_ARMENIAN                    =  51;
    public final static int TT_MAC_LANGID_GEORGIAN                    =  52;
    public final static int TT_MAC_LANGID_MOLDAVIAN                   =  53;
    public final static int TT_MAC_LANGID_KIRGHIZ                     =  54;
    public final static int TT_MAC_LANGID_TAJIKI                      =  55;
    public final static int TT_MAC_LANGID_TURKMEN                     =  56;
    public final static int TT_MAC_LANGID_MONGOLIAN                   =  57;
    public final static int TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT  =  57;
    public final static int TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT   =  58;
    public final static int TT_MAC_LANGID_PASHTO                      =  59;
    public final static int TT_MAC_LANGID_KURDISH                     =  60;
    public final static int TT_MAC_LANGID_KASHMIRI                    =  61;
    public final static int TT_MAC_LANGID_SINDHI                      =  62;
    public final static int TT_MAC_LANGID_TIBETAN                     =  63;
    public final static int TT_MAC_LANGID_NEPALI                      =  64;
    public final static int TT_MAC_LANGID_SANSKRIT                    =  65;
    public final static int TT_MAC_LANGID_MARATHI                     =  66;
    public final static int TT_MAC_LANGID_BENGALI                     =  67;
    public final static int TT_MAC_LANGID_ASSAMESE                    =  68;
    public final static int TT_MAC_LANGID_GUJARATI                    =  69;
    public final static int TT_MAC_LANGID_PUNJABI                     =  70;
    public final static int TT_MAC_LANGID_ORIYA                       =  71;
    public final static int TT_MAC_LANGID_MALAYALAM                   =  72;
    public final static int TT_MAC_LANGID_KANNADA                     =  73;
    public final static int TT_MAC_LANGID_TAMIL                       =  74;
    public final static int TT_MAC_LANGID_TELUGU                      =  75;
    public final static int TT_MAC_LANGID_SINHALESE                   =  76;
    public final static int TT_MAC_LANGID_BURMESE                     =  77;
    public final static int TT_MAC_LANGID_KHMER                       =  78;
    public final static int TT_MAC_LANGID_LAO                         =  79;
    public final static int TT_MAC_LANGID_VIETNAMESE                  =  80;
    public final static int TT_MAC_LANGID_INDONESIAN                  =  81;
    public final static int TT_MAC_LANGID_TAGALOG                     =  82;
    public final static int TT_MAC_LANGID_MALAY_ROMAN_SCRIPT          =  83;
    public final static int TT_MAC_LANGID_MALAY_ARABIC_SCRIPT         =  84;
    public final static int TT_MAC_LANGID_AMHARIC                     =  85;
    public final static int TT_MAC_LANGID_TIGRINYA                    =  86;
    public final static int TT_MAC_LANGID_GALLA                       =  87;
    public final static int TT_MAC_LANGID_SOMALI                      =  88;
    public final static int TT_MAC_LANGID_SWAHILI                     =  89;
    public final static int TT_MAC_LANGID_RUANDA                      =  90;
    public final static int TT_MAC_LANGID_RUNDI                       =  91;
    public final static int TT_MAC_LANGID_CHEWA                       =  92;
    public final static int TT_MAC_LANGID_MALAGASY                    =  93;
    public final static int TT_MAC_LANGID_ESPERANTO                   =  94;
    public final static int TT_MAC_LANGID_WELSH                       = 128;
    public final static int TT_MAC_LANGID_BASQUE                      = 129;
    public final static int TT_MAC_LANGID_CATALAN                     = 130;
    public final static int TT_MAC_LANGID_LATIN                       = 131;
    public final static int TT_MAC_LANGID_QUECHUA                     = 132;
    public final static int TT_MAC_LANGID_GUARANI                     = 133;
    public final static int TT_MAC_LANGID_AYMARA                      = 134;
    public final static int TT_MAC_LANGID_TATAR                       = 135;
    public final static int TT_MAC_LANGID_UIGHUR                      = 136;
    public final static int TT_MAC_LANGID_DZONGKHA                    = 137;
    public final static int TT_MAC_LANGID_JAVANESE                    = 138;
    public final static int TT_MAC_LANGID_SUNDANESE                   = 139;
  /* The following codes are new as of 2000-03-10 */
    public final static int TT_MAC_LANGID_GALICIAN                    = 140;
    public final static int TT_MAC_LANGID_AFRIKAANS                   = 141;
    public final static int TT_MAC_LANGID_BRETON                      = 142;
    public final static int TT_MAC_LANGID_INUKTITUT                   = 143;
    public final static int TT_MAC_LANGID_SCOTTISH_GAELIC             = 144;
    public final static int TT_MAC_LANGID_MANX_GAELIC                 = 145;
    public final static int TT_MAC_LANGID_IRISH_GAELIC                = 146;
    public final static int TT_MAC_LANGID_TONGAN                      = 147;
    public final static int TT_MAC_LANGID_GREEK_POLYTONIC             = 148;
    public final static int TT_MAC_LANGID_GREELANDIC                  = 149;
    public final static int TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT    = 150;

    /* =========================================================================
     *
     * Possible values of the language identifier field in the name records
     * of the TTF `name' table if the `platform' identifier code is
     * TT_PLATFORM_MICROSOFT.
     *
     * The canonical source for the MS assigned LCIDs is
     *
     *   http://www.microsoft.com/globaldev/reference/lcid-all.mspx
     *
     * =========================================================================
     */
    public final static int TT_MS_LANGID_ARABIC_GENERAL                    = 0x0001;
    public final static int TT_MS_LANGID_ARABIC_SAUDI_ARABIA               = 0x0401;
    public final static int TT_MS_LANGID_ARABIC_IRAQ                       = 0x0801;
    public final static int TT_MS_LANGID_ARABIC_EGYPT                      = 0x0c01;
    public final static int TT_MS_LANGID_ARABIC_LIBYA                      = 0x1001;
    public final static int TT_MS_LANGID_ARABIC_ALGERIA                    = 0x1401;
    public final static int TT_MS_LANGID_ARABIC_MOROCCO                    = 0x1801;
    public final static int TT_MS_LANGID_ARABIC_TUNISIA                    = 0x1c01;
    public final static int TT_MS_LANGID_ARABIC_OMAN                       = 0x2001;
    public final static int TT_MS_LANGID_ARABIC_YEMEN                      = 0x2401;
    public final static int TT_MS_LANGID_ARABIC_SYRIA                      = 0x2801;
    public final static int TT_MS_LANGID_ARABIC_JORDAN                     = 0x2c01;
    public final static int TT_MS_LANGID_ARABIC_LEBANON                    = 0x3001;
    public final static int TT_MS_LANGID_ARABIC_KUWAIT                     = 0x3401;
    public final static int TT_MS_LANGID_ARABIC_UAE                        = 0x3801;
    public final static int TT_MS_LANGID_ARABIC_BAHRAIN                    = 0x3c01;
    public final static int TT_MS_LANGID_ARABIC_QATAR                      = 0x4001;
    public final static int TT_MS_LANGID_BULGARIAN_BULGARIA                = 0x0402;
    public final static int TT_MS_LANGID_CATALAN_SPAIN                     = 0x0403;
    public final static int TT_MS_LANGID_CHINESE_GENERAL                   = 0x0004;
    public final static int TT_MS_LANGID_CHINESE_TAIWAN                    = 0x0404;
    public final static int TT_MS_LANGID_CHINESE_PRC                       = 0x0804;
    public final static int TT_MS_LANGID_CHINESE_HONG_KONG                 = 0x0c04;
    public final static int TT_MS_LANGID_CHINESE_SINGAPORE                 = 0x1004;
    public final static int TT_MS_LANGID_CHINESE_MACAU                     = 0x1404;
    public final static int TT_MS_LANGID_CZECH_CZECH_REPUBLIC              = 0x0405;
    public final static int TT_MS_LANGID_DANISH_DENMARK                    = 0x0406;
    public final static int TT_MS_LANGID_GERMAN_GERMANY                    = 0x0407;
    public final static int TT_MS_LANGID_GERMAN_SWITZERLAND                = 0x0807;
    public final static int TT_MS_LANGID_GERMAN_AUSTRIA                    = 0x0c07;
    public final static int TT_MS_LANGID_GERMAN_LUXEMBOURG                 = 0x1007;
    public final static int TT_MS_LANGID_GERMAN_LIECHTENSTEI               = 0x1407;
    public final static int TT_MS_LANGID_GREEK_GREECE                      = 0x0408;
    public final static int TT_MS_LANGID_ENGLISH_GENERAL                   = 0x0009;
    public final static int TT_MS_LANGID_ENGLISH_UNITED_STATES             = 0x0409;
    public final static int TT_MS_LANGID_ENGLISH_UNITED_KINGDOM            = 0x0809;
    public final static int TT_MS_LANGID_ENGLISH_AUSTRALIA                 = 0x0c09;
    public final static int TT_MS_LANGID_ENGLISH_CANADA                    = 0x1009;
    public final static int TT_MS_LANGID_ENGLISH_NEW_ZEALAND               = 0x1409;
    public final static int TT_MS_LANGID_ENGLISH_IRELAND                   = 0x1809;
    public final static int TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              = 0x1c09;
    public final static int TT_MS_LANGID_ENGLISH_JAMAICA                   = 0x2009;
    public final static int TT_MS_LANGID_ENGLISH_CARIBBEAN                 = 0x2409;
    public final static int TT_MS_LANGID_ENGLISH_BELIZE                    = 0x2809;
    public final static int TT_MS_LANGID_ENGLISH_TRINIDAD                  = 0x2c09;
    public final static int TT_MS_LANGID_ENGLISH_ZIMBABWE                  = 0x3009;
    public final static int TT_MS_LANGID_ENGLISH_PHILIPPINES               = 0x3409;
    public final static int TT_MS_LANGID_ENGLISH_INDONESIA                 = 0x3809;
    public final static int TT_MS_LANGID_ENGLISH_HONG_KONG                 = 0x3c09;
    public final static int TT_MS_LANGID_ENGLISH_INDIA                     = 0x4009;
    public final static int TT_MS_LANGID_ENGLISH_MALAYSIA                  = 0x4409;
    public final static int TT_MS_LANGID_ENGLISH_SINGAPORE                 = 0x4809;
    public final static int TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    = 0x040a;
    public final static int TT_MS_LANGID_SPANISH_MEXICO                    = 0x080a;
    public final static int TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT  = 0x0c0a;
    public final static int TT_MS_LANGID_SPANISH_GUATEMALA                 = 0x100a;
    public final static int TT_MS_LANGID_SPANISH_COSTA_RICA                = 0x140a;
    public final static int TT_MS_LANGID_SPANISH_PANAMA                    = 0x180a;
    public final static int TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        = 0x1c0a;
    public final static int TT_MS_LANGID_SPANISH_VENEZUELA                 = 0x200a;
    public final static int TT_MS_LANGID_SPANISH_COLOMBIA                  = 0x240a;
    public final static int TT_MS_LANGID_SPANISH_PERU                      = 0x280a;
    public final static int TT_MS_LANGID_SPANISH_ARGENTINA                 = 0x2c0a;
    public final static int TT_MS_LANGID_SPANISH_ECUADOR                   = 0x300a;
    public final static int TT_MS_LANGID_SPANISH_CHILE                     = 0x340a;
    public final static int TT_MS_LANGID_SPANISH_URUGUAY                   = 0x380a;
    public final static int TT_MS_LANGID_SPANISH_PARAGUAY                  = 0x3c0a;
    public final static int TT_MS_LANGID_SPANISH_BOLIVIA                   = 0x400a;
    public final static int TT_MS_LANGID_SPANISH_EL_SALVADOR               = 0x440a;
    public final static int TT_MS_LANGID_SPANISH_HONDURAS                  = 0x480a;
    public final static int TT_MS_LANGID_SPANISH_NICARAGUA                 = 0x4c0a;
    public final static int TT_MS_LANGID_SPANISH_PUERTO_RICO               = 0x500a;
    public final static int TT_MS_LANGID_SPANISH_UNITED_STATES             = 0x540a;
      /* The following ID blatantly violate MS specs by using a */
      /* sublanguage > 0x1F.                                    */
    public final static int TT_MS_LANGID_SPANISH_LATIN_AMERICA             = 0xE40a;
    public final static int TT_MS_LANGID_FINNISH_FINLAND                   = 0x040b;
    public final static int TT_MS_LANGID_FRENCH_FRANCE                     = 0x040c;
    public final static int TT_MS_LANGID_FRENCH_BELGIUM                    = 0x080c;
    public final static int TT_MS_LANGID_FRENCH_CANADA                     = 0x0c0c;
    public final static int TT_MS_LANGID_FRENCH_SWITZERLAND                = 0x100c;
    public final static int TT_MS_LANGID_FRENCH_LUXEMBOURG                 = 0x140c;
    public final static int TT_MS_LANGID_FRENCH_MONACO                     = 0x180c;
    public final static int TT_MS_LANGID_FRENCH_WEST_INDIES                = 0x1c0c;
    public final static int TT_MS_LANGID_FRENCH_REUNION                    = 0x200c;
    public final static int TT_MS_LANGID_FRENCH_CONGO                      = 0x240c;
      /* which was formerly: */
    public final static int TT_MS_LANGID_FRENCH_ZAIRE                      = 0x240c;
    public final static int TT_MS_LANGID_FRENCH_SENEGAL                    = 0x280c;
    public final static int TT_MS_LANGID_FRENCH_CAMEROON                   = 0x2c0c;
    public final static int TT_MS_LANGID_FRENCH_COTE_D_IVOIRE              = 0x300c;
    public final static int TT_MS_LANGID_FRENCH_MALI                       = 0x340c;
    public final static int TT_MS_LANGID_FRENCH_MOROCCO                    = 0x380c;
    public final static int TT_MS_LANGID_FRENCH_HAITI                      = 0x3c0c;
      /* and another violation of the spec (see 0xE40aU) */
    public final static int TT_MS_LANGID_FRENCH_NORTH_AFRICA               = 0xE40c;
    public final static int TT_MS_LANGID_HEBREW_ISRAEL                     = 0x040d;
    public final static int TT_MS_LANGID_HUNGARIAN_HUNGARY                 = 0x040e;
    public final static int TT_MS_LANGID_ICELANDIC_ICELAND                 = 0x040f;
    public final static int TT_MS_LANGID_ITALIAN_ITALY                     = 0x0410;
    public final static int TT_MS_LANGID_ITALIAN_SWITZERLAND               = 0x0810;
    public final static int TT_MS_LANGID_JAPANESE_JAPAN                    = 0x0411;
    public final static int TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA     = 0x0412;
    public final static int TT_MS_LANGID_KOREAN_JOHAB_KOREA                = 0x0812;
    public final static int TT_MS_LANGID_DUTCH_NETHERLANDS                 = 0x0413;
    public final static int TT_MS_LANGID_DUTCH_BELGIUM                     = 0x0813;
    public final static int TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL           = 0x0414;
    public final static int TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK          = 0x0814;
    public final static int TT_MS_LANGID_POLISH_POLAND                     = 0x0415;
    public final static int TT_MS_LANGID_PORTUGUESE_BRAZIL                 = 0x0416;
    public final static int TT_MS_LANGID_PORTUGUESE_PORTUGAL               = 0x0816;
    public final static int TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND        = 0x0417;
    public final static int TT_MS_LANGID_ROMANIAN_ROMANIA                  = 0x0418;
    public final static int TT_MS_LANGID_MOLDAVIAN_MOLDAVIA                = 0x0818;
    public final static int TT_MS_LANGID_RUSSIAN_RUSSIA                    = 0x0419;
    public final static int TT_MS_LANGID_RUSSIAN_MOLDAVIA                  = 0x0819;
    public final static int TT_MS_LANGID_CROATIAN_CROATIA                  = 0x041a;
    public final static int TT_MS_LANGID_SERBIAN_SERBIA_LATIN              = 0x081a;
    public final static int TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           = 0x0c1a;
    public final static int TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA       = 0x101a;
    public final static int TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        = 0x141a;
      /* and XPsp2 Platform SDK added (2004-07-26) */
      /* Names are shortened to be significant within 40 chars. */
    public final static int TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN         = 0x181a;
    public final static int TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC      = 0x181a;
    public final static int TT_MS_LANGID_SLOVAK_SLOVAKIA                   = 0x041b;
    public final static int TT_MS_LANGID_ALBANIAN_ALBANIA                  = 0x041c;
    public final static int TT_MS_LANGID_SWEDISH_SWEDEN                    = 0x041d;
    public final static int TT_MS_LANGID_SWEDISH_FINLAND                   = 0x081d;
    public final static int TT_MS_LANGID_THAI_THAILAND                     = 0x041e;
    public final static int TT_MS_LANGID_TURKISH_TURKEY                    = 0x041f;
    public final static int TT_MS_LANGID_URDU_PAKISTAN                     = 0x0420;
    public final static int TT_MS_LANGID_URDU_INDIA                        = 0x0820;
    public final static int TT_MS_LANGID_INDONESIAN_INDONESIA              = 0x0421;
    public final static int TT_MS_LANGID_UKRAINIAN_UKRAINE                 = 0x0422;
    public final static int TT_MS_LANGID_BELARUSIAN_BELARUS                = 0x0423;
    public final static int TT_MS_LANGID_SLOVENE_SLOVENIA                  = 0x0424;
    public final static int TT_MS_LANGID_ESTONIAN_ESTONIA                  = 0x0425;
    public final static int TT_MS_LANGID_LATVIAN_LATVIA                    = 0x0426;
    public final static int TT_MS_LANGID_LITHUANIAN_LITHUANIA              = 0x0427;
    public final static int TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA      = 0x0827;
    public final static int TT_MS_LANGID_TAJIK_TAJIKISTAN                  = 0x0428;
    public final static int TT_MS_LANGID_FARSI_IRAN                        = 0x0429;
    public final static int TT_MS_LANGID_VIETNAMESE_VIET_NAM               = 0x042a;
    public final static int TT_MS_LANGID_ARMENIAN_ARMENIA                  = 0x042b;
    public final static int TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            = 0x042c;
    public final static int TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         = 0x082c;
    public final static int TT_MS_LANGID_BASQUE_SPAIN                      = 0x042d;
    public final static int TT_MS_LANGID_SORBIAN_GERMANY                   = 0x042e;
    public final static int TT_MS_LANGID_MACEDONIAN_MACEDONIA              = 0x042f;
    public final static int TT_MS_LANGID_SUTU_SOUTH_AFRICA                 = 0x0430;
    public final static int TT_MS_LANGID_TSONGA_SOUTH_AFRICA               = 0x0431;
    public final static int TT_MS_LANGID_TSWANA_SOUTH_AFRICA               = 0x0432;
    public final static int TT_MS_LANGID_VENDA_SOUTH_AFRICA                = 0x0433;
    public final static int TT_MS_LANGID_XHOSA_SOUTH_AFRICA                = 0x0434;
    public final static int TT_MS_LANGID_ZULU_SOUTH_AFRICA                 = 0x0435;
    public final static int TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA            = 0x0436;
    public final static int TT_MS_LANGID_GEORGIAN_GEORGIA                  = 0x0437;
    public final static int TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS           = 0x0438;
    public final static int TT_MS_LANGID_HINDI_INDIA                       = 0x0439;
    public final static int TT_MS_LANGID_MALTESE_MALTA                     = 0x043a;
      /* Added by XPsp2 Platform SDK (2004-07-26) */
    public final static int TT_MS_LANGID_SAMI_NORTHERN_NORWAY              = 0x043b;
    public final static int TT_MS_LANGID_SAMI_NORTHERN_SWEDEN              = 0x083b;
    public final static int TT_MS_LANGID_SAMI_NORTHERN_FINLAND             = 0x0C3b;
    public final static int TT_MS_LANGID_SAMI_LULE_NORWAY                  = 0x103b;
    public final static int TT_MS_LANGID_SAMI_LULE_SWEDEN                  = 0x143b;
    public final static int TT_MS_LANGID_SAMI_SOUTHERN_NORWAY              = 0x183b;
    public final static int TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN              = 0x1C3b;
    public final static int TT_MS_LANGID_SAMI_SKOLT_FINLAND                = 0x203b;
    public final static int TT_MS_LANGID_SAMI_INARI_FINLAND                = 0x243b;
      /* ... and we also keep our old identifier... */
    public final static int TT_MS_LANGID_SAAMI_LAPONIA                     = 0x043b;
    public final static int TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    = 0x083c;
    public final static int TT_MS_LANGID_IRISH_GAELIC_IRELAND              = 0x043c;
    public final static int TT_MS_LANGID_YIDDISH_GERMANY                   = 0x043d;
    public final static int TT_MS_LANGID_MALAY_MALAYSIA                    = 0x043e;
    public final static int TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           = 0x083e;
    public final static int TT_MS_LANGID_KAZAK_KAZAKSTAN                   = 0x043f;
    public final static int TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ = 0x0440;
      /* alias declared in Windows 2000 */
    public final static int TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC          = 0x0440;
    public final static int TT_MS_LANGID_SWAHILI_KENYA                     = 0x0441;
    public final static int TT_MS_LANGID_TURKMEN_TURKMENISTAN              = 0x0442;
    public final static int TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN            = 0x0443;
    public final static int TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC         = 0x0843;
    public final static int TT_MS_LANGID_TATAR_TATARSTAN                   = 0x0444;
    public final static int TT_MS_LANGID_BENGALI_INDIA                     = 0x0445;
    public final static int TT_MS_LANGID_BENGALI_BANGLADESH                = 0x0845;
    public final static int TT_MS_LANGID_PUNJABI_INDIA                     = 0x0446;
    public final static int TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN           = 0x0846;
    public final static int TT_MS_LANGID_GUJARATI_INDIA                    = 0x0447;
    public final static int TT_MS_LANGID_ORIYA_INDIA                       = 0x0448;
    public final static int TT_MS_LANGID_TAMIL_INDIA                       = 0x0449;
    public final static int TT_MS_LANGID_TELUGU_INDIA                      = 0x044a;
    public final static int TT_MS_LANGID_KANNADA_INDIA                     = 0x044b;
    public final static int TT_MS_LANGID_MALAYALAM_INDIA                   = 0x044c;
    public final static int TT_MS_LANGID_ASSAMESE_INDIA                    = 0x044d;
    public final static int TT_MS_LANGID_MARATHI_INDIA                     = 0x044e;
    public final static int TT_MS_LANGID_SANSKRIT_INDIA                    = 0x044f;
    public final static int TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ = 0x0450;
    public final static int TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN      = 0x0850;
    public final static int TT_MS_LANGID_TIBETAN_CHINA                     = 0x0451;
      /* Don't use the next constant!  It has            */
      /*   (1) the wrong spelling (Dzonghka)             */
      /*   (2) Microsoft doesn't officially define it -- */
      /*       at least it is not in the List of Local   */
      /*       ID Values.                                */
      /*   (3) Dzongkha is not the same language as      */
      /*       Tibetan, so merging it is wrong anyway.   */
      /*                                                 */
      /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW.    */
    public final static int TT_MS_LANGID_DZONGHKA_BHUTAN                   = 0x0851;
      /* So we will continue to #define it, but with the correct value */
    public final static int TT_MS_LANGID_TIBETAN_BHUTAN                    = 0x0851;
    public final static int TT_MS_LANGID_WELSH_WALES                       = 0x0452;
    public final static int TT_MS_LANGID_KHMER_CAMBODIA                    = 0x0453;
    public final static int TT_MS_LANGID_LAO_LAOS                          = 0x0454;
    public final static int TT_MS_LANGID_BURMESE_MYANMAR                   = 0x0455;
    public final static int TT_MS_LANGID_GALICIAN_SPAIN                    = 0x0456;
    public final static int TT_MS_LANGID_KONKANI_INDIA                     = 0x0457;
    public final static int TT_MS_LANGID_MANIPURI_INDIA  /* Bengali */     = 0x0458;
    public final static int TT_MS_LANGID_SINDHI_INDIA /* Arabic */         = 0x0459;
    public final static int TT_MS_LANGID_SINDHI_PAKISTAN                   = 0x0859;
      /* Missing a LCID for Sindhi in Devanagari script */
    public final static int TT_MS_LANGID_SYRIAC_SYRIA                      = 0x045a;
    public final static int TT_MS_LANGID_SINHALESE_SRI_LANKA               = 0x045b;
    public final static int TT_MS_LANGID_CHEROKEE_UNITED_STATES            = 0x045c;
    public final static int TT_MS_LANGID_INUKTITUT_CANADA                  = 0x045d;
    public final static int TT_MS_LANGID_AMHARIC_ETHIOPIA                  = 0x045e;
    public final static int TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */    = 0x045f;
    public final static int TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN           = 0x085f;
      /* Missing a LCID for Tifinagh script */
    public final static int TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */    = 0x0460;
      /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */
      /* script is yet unclear... might be Arabic, Nagari or Sharada */
    public final static int TT_MS_LANGID_KASHMIRI_SASIA                    = 0x0860;
      /* ... and aliased (by MS) for compatibility reasons. */
    public final static int TT_MS_LANGID_KASHMIRI_INDIA                    = 0x0860;
    public final static int TT_MS_LANGID_NEPALI_NEPAL                      = 0x0461;
    public final static int TT_MS_LANGID_NEPALI_INDIA                      = 0x0861;
    public final static int TT_MS_LANGID_FRISIAN_NETHERLANDS               = 0x0462;
    public final static int TT_MS_LANGID_PASHTO_AFGHANISTAN                = 0x0463;
    public final static int TT_MS_LANGID_FILIPINO_PHILIPPINES              = 0x0464;
    public final static int TT_MS_LANGID_DHIVEHI_MALDIVES                  = 0x0465;
      /* alias declared in Windows 2000 */
    public final static int TT_MS_LANGID_DIVEHI_MALDIVES                   = 0x0465;
    public final static int TT_MS_LANGID_EDO_NIGERIA                       = 0x0466;
    public final static int TT_MS_LANGID_FULFULDE_NIGERIA                  = 0x0467;
    public final static int TT_MS_LANGID_HAUSA_NIGERIA                     = 0x0468;
    public final static int TT_MS_LANGID_IBIBIO_NIGERIA                    = 0x0469;
    public final static int TT_MS_LANGID_YORUBA_NIGERIA                    = 0x046a;
    public final static int TT_MS_LANGID_QUECHUA_BOLIVIA                   = 0x046b;
    public final static int TT_MS_LANGID_QUECHUA_ECUADOR                   = 0x086b;
    public final static int TT_MS_LANGID_QUECHUA_PERU                      = 0x0c6b;
    public final static int TT_MS_LANGID_SEPEDI_SOUTH_AFRICA               = 0x046c;
      /* Also spelled by XPsp2 Platform SDK (2004-07-26) */
    public final static int TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA       = 0x046c;
      /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */
    public final static int TT_MS_LANGID_IGBO_NIGERIA                      = 0x0470;
    public final static int TT_MS_LANGID_KANURI_NIGERIA                    = 0x0471;
    public final static int TT_MS_LANGID_OROMO_ETHIOPIA                    = 0x0472;
    public final static int TT_MS_LANGID_TIGRIGNA_ETHIOPIA                 = 0x0473;
    public final static int TT_MS_LANGID_TIGRIGNA_ERYTHREA                 = 0x0873;
      /* also spelled in the `Passport SDK' list as: */
    public final static int TT_MS_LANGID_TIGRIGNA_ERYTREA                  = 0x0873;
    public final static int TT_MS_LANGID_GUARANI_PARAGUAY                  = 0x0474;
    public final static int TT_MS_LANGID_HAWAIIAN_UNITED_STATES            = 0x0475;
    public final static int TT_MS_LANGID_LATIN                             = 0x0476;
    public final static int TT_MS_LANGID_SOMALI_SOMALIA                    = 0x0477;
      /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
      /*       not written (but OTOH the peculiar writing system is worth     */
      /*       studying).                                                     */
    public final static int TT_MS_LANGID_YI_CHINA                          = 0x0478;
    public final static int TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES   = 0x0479;
      /* language codes from 0x047a to 0x047f are (still) unknown. */
    public final static int TT_MS_LANGID_UIGHUR_CHINA                      = 0x0480;
    public final static int TT_MS_LANGID_MAORI_NEW_ZEALAND                 = 0x0481;

    /* =========================================================================
     *
     * Possible values of the `name' identifier field in the name records of
     * the TTF `name' table.  These values are platform independent.
     *
     * =========================================================================
     */
    public final static int TT_NAME_ID_COPYRIGHT           = 0;
    public final static int TT_NAME_ID_FONT_FAMILY         = 1;
    public final static int TT_NAME_ID_FONT_SUBFAMILY      = 2;
    public final static int TT_NAME_ID_UNIQUE_ID           = 3;
    public final static int TT_NAME_ID_FULL_NAME           = 4;
    public final static int TT_NAME_ID_VERSION_STRING      = 5;
    public final static int TT_NAME_ID_PS_NAME             = 6;
    public final static int TT_NAME_ID_TRADEMARK           = 7;
      /* the following values are from the OpenType spec */
    public final static int TT_NAME_ID_MANUFACTURER        = 8;
    public final static int TT_NAME_ID_DESIGNER            = 9;
    public final static int TT_NAME_ID_DESCRIPTION         = 10;
    public final static int TT_NAME_ID_VENDOR_URL          = 11;
    public final static int TT_NAME_ID_DESIGNER_URL        = 12;
    public final static int TT_NAME_ID_LICENSE             = 13;
    public final static int TT_NAME_ID_LICENSE_URL         = 14;
      /* number 15 is reserved */;
    public final static int TT_NAME_ID_PREFERRED_FAMILY    = 16;
    public final static int TT_NAME_ID_PREFERRED_SUBFAMILY = 17;
    public final static int TT_NAME_ID_MAC_FULL_NAME       = 18;
      /* The following code is new as of 2000-01-21 */
    public final static int TT_NAME_ID_SAMPLE_TEXT         = 19;
      /* This is new in OpenType 1.3 */
    public final static int TT_NAME_ID_CID_FINDFONT_NAME   = 20;
      /* This is new in OpenType 1.5 */
    public final static int TT_NAME_ID_WWS_FAMILY          = 21;
    public final static int TT_NAME_ID_WWS_SUBFAMILY       = 22;

    /* =========================================================================
     *
     * <Const>
     *    FT_STYLE_FLAG_XXX
     *
     * <Description>
     *    A list of bit-flags used to indicate the style of a given face.
     *    These are used in the `style_flags' field of @FT_FaceRec.
     *
     * <Values>
     *    FT_STYLE_FLAG_ITALIC ::
     *      Indicates that a given face style is italic or oblique.
     *
     *    FT_STYLE_FLAG_BOLD ::
     *      Indicates that a given face is bold.
     *
     * <Note>
     *    The style information as provided by FreeType is very basic.  More
     *    details are beyond the scope and should be done on a higher level
     *    (for example, by analyzing various fields of the `OS/2' table in
     *    SFNT based fonts).
     *
     * =========================================================================
     */
    public final static int FT_STYLE_FLAG_ITALIC  = (1 << 0);
    public final static int FT_STYLE_FLAG_BOLD    = (1 << 1);

    public Short format = 0;
    public Integer numNameRecords = 0;
    public Integer storageOffset = 0;
    public TTNameEntryRec[] names = null;
    public FTStreamRec stream = null;

    /* ==================== TTNameTableRec ================================== */
    public TTNameTableRec() {
      super(null);
    }
    
    /* ==================== TTNameTableRec ================================== */
    public TTNameTableRec(FTStreamRec stream) {
      super(stream);
      oid++;
      id = oid;
      my_class_name = "org.apwtcl.gles20.truetype.TTNameTableRec";
      if (frame_info.size() == 0) {
//        va = new FTInstanceVariable(my_class_name, this, "format_tag", 1);
//        frame_info.add(new FTFrameEntry("format_tag", va, readInt, VAR_IS_INT));
      }
//      fillVariables();
Debug(0, DBG_LOAD_GLYPH, TAG, "TTNameTableRec offset: "+String.format("0x%08x", stream.pos()));
      format = stream.readShort(stream);
      numNameRecords = (int)stream.readShort(stream);
      storageOffset = (int)stream.readShort(stream);
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * tt_name_entry_ascii_from_utf16
     * =====================================================================
     */
    /* convert a UTF-16 name entry to ASCII */
    static String tt_name_entry_ascii_from_utf16(TTNameEntryRec entry) {
      String string = null;
      Log.w(TAG, "WARNING: tt_name_entry_ascii_from_utf16 not yet implemented");
System.out.println("tt_name_entry_ascii_from_other not yet implemented");
/*
      Integer len;
      Integer code;
      Integer n;
      byte read = entry.string;
      int error;

      len = entry.stringLength / 2;
      string = new Byte[len + 1];
      for (n = 0; n < len; n++) {
        code = FT_NEXT_USHORT(read);
        if (code == 0) {
          break;
        }
        if (code < 32 || code > 127) {
          code = '?';
        }
        string[n] = (char)code;
      }
      string[n] = 0;
*/
      return string;
    }

    /* =====================================================================
     * tt_name_entry_ascii_from_other
     * =====================================================================
     */
    /* convert an Apple Roman or symbol name entry to ASCII */
    static String tt_name_entry_ascii_from_other(TTNameEntryRec entry) {
      String string = null;
      Log.w(TAG, "WARNING: tt_name_entry_ascii_from_other not yet implemented");
System.out.println("tt_name_entry_ascii_from_other not yet implemented");
/*
      Integer len;
      Integer code;
      Integer n;
      Byte[] read = (Byte)entry.string;
      int error;

      len = entry.stringLength;
      if (FT_NEW_ARRAY(string, len + 1)) {
        return null;
      }
      for (n = 0; n < len; n++) {
        code = *read++;
        if (code == 0) {
          break;
        }
        if (code < 32 || code > 127) {
          code = '?';
        }
        string[n] = (char)code;
      }
      string[n] = 0;
*/
      return string;
    }

}

Added ftbase/TTSizeFuncs.java.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

import android.util.Log;
  /* ===================================================================== */
  /*    TTSizeFuncs                                                        */
  /*                                                                       */
  /* ===================================================================== */

public class TTSizeFuncs extends FTDebug {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTSizeFuncs";
    
    /* ==================== TTSizeFuncs ================================== */
    public TTSizeFuncs() {
      oid++;
      id = oid;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
    /* =====================================================================
     * <Function>
     *    tt_size_init
     *
     * <Description>
     *    Initialize a new TrueType size object.
     *
     * <InOut>
     *    size :: A handle to the size object.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int tt_size_init(Object ... args) {
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_init");
      Object obj = args[0];
      FTReference<FTSizeRec> size_ref = (FTReference<FTSizeRec>)obj;
      FTSizeRec ttsize = (FTSizeRec)size_ref.Get();

      int error = 0;
      TTSizeRec size = (TTSizeRec)ttsize;

      size.bytecode_ready = false;
      size.cvt_ready = false;
      size.ttmetrics.valid = false;
      size.strike_index = 0xFFFFFFFFL;
      size_ref.Set(ttsize);
      return error;
    }

    /* =====================================================================
     *    tt_size_done
     *
     * =====================================================================
     */
    public static void tt_size_done(Object ... args) {   /* TT_Face */
      //TT_Face       face = (TT_Face)ttface;
      //FT_Memory     memory;
      //FT_Stream     stream;
      //SFNT_Service  sfnt;
Log.w(TAG, "tt_size_done not yet implemented!!");
    	
      FTTrace.Trace(7, TAG, "tt_size_done");
    }
 

    /* =====================================================================
     *    tt_size_done_bytecode
     *
     * =====================================================================
     */
    public static void tt_size_done_bytecode(Object ... args) {   /* TT_Face */
      FTSizeRec ftsize =  (FTSizeRec)args[0];
      TTSizeRec size = (TTSizeRec)ftsize;
//      TTFaceRec face = (TTFaceRec)ftsize.face;
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_done_bytecode");

      size.cvt = null;
      size.cvt_size = 0;
      /* twilight zone */
      TTGlyphZoneRec.tt_glyphzone_done(size.twilight);
      size.function_defs = null;
      size.instruction_defs = null;
      size.num_function_defs = 0;
      size.max_function_defs = 0;
      size.num_instruction_defs = 0;
      size.max_func = 0;
      size.max_ins  = 0;
      size.bytecode_ready = false;
      size.cvt_ready = false;
    }
 
    /* =====================================================================
     * tt_size_request
     * =====================================================================
     */
    public static int tt_size_request(Object ... args) {
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_request");
      int error = 0;
      FTReference<Object> size_ref = (FTReference<Object>)args[0];
      FTSizeRec size = (FTSizeRec)size_ref.Get();
      FTSizeRequestRec req = (FTSizeRequestRec)args[1];
      
      TTSizeRec ttsize = (TTSizeRec)size;
      FTSizeMetricsRec.FTRequestMetrics(ttsize.face, req);
      if ((size.face.face_flags & FTFaceRec.FT_FACE_FLAG_SCALABLE) != 0) {
        FTReference<TTSizeRec> tt_size_ref = new FTReference<TTSizeRec>();
        tt_size_ref.Set(ttsize);
    	error = tt_size_reset(tt_size_ref);
    	ttsize = tt_size_ref.Get();
//        ttsize.metrics = ttsize.metrics;
      }
      size_ref.Set((FTSizeRec)ttsize);
      return error;
    }

    /* =====================================================================
     * tt_size_reset
     *
     * <Description>
     *    Reset a TrueType size when resolutions and character dimensions
     *    have been changed.
     *
     * <Input>
     *    size :: A handle to the target size object.
     *
     * =====================================================================
     */
    public static int tt_size_reset(FTReference<TTSizeRec> size_ref) {
      TTFaceRec face;
      TTSizeRec size = size_ref.Get();
      int error = FTError.INTERP_ERR_OK;

Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_reset");
      size.ttmetrics.valid = false;
      face = (TTFaceRec)size.face;
      /* copy the result from base layer */
Debug(0, DBG_LOAD_GLYPH, TAG, "RES: "+size.metrics.x_ppem+"!"+size.metrics.x_ppem+"!"+size.local_metrics.x_ppem+"!"+size.local_metrics.x_ppem+"!");
      size.local_metrics = size.metrics;
      if (size.metrics.x_ppem < 1 || size.metrics.y_ppem < 1) {
        return FTError.GLYPH_INVALID_PPEM;
      }
      /* This bit flag, if set, indicates that the ppems must be       */
      /* rounded to integers.  Nearly all TrueType fonts have this bit */
      /* set, as hinting won't work really well otherwise.             */
      /*                                                               */
Debug(0, DBG_LOAD_GLYPH, TAG, "face.header.flags: "+(face.header.Flags & 8)+"!");
      if ((face.header.Flags & 8) != 0) {
        size.metrics.x_scale = FTCalc.FTDivFix((long)(size.metrics.x_ppem << 6),
                                      (long)face.units_per_EM);
        size.metrics.y_scale = FTCalc.FTDivFix((long)(size.metrics.y_ppem << 6),
                                      (long)face.units_per_EM );

        size.metrics.ascender = 
                FTCalc.FT_PIX_ROUND(FTCalc.FTMulFix((long)face.ascender, (long)size.metrics.y_scale));
        size.metrics.descender = 
                FTCalc.FT_PIX_ROUND(FTCalc.FTMulFix((long)face.descender, (long)size.metrics.y_scale));
        size.metrics.height = FTCalc.FT_PIX_ROUND(FTCalc.FTMulFix((long)face.height, (long)size.metrics.y_scale));
        size.metrics.max_advance = 
                FTCalc.FT_PIX_ROUND(FTCalc.FTMulFix((long)face.max_advance_width, size.metrics.x_scale));
      }
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_reset: size: "+size+"!");
      /* compute new transformation */
      if (size.metrics.x_ppem >= size.metrics.y_ppem) {
Debug(0, DBG_LOAD_GLYPH, TAG, "x_scale: "+size.metrics.x_scale+"!"+size.ttmetrics.scale+"!");
        size.ttmetrics.scale   = size.metrics.x_scale;
        size.ttmetrics.ppem    = size.metrics.x_ppem;
        size.ttmetrics.x_ratio = 0x10000L;
        size.ttmetrics.y_ratio = FTCalc.FTDivFix((long)size.metrics.y_ppem, (long)size.metrics.x_ppem);
      } else {
Debug(0, DBG_LOAD_GLYPH, TAG, "y_scale: "+size.metrics.x_scale+"!"+size.ttmetrics.scale+"!");
        size.ttmetrics.scale   = size.metrics.y_scale;
        size.ttmetrics.ppem    = size.metrics.y_ppem;
        size.ttmetrics.x_ratio = FTCalc.FTDivFix((long)size.metrics.x_ppem, (long)size.metrics.y_ppem);
        size.ttmetrics.y_ratio = 0x10000L;
      }
      size.cvt_ready = false;
      if (error == 0) {
        size.ttmetrics.valid = true;
      }
      size_ref.Set(size);
      return error;
    }
 
    /* =====================================================================
     * tt_size_ready_bytecode
     * =====================================================================
     */
    public static int tt_size_ready_bytecode(FTReference<TTSizeRec> size_ref, boolean pedantic) {
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_ready_bytecode");
      TTSizeRec size = size_ref.Get();
      int error = FTError.INTERP_ERR_OK;
 
      if (!size.bytecode_ready) {
        size_ref.Set(size);
        error = tt_size_init_bytecode(size_ref, pedantic);
        size = size_ref.Get();
        if (error != 0) {
          size_ref.Set(size);
          return error;
        }
      }
      /* rescale CVT when needed */
      if (!size.cvt_ready) {
        int i;
        TTFaceRec face = (TTFaceRec)size.face;

        /* Scale the cvt values to the new ppem.          */
        /* We use by default the y ppem to scale the CVT. */
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_ready_bytecode: "+size+"!");
        for (i = 0; i < size.cvt_size; i++) {
          size.cvt[i] = TTInterpInsFuncs1.FT_MulFix((long)face.cvt[i], size.ttmetrics.scale);
Debug(0, DBG_LOAD_GLYPH, TAG, "size->cvt: "+i+"!"+size.cvt[i]+"!"+face.cvt[i]+"!"+size.ttmetrics.scale+"!");
        }
        /* all twilight points are originally zero */
        for (i = 0; i < (int)size.twilight.n_points; i++) {
          size.twilight.org[i].x = 0L;
          size.twilight.org[i].y = 0L;
          size.twilight.cur[i].x = 0L;
          size.twilight.cur[i].y = 0L;
        }
        /* clear storage area */
        for (i = 0; i < (int)size.storage_size; i++) {
          size.storage[i] = 0L;
        }
        size.GS = new TTDefaultGraphicsStateClass();
        size_ref.Set(size);
        error = tt_size_run_prep(size_ref, pedantic);
        size = size_ref.Get();
        if (error == 0) {
          size.cvt_ready = true;
        }
      }
      size_ref.Set(size);
      return error;
    }
 
    /* =====================================================================
     * tt_size_run_prep
     *
     * <Description>
     *    Run the control value program.
     *
     * <Input>
     *    size     :: A handle to the size object.
     *
     *    pedantic :: Set if bytecode execution should be pedantic.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int tt_size_run_prep(FTReference<TTSizeRec> size_ref, boolean pedantic) {
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_run_prep");
      int error = 0;
      TTSizeRec size = size_ref.Get();
      TTFaceRec face = (TTFaceRec)size.face;
      TTExecContextRec exec;

      /* debugging instances have their own context */
      if (size.debug) {
        exec = size.context;
      } else {
        exec = ((TTDriverRec)face.driver).context;
      }
      if (exec == null) {
        return FTError.GLYPH_COULD_NOT_FIND_CONTEXT;
      }
      FTReference<TTExecContextRec> exec_ref = new FTReference<TTExecContextRec>();
      exec_ref.Set(exec);
      TTDriverRec.TTLoadContext(exec_ref, face, size);
      exec = exec_ref.Get();
      exec.callTop = 0;
      exec.top     = 0;
      exec.instruction_trap = false;
      exec.pedantic_hinting = pedantic;
      exec_ref.Set(exec);
      TTSetCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_CVT, face.cvt_program, null, (int)face.cvt_program_size);
      TTClearCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_GLYPH);
      exec = exec_ref.Get();
Debug(0, DBG_LOAD_GLYPH, TAG, "cvt_program_size: "+face.cvt_program_size+"!");
      if (face.cvt_program_size > 0) {
        error = TTGotoCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_CVT, 0);
        exec = exec_ref.Get();
        if (error == 0 && !size.debug) {
          FTTrace.Trace(7, TAG, "Executing `prep' table.");
for(int j = 0; j < 30; j++) {
  Debug(0, DBG_LOAD_GLYPH, TAG, String.format("j: %d 0x%02x\n", j, exec.code[j] & 0xFF));
}
          error = (int)face.interpreter.callClassMethod(exec);
        }
      } else {
        error = FTError.INTERP_ERR_OK;
      }

      /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
      /* graphics state variables to be modified by the CVT program.  */
      exec.GS.dualVector.x = 0x4000L;
      exec.GS.dualVector.y = 0L;
      exec.GS.projVector.x = 0x4000L;
      exec.GS.projVector.y = 0x0L;
      exec.GS.freeVector.x = 0x4000L;
      exec.GS.freeVector.y = 0x0L;
      exec.GS.rp0 = 0;
      exec.GS.rp1 = 0;
      exec.GS.rp2 = 0;
      exec.GS.gep0 = 1;
      exec.GS.gep1 = 1;
      exec.GS.gep2 = 1;
      exec.GS.loop = 1;
      /* save as default graphics state */
      size.GS = exec.GS;
      size_ref.Set(size);
      TTSaveContext(exec, size_ref);
      size = size_ref.Get();
      size_ref.Set(size);
      return error;
    }
 
    /* =====================================================================
     * tt_size_init_bytecode
     * =====================================================================
     */
    public static int tt_size_init_bytecode(FTReference<TTSizeRec> size_ref, boolean pedantic) {
Debug(0, DBG_LOAD_GLYPH, TAG, "tt_size_init_bytecode");
      TTSizeRec size = size_ref.Get();
      int error = 0;
      TTFaceRec face = (TTFaceRec)size.face;
      int i;

      short n_twilight;
      TTMaxProfile maxp = face.max_profile;
      size.bytecode_ready = true;
      size.cvt_ready = false;
      size.max_function_defs = maxp.maxFunctionDefs;
      size.max_instruction_defs = maxp.maxInstructionDefs;
      size.num_function_defs = 0;
      size.num_instruction_defs = 0;
      size.max_func = 0;
      size.max_ins = 0;
      size.cvt_size = face.cvt_size;
      size.storage_size = maxp.maxStorage;
      /* Set default metrics */
      {
        size.ttmetrics.rotated = false;
        size.ttmetrics.stretched = false;
        /* set default compensation (all 0) */
        for (i = 0; i < 4; i++) {
          size.ttmetrics.compensations[i] = 0;
        }
      }
      /* allocate function defs, instruction defs, cvt, and storage area */
      size.function_defs = new TTDefRec[size.max_function_defs];
      for (i = 0; i < size.max_function_defs; i++) {
        size.function_defs[i] = new TTDefRec();
      }
      size.instruction_defs = new TTDefRec[size.max_instruction_defs];
      for (i = 0; i < size.max_instruction_defs; i++) {
        size.instruction_defs[i] = new TTDefRec();
      }
      size.cvt = new long[(int)size.cvt_size];
      size.storage = new long[size.storage_size];
      /* reserve twilight zone */
      n_twilight = maxp.maxTwilightPoints;
      /* there are 4 phantom points (do we need this?) */
      n_twilight += 4;
      FTReference<TTGlyphZoneRec> zone_ref = new FTReference<TTGlyphZoneRec>();
      zone_ref.Set(size.twilight);
      error = TTGlyphZoneRec.tt_glyphzone_new(n_twilight, (short)0, zone_ref);
      size.twilight = zone_ref.Get();
      if (error != 0) {
        tt_size_done_bytecode(size);
        return error;
      }
      size.twilight.n_points = n_twilight;
      size.GS = new TTDefaultGraphicsStateClass();
      /* set `face.interpreter' according to the debug hook present */
      {
//        FTLibraryRec library = face.driver.library;

        String class_name = "org.apwtcl.apwfreetype.ftbase.TTInterpRun";
//        face.interpreter = (TTInterpRun) library.debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
        if (face.interpreter == null) {
          face.interpreter = new FTInstanceMethod(class_name, "TTRunIns", 1);
        }
      }
      /* Fine, now run the font program! */
      error = tt_size_run_fpgm(size, pedantic);
      if (error != 0) {
        tt_size_done_bytecode(size);
      }
      return error;
    }
 
    /* =====================================================================
     * TTSetCodeRange
     *
     * <Description>
     *    Sets a code range.
     *
     * <Input>
     *    range  :: The code range index.
     *
     *    base   :: The new code base.
     *
     *    length :: The range size in bytes.
     *
     * <InOut>
     *    exec   :: The target execution context.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int TTSetCodeRange(FTReference<TTExecContextRec> exec_ref, int range, byte[] byte_base, short[] short_base, int length) {
Debug(0, DBG_LOAD_GLYPH, TAG, "TTSetCodeRange: "+range+"!"+short_base+"!"+byte_base+"!"+length+"!");
      TTExecContextRec exec = exec_ref.Get();
      int error = FTError.INTERP_ERR_OK;

      if (range < 1 || range > 3) {
        error = FTError.INTERP_INVALID_ARGUMENT;
        return error;
      }
      exec.codeRangeTable[range - 1].short_base = short_base;
      exec.codeRangeTable[range - 1].base = byte_base;
      exec.codeRangeTable[range - 1].size = (long)length;
      return error;
    }
 
    /* =====================================================================
     * TTClearCodeRange
     *
     * <Description>
     *    Clears a code range.
     *
     * <Input>
     *    range :: The code range index.
     *
     * <InOut>
     *    exec  :: The target execution context.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * <Note>
     *    Does not set the Error variable.
     *
     * =====================================================================
     */
    public static int TTClearCodeRange(FTReference<TTExecContextRec> exec_ref, int range) {
Debug(0, DBG_LOAD_GLYPH, TAG, "TTClearCodeRange");
      TTExecContextRec exec = exec_ref.Get();
      int error = FTError.INTERP_ERR_OK;

      if (range < 1 || range > 3) {
        error = FTError.INTERP_INVALID_ARGUMENT;
        return error;
      }
      exec.codeRangeTable[range - 1].base = null;
      exec.codeRangeTable[range - 1].size = 0L;
      return error;
    }
 
    /* =====================================================================
     * TTGotoCodeRange
     *
     * <Description>
     *    Switches to a new code range (updates the code related elements in
     *    `exec', and `IP').
     *
     * <Input>
     *    range :: The new execution code range.
     *
     *    IP    :: The new IP in the new code range.
     *
     * <InOut>
     *    exec  :: The target execution context.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int TTGotoCodeRange(FTReference<TTExecContextRec> exec_ref, int range, long IP) {
Debug(0, DBG_LOAD_GLYPH, TAG, "TTGotoCodeRange");
      TTExecContextRec exec = exec_ref.Get();
      int error = FT_Error.INTERP_ERR_OK;

      if (range < 1 || range > 3) {
        error = FT_Error.INTERP_INVALID_ARGUMENT;
        return error;
      }
      if (exec.codeRangeTable[range - 1].base == null) {
        error = FT_Error.INTERP_INVALID_ARGUMENT;
        return error;
      }
      /* NOTE: Because the last instruction of a program may be a CALL */
      /*       which will return to the first byte *after* the code    */
      /*       range, we test for IP <= Size instead of IP < Size.     */
      /*                                                               */
      if ((long)IP > exec.codeRangeTable[range - 1].size) {
        error = FT_Error.INTERP_INVALID_ARGUMENT;
        return error;
      }
      exec.code = exec.codeRangeTable[range - 1].base;
      exec.cvt_code = exec.codeRangeTable[range - 1].short_base;
      exec.codeSize = exec.codeRangeTable[range - 1].size.intValue();
if (FTSizeRec.size_debug > 2) {
System.out.println(String.format("TTGotoCodeRange: size: %d", exec.codeSize));      
}
      exec.IP = (int)IP;
      exec.curRange = range;
      return error;
    }
 
    /* =====================================================================
     * tt_size_run_fpgm
     *
     * <Description>
     *    Run the font program.
     *
     * <Input>
     *    size     :: A handle to the size object.
     *
     *    pedantic :: Set if bytecode execution should be pedantic.
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int tt_size_run_fpgm(TTSizeRec size, boolean pedantic) {
if (FTSizeRec.size_debug > 2) {
System.out.println("tt_size_run_fpgm");
}
      int error = 0;
      TTFaceRec face = (TTFaceRec)size.face;
      TTExecContextRec exec;

      /* debugging instances have their own context */
      if (size.debug) {
        exec = size.context;
      } else {
        exec = ((TTDriverRec)face.driver).context;
      }
      if (exec == null) {
        error = FT_Error.GLYPH_COULD_NOT_FIND_CONTEXT;
        return error;
      }
      FTReference<TTExecContextRec> exec_ref = new FTReference<TTExecContextRec>();
      exec_ref.Set(exec);
      TTDriverRec.TTLoadContext(exec_ref, face, size);
      exec = exec_ref.Get();
      exec.callTop = 0;
      exec.top     = 0;
      exec.period    = 64;
      exec.phase     = 0;
      exec.threshold = 0;
      exec.instruction_trap = false;
      exec.F_dot_P = 0x4000L;
      exec.pedantic_hinting = pedantic;
      {
//FIXME!!
/* need to figure out how to avoid commenting out the next lines!!
        exec.metrics.x_ppem = 0;
        exec.metrics.y_ppem = 0;
        exec.metrics.x_scale = 0;
        exec.metrics.y_scale = 0;
        exec.tt_metrics.ppem = 0;
        exec.tt_metrics.scale = 0;
        exec.tt_metrics.ratio = 0x10000L;
*/
      }
      /* allow font program execution */
      exec_ref.Set(exec);
      TTSetCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_FONT, face.font_program, null, (int)face.font_program_size);
      /* disable CVT and glyph programs coderange */
      TTClearCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_CVT);
      TTClearCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_GLYPH);
      exec = exec_ref.Get();
      if (face.font_program_size > 0) {
        error = TTGotoCodeRange(exec_ref, TTCodeRange.TT_CODERANGE_FONT, 0);
        exec = exec_ref.Get();
        if (error == 0) {
          FT_Trace.Trace(7, TAG, "Executing `fpgm' table.");
          error = (int)face.interpreter.callClassMethod(exec);
        }
      } else {
        error = FT_Error.INTERP_ERR_OK;
      }
      if (error == 0) {
        FTReference<TTSizeRec> size_ref = new FTReference<TTSizeRec>();
    	size_ref.Set(size);
        TTSaveContext(exec, size_ref);
        size = size_ref.Get();
      }
      return error;
    }
 
    /* =====================================================================
     * TTSaveContext
     *
     * =====================================================================
     */
    public static int TTSaveContext(TTExecContextRec exec, FTReference<TTSizeRec> size_ref) {
if (FTSizeRec.size_debug > 2) {
System.out.println("TTSaveContext");
}
      TTSizeRec size = size_ref.Get();
      int error = 0;
      int i;

      /* XXX: Will probably disappear soon with all the code range */
      /*      management, which is now rather obsolete.            */
      /*                                                           */
      size.num_function_defs = exec.numFDefs;
      size.function_defs = exec.FDefs;
      size.num_instruction_defs = exec.numIDefs;
      size.instruction_defs = exec.IDefs;
      size.max_func = exec.maxFunc;
      size.max_ins  = exec.maxIns;
      size.ttmetrics = exec.tt_metrics;
      size.metrics = exec.metrics;
      for (i = 0; i < TTSizeRec.TT_MAX_CODE_RANGES; i++) {
        size.codeRangeTable[i] = exec.codeRangeTable[i];
      }
      size_ref.Set(size);
      return error;
    }

    /* =====================================================================
     * TTGetHMetrics
     *
     * =====================================================================
     */
    public static void TTGetHMetrics(TTFaceRec face, int idx, FTReference<Short> lsb_ref, FTReference<Short> aw_ref) {
      ((FTSfntInterfaceClass)face.sfnt).get_metrics.callClassMethod(face, false, idx, lsb_ref, aw_ref);
      FT_Trace.Trace(7, TAG, String.format("  advance width (font units): %d", aw_ref.Get()));
      FT_Trace.Trace(7, TAG, String.format("  left side bearing (font units): %d", lsb_ref.Get()));
    }

    /* =====================================================================
     * TTGetVMetrics
     *
     * Return the vertical metrics in font units for a given glyph.
     * Greg Hitchcock from Microsoft told us that if there were no `vmtx'
     * table, typoAscender/Descender from the `OS/2' table would be used
     * instead, and if there were no `OS/2' table, use ascender/descender
     * from the `hhea' table.  But that is not what Microsoft's rasterizer
     * apparently does: It uses the ppem value as the advance height, and
     * sets the top side bearing to be zero.
     *
     * =====================================================================
     */
    public static void TTGetVMetrics(TTFaceRec face, int idx, FTReference<Short> tsb_ref, FTReference<Short> ah_ref) {
      if (face.vertical_info) {
        ((FTSfntInterfaceClass)face.sfnt).get_metrics.callClassMethod(face, true, idx, tsb_ref, ah_ref);
      } else {
        tsb_ref.Set((short)0);
        ah_ref.Set(face.units_per_EM);
      }
      FT_Trace.Trace(7, TAG, String.format("  advance height (font units): %d", ah_ref.Get()));
      FT_Trace.Trace(7, TAG, String.format("  top side bearing (font units): %d", tsb_ref.Get()));
    }

    
    /* =====================================================================
     * tt_get_metrics
     *
     * =====================================================================
     */
    public static void tt_get_metrics(TTLoaderRec loader, int glyph_index) {
      TTFaceRec face = (TTFaceRec)loader.face;
      short left_bearing = 0;
      short top_bearing = 0;
      short advance_width = 0;
      short advance_height = 0;
      FTReference<Short> left_bearing_ref = new FTReference<Short>();
      FTReference<Short> top_bearing_ref = new FTReference<Short>();
      FTReference<Short> advance_width_ref = new FTReference<Short>();
      FTReference<Short> advance_height_ref = new FTReference<Short>();

if (FTSizeRec.size_debug > 2) {
System.out.println("tt_get_metrics");
}
      left_bearing_ref.Set(left_bearing);
      advance_width_ref.Set(advance_width);
      TTGetHMetrics(face, glyph_index, left_bearing_ref, advance_width_ref);
      left_bearing = left_bearing_ref.Get();
      advance_width = advance_width_ref.Get();
      top_bearing_ref.Set(top_bearing);
      advance_height_ref.Set(advance_height);
      TTGetVMetrics(face, glyph_index, top_bearing_ref, advance_height_ref);
      top_bearing = top_bearing_ref.Get();
      advance_height = advance_height_ref.Get();
      loader.left_bearing = left_bearing;
      loader.advance = advance_width;
      loader.top_bearing = top_bearing;
      loader.vadvance = advance_height;
      if (!loader.linear_def) {
        loader.linear_def = true;
        loader.linear = advance_width;
      }
    }
    
}

Added ftbase/TTSizeMetricsRec.java.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// ----------------------------------------------------------------
// TTSizeMetricsRec.java --
//
// Copyright (c) 2014 by Arnulf P. Wiedemann
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//------------------------------------------------------------------------

package ftbase;

/* ======================================================================= */
/*  This Java implementation is derived from the Freetype code             */
/*  and has been implemented to work together with the Apache batik code   */
/*  for reading .ttf ont files                                             */
/*                                                                         */
/*  Copyright (C) of the Java implementation 2014                          */
/*  Arnulf Wiedemann                                                       */
/*                                                                         */
/*  See the file "license.terms" for information on usage and              */
/*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.   */
/*                                                                         */
/*  in this directory the truetype opcode interpreter is ported to Java    */
/*                                                                         */
/*  the next blocks are taken from the original source code                */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
/*            2010 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/* ======================================================================= */

  /* ===================================================================== */
  /*    TTSizeMetricsRec                                                   */
  /*                                                                       */
  /* A note regarding non-squared pixels:                                  */
  /*                                                                       */
  /* (This text will probably go into some docs at some time; for now, it  */
  /* is kept here to explain some definitions in the TT_Size_Metrics       */
  /* record).                                                              */
  /*                                                                       */
  /* The CVT is a one-dimensional array containing values that control     */
  /* certain important characteristics in a font, like the height of all   */
  /* capitals, all lowercase letter, default spacing or stem width/height. */
  /*                                                                       */
  /* These values are found in FUnits in the font file, and must be scaled */
  /* to pixel coordinates before being used by the CVT and glyph programs. */
  /* Unfortunately, when using distinct x and y resolutions (or distinct x */
  /* and y pointsizes), there are two possible scalings.                   */
  /*                                                                       */
  /* A first try was to implement a `lazy' scheme where all values were    */
  /* scaled when first used.  However, while some values are always used   */
  /* in the same direction, some others are used under many different      */
  /* circumstances and orientations.                                       */
  /*                                                                       */
  /* I have found a simpler way to do the same, and it even seems to work  */
  /* in most of the cases:                                                 */
  /*                                                                       */
  /* - All CVT values are scaled to the maximum ppem size.                 */
  /*                                                                       */
  /* - When performing a read or write in the CVT, a ratio factor is used  */
  /*   to perform adequate scaling.  Example:                              */
  /*                                                                       */
  /*     x_ppem = 14                                                       */
  /*     y_ppem = 10                                                       */
  /*                                                                       */
  /*   We choose ppem = x_ppem = 14 as the CVT scaling size.  All cvt      */
  /*   entries are scaled to it.                                           */
  /*                                                                       */
  /*     x_ratio = 1.0                                                     */
  /*     y_ratio = y_ppem/ppem (< 1.0)                                     */
  /*                                                                       */
  /*   We compute the current ratio like:                                  */
  /*                                                                       */
  /*   - If projVector is horizontal,                                      */
  /*       ratio = x_ratio = 1.0                                           */
  /*                                                                       */
  /*   - if projVector is vertical,                                        */
  /*       ratio = y_ratio                                                 */
  /*                                                                       */
  /*   - else,                                                             */
  /*       ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
  /*                                                                       */
  /*   Reading a cvt value returns                                         */
  /*     ratio * cvt[index]                                                */
  /*                                                                       */
  /*   Writing a cvt value in pixels:                                      */
  /*     cvt[index] / ratio                                                */
  /*                                                                       */
  /*   The current ppem is simply                                          */
  /*     ratio * ppem                                                      */
  /* ===================================================================== */

public class TTSizeMetricsRec extends Object {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTSizeMetricsRec";

    /* for non-square pixels */
    public long x_ratio;
    public long y_ratio;
    public short ppem;          /* maximum ppem size              */
    public long ratio;          /* current ratio                  */
    public long scale;
    public int[] compensations; /* device-specific compensations  */
    public boolean valid;
    public boolean rotated;     /* `is the glyph rotated?'-flag   */
    public boolean stretched;   /* `is the glyph stretched?'-flag */

    /* ==================== TTSizeMetricsRec ================================== */
    public TTSizeMetricsRec() {
      oid++;
      id = oid;
      x_ratio = 0;
      y_ratio = 0;
      ppem = 0;
      ratio = 0;
      scale = 0;
      compensations = new int[4];
      compensations[0] = 0;
      compensations[1] = 0;
      compensations[2] = 0;
      compensations[3] = 0;
      valid = false;
      rotated = false;
      stretched = false;
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      String str = TAG+"!"+id+"!";
      return str;
    } 
        
    /* ==================== toString ===================================== */
    public String toString() {
      StringBuffer str = new StringBuffer(mySelf()+"!");
      return str.toString();
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}

Added ftbase/TTSizeRec.java.

























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* =====================================================================
 *  This Java implementation is derived from FreeType code
 *  Portions of this software are copyright (C) 2014 The FreeType
 *  Project (www.freetype.org).  All rights reserved.
 *
 *  Copyright (C) of the Java implementation 2014
 *  Arnulf Wiedemann arnulf at wiedemann-pri.de
 *
 *  See the file "license.terms" for information on usage and
 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * =====================================================================
 */

package ftbase;

  /* ===================================================================== */
  /*    TTSizeRec                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class TTSizeRec extends FTSizeRec {
    private static int oid = 0;

    private int id;
    private static String TAG = "TTSizeRec";
    
    public final static int TT_MAX_CODE_RANGES = 3;

    /* we have our own copy of metrics so that we can modify */
    /* it without affecting auto-hinting (when used)         */
    public FTSizeMetricsRec local_metrics = null;
    public TTSizeMetricsRec ttmetrics = null;
    public long strike_index = 0L;      /* 0xFFFFFFFF to indicate invalid */
    public int num_function_defs = 0; /* number of function definitions */
    public int max_function_defs = 0;
    public TTDefRec[] function_defs = null;     /* table of function definitions  */
    public int num_instruction_defs = 0;  /* number of ins. definitions */
    public int max_instruction_defs = 0;
    public TTDefRec[] instruction_defs = null;      /* table of ins. definitions  */
    public int max_func = 0;
    public int max_ins = 0;
    public TTCodeRange[] codeRangeTable = null;
    public TTGraphicsStateRec GS = null;
    public long cvt_size = 0L;      /* the scaled control value table */
    public long[] cvt = null;
    public short storage_size = 0; /* The storage area is now part of */
    public long[] storage = null;      /* the instance                    */
    public TTGlyphZoneRec twilight = null;     /* The instance's twilight zone    */
    /* debugging variables */
    /* When using the debugger, we must keep the */
    /* execution context tied to the instance    */
    /* object rather than asking it on demand.   */
    public boolean debug = false;
    public TTExecContextRec context = null;
    public boolean bytecode_ready = false;
    public boolean cvt_ready = false;

    /* ==================== TTSizeRec ================================== */
    public TTSizeRec() {
      oid++;
      id = oid;
      local_metrics = new FTSizeMetricsRec();
      ttmetrics = new TTSizeMetricsRec();
      function_defs = new TTDefRec[1];
      instruction_defs = new TTDefRec[1];
      codeRangeTable = new TTCodeRange[TT_MAX_CODE_RANGES];
      for (int i = 0; i < TT_MAX_CODE_RANGES; i++) {
        codeRangeTable[i] = new TTCodeRange();
      }
      GS = new TTDefaultGraphicsStateClass();
      twilight = new TTGlyphZoneRec("TTSizeRec.twilight");
      context = new TTExecContextRec();
Debug(0, DBG_INIT, TAG, "exec1 ttsize: "+context+"!");
    }
    
    /* ==================== mySelf ================================== */
    public String mySelf() {
      return TAG+"!"+id+"!";
    }
        
    /* ==================== toString ===================================== */
    public String toString() {
      return mySelf()+"!";
    }

    /* ==================== toDebugString ===================================== */
    public String toDebugString() {
      StringBuffer str = new StringBuffer(mySelf()+"\n");
      return str.toString();
    }
 
}