3 * (C) Copyright IBM Corp. 1998-2004 - 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
, GlyphPositionAdjustment
*theGlyphPositionAdjustments
, le_bool rightToLeft
, le_uint16 theLookupFlags
, LETag theFeatureTag
,
19 const GlyphDefinitionTableHeader
*theGlyphDefinitionTableHeader
)
20 : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
21 cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0),
22 glyphStorage(theGlyphStorage
), glyphPositionAdjustments(theGlyphPositionAdjustments
),
23 srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags
), featureTag(theFeatureTag
),
24 glyphClassDefinitionTable(NULL
), markAttachClassDefinitionTable(NULL
)
27 le_int32 glyphCount
= glyphStorage
.getGlyphCount();
29 if (theGlyphDefinitionTableHeader
!= NULL
) {
30 glyphClassDefinitionTable
= theGlyphDefinitionTableHeader
->getGlyphClassDefinitionTable();
31 markAttachClassDefinitionTable
= theGlyphDefinitionTableHeader
->getMarkAttachClassDefinitionTable();
34 nextLimit
= glyphCount
;
38 position
= glyphCount
;
40 prevLimit
= glyphCount
;
44 GlyphIterator::GlyphIterator(GlyphIterator
&that
)
45 : glyphStorage(that
.glyphStorage
)
47 direction
= that
.direction
;
48 position
= that
.position
;
49 nextLimit
= that
.nextLimit
;
50 prevLimit
= that
.prevLimit
;
52 cursiveFirstPosition
= that
.cursiveFirstPosition
;
53 cursiveLastPosition
= that
.cursiveLastPosition
;
55 glyphPositionAdjustments
= that
.glyphPositionAdjustments
;
56 srcIndex
= that
.srcIndex
;
57 destIndex
= that
.destIndex
;
58 lookupFlags
= that
.lookupFlags
;
59 featureTag
= that
.featureTag
;
60 glyphClassDefinitionTable
= that
.glyphClassDefinitionTable
;
61 markAttachClassDefinitionTable
= that
.markAttachClassDefinitionTable
;
64 GlyphIterator::GlyphIterator(GlyphIterator
&that
, LETag newFeatureTag
)
65 : glyphStorage(that
.glyphStorage
)
67 direction
= that
.direction
;
68 position
= that
.position
;
69 nextLimit
= that
.nextLimit
;
70 prevLimit
= that
.prevLimit
;
72 cursiveFirstPosition
= that
.cursiveFirstPosition
;
73 cursiveLastPosition
= that
.cursiveLastPosition
;
75 glyphPositionAdjustments
= that
.glyphPositionAdjustments
;
76 srcIndex
= that
.srcIndex
;
77 destIndex
= that
.destIndex
;
78 lookupFlags
= that
.lookupFlags
;
79 featureTag
= newFeatureTag
;
80 glyphClassDefinitionTable
= that
.glyphClassDefinitionTable
;
81 markAttachClassDefinitionTable
= that
.markAttachClassDefinitionTable
;
84 GlyphIterator::GlyphIterator(GlyphIterator
&that
, le_uint16 newLookupFlags
)
85 : glyphStorage(that
.glyphStorage
)
87 direction
= that
.direction
;
88 position
= that
.position
;
89 nextLimit
= that
.nextLimit
;
90 prevLimit
= that
.prevLimit
;
93 cursiveFirstPosition
= that
.cursiveFirstPosition
;
94 cursiveLastPosition
= that
.cursiveLastPosition
;
96 glyphPositionAdjustments
= that
.glyphPositionAdjustments
;
97 srcIndex
= that
.srcIndex
;
98 destIndex
= that
.destIndex
;
99 lookupFlags
= newLookupFlags
;
100 featureTag
= that
.featureTag
;
101 glyphClassDefinitionTable
= that
.glyphClassDefinitionTable
;
102 markAttachClassDefinitionTable
= that
.markAttachClassDefinitionTable
;
105 GlyphIterator::~GlyphIterator()
107 // nothing to do, right?
110 void GlyphIterator::reset(le_uint16 newLookupFlags
, LETag newFeatureTag
)
112 position
= prevLimit
;
113 featureTag
= newFeatureTag
;
114 lookupFlags
= newLookupFlags
;
117 LEGlyphID
*GlyphIterator::insertGlyphs(le_int32 count
)
119 return glyphStorage
.insertGlyphs(position
, count
);
122 le_int32
GlyphIterator::applyInsertions()
124 le_int32 newGlyphCount
= glyphStorage
.applyInsertions();
127 prevLimit
= newGlyphCount
;
129 nextLimit
= newGlyphCount
;
132 return newGlyphCount
;
135 le_int32
GlyphIterator::getCurrStreamPosition() const
140 le_bool
GlyphIterator::isRightToLeft() const
142 return direction
< 0;
145 le_bool
GlyphIterator::ignoresMarks() const
147 return (lookupFlags
& lfIgnoreMarks
) != 0;
150 le_bool
GlyphIterator::baselineIsLogicalEnd() const
152 return (lookupFlags
& lfBaselineIsLogicalEnd
) != 0;
155 le_bool
GlyphIterator::hasCursiveFirstExitPoint() const
157 return cursiveFirstPosition
>= 0;
160 le_bool
GlyphIterator::hasCursiveLastExitPoint() const
162 return cursiveLastPosition
>= 0;
165 LEGlyphID
GlyphIterator::getCurrGlyphID() const
168 if (position
<= nextLimit
|| position
>= prevLimit
) {
172 if (position
<= prevLimit
|| position
>= nextLimit
) {
177 return glyphStorage
[position
];
180 LEGlyphID
GlyphIterator::getCursiveLastGlyphID() const
183 if (cursiveLastPosition
<= nextLimit
|| cursiveLastPosition
>= prevLimit
) {
187 if (cursiveLastPosition
<= prevLimit
|| cursiveLastPosition
>= nextLimit
) {
192 return glyphStorage
[cursiveLastPosition
];
195 void GlyphIterator::getCursiveLastExitPoint(LEPoint
&exitPoint
) const
197 if (cursiveLastPosition
>= 0) {
198 exitPoint
= cursiveLastExitPoint
;
202 float GlyphIterator::getCursiveBaselineAdjustment() const
204 return cursiveBaselineAdjustment
;
207 void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment
&adjustment
) const
211 if (position
<= nextLimit
|| position
>= prevLimit
)
216 if (position
<= prevLimit
|| position
>= nextLimit
) {
221 adjustment
= glyphPositionAdjustments
[position
];
224 void GlyphIterator::getCursiveLastPositionAdjustment(GlyphPositionAdjustment
&adjustment
) const
228 if (cursiveLastPosition
<= nextLimit
|| cursiveLastPosition
>= prevLimit
)
233 if (cursiveLastPosition
<= prevLimit
|| cursiveLastPosition
>= nextLimit
) {
238 adjustment
= glyphPositionAdjustments
[cursiveLastPosition
];
241 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID
)
243 LEGlyphID glyph
= glyphStorage
[position
];
245 glyphStorage
[position
] = LE_SET_GLYPH(glyph
, glyphID
);
248 void GlyphIterator::setCurrStreamPosition(le_int32 newPosition
)
250 cursiveFirstPosition
= -1;
251 cursiveLastPosition
= -1;
252 cursiveBaselineAdjustment
= 0;
255 if (newPosition
>= prevLimit
) {
256 position
= prevLimit
;
260 if (newPosition
<= nextLimit
) {
261 position
= nextLimit
;
265 if (newPosition
<= prevLimit
) {
266 position
= prevLimit
;
270 if (newPosition
>= nextLimit
) {
271 position
= nextLimit
;
276 position
= newPosition
- direction
;
280 void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment
*adjustment
)
283 if (position
<= nextLimit
|| position
>= prevLimit
) {
287 if (position
<= prevLimit
|| position
>= nextLimit
) {
292 glyphPositionAdjustments
[position
] = *adjustment
;
295 void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset
)
298 if (position
<= nextLimit
|| position
>= prevLimit
) {
302 if (position
<= prevLimit
|| position
>= nextLimit
) {
307 glyphPositionAdjustments
[position
].setBaseOffset(baseOffset
);
310 void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust
, float yPlacementAdjust
,
311 float xAdvanceAdjust
, float yAdvanceAdjust
)
314 if (position
<= nextLimit
|| position
>= prevLimit
) {
318 if (position
<= prevLimit
|| position
>= nextLimit
) {
323 glyphPositionAdjustments
[position
].adjustXPlacement(xPlacementAdjust
);
324 glyphPositionAdjustments
[position
].adjustYPlacement(yPlacementAdjust
);
325 glyphPositionAdjustments
[position
].adjustXAdvance(xAdvanceAdjust
);
326 glyphPositionAdjustments
[position
].adjustYAdvance(yAdvanceAdjust
);
329 void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust
, float yPlacementAdjust
,
330 float xAdvanceAdjust
, float yAdvanceAdjust
)
333 if (position
<= nextLimit
|| position
>= prevLimit
) {
337 if (position
<= prevLimit
|| position
>= nextLimit
) {
342 glyphPositionAdjustments
[position
].setXPlacement(xPlacementAdjust
);
343 glyphPositionAdjustments
[position
].setYPlacement(yPlacementAdjust
);
344 glyphPositionAdjustments
[position
].setXAdvance(xAdvanceAdjust
);
345 glyphPositionAdjustments
[position
].setYAdvance(yAdvanceAdjust
);
348 void GlyphIterator::setCursiveFirstExitPoint()
351 if (position
<= nextLimit
|| position
>= prevLimit
) {
355 if (position
<= prevLimit
|| position
>= nextLimit
) {
360 cursiveFirstPosition
= position
;
363 void GlyphIterator::resetCursiveLastExitPoint()
365 if ((lookupFlags
& lfBaselineIsLogicalEnd
) != 0 && cursiveFirstPosition
>= 0 && cursiveLastPosition
>= 0) {
366 le_int32 savePosition
= position
, saveLimit
= nextLimit
;
368 position
= cursiveFirstPosition
- direction
;
369 nextLimit
= cursiveLastPosition
+ direction
;
371 while (nextInternal()) {
372 glyphPositionAdjustments
[position
].adjustYPlacement(-cursiveBaselineAdjustment
);
375 position
= savePosition
;
376 nextLimit
= saveLimit
;
379 cursiveLastPosition
= -1;
380 cursiveFirstPosition
= -1;
381 cursiveBaselineAdjustment
= 0;
384 void GlyphIterator::setCursiveLastExitPoint(LEPoint
&exitPoint
)
387 if (position
<= nextLimit
|| position
>= prevLimit
) {
391 if (position
<= prevLimit
|| position
>= nextLimit
) {
396 cursiveLastPosition
= position
;
397 cursiveLastExitPoint
= exitPoint
;
401 void GlyphIterator::setCursiveBaselineAdjustment(float adjustment
)
403 cursiveBaselineAdjustment
= adjustment
;
406 void GlyphIterator::adjustCursiveLastGlyphPositionAdjustment(float xPlacementAdjust
, float yPlacementAdjust
,
407 float xAdvanceAdjust
, float yAdvanceAdjust
)
410 if (cursiveLastPosition
<= nextLimit
|| cursiveLastPosition
>= prevLimit
) {
414 if (cursiveLastPosition
<= prevLimit
|| cursiveLastPosition
>= nextLimit
) {
419 glyphPositionAdjustments
[cursiveLastPosition
].adjustXPlacement(xPlacementAdjust
);
420 glyphPositionAdjustments
[cursiveLastPosition
].adjustYPlacement(yPlacementAdjust
);
421 glyphPositionAdjustments
[cursiveLastPosition
].adjustXAdvance(xAdvanceAdjust
);
422 glyphPositionAdjustments
[cursiveLastPosition
].adjustYAdvance(yAdvanceAdjust
);
425 le_bool
GlyphIterator::filterGlyph(le_uint32 index
) const
427 LEGlyphID glyphID
= glyphStorage
[index
];
428 le_int32 glyphClass
= gcdNoGlyphClass
;
430 if (LE_GET_GLYPH(glyphID
) >= 0xFFFE) {
434 if (glyphClassDefinitionTable
!= NULL
) {
435 glyphClass
= glyphClassDefinitionTable
->getGlyphClass(glyphID
);
440 case gcdNoGlyphClass
:
444 return (lookupFlags
& lfIgnoreBaseGlyphs
) != 0;
446 case gcdLigatureGlyph
:
447 return (lookupFlags
& lfIgnoreLigatures
) != 0;
451 if ((lookupFlags
& lfIgnoreMarks
) != 0) {
455 le_uint16 markAttachType
= (lookupFlags
& lfMarkAttachTypeMask
) >> lfMarkAttachTypeShift
;
457 if ((markAttachType
!= 0) && (markAttachClassDefinitionTable
!= NULL
)) {
458 return markAttachClassDefinitionTable
->getGlyphClass(glyphID
) != markAttachType
;
464 case gcdComponentGlyph
:
465 return (lookupFlags
& lfIgnoreBaseGlyphs
) != 0;
472 static const LETag emptyTag
= 0;
473 static const LETag defaultTag
= 0xFFFFFFFF;
475 le_bool
GlyphIterator::hasFeatureTag() const
477 if (featureTag
== defaultTag
|| featureTag
== emptyTag
) {
481 LEErrorCode success
= LE_NO_ERROR
;
482 const LETag
*tagList
= (const LETag
*) glyphStorage
.getAuxData(position
, success
);
484 if (tagList
!= NULL
) {
485 for (le_int32 tag
= 0; tagList
[tag
] != emptyTag
; tag
+= 1) {
486 if (tagList
[tag
] == featureTag
) {
495 le_bool
GlyphIterator::findFeatureTag()
497 while (nextInternal()) {
498 if (hasFeatureTag()) {
508 le_bool
GlyphIterator::nextInternal(le_uint32 delta
)
510 le_int32 newPosition
= position
;
512 while (newPosition
!= nextLimit
&& delta
> 0) {
514 newPosition
+= direction
;
515 } while (newPosition
!= nextLimit
&& filterGlyph(newPosition
));
520 position
= newPosition
;
522 return position
!= nextLimit
;
525 le_bool
GlyphIterator::next(le_uint32 delta
)
527 return nextInternal(delta
) && hasFeatureTag();
530 le_bool
GlyphIterator::prevInternal(le_uint32 delta
)
532 le_int32 newPosition
= position
;
534 while (newPosition
!= prevLimit
&& delta
> 0) {
536 newPosition
-= direction
;
537 } while (newPosition
!= prevLimit
&& filterGlyph(newPosition
));
542 position
= newPosition
;
544 return position
!= prevLimit
;
547 le_bool
GlyphIterator::prev(le_uint32 delta
)
549 return prevInternal(delta
) && hasFeatureTag();
552 le_int32
GlyphIterator::getMarkComponent(le_int32 markPosition
) const
554 le_int32 component
= 0;
557 for (posn
= position
; posn
!= markPosition
; posn
+= direction
) {
558 if (glyphStorage
[posn
] == 0xFFFE) {
566 // This is basically prevInternal except that it
567 // doesn't take a delta argument, and it doesn't
568 // filter out 0xFFFE glyphs.
569 le_bool
GlyphIterator::findMark2Glyph()
571 le_int32 newPosition
= position
;
574 newPosition
-= direction
;
575 } while (newPosition
!= prevLimit
&& glyphStorage
[newPosition
] != 0xFFFE && filterGlyph(newPosition
));
577 position
= newPosition
;
579 return position
!= prevLimit
;