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