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
);