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