3 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
8 #include "OpenTypeTables.h"
9 #include "GlyphDefinitionTables.h"
10 #include "GlyphPositionAdjustments.h"
11 #include "GlyphIterator.h"
12 #include "LEGlyphStorage.h"
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()
26 LEErrorCode success
= LE_NO_ERROR
; // TODO
27 le_int32 glyphCount
= glyphStorage
.getGlyphCount();
29 if (theGlyphDefinitionTableHeader
.isValid()) {
30 glyphClassDefinitionTable
= theGlyphDefinitionTableHeader
31 -> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader
, success
);
32 markAttachClassDefinitionTable
= theGlyphDefinitionTableHeader
33 ->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader
, success
);
36 nextLimit
= glyphCount
;
40 position
= glyphCount
;
42 prevLimit
= glyphCount
;
47 GlyphIterator::GlyphIterator(GlyphIterator
&that
)
48 : glyphStorage(that
.glyphStorage
)
50 direction
= that
.direction
;
51 position
= that
.position
;
52 nextLimit
= that
.nextLimit
;
53 prevLimit
= that
.prevLimit
;
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
;
66 GlyphIterator::GlyphIterator(GlyphIterator
&that
, FeatureMask newFeatureMask
)
67 : glyphStorage(that
.glyphStorage
)
69 direction
= that
.direction
;
70 position
= that
.position
;
71 nextLimit
= that
.nextLimit
;
72 prevLimit
= that
.prevLimit
;
74 glyphPositionAdjustments
= that
.glyphPositionAdjustments
;
75 srcIndex
= that
.srcIndex
;
76 destIndex
= that
.destIndex
;
77 lookupFlags
= that
.lookupFlags
;
78 featureMask
= newFeatureMask
;
80 glyphClassDefinitionTable
= that
.glyphClassDefinitionTable
;
81 markAttachClassDefinitionTable
= that
.markAttachClassDefinitionTable
;
85 GlyphIterator::GlyphIterator(GlyphIterator
&that
, le_uint16 newLookupFlags
)
86 : glyphStorage(that
.glyphStorage
)
88 direction
= that
.direction
;
89 position
= that
.position
;
90 nextLimit
= that
.nextLimit
;
91 prevLimit
= that
.prevLimit
;
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
;
104 GlyphIterator::~GlyphIterator()
106 // nothing to do, right?
109 void GlyphIterator::reset(le_uint16 newLookupFlags
, FeatureMask newFeatureMask
)
111 position
= prevLimit
;
112 featureMask
= newFeatureMask
;
114 lookupFlags
= newLookupFlags
;
118 LEGlyphID
*GlyphIterator::insertGlyphs(le_int32 count
, LEErrorCode
& success
)
120 return glyphStorage
.insertGlyphs(position
, count
, success
);
123 le_int32
GlyphIterator::applyInsertions()
125 le_int32 newGlyphCount
= glyphStorage
.applyInsertions();
128 prevLimit
= newGlyphCount
;
130 nextLimit
= newGlyphCount
;
133 return newGlyphCount
;
136 le_int32
GlyphIterator::getCurrStreamPosition() const
141 le_bool
GlyphIterator::isRightToLeft() const
143 return direction
< 0;
146 le_bool
GlyphIterator::ignoresMarks() const
148 return (lookupFlags
& lfIgnoreMarks
) != 0;
151 le_bool
GlyphIterator::baselineIsLogicalEnd() const
153 return (lookupFlags
& lfBaselineIsLogicalEnd
) != 0;
156 LEGlyphID
GlyphIterator::getCurrGlyphID() const
159 if (position
<= nextLimit
|| position
>= prevLimit
) {
163 if (position
<= prevLimit
|| position
>= nextLimit
) {
168 return glyphStorage
[position
];
171 void GlyphIterator::getCursiveEntryPoint(LEPoint
&entryPoint
) const
174 if (position
<= nextLimit
|| position
>= prevLimit
) {
178 if (position
<= prevLimit
|| position
>= nextLimit
) {
183 glyphPositionAdjustments
->getEntryPoint(position
, entryPoint
);
186 void GlyphIterator::getCursiveExitPoint(LEPoint
&exitPoint
) const
189 if (position
<= nextLimit
|| position
>= prevLimit
) {
193 if (position
<= prevLimit
|| position
>= nextLimit
) {
198 glyphPositionAdjustments
->getExitPoint(position
, exitPoint
);
201 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID
)
203 LEGlyphID glyph
= glyphStorage
[position
];
205 glyphStorage
[position
] = LE_SET_GLYPH(glyph
, glyphID
);
208 void GlyphIterator::setCurrStreamPosition(le_int32 newPosition
)
211 if (newPosition
>= prevLimit
) {
212 position
= prevLimit
;
216 if (newPosition
<= nextLimit
) {
217 position
= nextLimit
;
221 if (newPosition
<= prevLimit
) {
222 position
= prevLimit
;
226 if (newPosition
>= nextLimit
) {
227 position
= nextLimit
;
232 position
= newPosition
- direction
;
236 void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset
)
239 if (position
<= nextLimit
|| position
>= prevLimit
) {
243 if (position
<= prevLimit
|| position
>= nextLimit
) {
248 glyphPositionAdjustments
->setBaseOffset(position
, baseOffset
);
251 void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust
, float yPlacementAdjust
,
252 float xAdvanceAdjust
, float yAdvanceAdjust
)
255 if (position
<= nextLimit
|| position
>= prevLimit
) {
259 if (position
<= prevLimit
|| position
>= nextLimit
) {
264 glyphPositionAdjustments
->adjustXPlacement(position
, xPlacementAdjust
);
265 glyphPositionAdjustments
->adjustYPlacement(position
, yPlacementAdjust
);
266 glyphPositionAdjustments
->adjustXAdvance(position
, xAdvanceAdjust
);
267 glyphPositionAdjustments
->adjustYAdvance(position
, yAdvanceAdjust
);
270 void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust
, float yPlacementAdjust
,
271 float xAdvanceAdjust
, float yAdvanceAdjust
)
274 if (position
<= nextLimit
|| position
>= prevLimit
) {
278 if (position
<= prevLimit
|| position
>= nextLimit
) {
283 glyphPositionAdjustments
->setXPlacement(position
, xPlacementAdjust
);
284 glyphPositionAdjustments
->setYPlacement(position
, yPlacementAdjust
);
285 glyphPositionAdjustments
->setXAdvance(position
, xAdvanceAdjust
);
286 glyphPositionAdjustments
->setYAdvance(position
, yAdvanceAdjust
);
289 void GlyphIterator::clearCursiveEntryPoint()
292 if (position
<= nextLimit
|| position
>= prevLimit
) {
296 if (position
<= prevLimit
|| position
>= nextLimit
) {
301 glyphPositionAdjustments
->clearEntryPoint(position
);
304 void GlyphIterator::clearCursiveExitPoint()
307 if (position
<= nextLimit
|| position
>= prevLimit
) {
311 if (position
<= prevLimit
|| position
>= nextLimit
) {
316 glyphPositionAdjustments
->clearExitPoint(position
);
319 void GlyphIterator::setCursiveEntryPoint(LEPoint
&entryPoint
)
322 if (position
<= nextLimit
|| position
>= prevLimit
) {
326 if (position
<= prevLimit
|| position
>= nextLimit
) {
331 glyphPositionAdjustments
->setEntryPoint(position
, entryPoint
, baselineIsLogicalEnd());
334 void GlyphIterator::setCursiveExitPoint(LEPoint
&exitPoint
)
337 if (position
<= nextLimit
|| position
>= prevLimit
) {
341 if (position
<= prevLimit
|| position
>= nextLimit
) {
346 glyphPositionAdjustments
->setExitPoint(position
, exitPoint
, baselineIsLogicalEnd());
349 void GlyphIterator::setCursiveGlyph()
352 if (position
<= nextLimit
|| position
>= prevLimit
) {
356 if (position
<= prevLimit
|| position
>= nextLimit
) {
361 glyphPositionAdjustments
->setCursiveGlyph(position
, baselineIsLogicalEnd());
364 void GlyphIterator::filterResetCache(void) {
365 filterCacheValid
= FALSE
;
368 le_bool
GlyphIterator::filterGlyph(le_uint32 index
)
370 LEGlyphID glyphID
= glyphStorage
[index
];
372 if (!filterCacheValid
|| filterCache
.id
!= glyphID
) {
373 filterCache
.id
= glyphID
;
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) {
380 LEErrorCode success
= LE_NO_ERROR
;
381 le_int32 glyphClass
= gcdNoGlyphClass
;
382 if (glyphClassDefinitionTable
.isValid()) {
383 glyphClass
= glyphClassDefinitionTable
->getGlyphClass(glyphClassDefinitionTable
, glyphID
, success
);
385 switch (glyphClass
) {
386 case gcdNoGlyphClass
:
387 filterResult
= FALSE
;
391 filterResult
= (lookupFlags
& lfIgnoreBaseGlyphs
) != 0;
394 case gcdLigatureGlyph
:
395 filterResult
= (lookupFlags
& lfIgnoreLigatures
) != 0;
399 if ((lookupFlags
& lfIgnoreMarks
) != 0) {
402 le_uint16 markAttachType
= (lookupFlags
& lfMarkAttachTypeMask
) >> lfMarkAttachTypeShift
;
404 if ((markAttachType
!= 0) && (markAttachClassDefinitionTable
.isValid())) {
405 filterResult
= (markAttachClassDefinitionTable
406 -> getGlyphClass(markAttachClassDefinitionTable
, glyphID
, success
) != markAttachType
);
408 filterResult
= FALSE
;
413 case gcdComponentGlyph
:
414 filterResult
= ((lookupFlags
& lfIgnoreBaseGlyphs
) != 0);
418 filterResult
= FALSE
;
422 filterCacheValid
= TRUE
;
425 return filterCache
.result
;
428 le_bool
GlyphIterator::hasFeatureTag(le_bool matchGroup
) const
430 if (featureMask
== 0) {
434 LEErrorCode success
= LE_NO_ERROR
;
435 FeatureMask fm
= glyphStorage
.getAuxData(position
, success
);
437 return ((fm
& featureMask
) == featureMask
) && (!matchGroup
|| (le_int32
)(fm
& LE_GLYPH_GROUP_MASK
) == glyphGroup
);
440 le_bool
GlyphIterator::findFeatureTag()
444 while (nextInternal()) {
445 if (hasFeatureTag(FALSE
)) {
446 LEErrorCode success
= LE_NO_ERROR
;
448 glyphGroup
= (glyphStorage
.getAuxData(position
, success
) & LE_GLYPH_GROUP_MASK
);
457 le_bool
GlyphIterator::nextInternal(le_uint32 delta
)
459 le_int32 newPosition
= position
;
461 while (newPosition
!= nextLimit
&& delta
> 0) {
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
));
470 position
= newPosition
;
472 //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
473 return position
!= nextLimit
;
476 le_bool
GlyphIterator::next(le_uint32 delta
)
478 return nextInternal(delta
) && hasFeatureTag(TRUE
);
481 le_bool
GlyphIterator::prevInternal(le_uint32 delta
)
483 le_int32 newPosition
= position
;
485 while (newPosition
!= prevLimit
&& delta
> 0) {
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
));
494 position
= newPosition
;
496 //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
497 return position
!= prevLimit
;
500 le_bool
GlyphIterator::prev(le_uint32 delta
)
502 return prevInternal(delta
) && hasFeatureTag(TRUE
);
505 le_int32
GlyphIterator::getMarkComponent(le_int32 markPosition
) const
507 le_int32 component
= 0;
510 for (posn
= position
; posn
!= markPosition
; posn
+= direction
) {
511 if (glyphStorage
[posn
] == 0xFFFE) {
519 // This is basically prevInternal except that it
520 // doesn't take a delta argument, and it doesn't
521 // filter out 0xFFFE glyphs.
522 le_bool
GlyphIterator::findMark2Glyph()
524 le_int32 newPosition
= position
;
527 newPosition
-= direction
;
528 } while (newPosition
!= prevLimit
&& glyphStorage
[newPosition
] != 0xFFFE && filterGlyph(newPosition
));
530 position
= newPosition
;
532 return position
!= prevLimit
;