apwfreetypelib

Check-in [41fd1a1418]
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:41fd1a14186f1e8f2a0ee958d1230a1e14bfb833
User & Date: arnulf 2015-01-31 21:35:39
Context
2015-02-01
12:45
fixes, code moving and changes. check-in: 1c81d958fa user: arnulf tags: trunk
2015-01-31
21:35
fixes. check-in: 41fd1a1418 user: arnulf tags: trunk
2015-01-25
21:10
fixes, new code and refactoring. check-in: 064b26a0cc user: arnulf tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to aftbase/FTOutlineRec.java.

580
581
582
583
584
585
586










587










588
589
590
591
592
593
594
595
  }

  /* ==================== getPoint ================================== */
  public FTVectorRec getPoint(int idx) {
    return points[points_idx+idx];
  }











  /* ==================== setPoints ================================== */










  public void setPoints(int idx, FTVectorRec point) {
    points[points_idx+idx] = point;
  }

  /* ==================== getPoints ================================== */
  public FTVectorRec[] getPoints() {
    return points;
  }







>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  }

  /* ==================== getPoint ================================== */
  public FTVectorRec getPoint(int idx) {
    return points[points_idx+idx];
  }

  /* ==================== getPoint_x ================================== */
  public int getPoint_x(int idx) {
    return points[points_idx+idx].getX();
  }

  /* ==================== getPoint_y ================================== */
  public int getPoint_y(int idx) {
    return points[points_idx+idx].getY();
  }

  /* ==================== setPoint_x ================================== */
  public void setPoint_x(int idx, int val) {
    points[points_idx+idx].setX(val);
  }

  /* ==================== setPoint_y ================================== */
  public void setPoint_y(int idx, int val) {
    points[points_idx+idx].setY(val);
  }

  /* ==================== setPoint ================================== */
  public void setPoint(int idx, FTVectorRec point) {
    points[points_idx+idx] = point;
  }

  /* ==================== getPoints ================================== */
  public FTVectorRec[] getPoints() {
    return points;
  }

Changes to aftbase/FTRendererRec.java.

163
164
165
166
167
168
169

170

171
172
173
174
175
176
177
          node = cur;
        }
        result = renderer;
        break;
      }
      cur = cur.next;
    }

    list_node_ref.Set(node);

    return result;
  }

  /* =====================================================================
   * FTSetRenderer
   * =====================================================================
   */







>
|
>







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
          node = cur;
        }
        result = renderer;
        break;
      }
      cur = cur.next;
    }
    if (list_node_ref != null) {
      list_node_ref.Set(node);
    }
    return result;
  }

  /* =====================================================================
   * FTSetRenderer
   * =====================================================================
   */

Changes to afttruetype/TTGlyphLoaderFuncs.java.

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
    public static FTError.ErrorTag TTProcessSimpleGlyph(TTLoaderRec loader) {
      FTGlyphLoaderRec gloader = loader.getGloader();
      FTError.ErrorTag error = FTError.ErrorTag.ERR_OK;
      int n_points;

      n_points = gloader.getCurrent().getN_points();
      /* set phantom points */
      gloader.getCurrent().getPoints()[n_points] = loader.getPp1();
      gloader.getCurrent().getPoints()[n_points + 1] = loader.getPp2();
      gloader.getCurrent().getPoints()[n_points + 2] = loader.getPp3();
      gloader.getCurrent().getPoints()[n_points + 3] = loader.getPp4();
      gloader.getCurrent().getTags()[n_points] = Flags.Curve.CONIC;
      gloader.getCurrent().getTags()[n_points + 1] = Flags.Curve.CONIC;
      gloader.getCurrent().getTags()[n_points + 2] = Flags.Curve.CONIC;
      gloader.getCurrent().getTags()[n_points + 3] = Flags.Curve.CONIC;
      n_points += 4;
      if ((loader.getLoad_flags().getVal() & Flags.Load.NO_HINTING.getVal()) == 0) {
        loader.getZone().tt_prepare_zone(gloader.getCurrent(), 0, 0);
        for (int i = 0; i < (loader.getZone().getN_points() + 4); i++) {
          loader.getZone().setOrusPoint(i, new FTVectorRec());
          loader.getZone().getOrusPoint(i).setX(loader.getZone().getCurPoint_x(i));
          loader.getZone().getOrusPoint(i).setY(loader.getZone().getCurPoint_y(i));
        }
      }
      {
        int vecIdx = 0;
        int limit = n_points;
        int x_scale = 0; /* pacify compiler */
        int y_scale = 0;
        boolean do_scale = false;
        {
          /* scale the glyph */
          if ((loader.getLoad_flags().getVal() & Flags.Load.NO_SCALE.getVal()) == 0) {
            x_scale = ((TTSizeRec)loader.getSize()).getMetrics().getX_scale();
            y_scale = ((TTSizeRec)loader.getSize()).getMetrics().getY_scale();
            do_scale = true;
          }
        }
        if (do_scale) {
          for (vecIdx = 0; vecIdx < limit; vecIdx++) {
            gloader.getCurrent().getPoints()[vecIdx].setX(TTUtil.FTMulFix(gloader.getCurrent().getPoints()[vecIdx].getX(), x_scale));
            gloader.getCurrent().getPoints()[vecIdx].setY(TTUtil.FTMulFix(gloader.getCurrent().getPoints()[vecIdx].getY(), y_scale));
          }
          loader.setPp1(gloader.getCurrent().getPoints()[n_points - 4]);
          loader.setPp2(gloader.getCurrent().getPoints()[n_points - 3]);
          loader.setPp3(gloader.getCurrent().getPoints()[n_points - 2]);
          loader.setPp4(gloader.getCurrent().getPoints()[n_points - 1]);
        }
      }







|
|
|
|
|
|
|
|





|
|











|
|





|
|







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
    public static FTError.ErrorTag TTProcessSimpleGlyph(TTLoaderRec loader) {
      FTGlyphLoaderRec gloader = loader.getGloader();
      FTError.ErrorTag error = FTError.ErrorTag.ERR_OK;
      int n_points;

      n_points = gloader.getCurrent().getN_points();
      /* set phantom points */
      gloader.getCurrent().setPoint(n_points, loader.getPp1());
      gloader.getCurrent().setPoint(n_points + 1, loader.getPp2());
      gloader.getCurrent().setPoint(n_points + 2, loader.getPp3());
      gloader.getCurrent().setPoint(n_points + 3, loader.getPp4());
      gloader.getCurrent().setTag(n_points, Flags.Curve.CONIC);
      gloader.getCurrent().setTag(n_points + 1, Flags.Curve.CONIC);
      gloader.getCurrent().setTag(n_points + 2, Flags.Curve.CONIC);
      gloader.getCurrent().setTag(n_points + 3, Flags.Curve.CONIC);
      n_points += 4;
      if ((loader.getLoad_flags().getVal() & Flags.Load.NO_HINTING.getVal()) == 0) {
        loader.getZone().tt_prepare_zone(gloader.getCurrent(), 0, 0);
        for (int i = 0; i < (loader.getZone().getN_points() + 4); i++) {
          loader.getZone().setOrusPoint(i, new FTVectorRec());
          loader.getZone().setOrusPoint_x(i, loader.getZone().getCurPoint_x(i));
          loader.getZone().setOrusPoint_y(i, loader.getZone().getCurPoint_y(i));
        }
      }
      {
        int vecIdx = 0;
        int limit = n_points;
        int x_scale = 0; /* pacify compiler */
        int y_scale = 0;
        boolean do_scale = false;
        {
          /* scale the glyph */
          if ((loader.getLoad_flags().getVal() & Flags.Load.NO_SCALE.getVal()) == 0) {
            x_scale = (loader.getSize()).getMetrics().getX_scale();
            y_scale = (loader.getSize()).getMetrics().getY_scale();
            do_scale = true;
          }
        }
        if (do_scale) {
          for (vecIdx = 0; vecIdx < limit; vecIdx++) {
            gloader.getCurrent().setPoint_x(vecIdx, TTUtil.FTMulFix(gloader.getCurrent().getPoint_x(vecIdx), x_scale));
            gloader.getCurrent().setPoint_y(vecIdx, TTUtil.FTMulFix(gloader.getCurrent().getPoint_y(vecIdx), y_scale));
          }
          loader.setPp1(gloader.getCurrent().getPoints()[n_points - 4]);
          loader.setPp2(gloader.getCurrent().getPoints()[n_points - 3]);
          loader.setPp3(gloader.getCurrent().getPoints()[n_points - 2]);
          loader.setPp4(gloader.getCurrent().getPoints()[n_points - 1]);
        }
      }

Changes to afttruetype/TTGlyphZoneRec.java.

328
329
330
331
332
333
334

335
336
337
338
339
340
341
    tags = load.getTags();
    tags_idx = load.getTags_idx() + start_point;
    contours = load.getContours();
    contours_idx = load.getContours_idx() + start_contour;
    first_point = start_point;
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "zone org: " + load.getExtra_points() + "!" + load.getExtra_points_idx() + "!" + load.getExtra_points2() + "!" + load.getExtra_points2_idx() + "!");
    showLoaderZone("tt_prepare_zone", exec);

  }

  /* =====================================================================
   * tt_glyphzone_done
   *
   * <Description>
   *    Deallocate a glyph zone.







>







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
    tags = load.getTags();
    tags_idx = load.getTags_idx() + start_point;
    contours = load.getContours();
    contours_idx = load.getContours_idx() + start_contour;
    first_point = start_point;
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "zone org: " + load.getExtra_points() + "!" + load.getExtra_points_idx() + "!" + load.getExtra_points2() + "!" + load.getExtra_points2_idx() + "!");
    showLoaderZone("tt_prepare_zone", exec);
    load.showGloaderGlyph("tt_prepare_zone");
  }

  /* =====================================================================
   * tt_glyphzone_done
   *
   * <Description>
   *    Deallocate a glyph zone.

Changes to afttruetype/TTLoaderRec.java.

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
649
650
651
652
653
654
655


656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
...
710
711
712
713
714
715
716
717






718
719
720
721
722
723
724
725

      exec = size.isDebug() ? size.getContext()
                         : ((TTDriverRec)ttface.getDriver()).context;
      if (exec == null) {
        return FTError.ErrorTag.GLYPH_COULD_NOT_FIND_CONTEXT;
      }
      grayscale = (((load_flags.getVal() >> 16) & 15) != FTTags.RenderMode.MONO.getVal());
      FTReference<TTExecContextRec> exec_ref = new FTReference<TTExecContextRec>();
      exec_ref.Set(exec);
      exec.TTLoadContext(ttface, size);
      exec = exec_ref.Get();
      {
        /* a change from mono to grayscale rendering (and vice versa) */
        /* requires a re-execution of the CVT program                 */
        if (grayscale != exec.grayscale) {
          FTTrace.Trace(7, TAG, "tt_loader_init: grayscale change, re-executing `prep' table");
          exec.grayscale = grayscale;
          reexecute = true;
................................................................................
    int n_ins;

Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "TTHintGlyph: "+glyph.getControl_len());
    for(int i = 0; i < gloader.getCurrent().getN_points() + 4; i++) {
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("PP: %d %d %d\n", i, gloader.getCurrent().getPoints()[i].getX(),
          gloader.getCurrent().getPoints()[i].getY()));
    }


    if (glyph.getControl_len() > 0xFFFFL) {
      FTTrace.Trace(7, TAG, "TT_Hint_Glyph: too long instructions ");
      FTTrace.Trace(7, TAG, String.format("(0x%lx byte) is truncated",
          glyph.getControl_len()));
    }
    n_ins = (glyph.getControl_len());
    origin = zone.getCurPoint(zone.getN_points() - 4).getX();
    origin = FTCalc.FT_PIX_ROUND(origin) - origin;
    Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("origin: %d", origin));
    if (origin != 0) {
      FTGlyphLoaderRec.translate_array(zone.getN_points(), zone.getCur(), 0, origin, 0);
    }
    for (int i = 0; i < 5; i++) {
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d cur.x: %d, cur.y: %d", i, zone.getCurPoint_x(i), zone.getCurPoint_y(i)));
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d orus.x: %d, orus.y: %d", i, zone.getOrusPoint_x(i), zone.getOrusPoint_y(i)));
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d org.x: %d, org.y: %d", i, zone.getOrgPoint_x(i), zone.getOrgPoint_y(i)));
................................................................................
      /*      completely refer to the (already) hinted subglyphs.     */
    if (is_composite) {
      exec.metrics.setX_scale(1 << 16);
      exec.metrics.setY_scale(1 << 16);
      // FIXME !! eventually problem with Arrays.copyOf!!
      zone.xsetOrus(java.util.Arrays.copyOf(zone.getCur(), zone.getN_points()));
    } else {
      exec.metrics.setX_scale(((TTSizeRec)size).getMetrics().getX_scale());
      exec.metrics.setY_scale(((TTSizeRec)size).getMetrics().getY_scale());
    }
      /* round pp2 and pp4 */
    zone.setCurPoint_x(zone.getN_points() - 3, FTCalc.FT_PIX_ROUND(zone.getCurPoint_x(zone.getN_points() - 3)));
    zone.setCurPoint_y(zone.getN_points() - 1, FTCalc.FT_PIX_ROUND(zone.getCurPoint_y(zone.getN_points() - 1)));
    if (n_ins > 0) {
      boolean debug;
      FTGlyphLoaderRec gloader = this.gloader;
................................................................................
      error = exec.TTSetCodeRange(TTInterpTags.CodeRange.GLYPH, exec.glyphIns, null, n_ins);
      if (error != FTError.ErrorTag.ERR_OK) {
        return error;
      }
      exec.is_composite = is_composite;
      exec.pts.copy(zone);
      debug = ((load_flags.getVal() & Flags.Load.NO_SCALE.getVal()) == 0 && ((TTSizeRec)size).isDebug());
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "call TTRunContext");






//_showLoaderZone("before call TTRunContext");
      error = exec.TTRunContext(debug);
      if (error != FTError.ErrorTag.ERR_OK && exec.pedantic_hinting) {
        return error;
      }
        /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
      current_outline.getTags()[0] = Flags.Curve.getTableTag(current_outline.getTags()[0].getVal() |
          (exec.graphics_state.getScan_type() << 5) | Flags.Curve.HAS_SCANMODE.getVal());







<
<

<







 







>
>





|


|







 







|
|







 







|
>
>
>
>
>
>
|







156
157
158
159
160
161
162


163

164
165
166
167
168
169
170
...
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
...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730

      exec = size.isDebug() ? size.getContext()
                         : ((TTDriverRec)ttface.getDriver()).context;
      if (exec == null) {
        return FTError.ErrorTag.GLYPH_COULD_NOT_FIND_CONTEXT;
      }
      grayscale = (((load_flags.getVal() >> 16) & 15) != FTTags.RenderMode.MONO.getVal());


      exec.TTLoadContext(ttface, size);

      {
        /* a change from mono to grayscale rendering (and vice versa) */
        /* requires a re-execution of the CVT program                 */
        if (grayscale != exec.grayscale) {
          FTTrace.Trace(7, TAG, "tt_loader_init: grayscale change, re-executing `prep' table");
          exec.grayscale = grayscale;
          reexecute = true;
................................................................................
    int n_ins;

Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "TTHintGlyph: "+glyph.getControl_len());
    for(int i = 0; i < gloader.getCurrent().getN_points() + 4; i++) {
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("PP: %d %d %d\n", i, gloader.getCurrent().getPoints()[i].getX(),
          gloader.getCurrent().getPoints()[i].getY()));
    }
zone.showLoaderZone("TTHintGlyph1", exec);
gloader.getCurrent().showGloaderGlyph("TTHintGlyph1");
    if (glyph.getControl_len() > 0xFFFFL) {
      FTTrace.Trace(7, TAG, "TT_Hint_Glyph: too long instructions ");
      FTTrace.Trace(7, TAG, String.format("(0x%lx byte) is truncated",
          glyph.getControl_len()));
    }
    n_ins = glyph.getControl_len();
    origin = zone.getCurPoint(zone.getN_points() - 4).getX();
    origin = FTCalc.FT_PIX_ROUND(origin) - origin;
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("origin: %d", origin));
    if (origin != 0) {
      FTGlyphLoaderRec.translate_array(zone.getN_points(), zone.getCur(), 0, origin, 0);
    }
    for (int i = 0; i < 5; i++) {
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d cur.x: %d, cur.y: %d", i, zone.getCurPoint_x(i), zone.getCurPoint_y(i)));
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d orus.x: %d, orus.y: %d", i, zone.getOrusPoint_x(i), zone.getOrusPoint_y(i)));
      Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTHintGlyph 30A: i: %d org.x: %d, org.y: %d", i, zone.getOrgPoint_x(i), zone.getOrgPoint_y(i)));
................................................................................
      /*      completely refer to the (already) hinted subglyphs.     */
    if (is_composite) {
      exec.metrics.setX_scale(1 << 16);
      exec.metrics.setY_scale(1 << 16);
      // FIXME !! eventually problem with Arrays.copyOf!!
      zone.xsetOrus(java.util.Arrays.copyOf(zone.getCur(), zone.getN_points()));
    } else {
      exec.metrics.setX_scale((size).getMetrics().getX_scale());
      exec.metrics.setY_scale((size).getMetrics().getY_scale());
    }
      /* round pp2 and pp4 */
    zone.setCurPoint_x(zone.getN_points() - 3, FTCalc.FT_PIX_ROUND(zone.getCurPoint_x(zone.getN_points() - 3)));
    zone.setCurPoint_y(zone.getN_points() - 1, FTCalc.FT_PIX_ROUND(zone.getCurPoint_y(zone.getN_points() - 1)));
    if (n_ins > 0) {
      boolean debug;
      FTGlyphLoaderRec gloader = this.gloader;
................................................................................
      error = exec.TTSetCodeRange(TTInterpTags.CodeRange.GLYPH, exec.glyphIns, null, n_ins);
      if (error != FTError.ErrorTag.ERR_OK) {
        return error;
      }
      exec.is_composite = is_composite;
      exec.pts.copy(zone);
      debug = ((load_flags.getVal() & Flags.Load.NO_SCALE.getVal()) == 0 && ((TTSizeRec)size).isDebug());
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "call TTRunContext");
if (gloader.getBase() != null) {
  gloader.getBase().showGloaderGlyph("base before call TTRunContext");
}
if (gloader.getCurrent() != null) {
  gloader.getCurrent().showGloaderGlyph("current before call TTRunContext");
}
zone.showLoaderZone("before call TTRunContext", exec);
      error = exec.TTRunContext(debug);
      if (error != FTError.ErrorTag.ERR_OK && exec.pedantic_hinting) {
        return error;
      }
        /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
      current_outline.getTags()[0] = Flags.Curve.getTableTag(current_outline.getTags()[0].getVal() |
          (exec.graphics_state.getScan_type() << 5) | Flags.Curve.HAS_SCANMODE.getVal());

Changes to aftttinterpreter/TTCvtFunc.java.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
   * WriteCVT
   *
   * =====================================================================
   */
  /* ==================== writeCvt ===================================== */
  @Override
  public void writeCvt(int idx, int value) {
    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("WriteCVT: idx: %d value: %d", idx, value));

    cur.cvt[idx] = value;
  }

  /* =====================================================================
  * MoveCVT
  *







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
   * WriteCVT
   *
   * =====================================================================
   */
  /* ==================== writeCvt ===================================== */
  @Override
  public void writeCvt(int idx, int value) {
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("WriteCVT: idx: %d value: %d", idx, value));

    cur.cvt[idx] = value;
  }

  /* =====================================================================
  * MoveCVT
  *

Changes to aftttinterpreter/TTExecContextRec.java.

156
157
158
159
160
161
162

163
164
165
166
167
168
169
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
364
365
366
367
368
369
370

371
372
373
374
375
376
377
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

  /* ==================== SkipCode ========================= */
  public boolean SkipCode() {
    IP += length;
    if (IP < codeSize) {
      opcode = TTOpCode.OpCode.getTableTag(code[IP].getVal() & 0xFF);
      length = opcode.getOpCodeLength();

      if (length < 0) {
        if (IP + 1 >= codeSize) {
          error = FTError.ErrorTag.INTERP_CODE_OVERFLOW;
          return false;
        }
        length = 2 - length * (code[IP + 1].getVal() & 0xFF);
      }
................................................................................
  /* =====================================================================
   * TTRunContext
   * =====================================================================
   */

  public FTError.ErrorTag TTRunContext(boolean debug) {
    FTError.ErrorTag error;
    Debug(0, FTDebug.DebugTag.DBG_INTERP, TAG, String.format("TT_Run_Context %d", TTInterpTags.CodeRange.GLYPH)+" zp0.cur: "+zp0.getCur()+"\n zp1.cur: "+zp1.getCur());

    if ((error = TTGotoCodeRange(TTInterpTags.CodeRange.GLYPH, 0)) != FTError.ErrorTag.ERR_OK) {
      return error;
    }
    zp0 = pts;
    zp1 = pts;
    zp2 = pts;
    Debug(0, DebugTag.DBG_INTERP, TAG, "TT_Run_Context2 zp0.cur: "+zp0.getCur()+" \nzp1.cur: "+(Object)zp1.getCur());
    for( int i = 0; i < 6; i++) {
//  Debug(0, DebugTag.DBG_INTERP, TAG, String.format("zp1.org: %d x: %d, y: %d\n", i, cur.zp1.org[i].x, cur.zp1.org[i].y));
//  Debug(0, DebugTag.DBG_INTERP, TAG, String.format("zp0.org: %d x: %d, y: %d\n", i, cur.zp0.org[i].x, cur.zp0.org[i].y));
    }
    graphics_state.setGep0(1);
    graphics_state.setGep1(1);
    graphics_state.setGep2(1);
................................................................................
    graphics_state.getDualVector().setY(graphics_state.getProjVector().getY());
    graphics_state.setRound_state(TTInterpTags.Round.To_Grid);
    graphics_state.setLoop(1);
    /* some glyphs leave something on the stack. so we clean it */
    /* before a new execution.                                  */
    top = 0;
    callTop = 0;

    return face.Interpreter(this);
  }

  /* =====================================================================
   * TTSetCodeRange
   *
   * <Description>
................................................................................
   *
   * <Return>
   *    FreeType error code.  0 means success.
   *
   * =====================================================================
   */
  public FTError.ErrorTag TTGotoCodeRange(TTInterpTags.CodeRange range, int IP) {
    Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "TTGotoCodeRange");
    FTError.ErrorTag error = FTError.ErrorTag.ERR_OK;

    if (range.getVal() < TTInterpTags.CodeRange.FONT.getVal() || range.getVal() > TTInterpTags.CodeRange.GLYPH.getVal()) {
      error = FTError.ErrorTag.INTERP_INVALID_ARGUMENT;
      return error;
    }
    if (codeRangeTable[range.getVal() - 1].base == null) {
................................................................................
    if (IP > codeRangeTable[range.getVal() - 1].size) {
      error = FTError.ErrorTag.INTERP_INVALID_ARGUMENT;
      return error;
    }
    code = codeRangeTable[range.getVal() - 1].base;
    cvt_code = codeRangeTable[range.getVal() - 1].short_base;
    codeSize = codeRangeTable[range.getVal() - 1].size;
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTGotoCodeRange: size: %d", codeSize));
    this.IP = IP;
    curRange = range;
    return error;
  }

  /* ==================== funcRound ===================================== */
  protected int funcRound(int distance, int compensation) {     /* current rounding function */







>







 







|







|







 







>







 







|







 







|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

  /* ==================== SkipCode ========================= */
  public boolean SkipCode() {
    IP += length;
    if (IP < codeSize) {
      opcode = TTOpCode.OpCode.getTableTag(code[IP].getVal() & 0xFF);
      length = opcode.getOpCodeLength();
Debug(0, DebugTag.DBG_INTERP, TAG, "SkipCode: " + opcode);
      if (length < 0) {
        if (IP + 1 >= codeSize) {
          error = FTError.ErrorTag.INTERP_CODE_OVERFLOW;
          return false;
        }
        length = 2 - length * (code[IP + 1].getVal() & 0xFF);
      }
................................................................................
  /* =====================================================================
   * TTRunContext
   * =====================================================================
   */

  public FTError.ErrorTag TTRunContext(boolean debug) {
    FTError.ErrorTag error;
Debug(0, FTDebug.DebugTag.DBG_INTERP, TAG, "TT_Run_Context" + TTInterpTags.CodeRange.GLYPH+" zp0.cur: "+zp0.getCur()+"\n zp1.cur: "+zp1.getCur());

    if ((error = TTGotoCodeRange(TTInterpTags.CodeRange.GLYPH, 0)) != FTError.ErrorTag.ERR_OK) {
      return error;
    }
    zp0 = pts;
    zp1 = pts;
    zp2 = pts;
Debug(0, DebugTag.DBG_INTERP, TAG, "TT_Run_Context2 zp0.cur: "+zp0.getCur()+" \nzp1.cur: "+zp1.getCur());
    for( int i = 0; i < 6; i++) {
//  Debug(0, DebugTag.DBG_INTERP, TAG, String.format("zp1.org: %d x: %d, y: %d\n", i, cur.zp1.org[i].x, cur.zp1.org[i].y));
//  Debug(0, DebugTag.DBG_INTERP, TAG, String.format("zp0.org: %d x: %d, y: %d\n", i, cur.zp0.org[i].x, cur.zp0.org[i].y));
    }
    graphics_state.setGep0(1);
    graphics_state.setGep1(1);
    graphics_state.setGep2(1);
................................................................................
    graphics_state.getDualVector().setY(graphics_state.getProjVector().getY());
    graphics_state.setRound_state(TTInterpTags.Round.To_Grid);
    graphics_state.setLoop(1);
    /* some glyphs leave something on the stack. so we clean it */
    /* before a new execution.                                  */
    top = 0;
    callTop = 0;
DebugTag.DBG_INTERP.setLevel(0);
    return face.Interpreter(this);
  }

  /* =====================================================================
   * TTSetCodeRange
   *
   * <Description>
................................................................................
   *
   * <Return>
   *    FreeType error code.  0 means success.
   *
   * =====================================================================
   */
  public FTError.ErrorTag TTGotoCodeRange(TTInterpTags.CodeRange range, int IP) {
Debug(0, DebugTag.DBG_LOAD_GLYPH, TAG, "TTGotoCodeRange: "+range);
    FTError.ErrorTag error = FTError.ErrorTag.ERR_OK;

    if (range.getVal() < TTInterpTags.CodeRange.FONT.getVal() || range.getVal() > TTInterpTags.CodeRange.GLYPH.getVal()) {
      error = FTError.ErrorTag.INTERP_INVALID_ARGUMENT;
      return error;
    }
    if (codeRangeTable[range.getVal() - 1].base == null) {
................................................................................
    if (IP > codeRangeTable[range.getVal() - 1].size) {
      error = FTError.ErrorTag.INTERP_INVALID_ARGUMENT;
      return error;
    }
    code = codeRangeTable[range.getVal() - 1].base;
    cvt_code = codeRangeTable[range.getVal() - 1].short_base;
    codeSize = codeRangeTable[range.getVal() - 1].size;
Debug(2, DebugTag.DBG_LOAD_GLYPH, TAG, String.format("TTGotoCodeRange: size: %d", codeSize));
    this.IP = IP;
    curRange = range;
    return error;
  }

  /* ==================== funcRound ===================================== */
  protected int funcRound(int distance, int compensation) {     /* current rounding function */

Changes to aftttinterpreter/TTInstructionFuncGrp2.java.

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
...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  /* =====================================================================
   * CALL[]:       CALL function
   * Opcode range: 0x2B
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void CALL() {
    int F;
    TTCallRec call_rec;
    TTDefRec def;
    int defIdx = 0;

      /* first of all, check the index */
    F = (int)cur.stack[cur.stack_idx];
    Debug(0, DebugTag.DBG_INTERP, TAG, "insCall: "+F+"!"+cur.maxFunc+"!stack_idx: "+cur.stack_idx);
    if (TTUtil.BOUNDSL(F, cur.maxFunc + 1)) {
      cur.error = FTError.ErrorTag.INTERP_INVALID_REFERENCE;
      return;
    }
      /* Except for some old Apple fonts, all functions in a TrueType */
      /* font are defined in increasing order, starting from 0.  This */
      /* means that we normally have                                  */
      /*                                                              */
      /*    cur.maxFunc+1 == cur.numFDefs                             */
      /*    cur.FDefs[n].opc == n for n in 0..cur.maxFunc             */
      /*                                                              */
      /* If this isn't true, we need to look up the function table.   */

    def = cur.FDefs[F];
    if (cur.maxFunc + 1 != cur.numFDefs || def.getOpc() != F) {
        /* look up the FDefs table */
      int limit;

      def = cur.FDefs[defIdx];
      limit = defIdx + cur.numFDefs;
      while (defIdx < limit && def.getOpc() != F) {
        defIdx++;
      }
      if (defIdx == limit) {
        cur.error = FTError.ErrorTag.INTERP_INVALID_REFERENCE;
        return;
      }
    }
................................................................................
    call_rec = cur.callStack[cur.callTop];
    call_rec.setCaller_range(cur.curRange.getVal());
    call_rec.setCaller_IP(cur.IP + 1);
    call_rec.setCur_count(1);
    call_rec.setCur_restart(def.getStart());
    call_rec.setCur_end(def.getEnd());
    cur.callTop++;
Debug(0, DebugTag.DBG_INTERP, TAG, "GotoCodeRange: "+def.getRange()+"!"+def.getStart()+"!");
    cur.TTGotoCodeRange(TTInterpTags.CodeRange.getTableTag(def.getRange()), def.getStart());
    cur.step_ins = false;
    return;
  }

  /* =====================================================================
   * FDEF[]:       Function DEFinition
................................................................................
    rec = cur.FDefs[rec_idx];
    rec.setRange(cur.curRange.getVal());
    rec.setOpc(n);
    rec.setStart((cur.IP + 1));
    rec.setActive(true);
    rec.setInline_delta(false);
    rec.setSph_fdef_flags(0x0000);
    for (int j = 0; j < cur.stack_idx; j++) {
      Debug(0, DebugTag.DBG_INTERP, TAG, "stack: "+cur.stack[j]+"!");
    }
    if (n > cur.maxFunc) {
      cur.maxFunc = n;
    }
      /* Now skip the whole function definition. */
      /* We don't allow nested IDEFS & FDEFs.    */
    while (cur.SkipCode() == true) {
      switch (cur.opcode) {
................................................................................
        case IDEF:    /* IDEF */
        case FDEF:    /* FDEF */
          cur.error = FTError.ErrorTag.INTERP_NESTED_DEFS;
          return;
        case ENDF:   /* ENDF */
          rec.setEnd(cur.IP);
Debug(0, DebugTag.DBG_INTERP, TAG, "rec: " + rec.toDebugString());
for(int i = rec.getStart(); i < rec.getEnd(); i++) {
  Debug(0, DebugTag.DBG_INTERP, TAG, "CODE: "+cur.code[i]);
}
          return;
      }
    }
  }

  /* =====================================================================
   * ENDF[]:       END Function definition







|





|
|
|












|
|





|







 







|







 







<
<
<







 







<
<
<







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
...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
427
428
429
430
431
432
433



434
435
436
437
438
439
440
...
441
442
443
444
445
446
447



448
449
450
451
452
453
454
  /* =====================================================================
   * CALL[]:       CALL function
   * Opcode range: 0x2B
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void CALL() {
    int function_opc;
    TTCallRec call_rec;
    TTDefRec def;
    int defIdx = 0;

      /* first of all, check the index */
    function_opc = cur.stack[cur.stack_idx];
    Debug(0, DebugTag.DBG_INTERP, TAG, "Call: function_opc: "+function_opc+" maxFunc: "+cur.maxFunc+" stack_idx: "+cur.stack_idx);
    if (TTUtil.BOUNDSL(function_opc, cur.maxFunc + 1)) {
      cur.error = FTError.ErrorTag.INTERP_INVALID_REFERENCE;
      return;
    }
      /* Except for some old Apple fonts, all functions in a TrueType */
      /* font are defined in increasing order, starting from 0.  This */
      /* means that we normally have                                  */
      /*                                                              */
      /*    cur.maxFunc+1 == cur.numFDefs                             */
      /*    cur.FDefs[n].opc == n for n in 0..cur.maxFunc             */
      /*                                                              */
      /* If this isn't true, we need to look up the function table.   */

    def = cur.FDefs[function_opc];
    if (cur.maxFunc + 1 != cur.numFDefs || def.getOpc() != function_opc) {
        /* look up the FDefs table */
      int limit;

      def = cur.FDefs[defIdx];
      limit = defIdx + cur.numFDefs;
      while (defIdx < limit && def.getOpc() != function_opc) {
        defIdx++;
      }
      if (defIdx == limit) {
        cur.error = FTError.ErrorTag.INTERP_INVALID_REFERENCE;
        return;
      }
    }
................................................................................
    call_rec = cur.callStack[cur.callTop];
    call_rec.setCaller_range(cur.curRange.getVal());
    call_rec.setCaller_IP(cur.IP + 1);
    call_rec.setCur_count(1);
    call_rec.setCur_restart(def.getStart());
    call_rec.setCur_end(def.getEnd());
    cur.callTop++;
Debug(0, DebugTag.DBG_INTERP, TAG, "GotoCodeRange: "+def.getRange()+" start: "+def.getStart()+"!");
    cur.TTGotoCodeRange(TTInterpTags.CodeRange.getTableTag(def.getRange()), def.getStart());
    cur.step_ins = false;
    return;
  }

  /* =====================================================================
   * FDEF[]:       Function DEFinition
................................................................................
    rec = cur.FDefs[rec_idx];
    rec.setRange(cur.curRange.getVal());
    rec.setOpc(n);
    rec.setStart((cur.IP + 1));
    rec.setActive(true);
    rec.setInline_delta(false);
    rec.setSph_fdef_flags(0x0000);



    if (n > cur.maxFunc) {
      cur.maxFunc = n;
    }
      /* Now skip the whole function definition. */
      /* We don't allow nested IDEFS & FDEFs.    */
    while (cur.SkipCode() == true) {
      switch (cur.opcode) {
................................................................................
        case IDEF:    /* IDEF */
        case FDEF:    /* FDEF */
          cur.error = FTError.ErrorTag.INTERP_NESTED_DEFS;
          return;
        case ENDF:   /* ENDF */
          rec.setEnd(cur.IP);
Debug(0, DebugTag.DBG_INTERP, TAG, "rec: " + rec.toDebugString());



          return;
      }
    }
  }

  /* =====================================================================
   * ENDF[]:       END Function definition

Changes to aftttinterpreter/TTInstructionFuncGrp4.java.

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
   * =====================================================================
   */
  public void NPUSHB() {
    int length;
    int idx;

    length = cur.code[cur.IP + 1].getVal() & 0xFF;
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("NPUSHB: L: %d, cur.IP: %d", length, cur.IP));
    if (TTUtil.BOUNDS(length, cur.stackSize + 1 - cur.top)) {
      cur.error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
      return;
    }
    for (idx = 0; idx < length; idx++) {
      cur.stack[cur.stack_idx + idx] = cur.code[cur.IP + idx + 2].getVal() & 0xFF;
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("pushb: %d 0x%02x, new_top: %d ", idx, cur.stack[cur.stack_idx + idx], cur.new_top)+cur.code[cur.IP + idx]);







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
   * =====================================================================
   */
  public void NPUSHB() {
    int length;
    int idx;

    length = cur.code[cur.IP + 1].getVal() & 0xFF;
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("NPUSHB: length: %d, cur.IP: %d", length, cur.IP));
    if (TTUtil.BOUNDS(length, cur.stackSize + 1 - cur.top)) {
      cur.error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
      return;
    }
    for (idx = 0; idx < length; idx++) {
      cur.stack[cur.stack_idx + idx] = cur.code[cur.IP + idx + 2].getVal() & 0xFF;
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("pushb: %d 0x%02x, new_top: %d ", idx, cur.stack[cur.stack_idx + idx], cur.new_top)+cur.code[cur.IP + idx]);

Changes to aftttinterpreter/TTInstructionFuncGrp5.java.

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
...
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
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  /* =====================================================================
   * LT[]:         Less Than
   * Opcode range: 0x50
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void LT() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] < cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * LTEQ[]:       Less Than or EQual
   * Opcode range: 0x51
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void LTEQ() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] <= cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
  /* GT[]:         Greater Than
  /* Opcode range: 0x52
  /* Stack:        int32? int32? --> bool
  * =====================================================================
      */
  public void GT() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] > cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * GTEQ[]:       Greater Than or EQual
   * Opcode range: 0x53
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void GTEQ() {
    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("DO_GTEQ: %d >= %d", cur.stack[cur.stack_idx + 0], cur.stack[cur.stack_idx + 1]));
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] >= cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * EQ[]:         EQual
   * Opcode range: 0x54
   * Stack:        StkElt StkElt --> bool
   * =====================================================================
   */
  public void EQ() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] == cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * NEQ[]:        Not EQual
   * Opcode range: 0x55
   * Stack:        StkElt StkElt --> bool
   * =====================================================================
   */
  public void NEQ() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] != cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * ODD[]:        Is ODD
   * Opcode range: 0x56
   * Stack:        f26.6 --> bool
   * =====================================================================
   */
  public void ODD() {
    cur.stack[cur.stack_idx + 0] = (cur.render_funcs.curr_round_func.round(cur.stack[cur.stack_idx + 0], 0) & 127) == 64 ? 1 : 0;
  }

  /* =====================================================================
   * EVEN[]:       Is EVEN
   * Opcode range: 0x57
   * Stack:        f26.6 --> bool
   * =====================================================================
   */
  public void EVEN() {
    cur.stack[cur.stack_idx + 0] = (cur.render_funcs.curr_round_func.round(cur.stack[cur.stack_idx + 0], 0) & 127) == 0 ? 1 : 0;
  }

  /* =====================================================================
   * IF[]:         IF test
   * Opcode range: 0x58
   * Stack:        StkElt -->
   * =====================================================================
   */
  public void IF() {
    int nIfs;
    boolean Out;

    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("insIF: %d\n", cur.stack[cur.stack_idx + 0]));
    if (cur.stack[cur.stack_idx + 0] != 0) {
      return;
    }
    nIfs = 1;
    Out = false;
    do {
      if (cur.SkipCode() == false) {
        return;
................................................................................
  /* =====================================================================
   * AND[]:        logical AND
   * Opcode range: 0x5A
   * Stack:        uint32 uint32 --> uint32
   * =====================================================================
   */
  public void AND() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] != 0 && cur.stack[cur.stack_idx + 1] != 0) ? 1 : 0;
  }

  /* =====================================================================
   * OR[]:         logical OR
   * Opcode range: 0x5B
   * Stack:        uint32 uint32 --> uint32
   * =====================================================================
   */
  public void OR() {
    cur.stack[cur.stack_idx + 0] = (cur.stack[cur.stack_idx + 0] != 0 || cur.stack[cur.stack_idx + 1] != 0) ? 1 : 0;
  }

  /* =====================================================================
   * NOT[]:        logical NOT
   * Opcode range: 0x5C
   * Stack:        StkElt --> uint32
   * =====================================================================
   */
  public void NOT() {
    cur.stack[cur.stack_idx + 0] = cur.stack[cur.stack_idx + 0] == 0  ? 1 : 0;
  }

  /* =====================================================================
   * DELTAPn[]:    DELTA exceptions P1, P2, P3
   * Opcode range: 0x5D,0x71,0x72
   * Stack:        uint32 (2 * uint32)... -->
   * =====================================================================
................................................................................
  public void DELTAP() {
    int k;
    int nump;
    short A;
    int C;
    int B;

    Debug(0, DebugTag.DBG_INTERP, TAG, "insDELTAP");
    nump = cur.stack[cur.stack_idx + 0];   /* some points theoretically may occur more
                                     than once, thus UShort isn't enough */
    for (k = 1; k <= nump; k++) {
      if (cur.stack_idx < 2) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.ErrorTag.INTERP_TOO_FEW_ARGUMENTS;
        }
        cur.stack_idx = 0;
................................................................................
  /* =====================================================================
   * SDB[]:        Set Delta Base
   * Opcode range: 0x5E
   * Stack:        uint32 -->
   * =====================================================================
   */
  public void SDB() {
    cur.graphics_state.delta_base = (short)cur.stack[cur.stack_idx + 0];
  }

  /* =====================================================================
   * SDS[]:        Set Delta Shift
   * Opcode range: 0x5F
   * Stack:        uint32 -->
   * =====================================================================
   */
  public void SDS() {
    cur.graphics_state.delta_shift = (short)cur.stack[cur.stack_idx + 0];
  }

}







|









|









|









|
|









|









|









|









|












|
|







 







|









|









|







 







|
|







 







|









|



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
...
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
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  /* =====================================================================
   * LT[]:         Less Than
   * Opcode range: 0x50
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void LT() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] < cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * LTEQ[]:       Less Than or EQual
   * Opcode range: 0x51
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void LTEQ() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] <= cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
  /* GT[]:         Greater Than
  /* Opcode range: 0x52
  /* Stack:        int32? int32? --> bool
  * =====================================================================
      */
  public void GT() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] > cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * GTEQ[]:       Greater Than or EQual
   * Opcode range: 0x53
   * Stack:        int32? int32? --> bool
   * =====================================================================
   */
  public void GTEQ() {
    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("GTEQ: %d >= %d", cur.stack[cur.stack_idx + 0], cur.stack[cur.stack_idx + 1]));
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] >= cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * EQ[]:         EQual
   * Opcode range: 0x54
   * Stack:        StkElt StkElt --> bool
   * =====================================================================
   */
  public void EQ() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] == cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * NEQ[]:        Not EQual
   * Opcode range: 0x55
   * Stack:        StkElt StkElt --> bool
   * =====================================================================
   */
  public void NEQ() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] != cur.stack[cur.stack_idx + 1]) ? 1 : 0;
  }

  /* =====================================================================
   * ODD[]:        Is ODD
   * Opcode range: 0x56
   * Stack:        f26.6 --> bool
   * =====================================================================
   */
  public void ODD() {
    cur.stack[cur.stack_idx] = (cur.render_funcs.curr_round_func.round(cur.stack[cur.stack_idx], 0) & 127) == 64 ? 1 : 0;
  }

  /* =====================================================================
   * EVEN[]:       Is EVEN
   * Opcode range: 0x57
   * Stack:        f26.6 --> bool
   * =====================================================================
   */
  public void EVEN() {
    cur.stack[cur.stack_idx] = (cur.render_funcs.curr_round_func.round(cur.stack[cur.stack_idx], 0) & 127) == 0 ? 1 : 0;
  }

  /* =====================================================================
   * IF[]:         IF test
   * Opcode range: 0x58
   * Stack:        StkElt -->
   * =====================================================================
   */
  public void IF() {
    int nIfs;
    boolean Out;

    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("IF: %d\n", cur.stack[cur.stack_idx]));
    if (cur.stack[cur.stack_idx] != 0) {
      return;
    }
    nIfs = 1;
    Out = false;
    do {
      if (cur.SkipCode() == false) {
        return;
................................................................................
  /* =====================================================================
   * AND[]:        logical AND
   * Opcode range: 0x5A
   * Stack:        uint32 uint32 --> uint32
   * =====================================================================
   */
  public void AND() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] != 0 && cur.stack[cur.stack_idx + 1] != 0) ? 1 : 0;
  }

  /* =====================================================================
   * OR[]:         logical OR
   * Opcode range: 0x5B
   * Stack:        uint32 uint32 --> uint32
   * =====================================================================
   */
  public void OR() {
    cur.stack[cur.stack_idx] = (cur.stack[cur.stack_idx] != 0 || cur.stack[cur.stack_idx + 1] != 0) ? 1 : 0;
  }

  /* =====================================================================
   * NOT[]:        logical NOT
   * Opcode range: 0x5C
   * Stack:        StkElt --> uint32
   * =====================================================================
   */
  public void NOT() {
    cur.stack[cur.stack_idx] = cur.stack[cur.stack_idx] == 0  ? 1 : 0;
  }

  /* =====================================================================
   * DELTAPn[]:    DELTA exceptions P1, P2, P3
   * Opcode range: 0x5D,0x71,0x72
   * Stack:        uint32 (2 * uint32)... -->
   * =====================================================================
................................................................................
  public void DELTAP() {
    int k;
    int nump;
    short A;
    int C;
    int B;

    Debug(0, DebugTag.DBG_INTERP, TAG, "DELTAP");
    nump = cur.stack[cur.stack_idx];   /* some points theoretically may occur more
                                     than once, thus UShort isn't enough */
    for (k = 1; k <= nump; k++) {
      if (cur.stack_idx < 2) {
        if (cur.pedantic_hinting) {
          cur.error = FTError.ErrorTag.INTERP_TOO_FEW_ARGUMENTS;
        }
        cur.stack_idx = 0;
................................................................................
  /* =====================================================================
   * SDB[]:        Set Delta Base
   * Opcode range: 0x5E
   * Stack:        uint32 -->
   * =====================================================================
   */
  public void SDB() {
    cur.graphics_state.delta_base = (short)cur.stack[cur.stack_idx];
  }

  /* =====================================================================
   * SDS[]:        Set Delta Shift
   * Opcode range: 0x5F
   * Stack:        uint32 -->
   * =====================================================================
   */
  public void SDS() {
    cur.graphics_state.delta_shift = (short)cur.stack[cur.stack_idx];
  }

}

Changes to aftttinterpreter/TTInstructionFuncGrp8.java.

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
...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  /* =====================================================================
   * SCANCTRL[]:   SCAN ConTRoL
   * Opcode range: 0x85
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void SCANCTRL() {
    int A;

      /* Get Threshold */
    A = (cur.stack[cur.stack_idx + 0] & 0xFF);
    if (A == 0xFF) {
      cur.graphics_state.scan_control = true;
      return;
    } else {
      if ( A == 0 ) {
        cur.graphics_state.scan_control = false;
        return;
      }
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x100) != 0 && cur.tt_metrics.getPpem() <= A) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x200) != 0 && cur.tt_metrics.isRotated()) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x400) != 0 && cur.tt_metrics.isStretched()) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x800) != 0 && cur.tt_metrics.getPpem() > A) {
      cur.graphics_state.scan_control = false;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x1000) != 0 && cur.tt_metrics.isRotated()) {
      cur.graphics_state.scan_control = false;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x2000) != 0 && cur.tt_metrics.isStretched()) {
      cur.graphics_state.scan_control = false;
................................................................................
  /* =====================================================================
   * SCANTYPE[]:   SCAN TYPE
   * Opcode range: 0x8D
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void SCANTYPE() {
    if (cur.stack[cur.stack_idx + 0] >= 0) {
      cur.graphics_state.scan_type = (int)cur.stack[cur.stack_idx + 0];
    }
  }

  /* =====================================================================
   * INSTCTRL[]:   INSTruction ConTRoL
   * Opcode range: 0x8e
   * Stack:        int32 int32 -->







|


|
|



|




|








|







 







|
|







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
...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  /* =====================================================================
   * SCANCTRL[]:   SCAN ConTRoL
   * Opcode range: 0x85
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void SCANCTRL() {
    int threshold;

      /* Get Threshold */
    threshold = (cur.stack[cur.stack_idx + 0] & 0xFF);
    if (threshold == 0xFF) {
      cur.graphics_state.scan_control = true;
      return;
    } else {
      if (threshold == 0) {
        cur.graphics_state.scan_control = false;
        return;
      }
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x100) != 0 && cur.tt_metrics.getPpem() <= threshold) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x200) != 0 && cur.tt_metrics.isRotated()) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x400) != 0 && cur.tt_metrics.isStretched()) {
      cur.graphics_state.scan_control = true;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x800) != 0 && cur.tt_metrics.getPpem() > threshold) {
      cur.graphics_state.scan_control = false;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x1000) != 0 && cur.tt_metrics.isRotated()) {
      cur.graphics_state.scan_control = false;
    }
    if ((cur.stack[cur.stack_idx + 0] & 0x2000) != 0 && cur.tt_metrics.isStretched()) {
      cur.graphics_state.scan_control = false;
................................................................................
  /* =====================================================================
   * SCANTYPE[]:   SCAN TYPE
   * Opcode range: 0x8D
   * Stack:        uint32? -->
   * =====================================================================
   */
  public void SCANTYPE() {
    if (cur.stack[cur.stack_idx] >= 0) {
      cur.graphics_state.scan_type = cur.stack[cur.stack_idx];
    }
  }

  /* =====================================================================
   * INSTCTRL[]:   INSTruction ConTRoL
   * Opcode range: 0x8e
   * Stack:        int32 int32 -->

Changes to aftttinterpreter/TTInstructionFuncGrp9.java.

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
   */
  public void MDRP() {
    short point;
    int org_dist;
    int distance;
    int minimum_distance;

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

      org_dist = cur.funcDualproj(vec1.getX() - vec2.getX(), vec1.getY() - vec2.getY());
    } else {
      FTVectorRec vec1 = cur.zp1.getOrus()[cur.zp1.getOrus_idx() + point];
      FTVectorRec vec2 = cur.zp0.getOrus()[cur.zp1.getOrus_idx() + cur.graphics_state.rp0];

      Debug(0, DebugTag.DBG_INTERP, TAG, String.format("vec1: %d %d, vec2: %d %d\n", vec1.getX(), vec1.getY(), vec2.getX(), vec2.getY()));
      Debug(0, DebugTag.DBG_INTERP, TAG, String.format("x_scale: %d y_scale: %d", cur.metrics.getX_scale(), cur.metrics.getY_scale()));
      if (cur.metrics.getX_scale() == cur.metrics.getY_scale()) {
          /* this should be faster */
        org_dist = cur.render_funcs.curr_project_func.dualproject(vec1.getX() - vec2.getX(), vec1.getY() - vec2.getY());
        Debug(0, DebugTag.DBG_INTERP, TAG, String.format("d1: %d", org_dist));
        org_dist = TTUtil.FTMulFix(org_dist, cur.metrics.getX_scale());
        Debug(0, DebugTag.DBG_INTERP, TAG, String.format("d2: %d", org_dist));
      } else {
        FTVectorRec vec = new FTVectorRec();

        vec.setX(TTUtil.FTMulFix(vec1.getX() - vec2.getX(), cur.metrics.getX_scale()));
        vec.setY(TTUtil.FTMulFix(vec1.getY() - vec2.getY(), cur.metrics.getY_scale()));
        org_dist = cur.render_funcs.curr_project_func.dualproject(vec.getX(), vec.getY());
      }
    }
    Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist1: "+org_dist);
      /* single width cut-in test */
    if (FTCalc.FT_ABS(org_dist - cur.graphics_state.single_width_value) < cur.graphics_state.single_width_cutin) {
      if (org_dist >= 0) {
        org_dist = cur.graphics_state.single_width_value;
      } else {
        org_dist = -cur.graphics_state.single_width_value;
      }
    }
    Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist2: "+org_dist);
      /* round flag */
    if ((cur.opcode.getVal() & 4) != 0) {
      distance = cur.funcRound(org_dist, cur.tt_metrics.getCompensations()[cur.opcode.getVal() & 3]);
    } else {
      distance = cur.render_funcs.round_none.round(org_dist, cur.tt_metrics.getCompensations()[cur.opcode.getVal() & 3]);
    }
    Debug(0, DebugTag.DBG_INTERP, TAG, "distance1: "+distance);
      /* minimum distance flag */
    if ((cur.opcode.getVal() & 8) != 0) {
      if (org_dist >= 0) {
        if (distance < minimum_distance) {
          distance = minimum_distance;
        }
      } else {
        if (distance > -minimum_distance) {
          distance = -minimum_distance;
        }
      }
    }
    Debug(0, DebugTag.DBG_INTERP, TAG, "distance2: "+distance);
    Debug(0, DebugTag.DBG_INTERP, TAG, String.format("insMDRP 3: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.gep0: %d, cur.GS.gep1: %d", cur.graphics_state.rp0, cur.graphics_state.rp1, cur.graphics_state.gep0, cur.graphics_state.gep1));
      /* now move the point */
    org_dist = cur.funcProject(cur.zp1.getCurPoint_x(point) - cur.zp0.getCurPoint_x(cur.graphics_state.rp0),
        cur.zp1.getCurPoint_y(point) - cur.zp0.getCurPoint_y(cur.graphics_state.rp0));
    Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist3: "+org_dist);
    cur.render_funcs.curr_move_func.move(cur.zp1 , point,distance - org_dist);

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

  /* =====================================================================
   * PUSHW[abc]:   PUSH Words
   * Opcode range: 0xB8-0xBF
   * Stack:        --> int32...
   * =====================================================================
   */
  public void PUSHW() {
    int L;
    int K;

Debug(0, DebugTag.DBG_INTERP, TAG, "PUSHW");
    L = (cur.opcode.getVal() - 0xB8 + 1);
    if (TTUtil.BOUNDS(L, cur.stackSize + 1 - cur.top)) {
      cur.error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
      return;
    }
    cur.IP++;
    for (K = 0; K < L; K++) {
      cur.stack[cur.stack_idx + K] = TTInstructionFuncGrp4.GetShortIns(cur);
    }
    cur.step_ins = false;
  }

  /* =====================================================================
   * PUSHB[abc]:   PUSH Bytes
   * Opcode range: 0xB0-0xB7







|


|







 







|









|
|



|

|








|








|






|












|
|



|


|


|

|


|









|
|


|
|




|
|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
   */
  public void MDRP() {
    short point;
    int org_dist;
    int distance;
    int minimum_distance;

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

      org_dist = cur.funcDualproj(vec1.getX() - vec2.getX(), vec1.getY() - vec2.getY());
    } else {
      FTVectorRec vec1 = cur.zp1.getOrus()[cur.zp1.getOrus_idx() + point];
      FTVectorRec vec2 = cur.zp0.getOrus()[cur.zp1.getOrus_idx() + cur.graphics_state.rp0];

Debug(0, DebugTag.DBG_INTERP, TAG, String.format("vec1: %d %d, vec2: %d %d\n", vec1.getX(), vec1.getY(), vec2.getX(), vec2.getY()));
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("x_scale: %d y_scale: %d", cur.metrics.getX_scale(), cur.metrics.getY_scale()));
      if (cur.metrics.getX_scale() == cur.metrics.getY_scale()) {
          /* this should be faster */
        org_dist = cur.render_funcs.curr_project_func.dualproject(vec1.getX() - vec2.getX(), vec1.getY() - vec2.getY());
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("d1: %d", org_dist));
        org_dist = TTUtil.FTMulFix(org_dist, cur.metrics.getX_scale());
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("d2: %d", org_dist));
      } else {
        FTVectorRec vec = new FTVectorRec();

        vec.setX(TTUtil.FTMulFix(vec1.getX() - vec2.getX(), cur.metrics.getX_scale()));
        vec.setY(TTUtil.FTMulFix(vec1.getY() - vec2.getY(), cur.metrics.getY_scale()));
        org_dist = cur.render_funcs.curr_project_func.dualproject(vec.getX(), vec.getY());
      }
    }
Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist1: "+org_dist);
      /* single width cut-in test */
    if (FTCalc.FT_ABS(org_dist - cur.graphics_state.single_width_value) < cur.graphics_state.single_width_cutin) {
      if (org_dist >= 0) {
        org_dist = cur.graphics_state.single_width_value;
      } else {
        org_dist = -cur.graphics_state.single_width_value;
      }
    }
Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist2: "+org_dist);
      /* round flag */
    if ((cur.opcode.getVal() & 4) != 0) {
      distance = cur.funcRound(org_dist, cur.tt_metrics.getCompensations()[cur.opcode.getVal() & 3]);
    } else {
      distance = cur.render_funcs.round_none.round(org_dist, cur.tt_metrics.getCompensations()[cur.opcode.getVal() & 3]);
    }
Debug(0, DebugTag.DBG_INTERP, TAG, "distance1: "+distance);
      /* minimum distance flag */
    if ((cur.opcode.getVal() & 8) != 0) {
      if (org_dist >= 0) {
        if (distance < minimum_distance) {
          distance = minimum_distance;
        }
      } else {
        if (distance > -minimum_distance) {
          distance = -minimum_distance;
        }
      }
    }
Debug(0, DebugTag.DBG_INTERP, TAG, "distance2: "+distance);
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("MDRP 3: cur.GS.rp0: %d, cur.GS.rp1: %d, cur.GS.gep0: %d, cur.GS.gep1: %d", cur.graphics_state.rp0, cur.graphics_state.rp1, cur.graphics_state.gep0, cur.graphics_state.gep1));
      /* now move the point */
    org_dist = cur.funcProject(cur.zp1.getCurPoint_x(point) - cur.zp0.getCurPoint_x(cur.graphics_state.rp0),
        cur.zp1.getCurPoint_y(point) - cur.zp0.getCurPoint_y(cur.graphics_state.rp0));
Debug(0, DebugTag.DBG_INTERP, TAG, "org_dist3: "+org_dist);
    cur.render_funcs.curr_move_func.move(cur.zp1 , point,distance - org_dist);

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

  /* =====================================================================
   * PUSHW[abc]:   PUSH Words
   * Opcode range: 0xB8-0xBF
   * Stack:        --> int32...
   * =====================================================================
   */
  public void PUSHW() {
    int length;
    int idx;

Debug(0, DebugTag.DBG_INTERP, TAG, "PUSHW");
    length = (cur.opcode.getVal() - 0xB8 + 1);
    if (TTUtil.BOUNDS(length, cur.stackSize + 1 - cur.top)) {
      cur.error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
      return;
    }
    cur.IP++;
    for (idx = 0; idx < length; idx++) {
      cur.stack[cur.stack_idx + idx] = TTInstructionFuncGrp4.GetShortIns(cur);
    }
    cur.step_ins = false;
  }

  /* =====================================================================
   * PUSHB[abc]:   PUSH Bytes
   * Opcode range: 0xB0-0xB7

Changes to aftttinterpreter/TTOpCode.java.

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
...
345
346
347
348
349
350
351



352

353
354
355
356
357
358
359
    MIRP_24(248, TTUtil.Pack(2, 0), 1, "MIRP[24]", "Move Indirect Relative Point 24"),
    MIRP_25(249, TTUtil.Pack(2, 0), 1, "MIRP[25]", "Move Indirect Relative Point 25"),
    MIRP_26(250, TTUtil.Pack(2, 0), 1, "MIRP[26]", "Move Indirect Relative Point 26"),
    MIRP_27(251, TTUtil.Pack(2, 0), 1, "MIRP[27]", "Move Indirect Relative Point 27"),
    MIRP_28(252, TTUtil.Pack(2, 0), 1, "MIRP[28]", "Move Indirect Relative Point 28"),
    MIRP_29(253, TTUtil.Pack(2, 0), 1, "MIRP[29]", "Move Indirect Relative Point 29"),
    MIRP_30(254, TTUtil.Pack(2, 0), 1, "MIRP[30]", "Move Indirect Relative Point 30"),
    MIRP_31(255, TTUtil.Pack(2, 0), 1, "MIRP[31]", "Move Indirect Relative Point 31");


    private int val;
    private byte push_count;
    private int opcode_length;
    private String str;
    private String description;
    private static SparseArray<OpCode> tagToOpCodeMapping;
    public static OpCode getTableTag(int i) {
      if (tagToOpCodeMapping == null) {
        initMapping();
      }



      return tagToOpCodeMapping.get(i);

    }
    private static void initMapping() {
      tagToOpCodeMapping = new SparseArray<OpCode>();
      for (OpCode t : values()) {
        tagToOpCodeMapping.put(t.val, t);
      }
    }
................................................................................
    public int getVal() {
      return val;
    }
    public int getPushCount() {
      return push_count;
    }
    public String toString() {



      return String.format("opcode: 0x%02x %d ", val, val)+str+": \""+description+"\"\n..."+String.format(" length: %d", opcode_length)+String.format(" push_count: 0x%02x", push_count);

    }
  }

  /* ==================== TTOpcode ================================== */
  public TTOpCode()
  {
    oid++;







|
>











>
>
>
|
>







 







>
>
>
|
>







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
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    MIRP_24(248, TTUtil.Pack(2, 0), 1, "MIRP[24]", "Move Indirect Relative Point 24"),
    MIRP_25(249, TTUtil.Pack(2, 0), 1, "MIRP[25]", "Move Indirect Relative Point 25"),
    MIRP_26(250, TTUtil.Pack(2, 0), 1, "MIRP[26]", "Move Indirect Relative Point 26"),
    MIRP_27(251, TTUtil.Pack(2, 0), 1, "MIRP[27]", "Move Indirect Relative Point 27"),
    MIRP_28(252, TTUtil.Pack(2, 0), 1, "MIRP[28]", "Move Indirect Relative Point 28"),
    MIRP_29(253, TTUtil.Pack(2, 0), 1, "MIRP[29]", "Move Indirect Relative Point 29"),
    MIRP_30(254, TTUtil.Pack(2, 0), 1, "MIRP[30]", "Move Indirect Relative Point 30"),
    MIRP_31(255, TTUtil.Pack(2, 0), 1, "MIRP[31]", "Move Indirect Relative Point 31"),
    UNKNOWN(256, TTUtil.Pack(2, 0), 1, "UNKNOWN", "UNKNOWN instruction");

    private int val;
    private byte push_count;
    private int opcode_length;
    private String str;
    private String description;
    private static SparseArray<OpCode> tagToOpCodeMapping;
    public static OpCode getTableTag(int i) {
      if (tagToOpCodeMapping == null) {
        initMapping();
      }
      if (i <0 || i > 255) {
        return UNKNOWN;
      } else {
        return tagToOpCodeMapping.get(i);
      }
    }
    private static void initMapping() {
      tagToOpCodeMapping = new SparseArray<OpCode>();
      for (OpCode t : values()) {
        tagToOpCodeMapping.put(t.val, t);
      }
    }
................................................................................
    public int getVal() {
      return val;
    }
    public int getPushCount() {
      return push_count;
    }
    public String toString() {
      if (val >= 0 && val < 256) {
        return String.format("opcode: 0x%02x %d ", val, val) + str + ": \"" + description + "\"\n..." + String.format(" length: %d", opcode_length) + String.format(" push_count: 0x%02x", push_count);
      } else {
        return String.format("opcode: 0x%02x %d ", val, val) + "no opcode";
      }
    }
  }

  /* ==================== TTOpcode ================================== */
  public TTOpCode()
  {
    oid++;

Changes to aftttinterpreter/TTRunInstructions.java.

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        length = 2 - length * (code[IP + 1].getVal());
      }
      if (IP + length > codeSize) {
        return LErrorCodeOverflow();
      }
        /* First, let's check for empty stack and overflow */
      stack_idx = top - (opcode.getPushCount() >> 4);
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("stack_idx: %d top: %d stack[stack_idx]: %s", stack_idx, top, TTOpCode.OpCode.getTableTag(stack[stack_idx]).toString()));
        /* `args' is the top of the stack once arguments have been popped. */
        /* One can also interpret it as the index of the last argument.    */
      if (stack_idx < 0) {
        if (pedantic_hinting) {
          error = FTError.ErrorTag.INTERP_TOO_FEW_ARGUMENTS;
          return LError();
        }
................................................................................
        }
        stack_idx = 0;
      }
      new_top = stack_idx + (opcode.getPushCount() & 15);
        /* `new_top' is the new top of the stack, after the instruction's */
        /* execution.  `top' will be set to `new_top' after the `switch'  */
        /* statement.                                                     */
Debug(0, DebugTag.DBG_INTERP, TAG, "Stack: new_top: "+new_top+" stackSize: "+stackSize+"!");
      if (new_top > stackSize) {
        error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
        return LError();
      }
      step_ins = true;
      error = FTError.ErrorTag.ERR_OK;
      {







|







 







|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        length = 2 - length * (code[IP + 1].getVal());
      }
      if (IP + length > codeSize) {
        return LErrorCodeOverflow();
      }
        /* First, let's check for empty stack and overflow */
      stack_idx = top - (opcode.getPushCount() >> 4);
Debug(0, DebugTag.DBG_INTERP, TAG, String.format("stack_idx: %d top: %d stack[stack_idx]: %d 0x%08x", stack_idx, top, stack[stack_idx], stack[stack_idx]));
        /* `args' is the top of the stack once arguments have been popped. */
        /* One can also interpret it as the index of the last argument.    */
      if (stack_idx < 0) {
        if (pedantic_hinting) {
          error = FTError.ErrorTag.INTERP_TOO_FEW_ARGUMENTS;
          return LError();
        }
................................................................................
        }
        stack_idx = 0;
      }
      new_top = stack_idx + (opcode.getPushCount() & 15);
        /* `new_top' is the new top of the stack, after the instruction's */
        /* execution.  `top' will be set to `new_top' after the `switch'  */
        /* statement.                                                     */
//Debug(0, DebugTag.DBG_INTERP, TAG, "Stack: new_top: "+new_top+" stackSize: "+stackSize+"!");
      if (new_top > stackSize) {
        error = FTError.ErrorTag.INTERP_STACK_OVERFLOW;
        return LError();
      }
      step_ins = true;
      error = FTError.ErrorTag.ERR_OK;
      {

Changes to aftutil/FTDebug.java.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
59
60
61
62
63
64
65

66
67
68
69
70
71
72
  private static String TAG = "FTDebug";

  public enum DebugTag {
    DBG_BASE(1, 0, true, "DBG_BASE"),
    DBG_CACHE(2, 0, true, "DBG_CACHE"),
    DBG_CMAP(3, 0, true, "DBG_CMAP"),
    DBG_INIT(4, 2, true, "DBG_INIT"),
    DBG_INTERP(5, 0, true, "DBG_INTERP"),
    DBG_LIBRARY(6, 0, true, "DBG_LIBRARY"),
    DBG_LOAD_FACE(7, 0, true, "DBG_LOAD_FACE"),
    DBG_LOAD_GLYPH(8, 0, true, "DBG_LOAD_GLYPH"),
    DBG_RENDER(9, 0, true, "DBG_RENDER");

    private int val;
    private int level;
................................................................................
      this.val = val;
      this.level = level;
      this.dbgIsOn = isOn;
      this.str = str;
    }
    public boolean isOn() { return dbgIsOn; }
    public int level() { return level; }

    public int getVal() {
        return val;
      }
    public String getDescription() {
        return str;
      }
  }







|







 







>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  private static String TAG = "FTDebug";

  public enum DebugTag {
    DBG_BASE(1, 0, true, "DBG_BASE"),
    DBG_CACHE(2, 0, true, "DBG_CACHE"),
    DBG_CMAP(3, 0, true, "DBG_CMAP"),
    DBG_INIT(4, 2, true, "DBG_INIT"),
    DBG_INTERP(5, 2, true, "DBG_INTERP"),
    DBG_LIBRARY(6, 0, true, "DBG_LIBRARY"),
    DBG_LOAD_FACE(7, 0, true, "DBG_LOAD_FACE"),
    DBG_LOAD_GLYPH(8, 0, true, "DBG_LOAD_GLYPH"),
    DBG_RENDER(9, 0, true, "DBG_RENDER");

    private int val;
    private int level;
................................................................................
      this.val = val;
      this.level = level;
      this.dbgIsOn = isOn;
      this.str = str;
    }
    public boolean isOn() { return dbgIsOn; }
    public int level() { return level; }
    public void setLevel(int level) { this.level = level; }
    public int getVal() {
        return val;
      }
    public String getDescription() {
        return str;
      }
  }