OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [awt/] [font/] [autofit/] [GlyphHints.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* GlyphHints.java -- Data and methods for actual hinting
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.awt.font.autofit;
40
 
41
import gnu.java.awt.font.FontDelegate;
42
import gnu.java.awt.font.opentype.truetype.Fixed;
43
import gnu.java.awt.font.opentype.truetype.Point;
44
import gnu.java.awt.font.opentype.truetype.Zone;
45
 
46
/**
47
 * The data and methods used for the actual hinting process.
48
 */
49
class GlyphHints
50
  implements Constants
51
{
52
 
53
  int xScale;
54
  int xDelta;
55
  int yScale;
56
  int yDelta;
57
 
58
  AxisHints[] axis;
59
 
60
  Point[] points;
61
  int numPoints;
62
  int maxPoints;
63
 
64
  Point[] contours;
65
  int numContours;
66
  int maxContours;
67
 
68
  ScriptMetrics metrics;
69
 
70
  int flags;
71
 
72
  GlyphHints()
73
  {
74
    axis = new AxisHints[Constants.DIMENSION_MAX];
75
    axis[Constants.DIMENSION_VERT] = new AxisHints();
76
    axis[Constants.DIMENSION_HORZ] = new AxisHints();
77
 
78
    xScale = Fixed.ONE;
79
    yScale = Fixed.ONE;
80
  }
81
 
82
  void rescale(ScriptMetrics m)
83
  {
84
    metrics = m;
85
    // TODO: Copy scalerFlags.
86
  }
87
 
88
  void reload(Zone outline)
89
  {
90
    numPoints = 0;
91
    numContours = 0;
92
    axis[0].numSegments = 0;
93
    axis[0].numEdges = 0;
94
    axis[1].numSegments = 0;
95
    axis[1].numEdges = 0;
96
 
97
    // Create/reallocate the contours array.
98
    int newMax = outline.getNumContours();
99
    if (newMax > maxContours || contours == null)
100
      {
101
        newMax = (newMax + 3) & ~3; // Taken from afhints.c .
102
        Point[] newContours = new Point[newMax];
103
        if (contours != null)
104
          {
105
            System.arraycopy(contours, 0, newContours, 0, maxContours);
106
          }
107
        contours = newContours;
108
        maxContours = newMax;
109
      }
110
 
111
    // Create/reallocate the points array.
112
    newMax = outline.getSize() + 2;
113
    if (newMax > maxPoints || points == null)
114
      {
115
        newMax = (newMax + 2 + 7) & ~7; // Taken from afhints.c .
116
        Point[] newPoints = new Point[newMax];
117
        if (points != null)
118
          {
119
            System.arraycopy(points, 0, newPoints, 0, maxPoints);
120
          }
121
        points = newPoints;
122
        maxPoints = newMax;
123
      }
124
 
125
    numPoints = outline.getSize() - 4; // 4 phantom points.
126
    numContours = outline.getNumContours();
127
 
128
    // Set major direction. We don't handle Type 1 fonts yet.
129
    axis[DIMENSION_HORZ].majorDir = DIR_UP;
130
    axis[DIMENSION_VERT].majorDir = DIR_LEFT;
131
 
132
    // TODO: Freetype seems to scale and translate the glyph at that point.
133
    // I suppose that this is not really needed.
134
    // The scales are scaling from font units to 1/64 device pixels.
135
    xScale = Fixed.valueOf16(outline.scaleX * 64);
136
    yScale = Fixed.valueOf16(outline.scaleY * 64);
137
 
138
    // FIXME: What is that xDelta and yDelta used for?
139
    System.arraycopy(outline.getPoints(), 0, points, 0, numPoints);
140
 
141
    // Setup prev and next and contours array.
142
    // TODO: Probably cache this.
143
    contours = new Point[numContours];
144
    Point currentContour = points[0];
145
    for (int i = 0, cIndex = 0; i < numPoints; i++)
146
      {
147
        // Start new contour when the last point has been a contour end.
148
        if (outline.isContourEnd(i))
149
          {
150
            // Connect the contour end point to the start point.
151
            points[i].setNext(currentContour);
152
            currentContour.setPrev(points[i]);
153
            contours[cIndex] = currentContour;
154
            cIndex++;
155
            currentContour = i < numPoints - 1 ? points[i + 1] : null;
156
          }
157
        else
158
          {
159
            // Connect the current and the previous point.
160
            points[i].setNext(points[i + 1]);
161
            points[i + 1].setPrev(points[i]);
162
          }
163
      }
164
    // Compute directions of in and out vectors of all points as well
165
    // as the weak point flag.
166
    for (int i = 0; i < numPoints; i++)
167
      {
168
        // Compute in and out dir.
169
        Point p = points[i];
170
        Point prev = p.getPrev();
171
        int inX = p.getOrigX() - prev.getOrigX();
172
        int inY = p.getOrigY() - prev.getOrigY();
173
        p.setInDir(Utils.computeDirection(inX, inY));
174
        Point next = p.getNext();
175
        int outX = next.getOrigX() - p.getOrigX();
176
        int outY = next.getOrigY() - p.getOrigY();
177
        p.setOutDir(Utils.computeDirection(outX, outY));
178
 
179
        if (p.isControlPoint())
180
          {
181
            setWeakPoint(p);
182
          }
183
        else if (p.getOutDir() == p.getInDir())
184
          {
185
            if (p.getOutDir() != DIR_NONE)
186
              setWeakPoint(p);
187
            else
188
              {
189
                int angleIn = Utils.atan(inY, inX);
190
                int angleOut = Utils.atan(outY, outX);
191
                int delta = Utils.angleDiff(angleIn, angleOut);
192
                if (delta < 2 && delta > -2)
193
                  setWeakPoint(p);
194
              }
195
          }
196
        else if (p.getInDir() == - p.getOutDir())
197
          {
198
            setWeakPoint(p);
199
          }
200
      }
201
    computeInflectionPoints();
202
  }
203
 
204
  private void setWeakPoint(Point p)
205
  {
206
    p.setFlags((byte) (p.getFlags() | Point.FLAG_WEAK_INTERPOLATION));
207
  }
208
 
209
  /**
210
   * Computes the inflection points for a glyph.
211
   */
212
  private void computeInflectionPoints()
213
  {
214
    // Do each contour separately.
215
    contours : for (int c = 0; c < contours.length; c++)
216
      {
217
        Point point = contours[c];
218
        Point first = point;
219
        Point start = point;
220
        Point end = point;
221
        do
222
          {
223
            end = end.getNext();
224
            if (end == first)
225
              continue contours;
226
          } while (end.getOrigX() == first.getOrigX()
227
                   && end.getOrigY() == first.getOrigY());
228
 
229
        // Extend segment start whenever possible.
230
        Point before = start;
231
        int angleIn;
232
        int angleSeg = Utils.atan(end.getOrigX() - start.getOrigX(),
233
                                  end.getOrigY() - start.getOrigY());
234
        do
235
          {
236
            do
237
              {
238
                start = before;
239
                before = before.getPrev();
240
                if (before == first)
241
                  continue contours;
242
              } while (before.getOrigX() == start.getOrigX()
243
                       && before.getOrigY() == start.getOrigY());
244
            angleIn = Utils.atan(start.getOrigX() - before.getOrigX(),
245
                                 start.getOrigY() - before.getOrigY());
246
          } while (angleIn == angleSeg);
247
 
248
        first = start;
249
        int diffIn = Utils.angleDiff(angleIn, angleSeg);
250
        // Now, process all segments in the contour.
251
        Point after;
252
        boolean finished = false;
253
        int angleOut, diffOut;
254
        do
255
          {
256
            // First, extend the current segment's end whenever possible.
257
            after = end;
258
            do
259
              {
260
                do
261
                  {
262
                    end = after;
263
                    after = after.getNext();
264
                    if (after == first)
265
                      finished = true;
266
                  } while (end.getOrigX() == after.getOrigX()
267
                           && end.getOrigY() == after.getOrigY());
268
                angleOut = Utils.atan(after.getOrigX() - end.getOrigX(),
269
                                      after.getOrigY() - end.getOrigY());
270
              } while (angleOut == angleSeg);
271
            diffOut = Utils.angleDiff(angleSeg, angleOut);
272
            if ((diffIn ^ diffOut) < 0)
273
              {
274
                // diffIn and diffOut have different signs, we have
275
                // inflection points here.
276
                do
277
                  {
278
                    start.addFlags(Point.FLAG_INFLECTION);
279
                    start = start.getNext();
280
                  } while (start != end);
281
                start.addFlags(Point.FLAG_INFLECTION);
282
              }
283
            start = end;
284
            end = after;
285
            angleSeg = angleOut;
286
            diffIn = diffOut;
287
          } while (! finished);
288
      }
289
  }
290
 
291
  boolean doHorizontal()
292
  {
293
    return (flags & FontDelegate.FLAG_NO_HINT_HORIZONTAL) == 0;
294
  }
295
 
296
  boolean doVertical()
297
  {
298
    return (flags & FontDelegate.FLAG_NO_HINT_VERTICAL) == 0;
299
  }
300
 
301
  void alignWeakPoints(int dim)
302
  {
303
    short touchFlag;
304
    Point point;
305
    // PASS 1 : Move segments to edge positions.
306
    if (dim == DIMENSION_HORZ)
307
      {
308
        touchFlag = Point.FLAG_DONE_X;
309
        for (int p = 0; p < numPoints; p++)
310
          {
311
            point = points[p];
312
            point.setU(point.getX());
313
            point.setV(point.getScaledX());
314
          }
315
      }
316
    else
317
      {
318
        touchFlag = Point.FLAG_DONE_Y;
319
        for (int p = 0; p < numPoints; p++)
320
          {
321
            point = points[p];
322
            point.setU(point.getY());
323
            point.setV(point.getScaledY());
324
          }
325
      }
326
    point = points[0];
327
    for (int c = 0; c < numContours; c++)
328
      {
329
        point = contours[c];
330
        int idx = getPointIndex(point);
331
        Point endPoint = point.getPrev();
332
        int endIdx = getPointIndex(endPoint);
333
        int firstIdx = idx;
334
        while (idx <=  endIdx
335
            && (point.getFlags() & touchFlag) == 0)
336
          {
337
            idx++;
338
            point = points[idx];
339
          }
340
        if (idx <= endIdx)
341
          {
342
            int firstTouched = idx;
343
            int curTouched = idx;
344
            idx++;
345
            point = points[idx];
346
            while (idx <= endIdx)
347
              {
348
                if ((point.getFlags() & touchFlag) != 0)
349
                  {
350
                    // We found two successive touch points. We interpolate
351
                    // all contour points between them.
352
                    iupInterp(curTouched + 1, idx - 1, curTouched, idx);
353
                    curTouched = idx;
354
                  }
355
                idx++;
356
                point = points[idx];
357
              }
358
            if (curTouched == firstTouched)
359
              {
360
                // This is a special case: Only one point was touched in the
361
                // contour. We thus simply shift the whole contour.
362
                iupShift(firstIdx, endIdx, curTouched);
363
              }
364
            else
365
              {
366
                // Now interpolate after the last touched point to the end
367
                // of the contour.
368
                iupInterp(curTouched + 1, endIdx, curTouched, firstTouched);
369
                // If the first contour point isn't touched, interpolate
370
                // from the contour start to the first touched point.
371
                if (firstTouched > 0)
372
                  {
373
                    iupInterp(firstIdx, firstTouched - 1, curTouched,
374
                              firstTouched);
375
                  }
376
              }
377
          }
378
      }
379
    // Now store the values back.
380
    if (dim == DIMENSION_HORZ)
381
      {
382
        for (int p = 0; p < numPoints; p++)
383
          {
384
            point = points[p];
385
            point.setX(point.getU());
386
          }
387
      }
388
    else
389
      {
390
        for (int p = 0; p < numPoints; p++)
391
          {
392
            point = points[p];
393
            point.setY(point.getU());
394
          }
395
      }
396
  }
397
 
398
  private void iupShift(int p1, int p2, int ref)
399
  {
400
    int delta = points[ref].getU() - points[ref].getV();
401
    for (int p = p1; p < ref; p++)
402
      {
403
        points[p].setU(points[p].getV() + delta);
404
      }
405
    for (int p = ref + 1; p <= p2; p++)
406
      {
407
        points[p].setU(points[p].getV() + delta);
408
      }
409
  }
410
 
411
  private void iupInterp(int p1, int p2, int ref1, int ref2)
412
  {
413
    int v1 = points[ref1].getV();
414
    int v2 = points[ref2].getV();
415
    int d1 = points[ref1].getU() - v1;
416
    int d2 = points[ref2].getU() - v2;
417
    if (p1 > p2)
418
      return;
419
    if (v1 == v2)
420
      {
421
        for (int p = p1; p <= p2; p++)
422
          {
423
            int u = points[p].getV();
424
            if (u <= v1)
425
              u += d1;
426
            else
427
              u += d2;
428
            points[p].setU(u);
429
          }
430
      }
431
    else if (v1 < v2)
432
      {
433
        for (int p = p1; p <= p2; p++)
434
          {
435
            int u = points[p].getV();
436
            if (u <= v1)
437
              u += d1;
438
            else if (u >= v2)
439
              u += d2;
440
            else
441
              {
442
                u = points[ref1].getU() + Utils.mulDiv(u - v1,
443
                                                       points[ref2].getU()
444
                                                       - points[ref1].getU(),
445
                                                       v2 - v1);
446
              }
447
            points[p].setU(u);
448
          }
449
      }
450
    else
451
      {
452
        for (int p = p1; p <= p2; p++)
453
          {
454
            int u = points[p].getV();
455
            if (u <= v2)
456
              u += d2;
457
            else if (u >= v1)
458
              u += d1;
459
            else
460
              {
461
                u = points[ref1].getU() + Utils.mulDiv(u - v1,
462
                                                       points[ref2].getU()
463
                                                       - points[ref1].getU(),
464
                                                       v2 - v1);
465
              }
466
            points[p].setU(u);
467
          }
468
      }
469
  }
470
 
471
  void alignStrongPoints(int dim)
472
  {
473
    AxisHints ax = axis[dim];
474
    Edge[] edges = ax.edges;
475
    int numEdges = ax.numEdges;
476
    short touchFlag;
477
    if (dim == DIMENSION_HORZ)
478
      touchFlag = Point.FLAG_DONE_X;
479
    else
480
      touchFlag = Point.FLAG_DONE_Y;
481
 
482
    if (numEdges > 0)
483
      {
484
        for (int p = 0; p < numPoints; p++)
485
          {
486
            Point point = points[p];
487
            if ((point.getFlags() & touchFlag) != 0)
488
              continue;
489
            // If this point is a candidate for weak interpolation, we
490
            // interpolate it after all strong points have been processed.
491
            if ((point.getFlags() & Point.FLAG_WEAK_INTERPOLATION) != 0
492
                && (point.getFlags() & Point.FLAG_INFLECTION) == 0)
493
              continue;
494
 
495
            int u, ou, fu, delta;
496
            if (dim == DIMENSION_VERT)
497
              {
498
                u = point.getOrigY();
499
                ou = point.getScaledY();
500
              }
501
            else
502
              {
503
                u = point.getOrigX();
504
                ou = point.getScaledX();
505
              }
506
            fu = u;
507
            // Is the point before the first edge?
508
            Edge edge = edges[0];
509
            // Inversed vertical dimension.
510
            delta = edge.fpos - u;
511
            if (delta >= 0)
512
              {
513
                u = edge.pos - (edge.opos - ou);
514
                storePoint(point, u, dim, touchFlag);
515
              }
516
            else
517
              {
518
                // Is the point after the last edge?
519
                edge = edges[numEdges - 1];
520
                delta = u - edge.fpos;
521
                if (delta >= 0)
522
                  {
523
                    u = edge.pos + (ou - edge.opos);
524
                    storePoint(point, u, dim, touchFlag);
525
                  }
526
                else
527
                  {
528
                    // Find enclosing edges.
529
                    int min = 0;
530
                    int max = numEdges;
531
                    int mid, fpos;
532
                    boolean found = false;
533
                    while (min < max)
534
                      {
535
                        mid = (max + min) / 2;
536
                        edge = edges[mid];
537
                        fpos = edge.fpos;
538
                        if (u < fpos)
539
                          max = mid;
540
                        else if (u > fpos)
541
                          min = mid + 1;
542
                        else
543
                          {
544
                            // Directly on the edge.
545
                            u = edge.pos;
546
                            storePoint(point, u, dim, touchFlag);
547
                            found = true;
548
                            break;
549
                          }
550
                      }
551
                    if (! found)
552
                      {
553
                        Edge before = edges[min - 1];
554
                        Edge after = edges[min];
555
                        if (before.scale == 0)
556
                          {
557
                            before.scale = Fixed.div16(after.pos - before.pos,
558
                                                     after.fpos - before.fpos);
559
                          }
560
                        u = before.pos + Fixed.mul16(fu - before.fpos,
561
                                                     before.scale);
562
                      }
563
                    storePoint(point, u, dim, touchFlag);
564
                  }
565
              }
566
          }
567
      }
568
  }
569
 
570
  private void storePoint(Point p, int u, int dim, short touchFlag)
571
  {
572
    if (dim == DIMENSION_HORZ)
573
      p.setX(u);
574
    else
575
      p.setY(u);
576
    p.addFlags(touchFlag);
577
  }
578
 
579
  void alignEdgePoints(int dim)
580
  {
581
    AxisHints ax = axis[dim];
582
    Edge[] edges = ax.edges;
583
    int numEdges = ax.numEdges;
584
    for (int e = 0; e < numEdges; e++)
585
      {
586
        Edge edge = edges[e];
587
        Segment seg = edge.first;
588
        do
589
          {
590
            Point point = seg.first;
591
            while (true)
592
              {
593
                if (dim == DIMENSION_HORZ)
594
                  {
595
                    point.setX(edge.pos);
596
                    point.addFlags(Point.FLAG_DONE_X);
597
                  }
598
                else
599
                  {
600
                    point.setY(edge.pos);
601
                    point.addFlags(Point.FLAG_DONE_Y);
602
                  }
603
                if (point == seg.last)
604
                  break;
605
                point = point.getNext();
606
              }
607
            seg = seg.edgeNext;
608
          } while (seg != edge.first);
609
      }
610
  }
611
 
612
  private int getPointIndex(Point p)
613
  {
614
    int idx = -1;
615
    for (int i = 0; i < numPoints; i++)
616
      {
617
        if (p == points[i])
618
          {
619
            idx = i;
620
            break;
621
          }
622
      }
623
    return idx;
624
  }
625
 
626
  public boolean doAlignEdgePoints()
627
  {
628
    return (flags & FontDelegate.FLAG_NO_HINT_EDGE_POINTS) == 0;
629
  }
630
 
631
  public boolean doAlignStrongPoints()
632
  {
633
    return (flags & FontDelegate.FLAG_NO_HINT_STRONG_POINTS) == 0;
634
  }
635
 
636
  public boolean doAlignWeakPoints()
637
  {
638
    return (flags & FontDelegate.FLAG_NO_HINT_WEAK_POINTS) == 0;
639
  }
640
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.