]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/GlyphIterator.cpp
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
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
16 U_NAMESPACE_BEGIN
17
18 GlyphIterator::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
43 GlyphIterator::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
61 GlyphIterator::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
79 GlyphIterator::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
97 GlyphIterator::~GlyphIterator()
98 {
99 // nothing to do, right?
100 }
101
102 void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
103 {
104 position = prevLimit;
105 featureMask = newFeatureMask;
106 glyphGroup = 0;
107 lookupFlags = newLookupFlags;
108 }
109
110 LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
111 {
112 return glyphStorage.insertGlyphs(position, count, success);
113 }
114
115 le_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
128 le_int32 GlyphIterator::getCurrStreamPosition() const
129 {
130 return position;
131 }
132
133 le_bool GlyphIterator::isRightToLeft() const
134 {
135 return direction < 0;
136 }
137
138 le_bool GlyphIterator::ignoresMarks() const
139 {
140 return (lookupFlags & lfIgnoreMarks) != 0;
141 }
142
143 le_bool GlyphIterator::baselineIsLogicalEnd() const
144 {
145 return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
146 }
147
148 LEGlyphID 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
163 void 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
178 void 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
193 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
194 {
195 LEGlyphID glyph = glyphStorage[position];
196
197 glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
198 }
199
200 void 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
228 void 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
243 void 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
262 void 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
281 void 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
296 void 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
311 void 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
326 void 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
341 void 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
356 le_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
403 le_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
415 le_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
432 le_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
449 le_bool GlyphIterator::next(le_uint32 delta)
450 {
451 return nextInternal(delta) && hasFeatureTag(TRUE);
452 }
453
454 le_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
471 le_bool GlyphIterator::prev(le_uint32 delta)
472 {
473 return prevInternal(delta) && hasFeatureTag(TRUE);
474 }
475
476 le_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.
493 le_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
506 U_NAMESPACE_END