blob: e67b62fa25d9a6b277406ca1517d40d59400a2a0 [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 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
28 *
29 */
30
31#include "LETypes.h"
32#include "LEFontInstance.h"
33#include "OpenTypeTables.h"
34#include "AnchorTables.h"
35#include "MarkArrays.h"
36#include "GlyphPositioningTables.h"
37#include "AttachmentPosnSubtables.h"
38#include "MarkToLigaturePosnSubtables.h"
39#include "GlyphIterator.h"
40#include "LESwaps.h"
41
42LEGlyphID MarkToLigaturePositioningSubtable::findLigatureGlyph(GlyphIterator *glyphIterator) const
43{
44 if (glyphIterator->prev()) {
45 return glyphIterator->getCurrGlyphID();
46 }
47
48 return 0xFFFF;
49}
50
51le_int32 MarkToLigaturePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
52{
53 LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
54 le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
55
56 if (markCoverage < 0) {
57 // markGlyph isn't a covered mark glyph
58 return 0;
59 }
60
61 LEPoint markAnchor;
62 const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset));
63 le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor);
64 le_uint16 mcCount = SWAPW(classCount);
65
66 if (markClass < 0 || markClass >= mcCount) {
67 // markGlyph isn't in the mark array or its
68 // mark class is too big. The table is mal-formed!
69 return 0;
70 }
71
72 // FIXME: we probably don't want to find a ligature before a previous base glyph...
73 GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
74 LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
75 le_int32 ligatureCoverage = getBaseCoverage((LEGlyphID) ligatureGlyph);
76 const LigatureArray *ligatureArray = (const LigatureArray *) ((char *) this + SWAPW(baseArrayOffset));
77 le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount);
78
79 if (ligatureCoverage < 0 || ligatureCoverage >= ligatureCount) {
80 // The ligature glyph isn't covered, or the coverage
81 // index is too big. The latter means that the
82 // table is mal-formed...
83 return 0;
84 }
85
86 le_int32 markPosition = glyphIterator->getCurrStreamPosition();
87 Offset ligatureAttachOffset = SWAPW(ligatureArray->ligatureAttachTableOffsetArray[ligatureCoverage]);
88 const LigatureAttachTable *ligatureAttachTable = (const LigatureAttachTable *) ((char *) ligatureArray + ligatureAttachOffset);
89 le_int32 componentCount = SWAPW(ligatureAttachTable->componentCount);
90 le_int32 component = ligatureIterator.getMarkComponent(markPosition);
91
92 if (component >= componentCount) {
93 // should really just bail at this point...
94 component = componentCount - 1;
95 }
96
97 const ComponentRecord *componentRecord = &ligatureAttachTable->componentRecordArray[component * mcCount];
98 Offset anchorTableOffset = SWAPW(componentRecord->ligatureAnchorTableOffsetArray[markClass]);
99 const AnchorTable *anchorTable = (const AnchorTable *) ((char *) ligatureAttachTable + anchorTableOffset);
100 LEPoint ligatureAnchor, markAdvance, pixels;
101
102 anchorTable->getAnchor(ligatureGlyph, fontInstance, ligatureAnchor);
103
104 fontInstance->getGlyphAdvance(markGlyph, pixels);
105 fontInstance->pixelsToUnits(pixels, markAdvance);
106
107 float anchorDiffX = ligatureAnchor.fX - markAnchor.fX;
108 float anchorDiffY = ligatureAnchor.fY - markAnchor.fY;
109
110 glyphIterator->setCurrGlyphBaseOffset(ligatureIterator.getCurrStreamPosition());
111
112 if (glyphIterator->isRightToLeft()) {
113 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY);
114 } else {
115 LEPoint ligatureAdvance;
116
117 fontInstance->getGlyphAdvance(ligatureGlyph, pixels);
118 fontInstance->pixelsToUnits(pixels, ligatureAdvance);
119
120 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - ligatureAdvance.fX,
121 anchorDiffY - ligatureAdvance.fY, -markAdvance.fX, -markAdvance.fY);
122 }
123
124 return 1;
125}