• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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