]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * | |
3 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved | |
4 | * | |
5 | */ | |
6 | ||
7 | #include "LETypes.h" | |
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 "MarkToMarkPosnSubtables.h" | |
15 | #include "GlyphIterator.h" | |
16 | #include "LESwaps.h" | |
17 | ||
18 | U_NAMESPACE_BEGIN | |
19 | ||
20 | LEGlyphID MarkToMarkPositioningSubtable::findMark2Glyph(GlyphIterator *glyphIterator) const | |
21 | { | |
22 | if (glyphIterator->findMark2Glyph()) { | |
23 | return glyphIterator->getCurrGlyphID(); | |
24 | } | |
25 | ||
26 | return 0xFFFF; | |
27 | } | |
28 | ||
29 | le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const | |
30 | { | |
31 | LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); | |
32 | le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); | |
33 | ||
34 | if (markCoverage < 0) { | |
35 | // markGlyph isn't a covered mark glyph | |
36 | return 0; | |
37 | } | |
38 | ||
39 | LEPoint markAnchor; | |
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); | |
43 | ||
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! | |
47 | return 0; | |
48 | } | |
49 | ||
50 | GlyphIterator mark2Iterator(*glyphIterator); | |
51 | LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator); | |
52 | le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success); | |
53 | const Mark2Array *mark2Array = (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset)); | |
54 | le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount); | |
55 | ||
56 | if (mark2Coverage < 0 || mark2Coverage >= mark2Count) { | |
57 | // The mark2 glyph isn't covered, or the coverage | |
58 | // index is too big. The latter means that the | |
59 | // table is mal-formed... | |
60 | return 0; | |
61 | } | |
62 | ||
63 | const Mark2Record *mark2Record = &mark2Array->mark2RecordArray[mark2Coverage * mcCount]; | |
64 | Offset anchorTableOffset = SWAPW(mark2Record->mark2AnchorTableOffsetArray[markClass]); | |
65 | const AnchorTable *anchorTable = (const AnchorTable *) ((char *) mark2Array + anchorTableOffset); | |
66 | LEPoint mark2Anchor, markAdvance, pixels; | |
67 | ||
68 | if (anchorTableOffset == 0) { | |
69 | // this seems to mean that the marks don't attach... | |
70 | return 0; | |
71 | } | |
72 | ||
73 | anchorTable->getAnchor(mark2Glyph, fontInstance, mark2Anchor); | |
74 | ||
75 | fontInstance->getGlyphAdvance(markGlyph, pixels); | |
76 | fontInstance->pixelsToUnits(pixels, markAdvance); | |
77 | ||
78 | float anchorDiffX = mark2Anchor.fX - markAnchor.fX; | |
79 | float anchorDiffY = mark2Anchor.fY - markAnchor.fY; | |
80 | ||
81 | glyphIterator->setCurrGlyphBaseOffset(mark2Iterator.getCurrStreamPosition()); | |
82 | ||
83 | if (glyphIterator->isRightToLeft()) { | |
84 | glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY); | |
85 | } else { | |
86 | LEPoint mark2Advance; | |
87 | ||
88 | fontInstance->getGlyphAdvance(mark2Glyph, pixels); | |
89 | fontInstance->pixelsToUnits(pixels, mark2Advance); | |
90 | ||
91 | glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - mark2Advance.fX, anchorDiffY - mark2Advance.fY, -markAdvance.fX, -markAdvance.fY); | |
92 | } | |
93 | ||
94 | return 1; | |
95 | } | |
96 | ||
97 | U_NAMESPACE_END |