]> git.saurik.com Git - apple/icu.git/blame - icuSources/layout/GlyphIterator.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
CommitLineData
b75a7d8f
A
1/*
2 * %W% %E%
3 *
4 * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
5 *
6 */
7
8#include "LETypes.h"
9#include "OpenTypeTables.h"
10#include "GlyphDefinitionTables.h"
11#include "GlyphPositionAdjustments.h"
12#include "GlyphIterator.h"
13#include "Lookups.h"
14#include "LESwaps.h"
15
16U_NAMESPACE_BEGIN
17
18GlyphIterator::GlyphIterator(LEGlyphID *theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 theGlyphCount,
19 le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag *theGlyphTags[],
20 const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
21 : direction(1), position(-1), nextLimit(theGlyphCount), prevLimit(-1),
22 cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0),
23 glyphs(theGlyphs), glyphPositionAdjustments(theGlyphPositionAdjustments), lookupFlags(theLookupFlags),
24 featureTag(theFeatureTag), glyphTags(theGlyphTags),
25 glyphClassDefinitionTable(NULL),
26 markAttachClassDefinitionTable(NULL)
27
28{
29 if (theGlyphDefinitionTableHeader != NULL) {
30 glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
31 markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
32 }
33
34 if (rightToLeft) {
35 direction = -1;
36 position = theGlyphCount;
37 nextLimit = -1;
38 prevLimit = theGlyphCount;
39 }
40}
41
42GlyphIterator::GlyphIterator(GlyphIterator &that)
43{
44 direction = that.direction;
45 position = that.position;
46 nextLimit = that.nextLimit;
47 prevLimit = that.prevLimit;
48
49 cursiveFirstPosition = that.cursiveFirstPosition;
50 cursiveLastPosition = that.cursiveLastPosition;
51
52 glyphs = that.glyphs;
53 glyphPositionAdjustments = that.glyphPositionAdjustments;
54 lookupFlags = that.lookupFlags;
55 featureTag = that.featureTag;
56 glyphTags = that.glyphTags;
57 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
58 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
59}
60
61GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
62{
63 direction = that.direction;
64 position = that.position;
65 nextLimit = that.nextLimit;
66 prevLimit = that.prevLimit;
67
68 cursiveFirstPosition = that.cursiveFirstPosition;
69 cursiveLastPosition = that.cursiveLastPosition;
70
71 glyphs = that.glyphs;
72 glyphPositionAdjustments = that.glyphPositionAdjustments;
73 lookupFlags = that.lookupFlags;
74 featureTag = newFeatureTag;
75 glyphTags = that.glyphTags;
76 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
77 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
78}
79
80GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
81{
82 direction = that.direction;
83 position = that.position;
84 nextLimit = that.nextLimit;
85 prevLimit = that.prevLimit;
86
87
88 cursiveFirstPosition = that.cursiveFirstPosition;
89 cursiveLastPosition = that.cursiveLastPosition;
90
91 glyphs = that.glyphs;
92 glyphPositionAdjustments = that.glyphPositionAdjustments;
93 lookupFlags = newLookupFlags;
94 featureTag = that.featureTag;
95 glyphTags = that.glyphTags;
96 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
97 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
98}
99
100GlyphIterator::GlyphIterator()
101{
102};
103
104GlyphIterator::~GlyphIterator()
105{
106}
107
108le_int32 GlyphIterator::getCurrStreamPosition() const
109{
110 return position;
111}
112
113le_bool GlyphIterator::isRightToLeft() const
114{
115 return direction < 0;
116}
117
118le_bool GlyphIterator::ignoresMarks() const
119{
120 return (lookupFlags & lfIgnoreMarks) != 0;
121}
122
123le_bool GlyphIterator::baselineIsLogicalEnd() const
124{
125 return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
126}
127
128le_bool GlyphIterator::hasCursiveFirstExitPoint() const
129{
130 return cursiveFirstPosition >= 0;
131}
132
133le_bool GlyphIterator::hasCursiveLastExitPoint() const
134{
135 return cursiveLastPosition >= 0;
136}
137
138LEGlyphID GlyphIterator::getCurrGlyphID() const
139{
140 if (direction < 0) {
141 if (position <= nextLimit || position >= prevLimit) {
142 return 0xFFFF;
143 }
144 } else {
145 if (position <= prevLimit || position >= nextLimit) {
146 return 0xFFFF;
147 }
148 }
149
150 return glyphs[position];
151}
152
153LEGlyphID GlyphIterator::getCursiveLastGlyphID() const
154{
155 if (direction < 0) {
156 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
157 return 0xFFFF;
158 }
159 } else {
160 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
161 return 0xFFFF;
162 }
163 }
164
165 return glyphs[cursiveLastPosition];
166}
167
168void GlyphIterator::getCursiveLastExitPoint(LEPoint &exitPoint) const
169{
170 if (cursiveLastPosition >= 0) {
171 exitPoint = cursiveLastExitPoint;
172 }
173}
174
175float GlyphIterator::getCursiveBaselineAdjustment() const
176{
177 return cursiveBaselineAdjustment;
178}
179
180void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adjustment) const
181{
182 if (direction < 0)
183 {
184 if (position <= nextLimit || position >= prevLimit)
185 {
186 return;
187 }
188 } else {
189 if (position <= prevLimit || position >= nextLimit) {
190 return;
191 }
192 }
193
194 adjustment = glyphPositionAdjustments[position];
195}
196
197void GlyphIterator::getCursiveLastPositionAdjustment(GlyphPositionAdjustment &adjustment) const
198{
199 if (direction < 0)
200 {
201 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit)
202 {
203 return;
204 }
205 } else {
206 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
207 return;
208 }
209 }
210
211 adjustment = glyphPositionAdjustments[cursiveLastPosition];
212}
213
214void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
215{
216 glyphs[position] = LE_SET_GLYPH(glyphs[position], glyphID);
217}
218
219void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
220{
221 cursiveFirstPosition = -1;
222 cursiveLastPosition = -1;
223 cursiveBaselineAdjustment = 0;
224
225 if (direction < 0) {
226 if (newPosition >= prevLimit) {
227 position = prevLimit;
228 return;
229 }
230
231 if (newPosition <= nextLimit) {
232 position = nextLimit;
233 return;
234 }
235 } else {
236 if (newPosition <= prevLimit) {
237 position = prevLimit;
238 return;
239 }
240
241 if (newPosition >= nextLimit) {
242 position = nextLimit;
243 return;
244 }
245 }
246
247 position = newPosition - direction;
248 next();
249}
250
251void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment *adjustment)
252{
253 if (direction < 0) {
254 if (position <= nextLimit || position >= prevLimit) {
255 return;
256 }
257 } else {
258 if (position <= prevLimit || position >= nextLimit) {
259 return;
260 }
261 }
262
263 glyphPositionAdjustments[position] = *adjustment;
264}
265
266void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
267{
268 if (direction < 0) {
269 if (position <= nextLimit || position >= prevLimit) {
270 return;
271 }
272 } else {
273 if (position <= prevLimit || position >= nextLimit) {
274 return;
275 }
276 }
277
278 glyphPositionAdjustments[position].setBaseOffset(baseOffset);
279}
280
281void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
282 float xAdvanceAdjust, float yAdvanceAdjust)
283{
284 if (direction < 0) {
285 if (position <= nextLimit || position >= prevLimit) {
286 return;
287 }
288 } else {
289 if (position <= prevLimit || position >= nextLimit) {
290 return;
291 }
292 }
293
294 glyphPositionAdjustments[position].adjustXPlacement(xPlacementAdjust);
295 glyphPositionAdjustments[position].adjustYPlacement(yPlacementAdjust);
296 glyphPositionAdjustments[position].adjustXAdvance(xAdvanceAdjust);
297 glyphPositionAdjustments[position].adjustYAdvance(yAdvanceAdjust);
298}
299
300void GlyphIterator::setCursiveFirstExitPoint()
301{
302 if (direction < 0) {
303 if (position <= nextLimit || position >= prevLimit) {
304 return;
305 }
306 } else {
307 if (position <= prevLimit || position >= nextLimit) {
308 return;
309 }
310 }
311
312 cursiveFirstPosition = position;
313}
314
315void GlyphIterator::resetCursiveLastExitPoint()
316{
317 if ((lookupFlags & lfBaselineIsLogicalEnd) != 0 && cursiveFirstPosition >= 0 && cursiveLastPosition >= 0) {
318 le_int32 savePosition = position, saveLimit = nextLimit;
319
320 position = cursiveFirstPosition - direction;
321 nextLimit = cursiveLastPosition + direction;
322
323 while (nextInternal()) {
324 glyphPositionAdjustments[position].adjustYPlacement(-cursiveBaselineAdjustment);
325 }
326
327 position = savePosition;
328 nextLimit = saveLimit;
329 }
330
331 cursiveLastPosition = -1;
332 cursiveFirstPosition = -1;
333 cursiveBaselineAdjustment = 0;
334}
335
336void GlyphIterator::setCursiveLastExitPoint(LEPoint &exitPoint)
337{
338 if (direction < 0) {
339 if (position <= nextLimit || position >= prevLimit) {
340 return;
341 }
342 } else {
343 if (position <= prevLimit || position >= nextLimit) {
344 return;
345 }
346 }
347
348 cursiveLastPosition = position;
349 cursiveLastExitPoint = exitPoint;
350
351}
352
353void GlyphIterator::setCursiveBaselineAdjustment(float adjustment)
354{
355 cursiveBaselineAdjustment = adjustment;
356}
357
358void GlyphIterator::adjustCursiveLastGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
359 float xAdvanceAdjust, float yAdvanceAdjust)
360{
361 if (direction < 0) {
362 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
363 return;
364 }
365 } else {
366 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
367 return;
368 }
369 }
370
371 glyphPositionAdjustments[cursiveLastPosition].adjustXPlacement(xPlacementAdjust);
372 glyphPositionAdjustments[cursiveLastPosition].adjustYPlacement(yPlacementAdjust);
373 glyphPositionAdjustments[cursiveLastPosition].adjustXAdvance(xAdvanceAdjust);
374 glyphPositionAdjustments[cursiveLastPosition].adjustYAdvance(yAdvanceAdjust);
375}
376
377le_bool GlyphIterator::filterGlyph(le_uint32 index) const
378{
379 LEGlyphID glyphID = glyphs[index];
380 le_int32 glyphClass = gcdNoGlyphClass;
381
382 if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
383 return true;
384 }
385
386 if (glyphClassDefinitionTable != NULL) {
387 glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
388 }
389
390 switch (glyphClass)
391 {
392 case gcdNoGlyphClass:
393 return false;
394
395 case gcdSimpleGlyph:
396 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
397
398 case gcdLigatureGlyph:
399 return (lookupFlags & lfIgnoreLigatures) != 0;
400
401 case gcdMarkGlyph:
402 {
403 if ((lookupFlags & lfIgnoreMarks) != 0) {
404 return true;
405 }
406
407 le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
408
409 if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
410 return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
411 }
412
413 return false;
414 }
415
416 case gcdComponentGlyph:
417 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
418
419 default:
420 return false;
421 }
422}
423
424const LETag emptyTag = 0;
425const LETag defaultTag = 0xFFFFFFFF;
426
427le_bool GlyphIterator::hasFeatureTag() const
428{
429 if (featureTag == defaultTag || featureTag == emptyTag) {
430 return true;
431 }
432
433 if (glyphTags != NULL) {
434 const LETag *tagList = glyphTags[position];
435
436 for (le_int32 tag = 0; tagList[tag] != emptyTag; tag += 1) {
437 if (tagList[tag] == featureTag) {
438 return true;
439 }
440 }
441 }
442
443 return false;
444}
445
446le_bool GlyphIterator::findFeatureTag()
447{
448 while (nextInternal()) {
449 if (hasFeatureTag()) {
450 prevInternal();
451 return true;
452 }
453 }
454
455 return false;
456}
457
458
459le_bool GlyphIterator::nextInternal(le_uint32 delta)
460{
461 le_int32 newPosition = position;
462
463 while (newPosition != nextLimit && delta > 0) {
464 do {
465 newPosition += direction;
466 } while (newPosition != nextLimit && filterGlyph(newPosition));
467
468 delta -= 1;
469 }
470
471 position = newPosition;
472
473 return position != nextLimit;
474}
475
476le_bool GlyphIterator::next(le_uint32 delta)
477{
478 return nextInternal(delta) && hasFeatureTag();
479}
480
481le_bool GlyphIterator::prevInternal(le_uint32 delta)
482{
483 le_int32 newPosition = position;
484
485 while (newPosition != prevLimit && delta > 0) {
486 do {
487 newPosition -= direction;
488 } while (newPosition != prevLimit && filterGlyph(newPosition));
489
490 delta -= 1;
491 }
492
493 position = newPosition;
494
495 return position != prevLimit;
496}
497
498le_bool GlyphIterator::prev(le_uint32 delta)
499{
500 return prevInternal(delta) && hasFeatureTag();
501}
502
503le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
504{
505 le_int32 component = 0;
506 le_int32 posn;
507
508 for (posn = position; posn != markPosition; posn += direction) {
509 if (glyphs[posn] == 0xFFFE) {
510 component += 1;
511 }
512 }
513
514 return component;
515}
516
517// This is basically prevInternal except that it
518// doesn't take a delta argument, and it doesn't
519// filter out 0xFFFE glyphs.
520le_bool GlyphIterator::findMark2Glyph()
521{
522 le_int32 newPosition = position;
523
524 do {
525 newPosition -= direction;
526 } while (newPosition != prevLimit && glyphs[newPosition] != 0xFFFE && filterGlyph(newPosition));
527
528 position = newPosition;
529
530 return position != prevLimit;
531}
532
533U_NAMESPACE_END