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