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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* ZonePathIterator.java -- A PathIterator over glyph zones.
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
package gnu.java.awt.font.opentype.truetype;
39
 
40
import java.awt.geom.PathIterator;
41
 
42
 
43
/**
44
 * A PathIterator that enumerates the non-phantom points in a zone.
45
 *
46
 * <p><b>Lack of thread safety:</b> Instances of this class are
47
 * <i>not</i> safe to access from multiple concurrent threads.
48
 *
49
 * @see Zone
50
 *
51
 * @author Sascha Brawer (brawer@dandelis.ch)
52
 */
53
final class ZonePathIterator
54
  implements PathIterator
55
{
56
  /**
57
   * If <code>state</code> has this value, <code>currentSegment</code>
58
   * will emit a <code>SEG_LINETO</code> or <code>SEG_QUADTO</code> segment
59
   * to the current point. For a discussion of subtleties of on-curve
60
   * and off-curve points, please refer to the documentation for
61
   * {@link #getSegment}.
62
   */
63
  private static final int EMIT_SEGMENT = 0;
64
 
65
 
66
  /**
67
   * If <code>state</code> has this value, <code>currentSegment</code>
68
   * will emit a <code>SEG_CLOSE</code> in order to close the sub-path
69
   * for the current contour.
70
   */
71
  private static final int EMIT_CLOSE = 1;
72
 
73
 
74
  /**
75
   * If <code>state</code> has this value, <code>currentSegment</code>
76
   * will emit a <code>SEG_MOVETO</code> segment to the first point in
77
   * the current contour. If the first point is off-curve, a suitable
78
   * on-curve point is calculated.
79
   *
80
   * @see #getStartSegment
81
   */
82
  private static final int EMIT_MOVETO = 2;
83
 
84
 
85
  /**
86
   * The state of the iterator, which is one of
87
   * <code>EMIT_SEGMENT</code>, <code>EMIT_CLOSE</code>, or
88
   * <code>EMIT_MOVETO</code>.
89
   */
90
  private int state;
91
 
92
 
93
 
94
  /**
95
   * The zone whose segments are enumerated by this iterator.
96
   */
97
  private Zone zone;
98
 
99
 
100
  /**
101
   * The total number of points in the zone, not including the four
102
   * phantom points at its end.
103
   */
104
  private int numPoints;
105
 
106
 
107
  /**
108
   * The number of the current point.
109
   */
110
  private int curPoint;
111
 
112
 
113
  /**
114
   * The number of the first point in the current contour.
115
   */
116
  private int contourStart;
117
 
118
 
119
  private int type;
120
 
121
  /**
122
   * Constructs a ZonePathIterator for the specified zone.
123
   *
124
   * @param zone the zone whose segments will be enumerated
125
   * by this iterator.
126
   */
127
  ZonePathIterator(Zone zone, int t)
128
  {
129
    this.zone = zone;
130
    type = t;
131
    numPoints = zone.getSize() - /* four phantom points */ 4;
132
 
133
    // The first segment that needs to be emitted is a SEG_MOVETO.
134
    state = EMIT_MOVETO;
135
  }
136
 
137
 
138
  /**
139
   * Returns the winding rule. TrueType glyphs always use the non-zero
140
   * winding rule, so this method will always return {@link
141
   * PathIterator#WIND_NON_ZERO}.
142
   */
143
  public int getWindingRule()
144
  {
145
    return PathIterator.WIND_NON_ZERO;
146
  }
147
 
148
 
149
 
150
  public boolean isDone()
151
  {
152
    return (state != EMIT_CLOSE) && (curPoint >= numPoints);
153
  }
154
 
155
 
156
  public void next()
157
  {
158
    boolean onCurve;
159
 
160
    /* If the current point is the end of a segment, and no SEG_CLOSE
161
     * has been emitted yet, this will be the next segment.
162
     */
163
    if (zone.isContourEnd(curPoint) && (state != EMIT_CLOSE))
164
    {
165
      state = EMIT_CLOSE;
166
      return;
167
    }
168
 
169
    /* If the previously emitted segment was a SEG_CLOSE, we are now
170
     * at the beginning of a new contour.
171
     */
172
    if (state == EMIT_CLOSE)
173
    {
174
      contourStart = ++curPoint;
175
      state = EMIT_MOVETO;
176
      return;
177
    }
178
 
179
    onCurve = zone.isOnCurve(curPoint);
180
 
181
    /* If the last segment was a moveto, and the current point
182
     * (which is the first point in the contour) is off-curve,
183
     * we need to emit a quadto segment for the first point.
184
     */
185
    if ((state == EMIT_MOVETO) && !onCurve)
186
    {
187
      state = EMIT_SEGMENT;
188
      return;
189
    }
190
 
191
 
192
    curPoint++;
193
 
194
    /* If the last point has been off-curve, and the now current
195
     * point is on-curve, the last segment was a quadto that
196
     * had the now current point at its end. In this case, we can
197
     * skip a segment.
198
     */
199
    if (!onCurve && zone.isOnCurve(curPoint))
200
    {
201
      /* But if the skipped point is the end of a contour, we must not
202
       * skip the SEG_CLOSE. An example where this matters is the 'o'
203
       * glyph in the Helvetica font face that comes with MacOS X
204
       * 10.1.5.
205
       */
206
      if (zone.isContourEnd(curPoint))
207
      {
208
        state = EMIT_CLOSE;
209
        return;
210
      }
211
 
212
      curPoint++;
213
    }
214
 
215
    state = EMIT_SEGMENT;
216
  }
217
 
218
 
219
  /**
220
   * Determines the successor of the current point in the current
221
   * contour. The successor of the last point in a contour is the
222
   * start of that contour.
223
   *
224
   * @return the number of the point that follows the current point in
225
   * the same contour.
226
   */
227
  private int getSuccessor(int p)
228
  {
229
    if (zone.isContourEnd(p))
230
      return contourStart;
231
    else
232
      return p + 1;
233
  }
234
 
235
 
236
 
237
  /**
238
   * Retrieves the current path segment using single-precision
239
   * coordinate values.
240
   */
241
  public int currentSegment(float[] coords)
242
  {
243
    switch (state)
244
    {
245
    case EMIT_CLOSE:
246
      return PathIterator.SEG_CLOSE;
247
 
248
    case EMIT_MOVETO:
249
      return getStartSegment(curPoint, coords);
250
 
251
    default:
252
      return getSegment(curPoint, coords);
253
    }
254
  }
255
 
256
 
257
  /**
258
   * A helper array that is used by {@link
259
   * #currentSegment(double[])}.
260
   */
261
  float[] floats;
262
 
263
 
264
  /**
265
   * Retrieves the current path segment using double-precision
266
   * coordinate values.
267
   */
268
  public int currentSegment(double[] coords)
269
  {
270
    if (floats == null)
271
      floats = new float[6];
272
    int result;
273
 
274
    result = currentSegment(floats);
275
    for (int i = 0; i < 6; i++)
276
      coords[i] = floats[i];
277
    return result;
278
  }
279
 
280
 
281
  /**
282
   * Returns the segment for the specified point.
283
   *
284
   * <p><img src="doc-files/ZonePathIterator-1.png" width="426"
285
   * height="194" alt="An example curve" /></p>
286
   *
287
   * <p>If <code>cur</code> is an on-curve point, the returned segment
288
   * is a straight line to <code>cur</code>. In the illustration, this
289
   * would be the case for <code>cur = 4</code>.</p>
290
   *
291
   * <p>If <code>cur</code> is an off-curve point, and
292
   * <code>cur</code>&#x2019;s successor <code>succ</code> is also
293
   * off-curve, the returned segment is a quadratic B&eacute;zier
294
   * spline whose control point is <code>cur</code>, and whose end
295
   * point is located at the middle of the line connecting
296
   * <code>cur</code> and <code>succ</code>. In the illustration,
297
   * this would be the case for <code>cur = 5</code>.</p>
298
   *
299
   * <p>If <code>cur</code> is an off-curve point, and
300
   * <code>cur</code>&#x2019;s successor <code>succ</code> is
301
   * on-curve, the returned segment is a quadratic B&eacute;zier
302
   * spline whose control point is <code>cur</code>, and whose end
303
   * point is <code>succ</code>. In the illustration, this would
304
   * be the case for <code>cur = 6</code>.</p>
305
   *
306
   * @return either <code>PathIterator.SEG_LINETO</code> or
307
   * <code>PathIterator.SEG_QUADTO</code>.
308
   */
309
  private int getSegment(int cur, float[] coords)
310
  {
311
    int curX, curY;
312
    int succ, succX, succY;
313
 
314
    curX = zone.getX(cur, type);
315
    curY = zone.getY(cur, type);
316
    coords[0] = Fixed.floatValue(curX);
317
    coords[1] = Fixed.floatValue(curY);
318
 
319
    if (zone.isOnCurve(cur))
320
      return PathIterator.SEG_LINETO;
321
 
322
    succ = getSuccessor(cur);
323
    succX = zone.getX(succ, type);
324
    succY = zone.getY(succ, type);
325
 
326
    if (zone.isOnCurve(succ))
327
    {
328
      coords[2] = Fixed.floatValue(succX);
329
      coords[3] = Fixed.floatValue(succY);
330
    }
331
    else
332
    {
333
      coords[2] = Fixed.floatValue((curX + succX) / 2);
334
      coords[3] = Fixed.floatValue((curY + succY) / 2);
335
    }
336
    return PathIterator.SEG_QUADTO;
337
  }
338
 
339
 
340
  /**
341
   * Returns the start segment for the contour which starts
342
   * at the specified point.
343
   *
344
   * <p>If the contour starts with an on-curve point, the returned
345
   * segment is a <code>SEG_MOVETO</code> to that point.</p>
346
   *
347
   * <p>If the contour starts with an off-curve point, and the contour
348
   * ends with an on-curve point, the returned segment is a
349
   * <code>SEG_MOVETO</code> to the end point.</p>
350
   *
351
   * <p>If the contour starts with an off-curve point, and the contour
352
   * also ends with an off-curve point, the returned segment is a
353
   * <code>SEG_MOVETO</code> to the location at the middle between the
354
   * start and end points of the contour.</p>
355
   *
356
   * @return <code>PathIterator.SEG_MOVETO</code>.
357
   */
358
  private int getStartSegment(int contourStart, float[] coords)
359
  {
360
    int x, y;
361
 
362
    if (zone.isOnCurve(contourStart))
363
    {
364
      x = zone.getX(contourStart, type);
365
      y = zone.getY(contourStart, type);
366
    }
367
    else
368
    {
369
      /* Find the last point of the current contour. */
370
      int contourEnd = contourStart;
371
      while (!zone.isContourEnd(contourEnd))
372
        ++contourEnd;
373
 
374
      if (zone.isOnCurve(contourEnd))
375
      {
376
        /* An example is the 'o' glyph of the Helvetica which comes
377
         * with Apple MacOS X 10.1.5.
378
         */
379
        x = zone.getX(contourEnd, type);
380
        y = zone.getY(contourEnd, type);
381
      }
382
      else
383
      {
384
        x = (zone.getX(contourStart, type) + zone.getX(contourEnd, type)) / 2;
385
        y = (zone.getY(contourStart, type) + zone.getY(contourEnd, type)) / 2;
386
      }
387
    }
388
 
389
    coords[0] = Fixed.floatValue(x);
390
    coords[1] = Fixed.floatValue(y);
391
    return PathIterator.SEG_MOVETO;
392
  }
393
}

powered by: WebSVN 2.1.0

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