]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
729e4ab9 | 3 | * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved |
b75a7d8f A |
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 "MarkToBasePosnSubtables.h" | |
15 | #include "GlyphIterator.h" | |
16 | #include "LESwaps.h" | |
17 | ||
18 | U_NAMESPACE_BEGIN | |
19 | ||
20 | LEGlyphID MarkToBasePositioningSubtable::findBaseGlyph(GlyphIterator *glyphIterator) const | |
21 | { | |
22 | if (glyphIterator->prev()) { | |
23 | return glyphIterator->getCurrGlyphID(); | |
24 | } | |
25 | ||
26 | return 0xFFFF; | |
27 | } | |
28 | ||
29 | le_int32 MarkToBasePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const | |
30 | { | |
31 | LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); | |
32 | le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph); | |
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 | // 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); | |
56 | ||
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... | |
61 | return 0; | |
62 | } | |
63 | ||
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; | |
68 | ||
374ca955 A |
69 | if (anchorTableOffset == 0) { |
70 | // this means the table is mal-formed... | |
71 | glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition()); | |
72 | return 0; | |
73 | } | |
74 | ||
b75a7d8f A |
75 | anchorTable->getAnchor(baseGlyph, fontInstance, baseAnchor); |
76 | ||
77 | fontInstance->getGlyphAdvance(markGlyph, pixels); | |
78 | fontInstance->pixelsToUnits(pixels, markAdvance); | |
79 | ||
80 | float anchorDiffX = baseAnchor.fX - markAnchor.fX; | |
81 | float anchorDiffY = baseAnchor.fY - markAnchor.fY; | |
82 | ||
83 | glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition()); | |
84 | ||
85 | if (glyphIterator->isRightToLeft()) { | |
729e4ab9 A |
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?) | |
374ca955 | 88 | glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY); |
b75a7d8f A |
89 | } else { |
90 | LEPoint baseAdvance; | |
91 | ||
92 | fontInstance->getGlyphAdvance(baseGlyph, pixels); | |
729e4ab9 A |
93 | |
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(); | |
99 | LEPoint px; | |
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 | |
102 | pixels.fY += px.fY; | |
103 | gi.next(); | |
104 | } | |
105 | // end of JK patch | |
106 | ||
b75a7d8f A |
107 | fontInstance->pixelsToUnits(pixels, baseAdvance); |
108 | ||
374ca955 | 109 | glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - baseAdvance.fX, anchorDiffY - baseAdvance.fY, -markAdvance.fX, -markAdvance.fY); |
b75a7d8f A |
110 | } |
111 | ||
112 | return 1; | |
113 | } | |
114 | ||
115 | U_NAMESPACE_END |