3 * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
8 #include "LEFontInstance.h"
9 #include "OpenTypeTables.h"
10 #include "AnchorTables.h"
11 #include "MarkArrays.h"
12 #include "GlyphPositioningTables.h"
13 #include "AttachmentPosnSubtables.h"
14 #include "MarkToBasePosnSubtables.h"
15 #include "GlyphIterator.h"
20 LEGlyphID
MarkToBasePositioningSubtable::findBaseGlyph(GlyphIterator
*glyphIterator
) const
22 if (glyphIterator
->prev()) {
23 return glyphIterator
->getCurrGlyphID();
29 le_int32
MarkToBasePositioningSubtable::process(GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
) const
31 LEGlyphID markGlyph
= glyphIterator
->getCurrGlyphID();
32 le_int32 markCoverage
= getGlyphCoverage((LEGlyphID
) markGlyph
);
34 if (markCoverage
< 0) {
35 // markGlyph isn't a covered mark glyph
40 const MarkArray
*markArray
= (const MarkArray
*) ((char *) this + SWAPW(markArrayOffset
));
41 le_int32 markClass
= markArray
->getMarkClass(markGlyph
, markCoverage
, fontInstance
, markAnchor
);
42 le_uint16 mcCount
= SWAPW(classCount
);
44 if (markClass
< 0 || markClass
>= mcCount
) {
45 // markGlyph isn't in the mark array or its
46 // mark class is too big. The table is mal-formed!
50 // FIXME: We probably don't want to find a base glyph before a previous ligature...
51 GlyphIterator
baseIterator(*glyphIterator
, (le_uint16
) (lfIgnoreMarks
/*| lfIgnoreLigatures*/));
52 LEGlyphID baseGlyph
= findBaseGlyph(&baseIterator
);
53 le_int32 baseCoverage
= getBaseCoverage((LEGlyphID
) baseGlyph
);
54 const BaseArray
*baseArray
= (const BaseArray
*) ((char *) this + SWAPW(baseArrayOffset
));
55 le_uint16 baseCount
= SWAPW(baseArray
->baseRecordCount
);
57 if (baseCoverage
< 0 || baseCoverage
>= baseCount
) {
58 // The base glyph isn't covered, or the coverage
59 // index is too big. The latter means that the
60 // table is mal-formed...
64 const BaseRecord
*baseRecord
= &baseArray
->baseRecordArray
[baseCoverage
* mcCount
];
65 Offset anchorTableOffset
= SWAPW(baseRecord
->baseAnchorTableOffsetArray
[markClass
]);
66 const AnchorTable
*anchorTable
= (const AnchorTable
*) ((char *) baseArray
+ anchorTableOffset
);
67 LEPoint baseAnchor
, markAdvance
, pixels
;
69 if (anchorTableOffset
== 0) {
70 // this means the table is mal-formed...
71 glyphIterator
->setCurrGlyphBaseOffset(baseIterator
.getCurrStreamPosition());
75 anchorTable
->getAnchor(baseGlyph
, fontInstance
, baseAnchor
);
77 fontInstance
->getGlyphAdvance(markGlyph
, pixels
);
78 fontInstance
->pixelsToUnits(pixels
, markAdvance
);
80 float anchorDiffX
= baseAnchor
.fX
- markAnchor
.fX
;
81 float anchorDiffY
= baseAnchor
.fY
- markAnchor
.fY
;
83 glyphIterator
->setCurrGlyphBaseOffset(baseIterator
.getCurrStreamPosition());
85 if (glyphIterator
->isRightToLeft()) {
86 // FIXME: need similar patch to below; also in MarkToLigature and MarkToMark
87 // (is there a better way to approach this for all the cases?)
88 glyphIterator
->setCurrGlyphPositionAdjustment(anchorDiffX
, anchorDiffY
, -markAdvance
.fX
, -markAdvance
.fY
);
92 fontInstance
->getGlyphAdvance(baseGlyph
, pixels
);
94 //JK: adjustment needs to account for non-zero advance of any marks between base glyph and current mark
95 GlyphIterator
gi(baseIterator
, (le_uint16
)0); // copy of baseIterator that won't ignore marks
96 gi
.next(); // point beyond the base glyph
97 while (gi
.getCurrStreamPosition() < glyphIterator
->getCurrStreamPosition()) { // for all intervening glyphs (marks)...
98 LEGlyphID otherMark
= gi
.getCurrGlyphID();
100 fontInstance
->getGlyphAdvance(otherMark
, px
); // get advance, in case it's non-zero
101 pixels
.fX
+= px
.fX
; // and add that to the base glyph's advance
107 fontInstance
->pixelsToUnits(pixels
, baseAdvance
);
109 glyphIterator
->setCurrGlyphPositionAdjustment(anchorDiffX
- baseAdvance
.fX
, anchorDiffY
- baseAdvance
.fY
, -markAdvance
.fX
, -markAdvance
.fY
);