• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * (C) Copyright IBM Corp. 1998-2007 - 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 GlyphDefinitionTableHeader * theGlyphDefinitionTableHeader)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 
GlyphIterator(GlyphIterator & that)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 
GlyphIterator(GlyphIterator & that,FeatureMask newFeatureMask)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 
GlyphIterator(GlyphIterator & that,le_uint16 newLookupFlags)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 
~GlyphIterator()97 GlyphIterator::~GlyphIterator()
98 {
99     // nothing to do, right?
100 }
101 
reset(le_uint16 newLookupFlags,FeatureMask newFeatureMask)102 void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
103 {
104     position     = prevLimit;
105     featureMask  = newFeatureMask;
106     glyphGroup   = 0;
107     lookupFlags  = newLookupFlags;
108 }
109 
insertGlyphs(le_int32 count)110 LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count)
111 {
112     return glyphStorage.insertGlyphs(position, count);
113 }
114 
applyInsertions()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 
getCurrStreamPosition() const128 le_int32 GlyphIterator::getCurrStreamPosition() const
129 {
130     return position;
131 }
132 
isRightToLeft() const133 le_bool GlyphIterator::isRightToLeft() const
134 {
135     return direction < 0;
136 }
137 
ignoresMarks() const138 le_bool GlyphIterator::ignoresMarks() const
139 {
140     return (lookupFlags & lfIgnoreMarks) != 0;
141 }
142 
baselineIsLogicalEnd() const143 le_bool GlyphIterator::baselineIsLogicalEnd() const
144 {
145     return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
146 }
147 
getCurrGlyphID() const148 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 
getCursiveEntryPoint(LEPoint & entryPoint) const163 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 
getCursiveExitPoint(LEPoint & exitPoint) const178 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 
setCurrGlyphID(TTGlyphID glyphID)193 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
194 {
195     LEGlyphID glyph = glyphStorage[position];
196 
197     glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
198 }
199 
setCurrStreamPosition(le_int32 newPosition)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 
setCurrGlyphBaseOffset(le_int32 baseOffset)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 
adjustCurrGlyphPositionAdjustment(float xPlacementAdjust,float yPlacementAdjust,float xAdvanceAdjust,float yAdvanceAdjust)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 
setCurrGlyphPositionAdjustment(float xPlacementAdjust,float yPlacementAdjust,float xAdvanceAdjust,float yAdvanceAdjust)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 
clearCursiveEntryPoint()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 
clearCursiveExitPoint()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 
setCursiveEntryPoint(LEPoint & entryPoint)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 
setCursiveExitPoint(LEPoint & exitPoint)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 
setCursiveGlyph()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 
filterGlyph(le_uint32 index) const356 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 
hasFeatureTag(le_bool matchGroup) const403 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 || (fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
413 }
414 
findFeatureTag()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 
nextInternal(le_uint32 delta)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 
next(le_uint32 delta)449 le_bool GlyphIterator::next(le_uint32 delta)
450 {
451     return nextInternal(delta) && hasFeatureTag(TRUE);
452 }
453 
prevInternal(le_uint32 delta)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 
prev(le_uint32 delta)471 le_bool GlyphIterator::prev(le_uint32 delta)
472 {
473     return prevInternal(delta) && hasFeatureTag(TRUE);
474 }
475 
getMarkComponent(le_int32 markPosition) const476 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.
findMark2Glyph()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
507