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