• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
accept(LEGlyphID glyph) const29 le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
30 {
31     return fFontInstance->canDisplay((LEUnicode) glyph);
32 }
33 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)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 
ArabicOpenTypeLayoutEngine(const LEFontInstance * fontInstance,le_int32 scriptCode,le_int32 languageCode,le_int32 typoFlags,LEErrorCode & success)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 
~ArabicOpenTypeLayoutEngine()58 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
59 {
60     // nothing to do
61 }
62 
63 // Input: characters
64 // Output: characters, char indices, tags
65 // Returns: output character count
characterProcessing(const LEUnicode chars[],le_int32 offset,le_int32 count,le_int32 max,le_bool rightToLeft,LEUnicode * & outChars,LEGlyphStorage & glyphStorage,LEErrorCode & success)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 
adjustGlyphPositions(const LEUnicode chars[],le_int32 offset,le_int32 count,le_bool reverse,LEGlyphStorage & glyphStorage,LEErrorCode & success)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 
UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance * fontInstance,le_int32 scriptCode,le_int32 languageCode,le_int32 typoFlags,LEErrorCode & success)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 
~UnicodeArabicOpenTypeLayoutEngine()138 UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
139 {
140     delete fSubstitutionFilter;
141 }
142 
143 // "glyphs", "indices" -> glyphs, indices
glyphPostProcessing(LEGlyphStorage & tempGlyphStorage,LEGlyphStorage & glyphStorage,LEErrorCode & success)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 
mapCharsToGlyphs(const LEUnicode chars[],le_int32 offset,le_int32 count,le_bool reverse,le_bool,LEGlyphStorage & glyphStorage,LEErrorCode & success)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 
adjustGlyphPositions(const LEUnicode chars[],le_int32 offset,le_int32 count,le_bool reverse,LEGlyphStorage & glyphStorage,LEErrorCode & success)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 
218