ApwFreetypeLibrary

Check-in [10229f2a18]
Login

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

Overview
Comment:fixes.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:10229f2a18af13a23789b90c58760e15daee0498
User & Date: arnulf 2014-12-29 23:19:58
Context
2014-12-29
23:20
initial version. check-in: 477dcc17ba user: arnulf tags: trunk
23:19
fixes. check-in: 10229f2a18 user: arnulf tags: trunk
21:46
initial version check-in: b5c63cad02 user: arnulf tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ftbase/FTConstants.java.

179
180
181
182
183
184
185
186


187



188




















































































































































189









































    public final static int FT_SIZE_REQUEST_TYPE_NOMINAL = 0;
    public final static int FT_SIZE_REQUEST_TYPE_REAL_DIM = 1;
    public final static int FT_SIZE_REQUEST_TYPE_BBOX = 2;
    public final static int FT_SIZE_REQUEST_TYPE_CELL = 3;
    public final static int FT_SIZE_REQUEST_TYPE_SCALES = 4;
    public final static int FT_SIZE_REQUEST_TYPE_MAX = 5;




























































































































































}
















































>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

    public final static int FT_SIZE_REQUEST_TYPE_NOMINAL = 0;
    public final static int FT_SIZE_REQUEST_TYPE_REAL_DIM = 1;
    public final static int FT_SIZE_REQUEST_TYPE_BBOX = 2;
    public final static int FT_SIZE_REQUEST_TYPE_CELL = 3;
    public final static int FT_SIZE_REQUEST_TYPE_SCALES = 4;
    public final static int FT_SIZE_REQUEST_TYPE_MAX = 5;

  /* =====================================================================
   *   FT_LOAD_XXX
   *
   * @description:
   *   A list of bit-field constants used with @FT_Load_Glyph to indicate
   *   what kind of operations to perform during glyph loading.
   *
   * @values:
   *   FT_LOAD_DEFAULT ::
   *     Corresponding to~0, this value is used as the default glyph load
   *     operation.  In this case, the following happens:
   *
   *     1. FreeType looks for a bitmap for the glyph corresponding to the
   *        face's current size.  If one is found, the function returns.
   *        The bitmap data can be accessed from the glyph slot (see note
   *        below).
   *
   *     2. If no embedded bitmap is searched or found, FreeType looks for a
   *        scalable outline.  If one is found, it is loaded from the font
   *        file, scaled to device pixels, then `hinted' to the pixel grid
   *        in order to optimize it.  The outline data can be accessed from
   *        the glyph slot (see note below).
   *
   *     Note that by default, the glyph loader doesn't render outlines into
   *     bitmaps.  The following flags are used to modify this default
   *     behaviour to more specific and useful cases.
   *
   *   FT_LOAD_NO_SCALE ::
   *     Don't scale the loaded outline glyph but keep it in font units.
   *
   *     This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
   *     unsets @FT_LOAD_RENDER.
   *
   *     If the font is `tricky' (see @FT_FACE_FLAG_TRICKY for more), using
   *     FT_LOAD_NO_SCALE usually yields meaningless outlines because the
   *     subglyphs must be scaled and positioned with hinting instructions.
   *     This can be solved by loading the font without FT_LOAD_NO_SCALE and
   *     setting the character size to `font->units_per_EM'.
   *
   *   FT_LOAD_NO_HINTING ::
   *     Disable hinting.  This generally generates `blurrier' bitmap glyphs
   *     when the glyph are rendered in any of the anti-aliased modes.  See
   *     also the note below.
   *
   *     This flag is implied by @FT_LOAD_NO_SCALE.
   *
   *   FT_LOAD_RENDER ::
   *     Call @FT_Render_Glyph after the glyph is loaded.  By default, the
   *     glyph is rendered in @FT_RENDER_MODE_NORMAL mode.  This can be
   *     overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME.
   *
   *     This flag is unset by @FT_LOAD_NO_SCALE.
   *
   *   FT_LOAD_NO_BITMAP ::
   *     Ignore bitmap strikes when loading.  Bitmap-only fonts ignore this
   *     flag.
   *
   *     @FT_LOAD_NO_SCALE always sets this flag.
   *
   *   FT_LOAD_VERTICAL_LAYOUT ::
   *     Load the glyph for vertical text layout.  In particular, the
   *     `advance' value in the @FT_GlyphSlotRec structure is set to the
   *     `vertAdvance' value of the `metrics' field.
   *
   *     In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use
   *     this flag currently.  Reason is that in this case vertical metrics
   *     get synthesized, and those values are not always consistent across
   *     various font formats.
   *
   *   FT_LOAD_FORCE_AUTOHINT ::
   *     Indicates that the auto-hinter is preferred over the font's native
   *     hinter.  See also the note below.
   *
   *   FT_LOAD_CROP_BITMAP ::
   *     Indicates that the font driver should crop the loaded bitmap glyph
   *     (i.e., remove all space around its black bits).  Not all drivers
   *     implement this.
   *
   *   FT_LOAD_PEDANTIC ::
   *     Indicates that the font driver should perform pedantic verifications
   *     during glyph loading.  This is mostly used to detect broken glyphs
   *     in fonts.  By default, FreeType tries to handle broken fonts also.
   *
   *     In particular, errors from the TrueType bytecode engine are not
   *     passed to the application if this flag is not set; this might
   *     result in partially hinted or distorted glyphs in case a glyph's
   *     bytecode is buggy.
   *
   *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
   *     Ignored.  Deprecated.
   *
   *   FT_LOAD_NO_RECURSE ::
   *     This flag is only used internally.  It merely indicates that the
   *     font driver should not load composite glyphs recursively.  Instead,
   *     it should set the `num_subglyph' and `subglyphs' values of the
   *     glyph slot accordingly, and set `glyph->format' to
   *     @FT_GLYPH_FORMAT_COMPOSITE.
   *
   *     The description of sub-glyphs is not available to client
   *     applications for now.
   *
   *     This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
   *
   *   FT_LOAD_IGNORE_TRANSFORM ::
   *     Indicates that the transform matrix set by @FT_Set_Transform should
   *     be ignored.
   *
   *   FT_LOAD_MONOCHROME ::
   *     This flag is used with @FT_LOAD_RENDER to indicate that you want to
   *     render an outline glyph to a 1-bit monochrome bitmap glyph, with
   *     8~pixels packed into each byte of the bitmap data.
   *
   *     Note that this has no effect on the hinting algorithm used.  You
   *     should rather use @FT_LOAD_TARGET_MONO so that the
   *     monochrome-optimized hinting algorithm is used.
   *
   *   FT_LOAD_LINEAR_DESIGN ::
   *     Indicates that the `linearHoriAdvance' and `linearVertAdvance'
   *     fields of @FT_GlyphSlotRec should be kept in font units.  See
   *     @FT_GlyphSlotRec for details.
   *
   *   FT_LOAD_NO_AUTOHINT ::
   *     Disable auto-hinter.  See also the note below.
   *
   *   FT_LOAD_COLOR ::
   *     This flag is used to request loading of color embedded-bitmap
   *     images.  The resulting color bitmaps, if available, will have the
   *     @FT_PIXEL_MODE_BGRA format.  When the flag is not used and color
   *     bitmaps are found, they will be converted to 256-level gray
   *     bitmaps transparently.  Those bitmaps will be in the
   *     @FT_PIXEL_MODE_GRAY format.
   *
   * @note:
   *   By default, hinting is enabled and the font's native hinter (see
   *   @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter.  You can
   *   disable hinting by setting @FT_LOAD_NO_HINTING or change the
   *   precedence by setting @FT_LOAD_FORCE_AUTOHINT.  You can also set
   *   @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be
   *   used at all.
   *
   *   See the description of @FT_FACE_FLAG_TRICKY for a special exception
   *   (affecting only a handful of Asian fonts).
   *
   *   Besides deciding which hinter to use, you can also decide which
   *   hinting algorithm to use.  See @FT_LOAD_TARGET_XXX for details.
   *
   *   Note that the auto-hinter needs a valid Unicode cmap (either a native
   *   one or synthesized by FreeType) for producing correct results.  If a
   *   font provides an incorrect mapping (for example, assigning the
   *   character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a
   *   mathematical integral sign), the auto-hinter might produce useless
   *   results.
   *
   * =====================================================================
   */

    public final static long FT_LOAD_DEFAULT                     = 0x0;
    public final static long FT_LOAD_NO_SCALE                    = (1L << 0 );
    public final static long FT_LOAD_NO_HINTING                  = (1L << 1);
    public final static long FT_LOAD_RENDER                      = (1L << 2);
    public final static long FT_LOAD_NO_BITMAP                   = (1L << 3);
    public final static long FT_LOAD_VERTICAL_LAYOUT             = (1L << 4);
    public final static long FT_LOAD_FORCE_AUTOHINT              = (1L << 5);
    public final static long FT_LOAD_CROP_BITMAP                 = (1L << 6);
    public final static long FT_LOAD_PEDANTIC                    = (1L << 7);
    public final static long FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = (1L << 9);
    public final static long FT_LOAD_NO_RECURSE                  = (1L << 10);
    public final static long FT_LOAD_IGNORE_TRANSFORM            = (1L << 11);
    public final static long FT_LOAD_MONOCHROME                  = (1L << 12);
    public final static long FT_LOAD_LINEAR_DESIGN               = (1L << 13);
    public final static long FT_LOAD_NO_AUTOHINT                 = (1L << 15);
    /* Bits 16..19 are used by `FT_LOAD_TARGET_' */
    public final static long FT_LOAD_COLOR                       = (1L << 20);

    /* used longernally only by certain font drivers! */
    public final static long FT_LOAD_ADVANCE_ONLY                = (1L << 8);
    public final static long FT_LOAD_SBITS_ONLY                  = (1L << 14);

    public final static long FT_FACE_FLAG_SCALABLE         = (1L <<  0);
    public final static long FT_FACE_FLAG_FIXED_SIZES      = (1L <<  1);
    public final static long FT_FACE_FLAG_FIXED_WIDTH      = (1L <<  2);
    public final static long FT_FACE_FLAG_SFNT             = (1L <<  3);
    public final static long FT_FACE_FLAG_HORIZONTAL       = (1L <<  4);
    public final static long FT_FACE_FLAG_VERTICAL         = (1L <<  5);
    public final static long FT_FACE_FLAG_KERNING          = (1L <<  6);
    public final static long FT_FACE_FLAG_FAST_GLYPHS      = (1L <<  7);
    public final static long FT_FACE_FLAG_MULTIPLE_MASTERS = (1L <<  8);
    public final static long FT_FACE_FLAG_GLYPH_NAMES      = (1L <<  9);
    public final static long FT_FACE_FLAG_EXTERNAL_STREAM  = (1L << 10);
    public final static long FT_FACE_FLAG_HINTER           = (1L << 11);
    public final static long FT_FACE_FLAG_CID_KEYED        = (1L << 12);
    public final static long FT_FACE_FLAG_TRICKY           = (1L << 13);



}

Changes to ftbase/FTFaceRec.java.

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

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

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

    public final static long FT_FACE_FLAG_SCALABLE         = (1L <<  0);
    public final static long FT_FACE_FLAG_FIXED_SIZES      = (1L <<  1);
    public final static long FT_FACE_FLAG_FIXED_WIDTH      = (1L <<  2);
    public final static long FT_FACE_FLAG_SFNT             = (1L <<  3);
    public final static long FT_FACE_FLAG_HORIZONTAL       = (1L <<  4);
    public final static long FT_FACE_FLAG_VERTICAL         = (1L <<  5);
    public final static long FT_FACE_FLAG_KERNING          = (1L <<  6);
    public final static long FT_FACE_FLAG_FAST_GLYPHS      = (1L <<  7);
    public final static long FT_FACE_FLAG_MULTIPLE_MASTERS = (1L <<  8);
    public final static long FT_FACE_FLAG_GLYPH_NAMES      = (1L <<  9);
    public final static long FT_FACE_FLAG_EXTERNAL_STREAM  = (1L << 10);
    public final static long FT_FACE_FLAG_HINTER           = (1L << 11);
    public final static long FT_FACE_FLAG_CID_KEYED        = (1L << 12);
    public final static long FT_FACE_FLAG_TRICKY           = (1L << 13);

    private String initStr = "??";
    
    public int num_faces = 0;
    public int face_index =0;
    public long face_flags = 0L;
    public long style_flags = 0L;
    public int num_glyphs = 0;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







162
163
164
165
166
167
168















169
170
171
172
173
174
175

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

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
















    private String initStr = "??";
    
    public int num_faces = 0;
    public int face_index =0;
    public long face_flags = 0L;
    public long style_flags = 0L;
    public int num_glyphs = 0;

Changes to ftbase/FTGlyphLoaderRec.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
..
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
...
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
...
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
...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
...
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
...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
...
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
...
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
...
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
...
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
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
// ----------------------------------------------------------------
// FTGlyphLoaderRec.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 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.                                        */
/*                                                                         */
/* ======================================================================= */





  /* ===================================================================== */
  /*    FTGlyphLoaderRec                                                   */
  /*                                                                       */
  /* ===================================================================== */

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

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

    public static TTGlyphZoneRec loaderZone = null;
    public static FTGlyphLoadRec loaderLoad = null;
    public static FTGlyphLoaderRec loaderGloader = null;
    
    public static boolean doDebug = false;
    public static int glyph_debug = 0;

    public int max_points = 0;
    public int max_contours = 0;
    public int max_subglyphs = 0;
    public boolean use_extra = false;
    public FTGlyphLoadRec base = null;
    public FTGlyphLoadRec current = null;
................................................................................
      id = oid;
      base = new FTGlyphLoadRec();
      current = new FTGlyphLoadRec();
    }
    
    /* ==================== 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();
    }
 
    /* ==================== _showLoaderZone ================================== */
    public static void _showLoaderZone(String str) {
      int j;

      if (doDebug) {
        System.out.println(String.format("%s", str));
        if (TTGlyphLoaderFuncs.loader != null) {
          loaderZone = TTGlyphLoaderFuncs.loader.zone;
          loaderLoad = TTGlyphLoaderFuncs.loader.gloader.current;
        }
        if (TTInterpBase.cur != null) {
          if (TTInterpBase.cur.zp0 != null) {
            if (TTInterpBase.cur.zp0.cur != null) {
              System.out.println("zp0.cur: "+(Object)TTInterpBase.cur.zp0.cur);
              System.out.println("zp0.org: "+(Object)TTInterpBase.cur.zp0.org);
              System.out.println("zp0.orus: "+(Object)TTInterpBase.cur.zp0.orus);
            }
          }
          if (TTInterpBase.cur.zp1 != null) {
            if (TTInterpBase.cur.zp1.cur != null) {
              System.out.println("zp1.cur: "+(Object)TTInterpBase.cur.zp1.cur);
              System.out.println("zp1.org: "+(Object)TTInterpBase.cur.zp1.org);
              System.out.println("zp1.orus: "+(Object)TTInterpBase.cur.zp1.orus);
            }
          }
          if (TTInterpBase.cur.zp2 != null) {
            if (TTInterpBase.cur.zp2.cur != null) {
              System.out.println("zp2.cur: "+(Object)TTInterpBase.cur.zp2.cur);
              System.out.println("zp2.org: "+(Object)TTInterpBase.cur.zp2.org);
              System.out.println("zp2.orus: "+(Object)TTInterpBase.cur.zp2.orus);
	    }
	  }
        }
        if (loaderZone != null) {
          System.out.println(String.format("loaderZone: n_points: %d\n", loaderZone.n_points));
          if (loaderZone.cur != null) {
            System.out.println("loaderZone.cur: "+(Object)loaderZone.cur+"!"+loaderZone.cur_idx);
          }
          if (loaderZone.orus != null) {
            System.out.println("loaderZone.orus: "+(Object)loaderZone.orus+"!"+loaderZone.orus_idx);
          }
          if (loaderZone.cur != null) {
            System.out.println("loaderZone.org: "+(Object)loaderZone.org+"!"+loaderZone.org_idx);
          }
        }
        if (loaderLoad != null) {
          System.out.println(String.format("loaderLoad: n_points: %d", loaderLoad.outline.n_points));
          if (loaderLoad.outline.points != null) {
            System.out.println("loaderLoad.outline.points: "+(Object)loaderLoad.outline.points+"!"+loaderLoad.outline.points_idx);
          }
          if (loaderLoad.extra_points != null) {
            System.out.println("loaderLoad.extra_points: "+(Object)loaderLoad.extra_points+"!"+loaderLoad.extra_points_idx);
          }
          if (loaderLoad.extra_points2 != null) {
            System.out.println("loaderLoad.extra_points2: "+(Object)loaderLoad.extra_points2+"!"+loaderLoad.extra_points2_idx);
          }
        }
        if (loaderZone != null) {
  System.out.println("Show loaderZone");
          for (j = 0; j < loaderZone.n_points; j++) {
            if (loaderZone.cur != null) {
              if (j < loaderZone.cur.length) {
                if (loaderZone.cur[loaderZone.cur_idx + j] != null) {
                  System.out.println(String.format("  cur: %d %5d %5d", j, loaderZone.cur[loaderZone.cur_idx + j].x, loaderZone.cur[loaderZone.cur_idx + j].y));
                }
              }
            }
            if (loaderZone.orus != null) {
              if (j < loaderZone.orus.length) {
                if (loaderZone.orus[loaderZone.orus_idx + j] != null) {
                  System.out.println(String.format(" orus: %d %5d %5d", j, loaderZone.orus[loaderZone.orus_idx + j].x, loaderZone.orus[loaderZone.orus_idx + j].y));
                }
              }
            }
            if (loaderZone.org != null) {
              if (j < loaderZone.org.length) {
                if (loaderZone.org[loaderZone.org_idx + j] != null) {
                  System.out.println(String.format("  org: %d %5d %5d", j, loaderZone.org[loaderZone.org_idx + j].x, loaderZone.org[loaderZone.org_idx + j].y));
                }
              }
            }
          }
        }
        if (loaderLoad != null) {
System.out.println("Show loaderLoad");
          for (j = 0; j < loaderLoad.outline.n_points; j++) {
            if (loaderLoad.outline.points != null) {
              if (loaderLoad.outline.points_idx + j < loaderLoad.outline.points.length) {
                if (loaderLoad.outline.points[loaderLoad.outline.points_idx + j] != null) {
                  System.out.println(String.format(" outl: %d %5d %5d", j, loaderLoad.outline.points[loaderLoad.outline.points_idx + j].x, loaderLoad.outline.points[loaderLoad.outline.points_idx + j].y));
                }
              }
            }
            if (loaderLoad.extra_points != null) {
              if (j < loaderLoad.extra_points.length) {
                if (loaderLoad.extra_points[loaderLoad.extra_points_idx + j] != null) {
                  System.out.println(String.format(" ext1: %d %5d %5d", j, loaderLoad.extra_points[loaderLoad.extra_points_idx + j].x, loaderLoad.extra_points[loaderLoad.extra_points_idx + j].y));
                }
              }
            }
            if (loaderLoad.extra_points2 != null) {
              if (loaderLoad.extra_points2_idx + j < loaderLoad.extra_points2.length) {
                if (loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j] != null) {
                  System.out.println(String.format(" ext2: %d %5d %5d", j, loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j].x, loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j].y));
                }
              }
            }
          }
        }
      }
    }

    /* ==================== _showLoaderZone2 ================================== */
    public static void _showLoaderZone2(String str) {
      if (doDebug) {
        if (loaderZone != null) {
          System.out.println(String.format("%s: n_points: %d", str, loaderZone.n_points));
// int n_points = loaderZone.n_points;
int n_points = 5;
          for( int j = 0; j < n_points; j++) {
            if (loaderZone.cur != null) {
              if (j < loaderZone.cur.length) {
                System.out.println(String.format("  cur: %d %5d %5d", j, loaderZone.cur[loaderZone.cur_idx + j].x, loaderZone.cur[loaderZone.cur_idx + j].y));
              }
            }
            if (loaderZone.orus != null) {
              if (j < loaderZone.orus.length) {
                System.out.println(String.format(" orus: %d %5d %5d", j, loaderZone.orus[loaderZone.orus_idx + j].x, loaderZone.orus[loaderZone.orus_idx + j].y));
              }
            }
            if (loaderZone.org != null) {
              if (j < loaderZone.org.length) {
                System.out.println(String.format("  org: %d %5d %5d", j, loaderZone.org[loaderZone.org_idx + j].x, loaderZone.org[loaderZone.org_idx + j].y));
              }
            }
          }
        }
      }
    }

    /* ==================== FTGlyphLoaderDone ===================================== */
    public static void FTGlyphLoaderDone(FTGlyphLoaderRec loader) {
      FT_Trace.Trace(7, TAG, "WARNING: FTGlyphLoaderDone called");
    }

    /* ==================== FTGlyphLoaderNew ===================================== */
    public static int FTGlyphLoaderNew(FTReference<FTGlyphLoaderRec> loader_ref) {
      int error = 0;

if (doDebug) {
System.out.println("FTGlyphLoaderNew");      
}
      FTGlyphLoaderRec loader = new FTGlyphLoaderRec();
      loader_ref.Set(loader);
      return error;
    }

    /* =====================================================================
     * FTGlyphLoaderCreateExtra
     * =====================================================================
     */
    public static int FTGlyphLoaderCreateExtra(FTReference<FTGlyphLoaderRec> loader_ref) {
      int error = 0;
      FTGlyphLoaderRec loader = loader_ref.Get();

if (doDebug) {
System.out.println(String.format("FTGlyphLoaderCreateExtra: %d", loader.max_points));
}
       if (loader.max_points > 0) {
        loader.base.extra_points = new FTUnitVectorRec[2 * loader.max_points];
       }
if (doDebug) {
System.out.println("FTGlyphLoaderCreateExtra 2 extra: "+loader.base.extra_points+"!extra2: "+loader.base.extra_points2);
}
      if (loader.base.extra_points == null) {
        loader.use_extra = true;
        loader.base.extra_points_idx = 0;
        loader.base.extra_points2 = loader.base.extra_points;
        loader.base.extra_points2_idx = loader.base.extra_points_idx + loader.max_points;
        FTGlyphLoaderAdjustPoints(loader);
      }
................................................................................
      return error;
    }

    /* =====================================================================
     * GetSize
     * =====================================================================
     */
    public static int GetSize(FTDemoHandle handle, FTReference<FTSizeRec> size_erf) {
      Log.w(TAG, "WARNING: GetSize not yet implemented");
if (doDebug) {
      System.out.println("GetSize not yet implemented!!");
}
      return 1;
    }

    /* =====================================================================
     * FTDoneGlyph
     * =====================================================================
     */
    public static int FTDoneGlyph(FTGlyphRec glyph_lst) {
      Log.w(TAG, "WARNING: FTDoneGlyph not yet implemented");
if (doDebug) {
      System.out.println("FTDoneGlyph not yet implemented!!");
}
      return 1;
    }

    /* =====================================================================
     * FTVectorTransform
     * =====================================================================
     */
    public static int FTVectorTransform(FTReference<FTVectorRec> advance_ref,
            FTReference<FTMatrixRec> matrix_ref) {
      Log.w(TAG, "WARNING: FTVectorTransform not yet implemented");
if (doDebug) {
      System.out.println("FTVectorTransform not yet implemented!!");
}
      return 1;
    }
    
    /* =====================================================================
     * FTGlyphTransform
     * =====================================================================
     */
    public static int FTGlyphTransform(FTReference<FTGlyphRec> advance_ref,
            int val, FTReference<FTVectorRec> vector_ref) {
      Log.w(TAG, "WARNING: FTGlyphTransform not yet implemented");
if (doDebug) {
      System.out.println("FTGlyphTransform not yet implemented!!");
}
      return 1;
    }
    
    /* =====================================================================
     * FTGetGlyph
     * =====================================================================
     */
................................................................................

      int error;
      FTLibraryRec library;
      FTGlyphRec glyph = null;
      FTGlyphClassRec clazz = null;

      if (slot == null) {
        return FT_Error.LOAD_INVALID_SLOT_HANDLE;
      }
      library = slot.library;
      if (aglyph == null) {
        error = FT_Error.LOAD_INVALID_ARGUMENT;
        return error;
      }
      /* if it is a bitmap, that's easy :-) */
      if (slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_BITMAP) {
        FTBitmapGlyphClassRec glyph_class = new FTBitmapGlyphClassRec();
        clazz = glyph_class;
      } else {
        /* if it is an outline */
        if (slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_OUTLINE) {
          FTOutlineGlyphClass glyph_class = new FTOutlineGlyphClass();
          clazz = glyph_class;
        } else {
          /* try to find a renderer that supports the glyph image format */
          FTRendererRec render = FTRendererRec.FTLookupRenderer(library, slot.format, null);

          if (render != null) {
            clazz = render.glyph_class;
          }
        }
      }
      if (clazz == null) {
        error = FT_Error.LOAD_INVALID_GLYPH_FORMAT;
        return error;
      }
      /* create FT_Glyph object */
      glyph_ref.Set(glyph);
      error = FTGlyphLoaderFuncs.ft_new_glyph(library, clazz, glyph_ref);
      glyph = glyph_ref.Get();
      if (error != 0) {
................................................................................
      int n;

      if (loader == null) {
        return;
      }
      n_curr_contours = loader.current.outline.n_contours;
      n_base_points = loader.base.outline.n_points;
if (doDebug) {
System.out.println(String.format("FTGlyphLoaderAdd: n_base_points: %d, loader.current.outline.n_points: %d", n_base_points, loader.current.outline.n_points));
}
      loader.base.outline.n_points =
        (short)(loader.base.outline.n_points + loader.current.outline.n_points);
if (doDebug) {
System.out.println(String.format("FTGlyphLoaderAdd3: n_points: %d", loader.base.outline.n_points));
}
      loader.base.outline.n_contours =
        (short)(loader.base.outline.n_contours + loader.current.outline.n_contours);
      loader.base.num_subglyphs += loader.current.num_subglyphs;
      /* adjust contours count in newest outline */
      for (n = 0; n < n_curr_contours; n++) {
        loader.current.outline.contours[n] =
          (short)(loader.current.outline.contours[n] + n_base_points);
................................................................................
      FTLibraryRec library;
      boolean autohint = false;
      FTModuleRec hinter;
      boolean Load_Ok = false;
      TTFaceRec ttface = (TTFaceRec)face;

      if (face == null || face.size == null || face.glyph == null) {
        return FT_Error.LOAD_INVALID_FACE_HANDLE;
      }
      /* The validity test for `glyph_index' is performed by the */
      /* font drivers.                                           */
      slot = face.glyph;
      FTReference<FTGlyphSlotRec> slot_ref = new FTReference<FTGlyphSlotRec>();
      slot_ref.Set(slot);
      FTGlyphLoaderFuncs.ft_glyphslot_clear(slot_ref);
................................................................................
        /* XXX: This is really a temporary hack that should disappear */
        /*      promptly with FreeType 2.1!                           */
        /*                                                            */
        if ((face.face_flags & FTFaceRec.FT_FACE_FLAG_FIXED_SIZES) != 0 &&
            ((load_flags & FTGlyphLoaderFlags.FT_LOAD_NO_BITMAP) == 0)) {
          error = (int)driver.driver_clazz.load_glyph.callClassMethod(slot, face.size,
                 glyph_index, load_flags | FTGlyphLoaderFlags.FT_LOAD_SBITS_ONLY);
          if ((error != 0 )&& slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_BITMAP) {
            Load_Ok = true;
          }
        }
        if (! Load_Ok) {
          FTFaceInternalRec internal = face.internal;
          int transform_flags = internal.transform_flags;

................................................................................
        slot_ref.Set(slot); 
        error = (int)driver.driver_clazz.load_glyph.callClassMethod(slot_ref,
               face.size, glyph_index, load_flags);
        slot = slot_ref.Get();
        if (error != 0) {
          return error;
        }
if (doDebug) {
System.out.println("FT_Load_Glyph: slot->format is outline: "+(slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_OUTLINE));
}
        if (slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_OUTLINE) {
          /* check that the loaded outline is correct */
if (doDebug) {
System.out.println(String.format("CHKOUTLINE: %d", slot.outline.n_points));
}
          error = FTOutlineRec.FTOutlineCheck(slot.outline);
          if (error != 0) {
            return error;
          }
        }
      }
      /* compute the advance */
................................................................................
        FTSizeMetricsRec metrics = face.size.metrics;

        /* it's tricky! */
        slot.linearHoriAdvance = FTCalc.FT_MulDiv(slot.linearHoriAdvance, metrics.x_scale, 64L);
        slot.linearVertAdvance = FTCalc.FT_MulDiv(slot.linearVertAdvance, metrics.y_scale, 64L);
      }

if (doDebug) {
System.out.println(String.format("FT_LOAD_IGNORE_TRANSFORM: %d", (load_flags & FTGlyphLoaderFlags.FT_LOAD_IGNORE_TRANSFORM)));
}
      if ((load_flags & FTGlyphLoaderFlags.FT_LOAD_IGNORE_TRANSFORM) == 0) {
        FTFaceInternalRec internal = face.internal;
        FTReference<FTMatrixRec> matrix_ref = new FTReference<FTMatrixRec>();
        FTReference<FTVectorRec> delta_ref = new FTReference<FTVectorRec>();        

        /* now, transform the glyph image if needed */
        if (internal.transform_flags != 0) {
................................................................................
            matrix_ref.Set(internal.transform_matrix);
            delta_ref.Set(internal.transform_delta);
            error = (int)renderer.clazz.transform_glyph.callClassMethod(renderer, slot,
                    matrix_ref, delta_ref);
            internal.transform_matrix = matrix_ref.Get();
            internal.transform_delta = delta_ref.Get();
          } else {
            if (slot.format == FTGlyphFormat.FT_GLYPH_FORMAT_OUTLINE) {
              FTReference<FTOutlineRec> outline_ref = new FTReference<FTOutlineRec>();
              /* apply `standard' transformation if no renderer is available */
              if ((internal.transform_flags & 1) != 0) {
if (doDebug) {
System.out.println("standard outline transform");
}
                outline_ref.Set(slot.outline);
                matrix_ref.Set(internal.transform_matrix);
                FTOutlineRec.FTOutlineTransform(outline_ref, matrix_ref);
                slot.outline = outline_ref.Get();
                internal.transform_matrix = matrix_ref.Get();
                
              }
................................................................................
                FTOutlineRec.FTOutlineTranslate(outline_ref,
                        internal.transform_delta.x, internal.transform_delta.y);
                slot.outline = outline_ref.Get();
              }
            }
          }
          /* transform advance */
          FTReference<FTUnitVectorRec> advance_ref = new FTReference<FTUnitVectorRec>();
          advance_ref.Set(slot.advance);
          matrix_ref.Set(internal.transform_matrix);
          FTOutlineRec.FTVectorTransform(advance_ref, matrix_ref);
          slot.advance = advance_ref.Get();
          internal.transform_matrix = matrix_ref.Get();
        }
      }
      FT_Trace.Trace(7, TAG, String.format("  x advance: %d", slot.advance.x));
      FT_Trace.Trace(7, TAG, String.format("  y advance: %d", slot.advance.y));
      FT_Trace.Trace(7, TAG, String.format("  linear x advance: %d", slot.linearHoriAdvance));
      FT_Trace.Trace(7, TAG, String.format("  linear y advance: %d", slot.linearVertAdvance));
      /* do we need to render the image now? */
      if (error == 0 &&
           (slot.format != FTGlyphFormat.FT_GLYPH_FORMAT_BITMAP) &&
           (slot.format != FTGlyphFormat.FT_GLYPH_FORMAT_COMPOSITE) &&
           (load_flags & FTGlyphLoaderFlags.FT_LOAD_RENDER) != 0) {
        Long mode = (long)((load_flags >> 16) & 15);

        if ((mode == FTRendererRec.FT_RENDER_MODE_NORMAL) && 
        		(load_flags & FTGlyphLoaderFlags.FT_LOAD_MONOCHROME) != 0) {
          mode = (long)FTRendererRec.FT_RENDER_MODE_MONO;
        }
................................................................................
    }

    /* =====================================================================
     * translate_array
     *
     * =====================================================================
     */
    public static void translate_array(int n, FTReference<FTUnitVectorRec[]> coords_ref, int idx, long delta_x, long delta_y) {
      FTUnitVectorRec[] coords = coords_ref.Get();
      int k;

      if (delta_x != 0) {
        for (k = 0; k < n; k++) {
          coords[idx + k].x += delta_x;
        }
      }
................................................................................

    /* =====================================================================
     * FTGlyphLoaderAdjustPoints
     *
     * =====================================================================
     */
    public static void FTGlyphLoaderAdjustPoints(FTGlyphLoaderRec loader) {
if (doDebug) {
System.out.println("FTGlyphLoaderAdjustPoints: "+loader+"!");    	
}
_showLoaderZone("FT_GlyphLoader_Adjust_Points 1");
      loader.current.outline.points = loader.base.outline.points;
      loader.current.outline.points_idx = loader.base.outline.n_points;
      loader.current.outline.tags = loader.base.outline.tags;
      loader.current.outline.tags_idx =  loader.base.outline.n_points;
      loader.current.outline.contours = loader.base.outline.contours;
      loader.current.outline.contours_idx = loader.base.outline.n_contours;
_showLoaderZone("FT_GlyphLoader_Adjust_Points 2");
      /* handle extra points table - if any */
      if (loader.use_extra) {
if (doDebug) {
System.out.println("FTGlyphLoaderAdjustPoints 3: extra_points: "+loader.base.extra_points+"!"+loader.base.extra_points_idx+"!extra_points2: "+loader.base.extra_points2+"!"+loader.base.extra_points2_idx+"!");
}
        loader.current.extra_points = loader.base.extra_points;
        loader.current.extra_points_idx = loader.base.extra_points_idx + loader.base.outline.n_points;
        loader.current.extra_points2 = loader.base.extra_points2;
        loader.current.extra_points2_idx = loader.base.extra_points2_idx + loader.base.outline.n_points;
      }
_showLoaderZone("FT_GlyphLoader_Adjust_Points 3");
    }
................................................................................
    }

    /* =====================================================================
     * FTGlyphLoaderCheckP
     * =====================================================================
     */
    public static boolean FTGlyphLoaderCheckP(FTGlyphLoaderRec loader, int count) {
if (doDebug) {
System.out.println(String.format("CheckP: count: %d, base n_points: %d, current n_points: %d, max_points: %d",
    count, loader.base.outline.n_points, loader.current.outline.n_points, loader.max_points));
}
      return (count == 0 ||
            loader.base.outline.n_points +
            loader.current.outline.n_points + (long)count <=
            loader.max_points);
    }

    /* =====================================================================
     * FTGlyphLoaderCheckC
     * =====================================================================
     */
    public static boolean FTGlyphLoaderCheckC(FTGlyphLoaderRec loader, int count) {
if (doDebug) {
System.out.println(String.format("CheckC: count: %d, base n_contours: %d, current n_contours: %d, max_contours: %d",
    count, loader.base.outline.n_contours, loader.current.outline.n_contours, loader.max_contours));
}
      return (count == 0 ||
            loader.base.outline.n_contours +
            loader.current.outline.n_contours + (long)count <=
            loader.max_contours);
    }

    /* =====================================================================
................................................................................
     * Ensure that we can add `n_points' and `n_contours' to our glyph.
     * This function reallocates its outline tables if necessary.  Note that
     * it DOESN'T change the number of points within the loader!
     *
     * =====================================================================
     */
    public static int FTGlyphLoaderCheckPoints(FTGlyphLoaderRec loader, int n_points, int n_contours) {
      int error = FT_Error.INTERP_ERR_OK;
      boolean adjust = false;
      int new_max;
      int old_max;
      int k;

if (doDebug) {
System.out.println("FTGlyphLoaderCheckPoints: base.outline.points: "+loader.base.outline.points+"!base.outline.tags: "+loader.base.outline.tags+"!");      
}
      /* check points & tags */
      new_max = loader.base.outline.n_points + loader.current.outline.n_points + n_points;
      old_max = loader.max_points;
if (doDebug) {
System.out.println(String.format("n_points: base.outline.n_points: %d current.outline.n_points: %d n_points: %d", loader.base.outline.n_points, loader.current.outline.n_points, n_points));
System.out.println(String.format("FTGlyphLoaderCheckPoints: renew: old: %d new: %d", old_max, new_max));
}
      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 8).intValue();
        if (new_max > FTOutlineRec.FT_OUTLINE_POINTS_MAX) {
          return FT_Error.GLYPH_ARRAY_TOO_LARGE;
        }
if (doDebug) {
System.out.println("FT_RENEW_ARRAY: base.outline.points: "+loader.base.outline.points+"!");
}
        loader.base.outline.points = (FTUnitVectorRec[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.points, "FTUnitVector", old_max, new_max);
if (doDebug) {
System.out.println("after FT_RENEW_ARRAY: base.outline.points: "+loader.base.outline.points+"!");
System.out.println("FT_RENEW_ARRAY: base.outline.tags: "+loader.base.outline.tags);
}
        loader.base.outline.tags = (byte[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.tags, "byte", old_max, new_max);
if (doDebug) {
System.out.println("after FT_RENEW_ARRAY: base.outline.tags: "+loader.base.outline.tags);
}
//        if (FT_RENEW_ARRAY(loader.base.outline.points, old_max, new_max) ||
//             FT_RENEW_ARRAY(loader.base.outline.tags, old_max, new_max)) {
//          if (error != 0) {
//            FTGlyphLoaderReset(loader);
//          }
//          return error;
//        }
if (doDebug) {
System.out.println("FT_RENEW_ARRAY base.extra_points: "+loader.base.extra_points+"!use_extra: "+loader.use_extra+"!");
}
        if (loader.use_extra) {
          loader.base.extra_points = (FTUnitVectorRec[])FTUtil.FT_RENEW_ARRAY(loader.base.extra_points, "FTUnitVector", old_max * 2, new_max * 2);
if (doDebug) {
System.out.println("after FT_RENEW_ARRAY base.extra_points: "+loader.base.extra_points+"!use_extra: "+loader.use_extra+"!");
}
//          if (FT_RENEW_ARRAY(loader.base.extra_points, old_max * 2, new_max * 2)) {
//            if (error != 0) {
//              FTGlyphLoaderReset(loader);
//            }
//            return error;
//          }
          for (k = 0; k < old_max; k++) {
................................................................................
          }
//          FT_ARRAY_MOVE(loader.base.extra_points + new_max,
//                  loader.base.extra_points + old_max, old_max);
//          loader.base.extra_points2 = loader.base.extra_points;
//          loader.base.extra_points2_idx = loader.base.extra_points_idx + new_max;
//System.out.println("base extra points2 1: "+loader.base.extra_points2+"!"+loader.base.extra_points2_idx+"!");
//System.out.println("SZ: "+loader.base.extra_points2.length+"!"+loader.base.extra_points2+"!");
          loader.base.extra_points2 = new FTUnitVectorRec[new_max];
          for (k = old_max; k < old_max * 2; k++) {
            loader.base.extra_points2[k - old_max] = loader.base.extra_points[loader.base.extra_points_idx + k];
          }
          for (k = old_max; k < new_max; k++) {
            loader.base.extra_points2[k] = new FTUnitVectorRec();
          }
          loader.base.extra_points2_idx = 0;
          
        }
        adjust = true;
        loader.max_points = new_max;
      }
      /* check contours */
      old_max = loader.max_contours;
      new_max = loader.base.outline.n_contours + loader.current.outline.n_contours + n_contours;
if (doDebug) {
System.out.println(String.format("base.outline.n_contours: %d, current.outline.n_contours: %d, n_contours: %d", loader.base.outline.n_contours, loader.current.outline.n_contours, n_contours));
System.out.println(String.format("FTGlyphLoaderCheckContours: renew: old: %d new: %d", old_max, new_max));
}
      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 4).intValue();
        if (new_max > FTOutlineRec.FT_OUTLINE_CONTOURS_MAX) {
          return FT_Error.GLYPH_ARRAY_TOO_LARGE;
        }
        loader.base.outline.contours = (short[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.contours, "short", old_max, new_max);
//        if (FT_RENEW_ARRAY(loader.base.outline.contours, old_max, new_max)) {
//          if (error != 0) {
//            FTGlyphLoaderReset(loader);
//          }
//          return error;
................................................................................

    /* =====================================================================
     * FT_GLYPHLOADER_CHECK_POINTS
     * =====================================================================
     */
    public static int FT_GLYPHLOADER_CHECK_POINTS(FTGlyphLoaderRec loader, int points, int contours) {
      if (FTGlyphLoaderCheckP(loader, points) && FTGlyphLoaderCheckC(loader, contours)) {
        return FT_Error.INTERP_ERR_OK;
      } else {
        return FTGlyphLoaderCheckPoints(loader, points, contours);
      }
    }

    /* =====================================================================
     * FTGlyphLoaderReset
................................................................................
    }

    /* =====================================================================
     * FTGlyphLoaderCheckSubGlyphs
     * =====================================================================
     */
    public static int FTGlyphLoaderCheckSubGlyphs(FTGlyphLoaderRec loader, int n_subs) {
      int error = FT_Error.INTERP_ERR_OK;
      int new_max;
      int old_max;

      new_max = loader.base.num_subglyphs + loader.current.num_subglyphs + n_subs;
      old_max = loader.max_subglyphs;
      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 2).intValue();
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
>
>
>
|
<
<
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>

>
>
>





|










<







 







|
<
|



|
<













|







|
|
|




|
|
|




|
|
|
|
|


|

|


|


|



|

|


|


|



|




|






|






|






|




|






|






|












|





|




|




|









|






<
|
<













<
|
<

|

<
|
<







 







|

<
|
<









<
|
<










<
|
<










<
|
<







 







|



|



|




|












|







 







<
|
<


<
|
<







 







|







 







|







 







<
|
<
|

<
|
<







 







<
|
<







 







|



<
|
<







 







|







|
|
|
|


|
|







 







|
|







 







<
|
<










<
|
<







 







<
|

<











<
|

<







 







|





<
|
<



<
|
|
<



|

<
|
<
|
<
|
|
<

<
|
<







<
|
<

|
<
|
<







 







|




|










<
|
|
<



|







 







|







 







|





















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
..
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
...
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
...
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
...
360
361
362
363
364
365
366

367

368
369

370

371
372
373
374
375
376
377
...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
...
539
540
541
542
543
544
545

546

547
548

549

550
551
552
553
554
555
556
...
566
567
568
569
570
571
572

573

574
575
576
577
578
579
580
...
585
586
587
588
589
590
591
592
593
594
595

596

597
598
599
600
601
602
603
...
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
...
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
...
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
...
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
...
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
...
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
...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875














/* =====================================================================
 *  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;
  /* ===================================================================== */
  /*    FTGlyphLoaderRec                                                   */
  /*                                                                       */
  /* ===================================================================== */

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

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

    public static TTGlyphZoneRec loaderZone = null;
    public static FTGlyphLoadRec loaderLoad = null;
    public static FTGlyphLoaderRec loaderGloader = null;
    
    public static boolean doDebug = false;


    public int max_points = 0;
    public int max_contours = 0;
    public int max_subglyphs = 0;
    public boolean use_extra = false;
    public FTGlyphLoadRec base = null;
    public FTGlyphLoadRec current = null;
................................................................................
      id = oid;
      base = new FTGlyphLoadRec();
      current = new FTGlyphLoadRec();
    }
    
    /* ==================== 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();
    }
 
    /* ==================== _showLoaderZone ================================== */
    public static void _showLoaderZone(String str) {
      int j;

      if (doDebug) {
        Debug(0, DBG_LOAD_GLYPH, TAG, String.format("%s", str));
        if (TTGlyphLoaderFuncs.loader != null) {
          loaderZone = TTGlyphLoaderFuncs.loader.zone;
          loaderLoad = TTGlyphLoaderFuncs.loader.gloader.current;
        }
        if (TTInterpBase.cur != null) {
          if (TTInterpBase.cur.zp0 != null) {
            if (TTInterpBase.cur.zp0.cur != null) {
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp0.cur: "+(Object)TTInterpBase.cur.zp0.cur);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp0.org: "+(Object)TTInterpBase.cur.zp0.org);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp0.orus: "+(Object)TTInterpBase.cur.zp0.orus);
            }
          }
          if (TTInterpBase.cur.zp1 != null) {
            if (TTInterpBase.cur.zp1.cur != null) {
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp1.cur: "+(Object)TTInterpBase.cur.zp1.cur);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp1.org: "+(Object)TTInterpBase.cur.zp1.org);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp1.orus: "+(Object)TTInterpBase.cur.zp1.orus);
            }
          }
          if (TTInterpBase.cur.zp2 != null) {
            if (TTInterpBase.cur.zp2.cur != null) {
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp2.cur: "+(Object)TTInterpBase.cur.zp2.cur);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp2.org: "+(Object)TTInterpBase.cur.zp2.org);
              Debug(0, DBG_LOAD_GLYPH, TAG, "zp2.orus: "+(Object)TTInterpBase.cur.zp2.orus);
            }
          }
        }
        if (loaderZone != null) {
          Debug(0, DBG_LOAD_GLYPH, TAG, String.format("loaderZone: n_points: %d\n", loaderZone.n_points));
          if (loaderZone.cur != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderZone.cur: "+(Object)loaderZone.cur+"!"+loaderZone.cur_idx);
          }
          if (loaderZone.orus != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderZone.orus: "+(Object)loaderZone.orus+"!"+loaderZone.orus_idx);
          }
          if (loaderZone.cur != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderZone.org: "+(Object)loaderZone.org+"!"+loaderZone.org_idx);
          }
        }
        if (loaderLoad != null) {
          Debug(0, DBG_LOAD_GLYPH, TAG, String.format("loaderLoad: n_points: %d", loaderLoad.outline.n_points));
          if (loaderLoad.outline.points != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderLoad.outline.points: "+(Object)loaderLoad.outline.points+"!"+loaderLoad.outline.points_idx);
          }
          if (loaderLoad.extra_points != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderLoad.extra_points: "+(Object)loaderLoad.extra_points+"!"+loaderLoad.extra_points_idx);
          }
          if (loaderLoad.extra_points2 != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, "loaderLoad.extra_points2: "+(Object)loaderLoad.extra_points2+"!"+loaderLoad.extra_points2_idx);
          }
        }
        if (loaderZone != null) {
          Debug(0, DBG_LOAD_GLYPH, TAG, "Show loaderZone");
          for (j = 0; j < loaderZone.n_points; j++) {
            if (loaderZone.cur != null) {
              if (j < loaderZone.cur.length) {
                if (loaderZone.cur[loaderZone.cur_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format("  cur: %d %5d %5d", j, loaderZone.cur[loaderZone.cur_idx + j].x, loaderZone.cur[loaderZone.cur_idx + j].y));
                }
              }
            }
            if (loaderZone.orus != null) {
              if (j < loaderZone.orus.length) {
                if (loaderZone.orus[loaderZone.orus_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format(" orus: %d %5d %5d", j, loaderZone.orus[loaderZone.orus_idx + j].x, loaderZone.orus[loaderZone.orus_idx + j].y));
                }
              }
            }
            if (loaderZone.org != null) {
              if (j < loaderZone.org.length) {
                if (loaderZone.org[loaderZone.org_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format("  org: %d %5d %5d", j, loaderZone.org[loaderZone.org_idx + j].x, loaderZone.org[loaderZone.org_idx + j].y));
                }
              }
            }
          }
        }
        if (loaderLoad != null) {
          Debug(0, DBG_LOAD_GLYPH, TAG, "Show loaderLoad");
          for (j = 0; j < loaderLoad.outline.n_points; j++) {
            if (loaderLoad.outline.points != null) {
              if (loaderLoad.outline.points_idx + j < loaderLoad.outline.points.length) {
                if (loaderLoad.outline.points[loaderLoad.outline.points_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format(" outl: %d %5d %5d", j, loaderLoad.outline.points[loaderLoad.outline.points_idx + j].x, loaderLoad.outline.points[loaderLoad.outline.points_idx + j].y));
                }
              }
            }
            if (loaderLoad.extra_points != null) {
              if (j < loaderLoad.extra_points.length) {
                if (loaderLoad.extra_points[loaderLoad.extra_points_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format(" ext1: %d %5d %5d", j, loaderLoad.extra_points[loaderLoad.extra_points_idx + j].x, loaderLoad.extra_points[loaderLoad.extra_points_idx + j].y));
                }
              }
            }
            if (loaderLoad.extra_points2 != null) {
              if (loaderLoad.extra_points2_idx + j < loaderLoad.extra_points2.length) {
                if (loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j] != null) {
                  Debug(0, DBG_LOAD_GLYPH, TAG, String.format(" ext2: %d %5d %5d", j, loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j].x, loaderLoad.extra_points2[loaderLoad.extra_points2_idx + j].y));
                }
              }
            }
          }
        }
      }
    }

    /* ==================== _showLoaderZone2 ================================== */
    public static void _showLoaderZone2(String str) {
      if (doDebug) {
        if (loaderZone != null) {
            Debug(0, DBG_LOAD_GLYPH, TAG, String.format("%s: n_points: %d", str, loaderZone.n_points));
// int n_points = loaderZone.n_points;
int n_points = 5;
          for( int j = 0; j < n_points; j++) {
            if (loaderZone.cur != null) {
              if (j < loaderZone.cur.length) {
                Debug(0, DBG_LOAD_GLYPH, TAG, String.format("  cur: %d %5d %5d", j, loaderZone.cur[loaderZone.cur_idx + j].x, loaderZone.cur[loaderZone.cur_idx + j].y));
              }
            }
            if (loaderZone.orus != null) {
              if (j < loaderZone.orus.length) {
                Debug(0, DBG_LOAD_GLYPH, TAG, String.format(" orus: %d %5d %5d", j, loaderZone.orus[loaderZone.orus_idx + j].x, loaderZone.orus[loaderZone.orus_idx + j].y));
              }
            }
            if (loaderZone.org != null) {
              if (j < loaderZone.org.length) {
                Debug(0, DBG_LOAD_GLYPH, TAG, String.format("  org: %d %5d %5d", j, loaderZone.org[loaderZone.org_idx + j].x, loaderZone.org[loaderZone.org_idx + j].y));
              }
            }
          }
        }
      }
    }

    /* ==================== FTGlyphLoaderDone ===================================== */
    public static void FTGlyphLoaderDone(FTGlyphLoaderRec loader) {
      FTTrace.Trace(7, TAG, "WARNING: FTGlyphLoaderDone called");
    }

    /* ==================== FTGlyphLoaderNew ===================================== */
    public static int FTGlyphLoaderNew(FTReference<FTGlyphLoaderRec> loader_ref) {
      int error = 0;


Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphLoaderNew");

      FTGlyphLoaderRec loader = new FTGlyphLoaderRec();
      loader_ref.Set(loader);
      return error;
    }

    /* =====================================================================
     * FTGlyphLoaderCreateExtra
     * =====================================================================
     */
    public static int FTGlyphLoaderCreateExtra(FTReference<FTGlyphLoaderRec> loader_ref) {
      int error = 0;
      FTGlyphLoaderRec loader = loader_ref.Get();


Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FTGlyphLoaderCreateExtra: %d", loader.max_points));

       if (loader.max_points > 0) {
        loader.base.extra_points = new FTVectorRec[2 * loader.max_points];
       }

Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphLoaderCreateExtra 2 extra: "+loader.base.extra_points+"!extra2: "+loader.base.extra_points2);

      if (loader.base.extra_points == null) {
        loader.use_extra = true;
        loader.base.extra_points_idx = 0;
        loader.base.extra_points2 = loader.base.extra_points;
        loader.base.extra_points2_idx = loader.base.extra_points_idx + loader.max_points;
        FTGlyphLoaderAdjustPoints(loader);
      }
................................................................................
      return error;
    }

    /* =====================================================================
     * GetSize
     * =====================================================================
     */
    public static int GetSize(ftdemo.FTDemoHandle handle, FTReference<FTSizeRec> size_erf) {
      Log.w(TAG, "WARNING: GetSize not yet implemented");

Debug(0, DBG_LOAD_GLYPH, TAG, "GetSize not yet implemented!!");

      return 1;
    }

    /* =====================================================================
     * FTDoneGlyph
     * =====================================================================
     */
    public static int FTDoneGlyph(FTGlyphRec glyph_lst) {
      Log.w(TAG, "WARNING: FTDoneGlyph not yet implemented");

Debug(0, DBG_LOAD_GLYPH, TAG, "FTDoneGlyph not yet implemented!!");

      return 1;
    }

    /* =====================================================================
     * FTVectorTransform
     * =====================================================================
     */
    public static int FTVectorTransform(FTReference<FTVectorRec> advance_ref,
            FTReference<FTMatrixRec> matrix_ref) {
      Log.w(TAG, "WARNING: FTVectorTransform not yet implemented");

Debug(0, DBG_LOAD_GLYPH, TAG, "FTVectorTransform not yet implemented!!");

      return 1;
    }
    
    /* =====================================================================
     * FTGlyphTransform
     * =====================================================================
     */
    public static int FTGlyphTransform(FTReference<FTGlyphRec> advance_ref,
            int val, FTReference<FTVectorRec> vector_ref) {
      Log.w(TAG, "WARNING: FTGlyphTransform not yet implemented");

Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphTransform not yet implemented!!");

      return 1;
    }
    
    /* =====================================================================
     * FTGetGlyph
     * =====================================================================
     */
................................................................................

      int error;
      FTLibraryRec library;
      FTGlyphRec glyph = null;
      FTGlyphClassRec clazz = null;

      if (slot == null) {
        return FTError.LOAD_INVALID_SLOT_HANDLE;
      }
      library = slot.library;
      if (aglyph == null) {
        error = FTError.LOAD_INVALID_ARGUMENT;
        return error;
      }
      /* if it is a bitmap, that's easy :-) */
      if (slot.format == FT_GLYPH_FORMAT_BITMAP) {
        FTBitmapGlyphClassRec glyph_class = new FTBitmapGlyphClassRec();
        clazz = glyph_class;
      } else {
        /* if it is an outline */
        if (slot.format == FT_GLYPH_FORMAT_OUTLINE) {
          FTOutlineGlyphClass glyph_class = new FTOutlineGlyphClass();
          clazz = glyph_class;
        } else {
          /* try to find a renderer that supports the glyph image format */
          FTRendererRec render = FTRendererRec.FTLookupRenderer(library, slot.format, null);

          if (render != null) {
            clazz = render.glyph_class;
          }
        }
      }
      if (clazz == null) {
        error = FTError.LOAD_INVALID_GLYPH_FORMAT;
        return error;
      }
      /* create FT_Glyph object */
      glyph_ref.Set(glyph);
      error = FTGlyphLoaderFuncs.ft_new_glyph(library, clazz, glyph_ref);
      glyph = glyph_ref.Get();
      if (error != 0) {
................................................................................
      int n;

      if (loader == null) {
        return;
      }
      n_curr_contours = loader.current.outline.n_contours;
      n_base_points = loader.base.outline.n_points;

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FTGlyphLoaderAdd: n_base_points: %d, loader.current.outline.n_points: %d", n_base_points, loader.current.outline.n_points));

      loader.base.outline.n_points =
        (short)(loader.base.outline.n_points + loader.current.outline.n_points);

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FTGlyphLoaderAdd3: n_points: %d", loader.base.outline.n_points));

      loader.base.outline.n_contours =
        (short)(loader.base.outline.n_contours + loader.current.outline.n_contours);
      loader.base.num_subglyphs += loader.current.num_subglyphs;
      /* adjust contours count in newest outline */
      for (n = 0; n < n_curr_contours; n++) {
        loader.current.outline.contours[n] =
          (short)(loader.current.outline.contours[n] + n_base_points);
................................................................................
      FTLibraryRec library;
      boolean autohint = false;
      FTModuleRec hinter;
      boolean Load_Ok = false;
      TTFaceRec ttface = (TTFaceRec)face;

      if (face == null || face.size == null || face.glyph == null) {
        return FTError.LOAD_INVALID_FACE_HANDLE;
      }
      /* The validity test for `glyph_index' is performed by the */
      /* font drivers.                                           */
      slot = face.glyph;
      FTReference<FTGlyphSlotRec> slot_ref = new FTReference<FTGlyphSlotRec>();
      slot_ref.Set(slot);
      FTGlyphLoaderFuncs.ft_glyphslot_clear(slot_ref);
................................................................................
        /* XXX: This is really a temporary hack that should disappear */
        /*      promptly with FreeType 2.1!                           */
        /*                                                            */
        if ((face.face_flags & FTFaceRec.FT_FACE_FLAG_FIXED_SIZES) != 0 &&
            ((load_flags & FTGlyphLoaderFlags.FT_LOAD_NO_BITMAP) == 0)) {
          error = (int)driver.driver_clazz.load_glyph.callClassMethod(slot, face.size,
                 glyph_index, load_flags | FTGlyphLoaderFlags.FT_LOAD_SBITS_ONLY);
          if ((error != 0 )&& slot.format == FT_GLYPH_FORMAT_BITMAP) {
            Load_Ok = true;
          }
        }
        if (! Load_Ok) {
          FTFaceInternalRec internal = face.internal;
          int transform_flags = internal.transform_flags;

................................................................................
        slot_ref.Set(slot); 
        error = (int)driver.driver_clazz.load_glyph.callClassMethod(slot_ref,
               face.size, glyph_index, load_flags);
        slot = slot_ref.Get();
        if (error != 0) {
          return error;
        }

Debug(0, DBG_LOAD_GLYPH, TAG, "FT_Load_Glyph: slot->format is outline: "+(slot.format == FT_GLYPH_FORMAT_OUTLINE));

        if (slot.format == FT_GLYPH_FORMAT_OUTLINE) {
          /* check that the loaded outline is correct */

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("CHKOUTLINE: %d", slot.outline.n_points));

          error = FTOutlineRec.FTOutlineCheck(slot.outline);
          if (error != 0) {
            return error;
          }
        }
      }
      /* compute the advance */
................................................................................
        FTSizeMetricsRec metrics = face.size.metrics;

        /* it's tricky! */
        slot.linearHoriAdvance = FTCalc.FT_MulDiv(slot.linearHoriAdvance, metrics.x_scale, 64L);
        slot.linearVertAdvance = FTCalc.FT_MulDiv(slot.linearVertAdvance, metrics.y_scale, 64L);
      }


Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FT_LOAD_IGNORE_TRANSFORM: %d", (load_flags & FTGlyphLoaderFlags.FT_LOAD_IGNORE_TRANSFORM)));

      if ((load_flags & FTGlyphLoaderFlags.FT_LOAD_IGNORE_TRANSFORM) == 0) {
        FTFaceInternalRec internal = face.internal;
        FTReference<FTMatrixRec> matrix_ref = new FTReference<FTMatrixRec>();
        FTReference<FTVectorRec> delta_ref = new FTReference<FTVectorRec>();        

        /* now, transform the glyph image if needed */
        if (internal.transform_flags != 0) {
................................................................................
            matrix_ref.Set(internal.transform_matrix);
            delta_ref.Set(internal.transform_delta);
            error = (int)renderer.clazz.transform_glyph.callClassMethod(renderer, slot,
                    matrix_ref, delta_ref);
            internal.transform_matrix = matrix_ref.Get();
            internal.transform_delta = delta_ref.Get();
          } else {
            if (slot.format == FT_GLYPH_FORMAT_OUTLINE) {
              FTReference<FTOutlineRec> outline_ref = new FTReference<FTOutlineRec>();
              /* apply `standard' transformation if no renderer is available */
              if ((internal.transform_flags & 1) != 0) {

Debug(0, DBG_LOAD_GLYPH, TAG, "standard outline transform");

                outline_ref.Set(slot.outline);
                matrix_ref.Set(internal.transform_matrix);
                FTOutlineRec.FTOutlineTransform(outline_ref, matrix_ref);
                slot.outline = outline_ref.Get();
                internal.transform_matrix = matrix_ref.Get();
                
              }
................................................................................
                FTOutlineRec.FTOutlineTranslate(outline_ref,
                        internal.transform_delta.x, internal.transform_delta.y);
                slot.outline = outline_ref.Get();
              }
            }
          }
          /* transform advance */
          FTReference<FTVectorRec> advance_ref = new FTReference<FTVectorRec>();
          advance_ref.Set(slot.advance);
          matrix_ref.Set(internal.transform_matrix);
          FTOutlineRec.FTVectorTransform(advance_ref, matrix_ref);
          slot.advance = advance_ref.Get();
          internal.transform_matrix = matrix_ref.Get();
        }
      }
      FTTrace.Trace(7, TAG, String.format("  x advance: %d", slot.advance.x));
      FTTrace.Trace(7, TAG, String.format("  y advance: %d", slot.advance.y));
      FTTrace.Trace(7, TAG, String.format("  linear x advance: %d", slot.linearHoriAdvance));
      FTTrace.Trace(7, TAG, String.format("  linear y advance: %d", slot.linearVertAdvance));
      /* do we need to render the image now? */
      if (error == 0 &&
           (slot.format != FT_GLYPH_FORMAT_BITMAP) &&
           (slot.format != FT_GLYPH_FORMAT_COMPOSITE) &&
           (load_flags & FTGlyphLoaderFlags.FT_LOAD_RENDER) != 0) {
        Long mode = (long)((load_flags >> 16) & 15);

        if ((mode == FTRendererRec.FT_RENDER_MODE_NORMAL) && 
        		(load_flags & FTGlyphLoaderFlags.FT_LOAD_MONOCHROME) != 0) {
          mode = (long)FTRendererRec.FT_RENDER_MODE_MONO;
        }
................................................................................
    }

    /* =====================================================================
     * translate_array
     *
     * =====================================================================
     */
    public static void translate_array(int n, FTReference<FTVectorRec[]> coords_ref, int idx, long delta_x, long delta_y) {
      FTVectorRec[] coords = coords_ref.Get();
      int k;

      if (delta_x != 0) {
        for (k = 0; k < n; k++) {
          coords[idx + k].x += delta_x;
        }
      }
................................................................................

    /* =====================================================================
     * FTGlyphLoaderAdjustPoints
     *
     * =====================================================================
     */
    public static void FTGlyphLoaderAdjustPoints(FTGlyphLoaderRec loader) {

Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphLoaderAdjustPoints: "+loader+"!");

_showLoaderZone("FT_GlyphLoader_Adjust_Points 1");
      loader.current.outline.points = loader.base.outline.points;
      loader.current.outline.points_idx = loader.base.outline.n_points;
      loader.current.outline.tags = loader.base.outline.tags;
      loader.current.outline.tags_idx =  loader.base.outline.n_points;
      loader.current.outline.contours = loader.base.outline.contours;
      loader.current.outline.contours_idx = loader.base.outline.n_contours;
_showLoaderZone("FT_GlyphLoader_Adjust_Points 2");
      /* handle extra points table - if any */
      if (loader.use_extra) {

Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphLoaderAdjustPoints 3: extra_points: "+loader.base.extra_points+"!"+loader.base.extra_points_idx+"!extra_points2: "+loader.base.extra_points2+"!"+loader.base.extra_points2_idx+"!");

        loader.current.extra_points = loader.base.extra_points;
        loader.current.extra_points_idx = loader.base.extra_points_idx + loader.base.outline.n_points;
        loader.current.extra_points2 = loader.base.extra_points2;
        loader.current.extra_points2_idx = loader.base.extra_points2_idx + loader.base.outline.n_points;
      }
_showLoaderZone("FT_GlyphLoader_Adjust_Points 3");
    }
................................................................................
    }

    /* =====================================================================
     * FTGlyphLoaderCheckP
     * =====================================================================
     */
    public static boolean FTGlyphLoaderCheckP(FTGlyphLoaderRec loader, int count) {

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("CheckP: count: %d, base n_points: %d, current n_points: %d, max_points: %d",
    count, loader.base.outline.n_points, loader.current.outline.n_points, loader.max_points));

      return (count == 0 ||
            loader.base.outline.n_points +
            loader.current.outline.n_points + (long)count <=
            loader.max_points);
    }

    /* =====================================================================
     * FTGlyphLoaderCheckC
     * =====================================================================
     */
    public static boolean FTGlyphLoaderCheckC(FTGlyphLoaderRec loader, int count) {

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("CheckC: count: %d, base n_contours: %d, current n_contours: %d, max_contours: %d",
    count, loader.base.outline.n_contours, loader.current.outline.n_contours, loader.max_contours));

      return (count == 0 ||
            loader.base.outline.n_contours +
            loader.current.outline.n_contours + (long)count <=
            loader.max_contours);
    }

    /* =====================================================================
................................................................................
     * Ensure that we can add `n_points' and `n_contours' to our glyph.
     * This function reallocates its outline tables if necessary.  Note that
     * it DOESN'T change the number of points within the loader!
     *
     * =====================================================================
     */
    public static int FTGlyphLoaderCheckPoints(FTGlyphLoaderRec loader, int n_points, int n_contours) {
      int error = FTError.INTERP_ERR_OK;
      boolean adjust = false;
      int new_max;
      int old_max;
      int k;


Debug(0, DBG_LOAD_GLYPH, TAG, "FTGlyphLoaderCheckPoints: base.outline.points: "+loader.base.outline.points+"!base.outline.tags: "+loader.base.outline.tags+"!");

      /* check points & tags */
      new_max = loader.base.outline.n_points + loader.current.outline.n_points + n_points;
      old_max = loader.max_points;

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("n_points: base.outline.n_points: %d current.outline.n_points: %d n_points: %d", loader.base.outline.n_points, loader.current.outline.n_points, n_points));
Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FTGlyphLoaderCheckPoints: renew: old: %d new: %d", old_max, new_max));

      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 8).intValue();
        if (new_max > FTOutlineRec.FT_OUTLINE_POINTS_MAX) {
          return FTError.GLYPH_ARRAY_TOO_LARGE;
        }

Debug(0, DBG_LOAD_GLYPH, TAG, "FT_RENEW_ARRAY: base.outline.points: "+loader.base.outline.points+"!");

        loader.base.outline.points = (FTVectorRec[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.points, "FTUnitVector", old_max, new_max);

Debug(0, DBG_LOAD_GLYPH, TAG, "after FT_RENEW_ARRAY: base.outline.points: "+loader.base.outline.points+"!");
Debug(0, DBG_LOAD_GLYPH, TAG, "FT_RENEW_ARRAY: base.outline.tags: "+loader.base.outline.tags);

        loader.base.outline.tags = (byte[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.tags, "byte", old_max, new_max);

Debug(0, DBG_LOAD_GLYPH, TAG, "after FT_RENEW_ARRAY: base.outline.tags: "+loader.base.outline.tags);

//        if (FT_RENEW_ARRAY(loader.base.outline.points, old_max, new_max) ||
//             FT_RENEW_ARRAY(loader.base.outline.tags, old_max, new_max)) {
//          if (error != 0) {
//            FTGlyphLoaderReset(loader);
//          }
//          return error;
//        }

Debug(0, DBG_LOAD_GLYPH, TAG, "FT_RENEW_ARRAY base.extra_points: "+loader.base.extra_points+"!use_extra: "+loader.use_extra+"!");

        if (loader.use_extra) {
          loader.base.extra_points = (FTVectorRec[])FTUtil.FT_RENEW_ARRAY(loader.base.extra_points, "FTUnitVector", old_max * 2, new_max * 2);

Debug(0, DBG_LOAD_GLYPH, TAG, "after FT_RENEW_ARRAY base.extra_points: "+loader.base.extra_points+"!use_extra: "+loader.use_extra+"!");

//          if (FT_RENEW_ARRAY(loader.base.extra_points, old_max * 2, new_max * 2)) {
//            if (error != 0) {
//              FTGlyphLoaderReset(loader);
//            }
//            return error;
//          }
          for (k = 0; k < old_max; k++) {
................................................................................
          }
//          FT_ARRAY_MOVE(loader.base.extra_points + new_max,
//                  loader.base.extra_points + old_max, old_max);
//          loader.base.extra_points2 = loader.base.extra_points;
//          loader.base.extra_points2_idx = loader.base.extra_points_idx + new_max;
//System.out.println("base extra points2 1: "+loader.base.extra_points2+"!"+loader.base.extra_points2_idx+"!");
//System.out.println("SZ: "+loader.base.extra_points2.length+"!"+loader.base.extra_points2+"!");
          loader.base.extra_points2 = new FTVectorRec[new_max];
          for (k = old_max; k < old_max * 2; k++) {
            loader.base.extra_points2[k - old_max] = loader.base.extra_points[loader.base.extra_points_idx + k];
          }
          for (k = old_max; k < new_max; k++) {
            loader.base.extra_points2[k] = new FTVectorRec();
          }
          loader.base.extra_points2_idx = 0;
          
        }
        adjust = true;
        loader.max_points = new_max;
      }
      /* check contours */
      old_max = loader.max_contours;
      new_max = loader.base.outline.n_contours + loader.current.outline.n_contours + n_contours;

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("base.outline.n_contours: %d, current.outline.n_contours: %d, n_contours: %d", loader.base.outline.n_contours, loader.current.outline.n_contours, n_contours));
Debug(0, DBG_LOAD_GLYPH, TAG, String.format("FTGlyphLoaderCheckContours: renew: old: %d new: %d", old_max, new_max));

      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 4).intValue();
        if (new_max > FTOutlineRec.FT_OUTLINE_CONTOURS_MAX) {
          return FTError.GLYPH_ARRAY_TOO_LARGE;
        }
        loader.base.outline.contours = (short[])FTUtil.FT_RENEW_ARRAY(loader.base.outline.contours, "short", old_max, new_max);
//        if (FT_RENEW_ARRAY(loader.base.outline.contours, old_max, new_max)) {
//          if (error != 0) {
//            FTGlyphLoaderReset(loader);
//          }
//          return error;
................................................................................

    /* =====================================================================
     * FT_GLYPHLOADER_CHECK_POINTS
     * =====================================================================
     */
    public static int FT_GLYPHLOADER_CHECK_POINTS(FTGlyphLoaderRec loader, int points, int contours) {
      if (FTGlyphLoaderCheckP(loader, points) && FTGlyphLoaderCheckC(loader, contours)) {
        return FTError.INTERP_ERR_OK;
      } else {
        return FTGlyphLoaderCheckPoints(loader, points, contours);
      }
    }

    /* =====================================================================
     * FTGlyphLoaderReset
................................................................................
    }

    /* =====================================================================
     * FTGlyphLoaderCheckSubGlyphs
     * =====================================================================
     */
    public static int FTGlyphLoaderCheckSubGlyphs(FTGlyphLoaderRec loader, int n_subs) {
      int error = FTError.INTERP_ERR_OK;
      int new_max;
      int old_max;

      new_max = loader.base.num_subglyphs + loader.current.num_subglyphs + n_subs;
      old_max = loader.max_subglyphs;
      if (new_max > old_max) {
        new_max = FTCalc.FT_PAD_CEIL((long)new_max, 2).intValue();

Changes to 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
...
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
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
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.         */
  /*                                                                       */
................................................................................

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;
    /* ===================================================================== */
    /*                                                                     */
................................................................................
    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 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);
    }
 
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
>
>
>
|
<
<
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>

>
>







 







|


|
|
|


|


|
|


|
|
|
|
|
|












|

|







 







|







 







|
|
<
|
<




|
<
|



|
<







 







|
|
|
|
|

















1
2



3
4
5
6


7
8
9
10















11
12
13
14
15
16
17
18
19
20
21
22
...
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
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
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














/* =====================================================================
 *  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;

  /* ===================================================================== */
  /*    TTFaceRec                                                          */
  /*                                                                       */
  /* <Description>                                                         */
  /*    The TrueType face class.  These objects model the resolution and   */
  /*    point-size independent data found in a TrueType font file.         */
  /*                                                                       */
................................................................................

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

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

    public ftsfnt.TTCHeaderRec ttc_header = null;
    public long format_tag = 0L;
    public short num_tables = 0;
    public ftsfnt.TTTableRec[] dir_tables = null;
    public ftsfnt.TTHeaderRec header = null;           /* TrueType header table          */
    public ftsfnt.TTHoriHeader horizontal = null;   /* TrueType horizontal header     */
    public TTMaxProfile max_profile = null;
    public boolean vertical_info = false;
    public ftsfnt.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 ftsfnt.TTOS2 os2 = null;                 /* TrueType OS/2 table            */
    public ftsfnt.TTPostscript postscript = null;   /* TrueType Postscript table      */
    public byte[] cmap_table = null;   /* extracted `cmap' table */
    public long cmap_size = 0L;
    public FTInstanceMethod goto_table = null;
    public FTInstanceMethod access_glyph_frame = null;
    public FTInstanceMethod forget_glyph_frame = null;
    public FTInstanceMethod read_glyph_header = null;
    public FTInstanceMethod read_simple_glyph = null;
    public FTInstanceMethod 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 ftsfnt.TTGaspRec gasp = null;                 /* the `gasp' table */
    /* PCL 5 table */
    public ftsfnt.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;
    /* ===================================================================== */
    /*                                                                     */
................................................................................
    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 FTInstanceMethod interpreter = null;
    /* ===================================================================== */
    /*                                                                     */
    /* Other tables or fields. This is used by derivative formats like     */
    /* OpenType.                                                           */
    /*                                                                     */
    /* ===================================================================== */
//    FT_Generic            extra;
................................................................................
    public long vert_metrics_offset = 0L;
 
    /* ==================== TTFaceRec ================================== */
    public TTFaceRec() {
      super("TTFaceRec");
      oid++;
      id = oid; 
      ttc_header = new ftsfnt.TTCHeaderRec();
      header = new ftsfnt.TTHeaderRec();

Debug(0, DBG_INIT, TAG, "ttface1: "+cvt+"!"+mySelf()+"!");

    }
        
    /* ==================== 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();
    }
................................................................................
 
    /* =====================================================================
     * TTInitGlyphLoading
     * =====================================================================
     */
    public static void TTInitGlyphLoading(TTFaceRec face) {
      String class_name = "org.apwtcl.gles20.truetype.TTGlyphLoadingFuncs";
      face.access_glyph_frame = new FTInstanceMethod(class_name, "tt_access_glyph_frame", 1);
      face.read_glyph_header = new FTInstanceMethod(class_name, "tt_load_glyph_header", 1);
      face.read_simple_glyph = new FTInstanceMethod(class_name, "tt_load_simple_glyph", 1);
      face.read_composite_glyph = new FTInstanceMethod(class_name, "tt_load_composite_glyph", 1);
      face.forget_glyph_frame = new FTInstanceMethod(class_name, "tt_forget_glyph_frame", 1);
    }
 
}

Changes to ftbase/TTInterpOpcodeFuncs1.java.

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
...
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
...
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
...
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
...
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
...
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
...
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
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
...
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
....
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
....
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
....
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
....
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
....
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
....
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
     *
     * <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
................................................................................
     * <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;
    }

................................................................................

    /* ==================== 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_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;
................................................................................
    }

    /* ==================== 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;
................................................................................
      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];
    }

................................................................................
      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() {
................................................................................

    /* ==================== 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_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() {
................................................................................
    /* ==================== 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;
    }
................................................................................
    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() {
................................................................................

    /* ==================== 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]);
    }

................................................................................
      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
     *
................................................................................
//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 {







<
|
<



<
|
<



<
|
<



<
|
<



<
|
<



<
|
<



<
|
<



<
|
<



<
|
<







 







|


|





|
|







 







|



|
|

<
|
<


|







<
|
<













<
|
<

|
<
|
<










|
|
|
|
|
|










|
|
|
|










|
|





|


<
|
<









|







 







|







 







|







 







|
|




|
|





<
|
<







 







|







 







<
|
<













<
|
<







 







|











|




|








|




|








|




|







 







<
|
<







 







|







 







|







 







|












|







 







|












|








|







 







|







 







|
|







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
...
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
...
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
...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
...
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
...
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
...
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
...
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
...
983
984
985
986
987
988
989

990

991
992
993
994
995
996
997
....
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
....
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
....
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
....
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
....
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
     *
     * <Input>
     *    round_mode :: The rounding mode to be used.
     *
     * =====================================================================
     */
    protected static void ComputeRound(byte round_mode) {

Debug(0, DBG_INTERP, TAG, "ComputeRound");

      switch (round_mode) {
      case TT_Round_Off:
        cur.func_round = TTInterpRun.RoundNone;

Debug(0, DBG_INTERP, TAG, "RoundNone");

        break;
      case TT_Round_To_Grid:
        cur.func_round = TTInterpRun.RoundToGrid;

Debug(0, DBG_INTERP, TAG, "RoundToGrid");

        break;
      case TT_Round_Up_To_Grid:
        cur.func_round = TTInterpRun.RoundUpToGrid;

Debug(0, DBG_INTERP, TAG, "RoundUpToGrid");

        break;
      case TT_Round_Down_To_Grid:
        cur.func_round = TTInterpRun.RoundDownToGrid;

Debug(0, DBG_INTERP, TAG, "RoundDownToGrid");

        break;
      case TT_Round_To_Half_Grid:
        cur.func_round = TTInterpRun.RoundToHalfGrid;

Debug(0, DBG_INTERP, TAG, "RoundToHalfGrid");

        break;
      case TT_Round_To_Double_Grid:
        cur.func_round = TTInterpRun.RoundToDoubleGrid;

Debug(0, DBG_INTERP, TAG, "RoundToDoubleGrid");

        break;
      case TT_Round_Super:
        cur.func_round = TTInterpRun.RoundSuper;

Debug(0, DBG_INTERP, TAG, "RoundSuper");

        break;
      case TT_Round_Super_45:
        cur.func_round = TTInterpRun.RoundSuper45;

Debug(0, DBG_INTERP, TAG, "RoundSuper45");

        break;
      }
    }

    /* ====================================================================
     * <Function>
     *    CurrentRatio
................................................................................
     * <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.y == 0) {
          cur.tt_metrics.ratio = cur.tt_metrics.x_ratio;
        } else {
          if (cur.GS.projVector.x == 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.x << 2);
            y = TT_MulFix14(cur.tt_metrics.y_ratio, cur.GS.projVector.y << 2);
            cur.tt_metrics.ratio = FTCalc.FTHypot(x, y);
          }
        }
      }
      return cur.tt_metrics.ratio;
    }

................................................................................

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

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


Debug(0, DBG_INTERP, TAG, 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 = FTError.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;

Debug(0, DBG_INTERP, TAG, 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;
      }

Debug(0, DBG_INTERP, TAG, String.format("2: A: %d B: %d", A, B));

      Normalize(A, B, vec_ref);
FTVectorRec vec = vec_ref.Get();

Debug(0, DBG_INTERP, TAG, 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.x = (long)A;
      cur.GS.projVector.x = (long)A;
      cur.GS.dualVector.x = (long)A;
      cur.GS.freeVector.y = (long)B;
      cur.GS.projVector.y = (long)B;
      cur.GS.dualVector.y = (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.x = (long)A;
      cur.GS.dualVector.x = (long)A;
      cur.GS.projVector.y = (long)B;
      cur.GS.dualVector.y = (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.x = (long)A;
      cur.GS.freeVector.y = (long)B;
      computeFuncs();
    }

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

      ft_unit_ref.Set(cur.GS.projVector);

Debug(0, DBG_INTERP, TAG, 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<FTVectorRec> ft_unit_ref = new FTReference<FTVectorRec>();

      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_SPVFS ===================================== */
    protected static void DO_SPVFS () {
      short S;
      long X;
      long Y;
      FTReference<FTVectorRec> ft_unit_ref = new FTReference<FTVectorRec>();

      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;
................................................................................
    }

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

      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;
................................................................................
      cur.GS.freeVector = ft_unit_ref.Get();
      computeFuncs();
    }


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

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

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

Debug(0, DBG_INTERP, TAG, 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];
    }

................................................................................
      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 = FTError.INTERP_BAD_ARGUMENT;
      } else {
        cur.GS.loop = cur.stack[cur.numArgs + 0];
      }
    }

    /* ==================== DO_SMD ===================================== */
    protected static void DO_SMD() {
................................................................................

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

    /* ==================== DO_MPPEM ===================================== */
    protected static void DO_MPPEM() {

Debug(0, DBG_INTERP, TAG, 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];

Debug(0, DBG_INTERP, TAG, 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_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 = FTError.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 = FTError.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 = FTError.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 = FTError.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 = FTError.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 = FTError.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 = FTError.INTERP_BAD_ARGUMENT;
        }
        cur.step_ins = false;
      }
    }

    /* ==================== DO_LT ===================================== */
    protected static void DO_LT() {
................................................................................
    /* ==================== 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() {

Debug(0, DBG_INTERP, TAG, 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;
    }
................................................................................
    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 = FTError.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() {
................................................................................

    /* ==================== 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 = FTError.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 = FTError.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 = FTError.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 = FTError.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 = FTError.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 = FTError.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]);
    }

................................................................................
      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 = FTError.INTERP_INVALID_REFERENCE;
    }

    /* =====================================================================
     *
     * <Function>
     *    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.x * cur.GS.freeVector.x +
                        (int)cur.GS.projVector.y * 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 {

Changes to ftbase/TTInterpRun.java.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
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
...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
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 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;
................................................................................
              }
            }
          }
          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;
................................................................................
                  }
                  useSuiteLabel = true;
                  break;
                }
              }
            }
            if (!useSuiteLabel) {
              cur.error = FT_Error.INTERP_INVALID_OPCODE;
              return LError();
            }
            default: 
              return LError();
            }
          }
          if (!useSuiteLabel) {







<







 







|







 







|











|







 







|







21
22
23
24
25
26
27

28
29
30
31
32
33
34
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...
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
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
public class TTInterpRun extends TTInterpInsFuncs2 {
    private static int oid = 0;

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

    public static int numInstructions = 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 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;
................................................................................
              }
            }
          }
          boolean useSuiteLabel = false;
          if (cur.error != 0) {
            switch (cur.error) {
              /* looking for redefined instructions */
            case FTError.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 = FTError.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;
................................................................................
                  }
                  useSuiteLabel = true;
                  break;
                }
              }
            }
            if (!useSuiteLabel) {
              cur.error = FTError.INTERP_INVALID_OPCODE;
              return LError();
            }
            default: 
              return LError();
            }
          }
          if (!useSuiteLabel) {

Changes to ftbase/TTSizeFuncs.java.

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
...
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
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
...
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
     *    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
................................................................................
     *
     * <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;
................................................................................
      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();
      }
................................................................................
 
    /* =====================================================================
     * 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.            */
      /*                                                           */
................................................................................
    /* =====================================================================
     * 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'
................................................................................
    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
     *
     * =====================================================================
................................................................................
      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);







|


|



|







|





<
|
<







 







<
|
<











|







 







|



|







 







<
|
<







 







|
|







 







|
|







 







<
|
<







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
...
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
...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
...
628
629
630
631
632
633
634

635

636
637
638
639
640
641
642
...
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
...
703
704
705
706
707
708
709

710

711
712
713
714
715
716
717
     *    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 = FTError.INTERP_ERR_OK;

      if (range < 1 || range > 3) {
        error = FTError.INTERP_INVALID_ARGUMENT;
        return error;
      }
      if (exec.codeRangeTable[range - 1].base == null) {
        error = FTError.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 = FTError.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();

Debug(0, DBG_LOAD_GLYPH, TAG, String.format("TTGotoCodeRange: size: %d", exec.codeSize));

      exec.IP = (int)IP;
      exec.curRange = range;
      return error;
    }
 
    /* =====================================================================
     * tt_size_run_fpgm
................................................................................
     *
     * <Return>
     *    FreeType error code.  0 means success.
     *
     * =====================================================================
     */
    public static int tt_size_run_fpgm(TTSizeRec size, boolean pedantic) {

Debug(0, DBG_LOAD_GLYPH, TAG, "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 = FTError.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;
................................................................................
      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) {
          FTTrace.Trace(7, TAG, "Executing `fpgm' table.");
          error = (int)face.interpreter.callClassMethod(exec);
        }
      } else {
        error = FTError.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();
      }
................................................................................
 
    /* =====================================================================
     * TTSaveContext
     *
     * =====================================================================
     */
    public static int TTSaveContext(TTExecContextRec exec, FTReference<TTSizeRec> size_ref) {

Debug(0, DBG_LOAD_GLYPH, TAG, "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.            */
      /*                                                           */
................................................................................
    /* =====================================================================
     * 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);
      FTTrace.Trace(7, TAG, String.format("  advance width (font units): %d", aw_ref.Get()));
      FTTrace.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'
................................................................................
    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);
      }
      FTTrace.Trace(7, TAG, String.format("  advance height (font units): %d", ah_ref.Get()));
      FTTrace.Trace(7, TAG, String.format("  top side bearing (font units): %d", tsb_ref.Get()));
    }

    
    /* =====================================================================
     * tt_get_metrics
     *
     * =====================================================================
................................................................................
      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>();


Debug(0, DBG_LOAD_GLYPH, TAG, "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);

Changes to ftdemo/FTDemoBitmapUtil.java.

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
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      height = handle.scaler.height;
      if (handle.use_sbits_cache && handle.scaler.pixel == 0) {
        width  = ((width * handle.scaler.x_res + 36) / 72) >> 6;
        height = ((height * handle.scaler.y_res + 36) / 72) >> 6;
      }
Debug(0, DBG_LOAD_GLYPH, TAG, "FTDemoIndexToBitmap2: "+handle.sbits_cache+"!");
      if (handle.use_sbits_cache && width < 48 && height < 48) {
        FTCSBitRec sbit = null;
        ftbase.FTBitmapRec source = new ftbase.FTBitmapRec();

        ftbase.FTReference<FTCScalerRec> scaler_ref = new ftbase.FTReference<FTCScalerRec>();
        ftbase.FTReference<FTCSBitRec> sbit_ref = new ftbase.FTReference<FTCSBitRec>();
        scaler_ref.Set(handle.scaler);
        sbit_ref.Set(sbit);
        error = FTCBasicSCacheFuncs.FTCSCacheLookupScaler(handle.sbits_cache, scaler_ref,
               handle.load_flags, glyphIndex, sbit_ref, null);
        handle.scaler = scaler_ref.Get();
        sbit = (FTCSBitRec)sbit_ref.Get();
        if (error != 0) {
          /* don't accept a `missing' character with zero or negative width */
          if (glyphIndex == 0 && x_advance <= 0) {
            x_advance = 1;
          }
          x_advance_ref.Set(x_advance);
          return error;
................................................................................
          y_advance_ref.Set(y_advance);
          return error;
        }
      }
      /* otherwise, use an image cache to store glyph outlines, and render */
      /* them on demand. we can thus support very large sizes easily..     */
      {
        ftbase.FTReference<FTCScalerRec> scaler_ref = new ftbase.FTReference<FTCScalerRec>();
        scaler_ref.Set(handle.scaler);
        error = FTCBasicICacheFuncs.FTCImageCacheLookupScaler(handle.image_cache,
                scaler_ref, (long)handle.load_flags, glyphIndex, glyph_ref, null);
        glyf = glyph_ref.Get();
        if (scaler_ref != null) {
          handle.scaler = scaler_ref.Get();
        }
        if (error == 0) {
          ftbase.FTReference<FTDemoHandle> handle_ref = new ftbase.FTReference<FTDemoHandle>();







|


|
|


|


|







 







|

|







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
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      height = handle.scaler.height;
      if (handle.use_sbits_cache && handle.scaler.pixel == 0) {
        width  = ((width * handle.scaler.x_res + 36) / 72) >> 6;
        height = ((height * handle.scaler.y_res + 36) / 72) >> 6;
      }
Debug(0, DBG_LOAD_GLYPH, TAG, "FTDemoIndexToBitmap2: "+handle.sbits_cache+"!");
      if (handle.use_sbits_cache && width < 48 && height < 48) {
        ftcache.FTCSBitRec sbit = null;
        ftbase.FTBitmapRec source = new ftbase.FTBitmapRec();

        ftbase.FTReference<ftcache.FTCScalerRec> scaler_ref = new ftbase.FTReference<ftcache.FTCScalerRec>();
        ftbase.FTReference<ftcache.FTCSBitRec> sbit_ref = new ftbase.FTReference<ftcache.FTCSBitRec>();
        scaler_ref.Set(handle.scaler);
        sbit_ref.Set(sbit);
        error = ftcache.FTCBasicSCacheFuncs.FTCSCacheLookupScaler(handle.sbits_cache, scaler_ref,
               handle.load_flags, glyphIndex, sbit_ref, null);
        handle.scaler = scaler_ref.Get();
        sbit = (ftcache.FTCSBitRec)sbit_ref.Get();
        if (error != 0) {
          /* don't accept a `missing' character with zero or negative width */
          if (glyphIndex == 0 && x_advance <= 0) {
            x_advance = 1;
          }
          x_advance_ref.Set(x_advance);
          return error;
................................................................................
          y_advance_ref.Set(y_advance);
          return error;
        }
      }
      /* otherwise, use an image cache to store glyph outlines, and render */
      /* them on demand. we can thus support very large sizes easily..     */
      {
        ftbase.FTReference<ftcache.FTCScalerRec> scaler_ref = new ftbase.FTReference<ftcache.FTCScalerRec>();
        scaler_ref.Set(handle.scaler);
        error = ftcache.FTCBasicICacheFuncs.FTCImageCacheLookupScaler(handle.image_cache,
                scaler_ref, (long)handle.load_flags, glyphIndex, glyph_ref, null);
        glyf = glyph_ref.Get();
        if (scaler_ref != null) {
          handle.scaler = scaler_ref.Get();
        }
        if (error == 0) {
          ftbase.FTReference<FTDemoHandle> handle_ref = new ftbase.FTReference<FTDemoHandle>();

Changes to ftdemo/FTDemoUtil.java.

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
..
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
...
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
...
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
...
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
...
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
...
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
...
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
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
...
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
...
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
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
...
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
import ftbase.FTReference;

  /* ===================================================================== */
  /*    FTDemoUtil                                                          */
  /*                                                                       */
  /* ===================================================================== */

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

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

    private final static int FT_LOAD_TARGET_NORMAL = (FTRendererRec.FT_RENDER_MODE_NORMAL & 15) << 16;
    private final static int FT_LOAD_TARGET_LIGHT = (FTRendererRec.FT_RENDER_MODE_LIGHT & 15) << 16;
    private final static int FT_LOAD_TARGET_MONO = (FTRendererRec.FT_RENDER_MODE_MONO & 15) << 16;
    private final static int FT_LOAD_TARGET_LCD = (FTRendererRec.FT_RENDER_MODE_LCD & 15) << 16;
    private final static int FT_LOAD_TARGET_LCD_V = (FTRendererRec.FT_RENDER_MODE_LCD_V  & 15) << 16;

    public final static int LCD_MODE_AA = 0;
    public final static int LCD_MODE_LIGHT = 1;
    public final static int LCD_MODE_RGB = 2;
    public final static int LCD_MODE_BGR = 3;
    public final static int LCD_MODE_VRGB = 4;
    public final static int LCD_MODE_VBGR = 5;
................................................................................
    /* =====================================================================
     * FTDemoNew
     * =====================================================================
     */
    public static FTDemoHandle FTDemoNew() {
      FTDemoHandle handle;
      ftbase.FTReference<ftbase.FTLibraryRec> library_ref = new ftbase.FTReference<ftbase.FTLibraryRec>();
      ftbase.FTReference<FTCManagerRec> cache_manager_ref = new ftbase.FTReference<FTCManagerRec>();
      ftbase.FTReference<FTCGCacheRec> sbits_cache_ref = new ftbase.FTReference<FTCGCacheRec>();
      ftbase.FTReference<FTCGCacheRec> cmap_cache_ref = new ftbase.FTReference<FTCGCacheRec>();
      ftbase.FTReference<FTBitmapRec> bitmap_ref = new ftbase.FTReference<FTBitmapRec>();
      ftbase.FTReference<FTCGCacheRec> image_cache_ref = new ftbase.FTReference<FTCGCacheRec>();
      ftbase.  FTReference<FTStrokerRec> stroker_ref = new ftbase.FTReference<FTStrokerRec>();
      ftbase.FTInit ft_init = new ftbase.FTInit();
      ftbase.FTInstanceMethod requester;
      String class_name = "org.apwtcl.gles20.truetype.FTDemoUtil";
      int error = 0;
      
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemoNew\n");
// Test1Rec t1 = new Test1Rec();
// Test2Rec t2 = new Test2Rec();
// FTReference<Test1Rec> ref = new FTReference<Test1Rec>();
// ref.Set(t1);
// t2.NewRec(ref);
// Log.i(TAG, ref.Get().toDebugString());
// Log.i(TAG, "t1: "+t1+"!"+ref.Get()+"!");
................................................................................
      handle.library = library_ref.Get();
      if (error != 0) {
        System.out.println("could not initialize FreeType");
        return null;
      }
    ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "after call FTInitFreeType");
      cache_manager_ref.Set(handle.cache_manager);
      requester = new TTInstanceMethod(class_name, "my_face_requester", 1);
      error = FTCManagerRec.FTCManagerNew(handle.library, 0, 0,
              requester, 0, cache_manager_ref);
      handle.cache_manager = cache_manager_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize cache manager");
        return null;
      }
      sbits_cache_ref.Set(handle.sbits_cache);
      error = FTCManagerRec.FTCSBitCacheNew(handle.cache_manager, sbits_cache_ref);
      handle.sbits_cache = sbits_cache_ref.Get();
    ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "handle.sbits_cache: "+((FTCCacheRec)(handle.sbits_cache)).toDebugString());
      if (error != 0) {
        Log.e(TAG, "could not initialize small bitmaps cache");
        return null;
      }
      image_cache_ref.Set(handle.image_cache);
      error = FTCManagerRec.FTCImageCacheNew(handle.cache_manager, image_cache_ref);
      handle.image_cache = image_cache_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize glyph image cache");
        return null;
      }
      cmap_cache_ref.Set(handle.cmap_cache);
      error = FTCManagerRec.FTCCMapCacheNew(handle.cache_manager, cmap_cache_ref);
      handle.cmap_cache = cmap_cache_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize charmap cache");
        return null;
      }
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "call FTBitmapNew");
      bitmap_ref.Set(handle.bitmap);
      FTBitmapRec.FTBitmapNew(bitmap_ref);
      handle.bitmap = bitmap_ref.Get();
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "call FTStrokerNew");
      stroker_ref.Set(handle.stroker);
      FTStrokerRec.FTStrokerNew(handle.library, stroker_ref);
      handle.stroker = stroker_ref.Get();
      handle.encoding = FTEncoding.FT_ENCODING_NONE;
      handle.hinted = true;
      handle.antialias = true;
      handle.use_sbits = true;
      handle.autohint  = false;
      handle.lcd_mode  = 0;
      handle.color     = true;
      handle.use_sbits_cache = true;
................................................................................
     * my_face_requester
     * =====================================================================
     */
    public static int my_face_requester(Object ... args) {
      Object face_id = args[0];
      ftbase.FTLibraryRec lib = (ftbase.FTLibraryRec)args[1];
//      Object request_data = args[2];
      FTReference<FTFaceRec> face_ref = (FTReference<FTFaceRec>)args[3];
      FTFaceRec face = null;
      int error = 0;
      TFont font = (TFont)face_id;

      face_ref.Set(null);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "my_face_requester");
      if (font.file_address != null) {
Log.w(TAG, "file_address not yet implemented");
//        error = FTNewMemoryFace(lib,
//               (byte[]*)font.file_address, font.file_size, font.face_index, aface);
      } else {
        error = FTFaceRec.FTNewFace(lib, font.filepathname, font.face_index, face_ref);
        face = face_ref.Get();
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FACE: "+face+"!"+face.driver+"!");
      }
      if (error == 0) {
/*
         format = FT_Get_X11_Font_Format( *aface );

        if ( !strcmp( format, "Type 1" ) ) {
          char   orig[5];
................................................................................
     * =====================================================================
     */
    public static int FTDemoInstallFont(FTDemoHandle handle, String filepath) {
      StringBuffer filename = new StringBuffer();
      int i = 0;
      int error = 0;
      int num_faces = 0;
      FTFaceRec face = new FTFaceRec("InstallFont");
      FTReference<FTFaceRec> face_ref = new FTReference<FTFaceRec>();

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemoInstallFont: "+filepath);
      filename.append(filepath);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "InstallFont call FTNewFace");
      face_ref.Set(face);
      error = FTFaceRec.FTNewFace(handle.library, filename.toString(), 0, face_ref);
      face = face_ref.Get();
      if (error != 0) {
        return error;
      }
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "InstallFont AFTER call FTNewFace: "+error+"!"+face+"!"+face.stream+"!");
      /* allocate new font object */
      num_faces = face.num_faces;
      for (i = 0; i < num_faces; i++) {
        TFont font;

        if (i > 0) {
          face_ref.Set(face);
          error = FTFaceRec.FTNewFace(handle.library, filename.toString(), i, face_ref);
          face = face_ref.Get();
          if (error != 0) {
            continue;
          }
        }
        if (handle.encoding != FTCharMapRec.FT_ENCODING_NONE) {
          FTCharMapRec charmap = new FTCharMapRec();
          error = charmap.FTSelectCharmap(face, handle.encoding);
          if (error != 0) {
//            face.FTDoneFace(face);
            return error;
          }
        }
        font = new TFont();
        /* We allocate four more bytes since we want to attach an AFM */
        /* or PFM file for Type 1 fonts (if available).  Such fonts   */
        /* always have the extension `.afm' or `.pfm'.                */
        font.filepathname = filename.toString();
        font.face_index = i;
        font.cmap_index = face.charmap != null ? FTCharMapRec.FTGetCharmapIndex(face.charmap) : 0;
        if (handle.preload) {
          try {
            RandomAccessFile file = new RandomAccessFile(filename.toString(), "r");
            long file_size;

            file_size = file.length();
            font.file_address = new byte[(int)file_size];
................................................................................
          } catch(IOException e) {
          e.printStackTrace();
          }
        } else {
          font.file_address = null;
          font.file_size = 0L;
        }
        if (handle.encoding == FTCharMapRec.FT_ENCODING_NONE) {
          font.num_indices = face.num_glyphs;
        } else {
          if (handle.encoding == FTCharMapRec.FT_ENCODING_UNICODE) {
            font.num_indices = 0x110000L;
          } else {
            if (handle.encoding == FTCharMapRec.FT_ENCODING_ADOBE_LATIN_1 ||
                handle.encoding == FTCharMapRec.FT_ENCODING_ADOBE_STANDARD ||
                handle.encoding == FTCharMapRec.FT_ENCODING_ADOBE_EXPERT ||
                handle.encoding == FTCharMapRec.FT_ENCODING_ADOBE_CUSTOM ||
                handle.encoding == FTCharMapRec.FT_ENCODING_APPLE_ROMAN) {
              font.num_indices = 0x100L;
            } else {
              /* some fonts use range 0x00-0x100, others have 0xF000-0xF0FF */
              if(handle.encoding == FTCharMapRec.FT_ENCODING_MS_SYMBOL) {
                font.num_indices = 0x10000L;
              } else {
                font.num_indices = 0x10000L;
              }
            }
          }
        }
................................................................................
//            handle.fonts = (PFont*)realloc( handle->fonts, handle->max_fonts * sizeof ( PFont ) );

//            memset( &handle->fonts[handle->num_fonts], 0, ( handle->max_fonts - handle->num_fonts ) * sizeof ( PFont ) );
          }
        }
        handle.fonts[handle.num_fonts++] = font;
      }
      return FT_Error.INTERP_ERR_OK;
    }

    /* =====================================================================
     * FTDemoGetIndex
     * =====================================================================
     */
    public static int FTDemoGetIndex(FTDemoHandle handle, int char_code) {
      Object face_id = handle.scaler.face_id;
      TFont font = handle.current_font;
      int result = 0;

      result = FTCCMapCacheFuncs.FTCCMapCacheLookup(handle.cmap_cache, face_id, font.cmap_index, char_code);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("FTDemoGetIndex: %c 0x%04x %d", char_code, char_code, result));
      return result;
    }

    /* =====================================================================
     * RenderAll
     * =====================================================================
     */
    public static int RenderAll(FTDemoHandle handle, int num_indices, int offset) {
      int error = 0;
      int i;
      int have_topleft;
      FTReference<FTSizeRec> size_ref = new FTReference<FTSizeRec>();;
      FTSizeRec size;

System.out.println(String.format("=== Render_All %d %d", num_indices, offset));
      error = FTDemoGetSize(handle, size_ref);
      size = size_ref.Get();
      if (error != 0) {
        /* probably a non-existent bitmap font size */
        return error;
      }
      InitSize(size);
................................................................................
      for (i = offset; i < num_indices; i++) {
        int  glyph_idx = 0;
//        if (i != 38 && i != 47 && i != 55) {
        if (i != 38 ) {
          continue;
        }

        if (handle.encoding == FTEncoding.FT_ENCODING_NONE) {
          glyph_idx = i;
        } else {
//          glyph_idx = FTDemoGetIndex(handle, i);
        }
        FTReference<Integer> x_ref = new FTReference<Integer>();
        FTReference<Integer> y_ref = new FTReference<Integer>();
        x_ref.Set(x);
        y_ref.Set(y);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("x1: %d y: %d", x, y));
        error = FTDemoDrawIndex(handle, glyph_idx, x_ref, y_ref);
        x = x_ref.Get();
        y = y_ref.Get();
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("x2: %d y: %d", x, y));

        if (have_topleft == 0) ;
/*
        error = FTDemoDrawIndex(handle, display, glyph_idx, &x, &y);
        if (error != 0) {
          if (have_topleft == 0) {
            have_topleft   = 1;
................................................................................
            if (Y_TOO_LONG(y, size, display)) {
              break;
            }
          }
        }
*/
      }
      return FT_Error.INTERP_ERR_OK;
    }

    /* =====================================================================
     * RenderText
     * =====================================================================
     */
    public static int RenderText(FTDemoHandle handle, StringBuffer text, int offset) {
      FTReference<FTSizeRec> size_ref = new FTReference<FTSizeRec>();;
      FTSizeRec size = new FTSizeRec();
      boolean have_topleft;
      int error = 0;

//      char*  p;
//      char*  pEnd;
      int ch = 0;

................................................................................
      int num_indices = text.length();
//      text = new StringBuffer("Hello TCLers");
      while (num_indices-- > 0) {
        int glyph_idx;

ch = text.charAt(idx++);
FTDemoHandle.currCharacter = (char)ch;
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "Handling char: %c",  ch));
/*
        ch = utf8_next( &p, pEnd );
        if (ch < 0) {
          p  = Text;
          ch = utf8_next( &p, pEnd );
        }
*/
        glyph_idx = FTDemoGetIndex(handle, ch);
        FTDemoHandle.currGIndex = glyph_idx;
        FTReference<Integer> x_ref = new FTReference<Integer>();
        FTReference<Integer> y_ref = new FTReference<Integer>();
        x_ref.Set(x);
        y_ref.Set(y);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("x1: %d y: %d", x, y));
        error = FTDemoDrawIndex(handle, glyph_idx, x_ref, y_ref);
        x = x_ref.Get();
        y = y_ref.Get();
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("x2: %d y: %d", x, y));
        if (error == 0) {
          if (!have_topleft) {
            have_topleft = true;
            status.topleft = ch;
          }
        }
        if (error != 0) {
................................................................................
            if (Y_TOO_LONG(y, size, display)) {
              break;
            }
          }
*/
        }
      }
      return FT_Error.INTERP_ERR_OK;
    }

    /* =====================================================================
     * FTDemoGetSize
     * =====================================================================
     */
    public static int FTDemoGetSize(FTDemoHandle handle, FTReference<FTSizeRec> size_ref) {
      int error = 0;
//      FTSizeRec size;
      FTReference<FTCScalerRec> scaler_ref = new FTReference<FTCScalerRec>();

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemoGetSize");
      scaler_ref.Set(handle.scaler);
      error = FTCManagerRec.FTCManagerLookupSize(handle.cache_manager, scaler_ref, size_ref);
      handle.scaler = scaler_ref.Get();
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("h: %d w: %d xres:%d yres: %d", handle.scaler.height, handle.scaler.width, handle.scaler.x_res, handle.scaler.y_res));
      return error;
    }

    /* =====================================================================
     * InitSize
     * =====================================================================
     */
    public static int InitSize(FTSizeRec size) {
      int error = 0;

      start_x = 19 * 8;
      start_y = (((int)size.metrics.height + 63) >> 6) + 4 * 12;
      step_y  = (((int)size.metrics.height + 63) >> 6) + 4;
      x = start_x;
      y = start_y;
................................................................................
    /* =====================================================================
     * FTDemoSetCurrentFont
     * =====================================================================
     */
    public static int FTDemoSetCurrentFont(FTDemoHandle handle, TFont font) {
      int error = 0;

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemo_Set_Current_Font");
      handle.current_font = font;
      handle.scaler.face_id = (Object)font;
      handle.string_reload = true;
      return error;
    }

    /* =====================================================================
................................................................................
     * =====================================================================
     */
    public static int FTDemoUpdateCurrentFlags(FTDemoHandle handle) {
      int error = 0;
      int flags;
      int target;

      flags = (int)FTGlyphLoaderFlags.FT_LOAD_DEFAULT;  /* really 0 */
      if (handle.autohint) {
        flags |= FTGlyphLoaderFlags.FT_LOAD_FORCE_AUTOHINT;
      }
      if (!handle.use_sbits) {
        flags |= FTGlyphLoaderFlags.FT_LOAD_NO_BITMAP;
      }
      if (handle.hinted) {
        target = 0;
        if (handle.antialias) {
          switch (handle.lcd_mode) {
          case LCD_MODE_LIGHT:
            target = FT_LOAD_TARGET_LIGHT;
................................................................................
            target = FT_LOAD_TARGET_NORMAL;
          }
        } else {
          target = FT_LOAD_TARGET_MONO;
        }
        flags |= target;
      } else {
        flags |= FTGlyphLoaderFlags.FT_LOAD_NO_HINTING;
        if (!handle.antialias) {
          flags |= FTGlyphLoaderFlags.FT_LOAD_MONOCHROME;
        }
      }
      if (handle.color) {
        flags |= FTGlyphLoaderFlags.FT_LOAD_COLOR;
      }
      handle.load_flags = (long)flags;
      handle.string_reload = true;
      return error;
    }

    /* =====================================================================
................................................................................
      int pen_y = pen_y_ref.Get();
      int error = 0;
      FTReference<Integer> left_ref = new FTReference<Integer>();
      FTReference<Integer> top_ref = new FTReference<Integer>();
      FTReference<Integer> x_advance_ref = new FTReference<Integer>();
      FTReference<Integer> y_advance_ref = new FTReference<Integer>();
      FTReference<grBitmap> bit3_ref = new FTReference<grBitmap>();
      FTReference<FTGlyphRec> glyph_ref = new FTReference<FTGlyphRec>();
      int left = 0;
      int top = 0;
      int x_advance = 0;
      int y_advance = 0;
      grBitmap bit3 = handle.grBitmap;
      FTGlyphRec glyf = new FTGlyphRec();

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemoDrawIndex");
      left_ref.Set(left);
      top_ref.Set(top);
      x_advance_ref.Set(x_advance);
      y_advance_ref.Set(y_advance);
      bit3_ref.Set(bit3);
      glyph_ref.Set(glyf);
      error = FTDemoBitmapUtil.FTDemoIndexToBitmap(handle, glyphIndex, bit3_ref,
................................................................................
      bitmap_ref.Set(handle.display.bitmap);
      GBlenderCell color = new GBlenderCell();
      color.red = 0;
      color.green = 0;
      color.blue = 0;
      color.alpha = 0;

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("===1 pen_x: %d, left: %d, top: %d, x_advance: %d, y_advance: %d bitmap: " + handle.display.bitmap,
        pen_x, left, top, x_advance, y_advance));
      FTDemoBitmapUtil.grBlitGlyphToBitmap(bitmap_ref, bit3_ref, pen_x + left, pen_y - top, color);
      handle.display.bitmap = bitmap_ref.Get();
      if (glyf != null) {
//        FTDoneGlyph(glyf);
      }
      pen_x += x_advance + 1;
................................................................................
    /* =====================================================================
     * stringLoad
     * =====================================================================
     */
    public int stringLoad(FTDemoHandle handle) {
        int error;
        int n;
        FTSizeRec size;
        FTFaceRec face;
        Long prev_rsb_delta = 0L;
        ftbase.FTReference<FTSizeRec> size_ref = new ftbase.FTReference<FTSizeRec>();

        error = FTError.INTERP_ERR_OK
        size_ref.Set(null);
        error = FTGlyphLoaderRec.GetSize(handle, size_ref);
        if (error != 0) {
            return error;
        }
        size = size_ref.Get();
        face = size.face;
        for (n = 0; n < handle.string_length; n++) {
            TGlyph glyph = handle.string[n];
            ftbase.FTReference<FTGlyphRec> image_ref = new ftbase.FTReference<FTGlyphRec>();
            ftbase.FTReference<FTFaceRec> face_ref = new ftbase.FTReference<FTFaceRec>();
            ftbase.FTReference<FTGlyphSlotRec> glyph_slot_ref = new ftbase.FTReference<FTGlyphSlotRec>();

        /* clear existing image if there is one */
            if (glyph.image != null) {
                FTGlyphLoaderRec.FTDoneGlyph(glyph.image);
                glyph.image = null;
            }
        /* load the glyph and get the image */
            image_ref.Set(glyph.image);
            glyph_slot_ref.Set(face.glyph);
            if (FTGlyphLoaderRec.FTLoadGlyph(face_ref, glyph.glyph_index, handle.load_flags.intValue()) == 0 &&
                    FTGlyphLoaderRec.FTGetGlyph(glyph_slot_ref, image_ref) == 0) {
                face.glyph = glyph_slot_ref.Get();
                glyph.image = image_ref.Get();

          /* note that in vertical layout, y-positive goes downwards */
                glyph.vvector.x  =  face.glyph.metrics.vertBearingX - face.glyph.metrics.horiBearingX;
                glyph.vvector.y  = -face.glyph.metrics.vertBearingY - face.glyph.metrics.horiBearingY;
                glyph.vadvance.x = 0L;







|





|
|
|
|
|







 







|
|
|
|
|
|





|







 







|
|







|

|





|






|





|

|

|

|

|







 







|
|




|





|

|







 







|
|





|












|





|
|












|







 







|


|


|
|
|
|
|



|







 







|











|












|
|

|







 







|








|



|







 







|







|
|







 







|













|



|







 







|






|


|

|

|

|







|







 







|







 







|

|


|







 







|

|



|







 







|





|

|







 







|







 







|
|

|

|

|







|
|
|



|





|
|







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
..
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
...
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
...
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
...
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
...
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
...
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
...
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
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
...
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
...
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
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
...
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
import ftbase.FTReference;

  /* ===================================================================== */
  /*    FTDemoUtil                                                          */
  /*                                                                       */
  /* ===================================================================== */

public class FTDemoUtil extends ftbase.FTDebug {
    private static int oid = 0;

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

    private final static int FT_LOAD_TARGET_NORMAL = (ftbase.FTRendererRec.FT_RENDER_MODE_NORMAL & 15) << 16;
    private final static int FT_LOAD_TARGET_LIGHT = (ftbase.FTRendererRec.FT_RENDER_MODE_LIGHT & 15) << 16;
    private final static int FT_LOAD_TARGET_MONO = (ftbase.FTRendererRec.FT_RENDER_MODE_MONO & 15) << 16;
    private final static int FT_LOAD_TARGET_LCD = (ftbase.FTRendererRec.FT_RENDER_MODE_LCD & 15) << 16;
    private final static int FT_LOAD_TARGET_LCD_V = (ftbase.FTRendererRec.FT_RENDER_MODE_LCD_V  & 15) << 16;

    public final static int LCD_MODE_AA = 0;
    public final static int LCD_MODE_LIGHT = 1;
    public final static int LCD_MODE_RGB = 2;
    public final static int LCD_MODE_BGR = 3;
    public final static int LCD_MODE_VRGB = 4;
    public final static int LCD_MODE_VBGR = 5;
................................................................................
    /* =====================================================================
     * FTDemoNew
     * =====================================================================
     */
    public static FTDemoHandle FTDemoNew() {
      FTDemoHandle handle;
      ftbase.FTReference<ftbase.FTLibraryRec> library_ref = new ftbase.FTReference<ftbase.FTLibraryRec>();
      ftbase.FTReference<ftcache.FTCManagerRec> cache_manager_ref = new ftbase.FTReference<ftcache.FTCManagerRec>();
      ftbase.FTReference<ftcache.FTCGCacheRec> sbits_cache_ref = new ftbase.FTReference<ftcache.FTCGCacheRec>();
      ftbase.FTReference<ftcache.FTCGCacheRec> cmap_cache_ref = new ftbase.FTReference<ftcache.FTCGCacheRec>();
      ftbase.FTReference<ftbase.FTBitmapRec> bitmap_ref = new ftbase.FTReference<ftbase.FTBitmapRec>();
      ftbase.FTReference<ftcache.FTCGCacheRec> image_cache_ref = new ftbase.FTReference<ftcache.FTCGCacheRec>();
      ftbase.  FTReference<ftbase.FTStrokerRec> stroker_ref = new ftbase.FTReference<ftbase.FTStrokerRec>();
      ftbase.FTInit ft_init = new ftbase.FTInit();
      ftbase.FTInstanceMethod requester;
      String class_name = "org.apwtcl.gles20.truetype.FTDemoUtil";
      int error = 0;
      
Debug(0, DBG_INIT, TAG, "FTDemoNew\n");
// Test1Rec t1 = new Test1Rec();
// Test2Rec t2 = new Test2Rec();
// FTReference<Test1Rec> ref = new FTReference<Test1Rec>();
// ref.Set(t1);
// t2.NewRec(ref);
// Log.i(TAG, ref.Get().toDebugString());
// Log.i(TAG, "t1: "+t1+"!"+ref.Get()+"!");
................................................................................
      handle.library = library_ref.Get();
      if (error != 0) {
        System.out.println("could not initialize FreeType");
        return null;
      }
    ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "after call FTInitFreeType");
      cache_manager_ref.Set(handle.cache_manager);
      requester = new ftbase.FTInstanceMethod(class_name, "my_face_requester", 1);
      error = ftcache.FTCManagerRec.FTCManagerNew(handle.library, 0, 0,
              requester, 0, cache_manager_ref);
      handle.cache_manager = cache_manager_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize cache manager");
        return null;
      }
      sbits_cache_ref.Set(handle.sbits_cache);
      error = ftcache.FTCManagerRec.FTCSBitCacheNew(handle.cache_manager, sbits_cache_ref);
      handle.sbits_cache = sbits_cache_ref.Get();
Debug(0, DBG_INIT, TAG, "handle.sbits_cache: "+((ftcache.FTCCacheRec)(handle.sbits_cache)).toDebugString());
      if (error != 0) {
        Log.e(TAG, "could not initialize small bitmaps cache");
        return null;
      }
      image_cache_ref.Set(handle.image_cache);
      error = ftcache.FTCManagerRec.FTCImageCacheNew(handle.cache_manager, image_cache_ref);
      handle.image_cache = image_cache_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize glyph image cache");
        return null;
      }
      cmap_cache_ref.Set(handle.cmap_cache);
      error = ftcache.FTCManagerRec.FTCCMapCacheNew(handle.cache_manager, cmap_cache_ref);
      handle.cmap_cache = cmap_cache_ref.Get();
      if (error != 0) {
        Log.e(TAG, "could not initialize charmap cache");
        return null;
      }
Debug(0, DBG_INIT, TAG, "call FTBitmapNew");
      bitmap_ref.Set(handle.bitmap);
      ftbase.FTBitmapRec.FTBitmapNew(bitmap_ref);
      handle.bitmap = bitmap_ref.Get();
Debug(0, DBG_INIT, TAG, "call FTStrokerNew");
      stroker_ref.Set(handle.stroker);
      ftbase.FTStrokerRec.FTStrokerNew(handle.library, stroker_ref);
      handle.stroker = stroker_ref.Get();
      handle.encoding = ftbase.FTEncoding.FT_ENCODING_NONE;
      handle.hinted = true;
      handle.antialias = true;
      handle.use_sbits = true;
      handle.autohint  = false;
      handle.lcd_mode  = 0;
      handle.color     = true;
      handle.use_sbits_cache = true;
................................................................................
     * my_face_requester
     * =====================================================================
     */
    public static int my_face_requester(Object ... args) {
      Object face_id = args[0];
      ftbase.FTLibraryRec lib = (ftbase.FTLibraryRec)args[1];
//      Object request_data = args[2];
      FTReference<ftbase.FTFaceRec> face_ref = (FTReference<ftbase.FTFaceRec>)args[3];
      ftbase.FTFaceRec face = null;
      int error = 0;
      TFont font = (TFont)face_id;

      face_ref.Set(null);
Debug(0, DBG_INIT, TAG, "my_face_requester");
      if (font.file_address != null) {
Log.w(TAG, "file_address not yet implemented");
//        error = FTNewMemoryFace(lib,
//               (byte[]*)font.file_address, font.file_size, font.face_index, aface);
      } else {
        error = ftbase.FTFaceRec.FTNewFace(lib, font.filepathname, font.face_index, face_ref);
        face = face_ref.Get();
Debug(0, DBG_INIT, TAG, "FACE: "+face+"!"+face.driver+"!");
      }
      if (error == 0) {
/*
         format = FT_Get_X11_Font_Format( *aface );

        if ( !strcmp( format, "Type 1" ) ) {
          char   orig[5];
................................................................................
     * =====================================================================
     */
    public static int FTDemoInstallFont(FTDemoHandle handle, String filepath) {
      StringBuffer filename = new StringBuffer();
      int i = 0;
      int error = 0;
      int num_faces = 0;
      ftbase.FTFaceRec face = new ftbase.FTFaceRec("InstallFont");
      FTReference<ftbase.FTFaceRec> face_ref = new FTReference<ftbase.FTFaceRec>();

ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "FTDemoInstallFont: "+filepath);
      filename.append(filepath);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "InstallFont call FTNewFace");
      face_ref.Set(face);
      error = ftbase.FTFaceRec.FTNewFace(handle.library, filename.toString(), 0, face_ref);
      face = face_ref.Get();
      if (error != 0) {
        return error;
      }
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, "InstallFont AFTER call FTNewFace: "+error+"!"+face+"!"+face.stream+"!");
      /* allocate new font object */
      num_faces = face.num_faces;
      for (i = 0; i < num_faces; i++) {
        TFont font;

        if (i > 0) {
          face_ref.Set(face);
          error = ftbase.FTFaceRec.FTNewFace(handle.library, filename.toString(), i, face_ref);
          face = face_ref.Get();
          if (error != 0) {
            continue;
          }
        }
        if (handle.encoding != ftbase.FTCharMapRec.FT_ENCODING_NONE) {
            ftbase.FTCharMapRec charmap = new ftbase.FTCharMapRec();
          error = charmap.FTSelectCharmap(face, handle.encoding);
          if (error != 0) {
//            face.FTDoneFace(face);
            return error;
          }
        }
        font = new TFont();
        /* We allocate four more bytes since we want to attach an AFM */
        /* or PFM file for Type 1 fonts (if available).  Such fonts   */
        /* always have the extension `.afm' or `.pfm'.                */
        font.filepathname = filename.toString();
        font.face_index = i;
        font.cmap_index = face.charmap != null ? ftbase.FTCharMapRec.FTGetCharmapIndex(face.charmap) : 0;
        if (handle.preload) {
          try {
            RandomAccessFile file = new RandomAccessFile(filename.toString(), "r");
            long file_size;

            file_size = file.length();
            font.file_address = new byte[(int)file_size];
................................................................................
          } catch(IOException e) {
          e.printStackTrace();
          }
        } else {
          font.file_address = null;
          font.file_size = 0L;
        }
        if (handle.encoding == FT_ENCODING_NONE) {
          font.num_indices = face.num_glyphs;
        } else {
          if (handle.encoding == FT_ENCODING_UNICODE) {
            font.num_indices = 0x110000L;
          } else {
            if (handle.encoding == FT_ENCODING_ADOBE_LATIN_1 ||
                handle.encoding == FT_ENCODING_ADOBE_STANDARD ||
                handle.encoding == FT_ENCODING_ADOBE_EXPERT ||
                handle.encoding == FT_ENCODING_ADOBE_CUSTOM ||
                handle.encoding == FT_ENCODING_APPLE_ROMAN) {
              font.num_indices = 0x100L;
            } else {
              /* some fonts use range 0x00-0x100, others have 0xF000-0xF0FF */
              if(handle.encoding == FT_ENCODING_MS_SYMBOL) {
                font.num_indices = 0x10000L;
              } else {
                font.num_indices = 0x10000L;
              }
            }
          }
        }
................................................................................
//            handle.fonts = (PFont*)realloc( handle->fonts, handle->max_fonts * sizeof ( PFont ) );

//            memset( &handle->fonts[handle->num_fonts], 0, ( handle->max_fonts - handle->num_fonts ) * sizeof ( PFont ) );
          }
        }
        handle.fonts[handle.num_fonts++] = font;
      }
      return FTError.INTERP_ERR_OK;
    }

    /* =====================================================================
     * FTDemoGetIndex
     * =====================================================================
     */
    public static int FTDemoGetIndex(FTDemoHandle handle, int char_code) {
      Object face_id = handle.scaler.face_id;
      TFont font = handle.current_font;
      int result = 0;

      result = ftcache.FTCCMapCacheFuncs.FTCCMapCacheLookup(handle.cmap_cache, face_id, font.cmap_index, char_code);
ftbase.FTDebug.Debug(0, ftbase.FTDebug.DBG_INIT, TAG, String.format("FTDemoGetIndex: %c 0x%04x %d", char_code, char_code, result));
      return result;
    }

    /* =====================================================================
     * RenderAll
     * =====================================================================
     */
    public static int RenderAll(FTDemoHandle handle, int num_indices, int offset) {
      int error = 0;
      int i;
      int have_topleft;
      FTReference<ftbase.FTSizeRec> size_ref = new FTReference<ftbase.FTSizeRec>();;
      ftbase.FTSizeRec size;

Debug(0, DBG_INIT, TAG, String.format("=== Render_All %d %d", num_indices, offset));
      error = FTDemoGetSize(handle, size_ref);
      size = size_ref.Get();
      if (error != 0) {
        /* probably a non-existent bitmap font size */
        return error;
      }
      InitSize(size);
................................................................................
      for (i = offset; i < num_indices; i++) {
        int  glyph_idx = 0;
//        if (i != 38 && i != 47 && i != 55) {
        if (i != 38 ) {
          continue;
        }

        if (handle.encoding == FT_ENCODING_NONE) {
          glyph_idx = i;
        } else {
//          glyph_idx = FTDemoGetIndex(handle, i);
        }
        FTReference<Integer> x_ref = new FTReference<Integer>();
        FTReference<Integer> y_ref = new FTReference<Integer>();
        x_ref.Set(x);
        y_ref.Set(y);
Debug(0, DBG_INIT, TAG, String.format("x1: %d y: %d", x, y));
        error = FTDemoDrawIndex(handle, glyph_idx, x_ref, y_ref);
        x = x_ref.Get();
        y = y_ref.Get();
Debug(0, DBG_INIT, TAG, String.format("x2: %d y: %d", x, y));

        if (have_topleft == 0) ;
/*
        error = FTDemoDrawIndex(handle, display, glyph_idx, &x, &y);
        if (error != 0) {
          if (have_topleft == 0) {
            have_topleft   = 1;
................................................................................
            if (Y_TOO_LONG(y, size, display)) {
              break;
            }
          }
        }
*/
      }
      return FTError.INTERP_ERR_OK;
    }

    /* =====================================================================
     * RenderText
     * =====================================================================
     */
    public static int RenderText(FTDemoHandle handle, StringBuffer text, int offset) {
      FTReference<ftbase.FTSizeRec> size_ref = new FTReference<ftbase.FTSizeRec>();;
      ftbase.FTSizeRec size = new ftbase.FTSizeRec();
      boolean have_topleft;
      int error = 0;

//      char*  p;
//      char*  pEnd;
      int ch = 0;

................................................................................
      int num_indices = text.length();
//      text = new StringBuffer("Hello TCLers");
      while (num_indices-- > 0) {
        int glyph_idx;

ch = text.charAt(idx++);
FTDemoHandle.currCharacter = (char)ch;
Debug(0, DBG_INIT, TAG, String.format("Handling char: %c",  ch));
/*
        ch = utf8_next( &p, pEnd );
        if (ch < 0) {
          p  = Text;
          ch = utf8_next( &p, pEnd );
        }
*/
        glyph_idx = FTDemoGetIndex(handle, ch);
        FTDemoHandle.currGIndex = glyph_idx;
        FTReference<Integer> x_ref = new FTReference<Integer>();
        FTReference<Integer> y_ref = new FTReference<Integer>();
        x_ref.Set(x);
        y_ref.Set(y);
Debug(0, DBG_INIT, TAG, String.format("x1: %d y: %d", x, y));
        error = FTDemoDrawIndex(handle, glyph_idx, x_ref, y_ref);
        x = x_ref.Get();
        y = y_ref.Get();
Debug(0, DBG_INIT, TAG, String.format("x2: %d y: %d", x, y));
        if (error == 0) {
          if (!have_topleft) {
            have_topleft = true;
            status.topleft = ch;
          }
        }
        if (error != 0) {
................................................................................
            if (Y_TOO_LONG(y, size, display)) {
              break;
            }
          }
*/
        }
      }
      return FTError.INTERP_ERR_OK;
    }

    /* =====================================================================
     * FTDemoGetSize
     * =====================================================================
     */
    public static int FTDemoGetSize(FTDemoHandle handle, FTReference<ftbase.FTSizeRec> size_ref) {
      int error = 0;
//      FTSizeRec size;
      FTReference<ftcache.FTCScalerRec> scaler_ref = new FTReference<ftcache.FTCScalerRec>();

Debug(0, DBG_INIT, TAG, "FTDemoGetSize");
      scaler_ref.Set(handle.scaler);
      error = ftcache.FTCManagerRec.FTCManagerLookupSize(handle.cache_manager, scaler_ref, size_ref);
      handle.scaler = scaler_ref.Get();
Debug(0, DBG_INIT, TAG, String.format("h: %d w: %d xres:%d yres: %d", handle.scaler.height, handle.scaler.width, handle.scaler.x_res, handle.scaler.y_res));
      return error;
    }

    /* =====================================================================
     * InitSize
     * =====================================================================
     */
    public static int InitSize(ftbase.FTSizeRec size) {
      int error = 0;

      start_x = 19 * 8;
      start_y = (((int)size.metrics.height + 63) >> 6) + 4 * 12;
      step_y  = (((int)size.metrics.height + 63) >> 6) + 4;
      x = start_x;
      y = start_y;
................................................................................
    /* =====================================================================
     * FTDemoSetCurrentFont
     * =====================================================================
     */
    public static int FTDemoSetCurrentFont(FTDemoHandle handle, TFont font) {
      int error = 0;

Debug(0, DBG_INIT, TAG, "FTDemo_Set_Current_Font");
      handle.current_font = font;
      handle.scaler.face_id = (Object)font;
      handle.string_reload = true;
      return error;
    }

    /* =====================================================================
................................................................................
     * =====================================================================
     */
    public static int FTDemoUpdateCurrentFlags(FTDemoHandle handle) {
      int error = 0;
      int flags;
      int target;

      flags = (int)FT_LOAD_DEFAULT;  /* really 0 */
      if (handle.autohint) {
        flags |= FT_LOAD_FORCE_AUTOHINT;
      }
      if (!handle.use_sbits) {
        flags |= FT_LOAD_NO_BITMAP;
      }
      if (handle.hinted) {
        target = 0;
        if (handle.antialias) {
          switch (handle.lcd_mode) {
          case LCD_MODE_LIGHT:
            target = FT_LOAD_TARGET_LIGHT;
................................................................................
            target = FT_LOAD_TARGET_NORMAL;
          }
        } else {
          target = FT_LOAD_TARGET_MONO;
        }
        flags |= target;
      } else {
        flags |= FT_LOAD_NO_HINTING;
        if (!handle.antialias) {
          flags |= FT_LOAD_MONOCHROME;
        }
      }
      if (handle.color) {
        flags |= FT_LOAD_COLOR;
      }
      handle.load_flags = (long)flags;
      handle.string_reload = true;
      return error;
    }

    /* =====================================================================
................................................................................
      int pen_y = pen_y_ref.Get();
      int error = 0;
      FTReference<Integer> left_ref = new FTReference<Integer>();
      FTReference<Integer> top_ref = new FTReference<Integer>();
      FTReference<Integer> x_advance_ref = new FTReference<Integer>();
      FTReference<Integer> y_advance_ref = new FTReference<Integer>();
      FTReference<grBitmap> bit3_ref = new FTReference<grBitmap>();
      FTReference<ftbase.FTGlyphRec> glyph_ref = new FTReference<ftbase.FTGlyphRec>();
      int left = 0;
      int top = 0;
      int x_advance = 0;
      int y_advance = 0;
      grBitmap bit3 = handle.grBitmap;
      ftbase.FTGlyphRec glyf = new ftbase.FTGlyphRec();

Debug(0, DBG_INIT, TAG, "FTDemoDrawIndex");
      left_ref.Set(left);
      top_ref.Set(top);
      x_advance_ref.Set(x_advance);
      y_advance_ref.Set(y_advance);
      bit3_ref.Set(bit3);
      glyph_ref.Set(glyf);
      error = FTDemoBitmapUtil.FTDemoIndexToBitmap(handle, glyphIndex, bit3_ref,
................................................................................
      bitmap_ref.Set(handle.display.bitmap);
      GBlenderCell color = new GBlenderCell();
      color.red = 0;
      color.green = 0;
      color.blue = 0;
      color.alpha = 0;

Debug(0, DBG_INIT, TAG, String.format("===1 pen_x: %d, left: %d, top: %d, x_advance: %d, y_advance: %d bitmap: " + handle.display.bitmap,
        pen_x, left, top, x_advance, y_advance));
      FTDemoBitmapUtil.grBlitGlyphToBitmap(bitmap_ref, bit3_ref, pen_x + left, pen_y - top, color);
      handle.display.bitmap = bitmap_ref.Get();
      if (glyf != null) {
//        FTDoneGlyph(glyf);
      }
      pen_x += x_advance + 1;
................................................................................
    /* =====================================================================
     * stringLoad
     * =====================================================================
     */
    public int stringLoad(FTDemoHandle handle) {
        int error;
        int n;
        ftbase.FTSizeRec size;
        ftbase.FTFaceRec face;
        Long prev_rsb_delta = 0L;
        ftbase.FTReference<ftbase.FTSizeRec> size_ref = new ftbase.FTReference<ftbase.FTSizeRec>();

        error = FTError.INTERP_ERR_OK;
        size_ref.Set(null);
        error = ftbase.FTGlyphLoaderRec.GetSize(handle, size_ref);
        if (error != 0) {
            return error;
        }
        size = size_ref.Get();
        face = size.face;
        for (n = 0; n < handle.string_length; n++) {
            TGlyph glyph = handle.string[n];
            ftbase.FTReference<ftbase.FTGlyphRec> image_ref = new ftbase.FTReference<ftbase.FTGlyphRec>();
            ftbase.FTReference<ftbase.FTFaceRec> face_ref = new ftbase.FTReference<ftbase.FTFaceRec>();
            ftbase.FTReference<ftbase.FTGlyphSlotRec> glyph_slot_ref = new ftbase.FTReference<ftbase.FTGlyphSlotRec>();

        /* clear existing image if there is one */
            if (glyph.image != null) {
                ftbase.FTGlyphLoaderRec.FTDoneGlyph(glyph.image);
                glyph.image = null;
            }
        /* load the glyph and get the image */
            image_ref.Set(glyph.image);
            glyph_slot_ref.Set(face.glyph);
            if (ftbase.FTGlyphLoaderRec.FTLoadGlyph(face_ref, glyph.glyph_index, handle.load_flags.intValue()) == 0 &&
                    ftbase.FTGlyphLoaderRec.FTGetGlyph(glyph_slot_ref, image_ref) == 0) {
                face.glyph = glyph_slot_ref.Get();
                glyph.image = image_ref.Get();

          /* note that in vertical layout, y-positive goes downwards */
                glyph.vvector.x  =  face.glyph.metrics.vertBearingX - face.glyph.metrics.horiBearingX;
                glyph.vvector.y  = -face.glyph.metrics.vertBearingY - face.glyph.metrics.horiBearingY;
                glyph.vadvance.x = 0L;