]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/layout/ArabicLayoutEngine.cpp
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / layout / ArabicLayoutEngine.cpp
... / ...
CommitLineData
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
27U_NAMESPACE_BEGIN
28
29le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
30{
31 return fFontInstance->canDisplay((LEUnicode) glyph);
32}
33
34UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
35
36ArabicOpenTypeLayoutEngine::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
44ArabicOpenTypeLayoutEngine::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
58ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
59{
60 // nothing to do
61}
62
63// Input: characters
64// Output: characters, char indices, tags
65// Returns: output character count
66le_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
103void 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
129UnicodeArabicOpenTypeLayoutEngine::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
138UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
139{
140 delete fSubstitutionFilter;
141}
142
143// "glyphs", "indices" -> glyphs, indices
144le_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
174void 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
199void 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
216U_NAMESPACE_END
217