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