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