blob: 259ab207bf1080c345c37d469d110ec2b99338dd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 */
25
26/*
27 *
28 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
29 *
30 */
31
32#include "LETypes.h"
33#include "LEFontInstance.h"
34#include "OpenTypeTables.h"
35#include "AnchorTables.h"
36#include "MarkArrays.h"
37#include "GlyphPositioningTables.h"
38#include "AttachmentPosnSubtables.h"
39#include "MarkToBasePosnSubtables.h"
40#include "GlyphIterator.h"
41#include "LESwaps.h"
42
43LEGlyphID MarkToBasePositioningSubtable::findBaseGlyph(GlyphIterator *glyphIterator) const
44{
45 if (glyphIterator->prev()) {
46 return glyphIterator->getCurrGlyphID();
47 }
48
49 return 0xFFFF;
50}
51
52le_int32 MarkToBasePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
53{
54 LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
55 le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
56
57 if (markCoverage < 0) {
58 // markGlyph isn't a covered mark glyph
59 return 0;
60 }
61
62 LEPoint markAnchor;
63 const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset));
64 le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor);
65 le_uint16 mcCount = SWAPW(classCount);
66
67 if (markClass < 0 || markClass >= mcCount) {
68 // markGlyph isn't in the mark array or its
69 // mark class is too big. The table is mal-formed!
70 return 0;
71 }
72
73 // FIXME: We probably don't want to find a base glyph before a previous ligature...
74 GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/));
75 LEGlyphID baseGlyph = findBaseGlyph(&baseIterator);
76 le_int32 baseCoverage = getBaseCoverage((LEGlyphID) baseGlyph);
77 const BaseArray *baseArray = (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset));
78 le_uint16 baseCount = SWAPW(baseArray->baseRecordCount);
79
80 if (baseCoverage < 0 || baseCoverage >= baseCount) {
81 // The base glyph isn't covered, or the coverage
82 // index is too big. The latter means that the
83 // table is mal-formed...
84 return 0;
85 }
86
87 const BaseRecord *baseRecord = &baseArray->baseRecordArray[baseCoverage * mcCount];
88 Offset anchorTableOffset = SWAPW(baseRecord->baseAnchorTableOffsetArray[markClass]);
89 const AnchorTable *anchorTable = (const AnchorTable *) ((char *) baseArray + anchorTableOffset);
90 LEPoint baseAnchor, markAdvance, pixels;
91
92 if (anchorTableOffset == 0) {
93 // this means the table is mal-formed...
94 glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition());
95 return 0;
96 }
97
98 anchorTable->getAnchor(baseGlyph, fontInstance, baseAnchor);
99
100 fontInstance->getGlyphAdvance(markGlyph, pixels);
101 fontInstance->pixelsToUnits(pixels, markAdvance);
102
103 float anchorDiffX = baseAnchor.fX - markAnchor.fX;
104 float anchorDiffY = baseAnchor.fY - markAnchor.fY;
105
106 glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition());
107
108 if (glyphIterator->isRightToLeft()) {
109 // dlf flip advance to local coordinate system
110 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY);
111 } else {
112 LEPoint baseAdvance;
113
114 fontInstance->getGlyphAdvance(baseGlyph, pixels);
115 fontInstance->pixelsToUnits(pixels, baseAdvance);
116
117 // flip advances to local coordinate system
118 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - baseAdvance.fX, anchorDiffY - baseAdvance.fY, -markAdvance.fX, -markAdvance.fY);
119 }
120
121 return 1;
122}