blob: 85b73a1626a2b9aa052670009fe94edc0cc98761 [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 *
29 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
30 *
31 */
32
33#include "LETypes.h"
34#include "LEScripts.h"
35#include "LEGlyphFilter.h"
36#include "LEGlyphStorage.h"
37#include "LayoutEngine.h"
38#include "OpenTypeLayoutEngine.h"
39#include "ArabicLayoutEngine.h"
40#include "ScriptAndLanguageTags.h"
41#include "CharSubstitutionFilter.h"
42
43#include "GlyphSubstitutionTables.h"
44#include "GlyphDefinitionTables.h"
45#include "GlyphPositioningTables.h"
46
47#include "GDEFMarkFilter.h"
48
49#include "ArabicShaping.h"
50#include "CanonShaping.h"
51
52le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
53{
54 return fFontInstance->canDisplay((LEUnicode) glyph);
55}
56
57ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(
58 const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
59 le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable)
60 : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable)
61{
62 fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
63 fFeatureOrder = TRUE;
64}
65
66ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(
67 const LEFontInstance *fontInstance,
68 le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags)
69 : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags)
70{
71 fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
72
73 // NOTE: We don't need to set fFeatureOrder to TRUE here
74 // because this constructor is only called by the constructor
75 // for UnicodeArabicOpenTypeLayoutEngine, which uses a pre-built
76 // GSUB table that has the features in the correct order.
77
78 //fFeatureOrder = TRUE;
79}
80
81ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
82{
83 // nothing to do
84}
85
86// Input: characters
87// Output: characters, char indices, tags
88// Returns: output character count
89le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[],
90 le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
91 LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
92{
93 if (LE_FAILURE(success)) {
94 return 0;
95 }
96
97 if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
98 success = LE_ILLEGAL_ARGUMENT_ERROR;
99 return 0;
100 }
101
102 outChars = LE_NEW_ARRAY(LEUnicode, count);
103
104 if (outChars == NULL) {
105 success = LE_MEMORY_ALLOCATION_ERROR;
106 return 0;
107 }
108
109 glyphStorage.allocateGlyphArray(count, rightToLeft, success);
110 glyphStorage.allocateAuxData(success);
111
112 if (LE_FAILURE(success)) {
113 LE_DELETE_ARRAY(outChars);
114 return 0;
115 }
116
117 CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
118
119 // Note: This processes the *original* character array so we can get context
120 // for the first and last characters. This is OK because only the marks
121 // will have been reordered, and they don't contribute to shaping.
122 ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
123
124 return count;
125}
126
127void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset,
128 le_int32 count, le_bool reverse, LEGlyphStorage &glyphStorage, LEErrorCode &success)
129{
130 if (LE_FAILURE(success)) {
131 return;
132 }
133
134 if (chars == NULL || offset < 0 || count < 0) {
135 success = LE_ILLEGAL_ARGUMENT_ERROR;
136 return;
137 }
138
139 if (fGPOSTable != NULL) {
140 OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count,
141 reverse, glyphStorage, success);
142 } else if (fGDEFTable != NULL) {
143 GDEFMarkFilter filter(fGDEFTable);
144
145 adjustMarkGlyphs(glyphStorage, &filter, success);
146 } else {
147 GlyphDefinitionTableHeader *gdefTable =
148 (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
149 GDEFMarkFilter filter(gdefTable);
150
151 adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
152 }
153}
154
155UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(
156 const LEFontInstance *fontInstance,
157 le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags)
158 : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags)
159{
160 fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
161 fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
162
163 fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
164}
165
166UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
167{
168 delete fSubstitutionFilter;
169}
170
171// "glyphs", "indices" -> glyphs, indices
172le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(
173 LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
174{
175 if (LE_FAILURE(success)) {
176 return 0;
177 }
178
179 // FIXME: we could avoid the memory allocation and copy if we
180 // made a clone of mapCharsToGlyphs which took the fake glyphs
181 // directly.
182 le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
183 LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
184
185 if (tempChars == NULL) {
186 success = LE_MEMORY_ALLOCATION_ERROR;
187 return 0;
188 }
189
190 for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
191 tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
192 }
193
194 glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
195
196 ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE,
197 TRUE, glyphStorage, success);
198
199 LE_DELETE_ARRAY(tempChars);
200
201 return tempGlyphCount;
202}
203
204void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[],
205 le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/,
206 LEGlyphStorage &glyphStorage, LEErrorCode &success)
207{
208 if (LE_FAILURE(success)) {
209 return;
210 }
211
212 if (chars == NULL || offset < 0 || count < 0) {
213 success = LE_ILLEGAL_ARGUMENT_ERROR;
214 return;
215 }
216
217 le_int32 i, dir = 1, out = 0;
218
219 if (reverse) {
220 out = count - 1;
221 dir = -1;
222 }
223
224 glyphStorage.allocateGlyphArray(count, reverse, success);
225
226 for (i = 0; i < count; i += 1, out += dir) {
227 glyphStorage[out] = (LEGlyphID) chars[offset + i];
228 }
229}
230
231void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[],
232 le_int32 offset, le_int32 count, le_bool reverse,
233 LEGlyphStorage &glyphStorage, LEErrorCode &success)
234{
235 if (LE_FAILURE(success)) {
236 return;
237 }
238
239 if (chars == NULL || offset < 0 || count < 0) {
240 success = LE_ILLEGAL_ARGUMENT_ERROR;
241 return;
242 }
243
244 GDEFMarkFilter filter(fGDEFTable);
245
246 adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
247}