4 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
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"
18 #include "GlyphSubstitutionTables.h"
19 #include "GlyphDefinitionTables.h"
20 #include "GlyphPositioningTables.h"
22 #include "GDEFMarkFilter.h"
24 #include "ArabicShaping.h"
25 #include "CanonShaping.h"
29 le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
31 return fFontInstance->canDisplay((LEUnicode) glyph);
34 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
36 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
37 le_int32 languageCode, le_int32 typoFlags,
38 const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable,
40 : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
42 fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
46 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
47 le_int32 languageCode,
48 le_int32 typoFlags, LEErrorCode &success)
49 : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
51 fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
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.
58 //fFeatureOrder = TRUE;
61 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
67 // Output: characters, char indices, tags
68 // Returns: output character count
69 le_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)
73 if (LE_FAILURE(success)) {
77 if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
78 success = LE_ILLEGAL_ARGUMENT_ERROR;
82 outChars = LE_NEW_ARRAY(LEUnicode, count);
84 if (outChars == NULL) {
85 success = LE_MEMORY_ALLOCATION_ERROR;
89 glyphStorage.allocateGlyphArray(count, rightToLeft, success);
90 glyphStorage.allocateAuxData(success);
92 if (LE_FAILURE(success)) {
93 LE_DELETE_ARRAY(outChars);
97 CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
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.
102 ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
107 void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
108 LEGlyphStorage &glyphStorage, LEErrorCode &success)
110 if (LE_FAILURE(success)) {
114 if (chars == NULL || offset < 0 || count < 0) {
115 success = LE_ILLEGAL_ARGUMENT_ERROR;
119 if (!fGPOSTable.isEmpty()) {
120 OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
121 } else if (!fGDEFTable.isEmpty()) {
122 GDEFMarkFilter filter(fGDEFTable, success);
123 adjustMarkGlyphs(glyphStorage, &filter, success);
125 LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
126 GDEFMarkFilter filter(gdefTable, success);
128 adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
132 UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
133 : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
135 fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
136 fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
137 /* OpenTypeLayoutEngine will allocate a substitution filter */
140 UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
142 /* OpenTypeLayoutEngine will cleanup the substitution filter */
145 // "glyphs", "indices" -> glyphs, indices
146 le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
148 if (LE_FAILURE(success)) {
152 // FIXME: we could avoid the memory allocation and copy if we
153 // made a clone of mapCharsToGlyphs which took the fake glyphs
155 le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
156 LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
158 if (tempChars == NULL) {
159 success = LE_MEMORY_ALLOCATION_ERROR;
163 for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
164 tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
167 glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
169 ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE, TRUE, glyphStorage, success);
171 LE_DELETE_ARRAY(tempChars);
173 return tempGlyphCount;
176 void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
178 if (LE_FAILURE(success)) {
182 if (chars == NULL || offset < 0 || count < 0) {
183 success = LE_ILLEGAL_ARGUMENT_ERROR;
187 le_int32 i, dir = 1, out = 0;
194 glyphStorage.allocateGlyphArray(count, reverse, success);
196 for (i = 0; i < count; i += 1, out += dir) {
197 glyphStorage[out] = (LEGlyphID) chars[offset + i];
201 void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
202 LEGlyphStorage &glyphStorage, LEErrorCode &success)
204 if (LE_FAILURE(success)) {
208 if (chars == NULL || offset < 0 || count < 0) {
209 success = LE_ILLEGAL_ARGUMENT_ERROR;
213 GDEFMarkFilter filter(fGDEFTable, success);
215 adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);