4 * (C) Copyright IBM Corp. 1998-2008 - 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
, le_int32 languageCode
,
37 le_int32 typoFlags
, const GlyphSubstitutionTableHeader
*gsubTable
, LEErrorCode
&success
)
38 : OpenTypeLayoutEngine(fontInstance
, scriptCode
, languageCode
, typoFlags
, gsubTable
, success
)
40 fFeatureMap
= ArabicShaping::getFeatureMap(fFeatureMapCount
);
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
)
48 fFeatureMap
= ArabicShaping::getFeatureMap(fFeatureMapCount
);
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.
55 //fFeatureOrder = TRUE;
58 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
64 // Output: characters, char indices, tags
65 // Returns: output character count
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
)
69 if (LE_FAILURE(success
)) {
73 if (chars
== NULL
|| offset
< 0 || count
< 0 || max
< 0 || offset
>= max
|| offset
+ count
> max
) {
74 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
78 outChars
= LE_NEW_ARRAY(LEUnicode
, count
);
80 if (outChars
== NULL
) {
81 success
= LE_MEMORY_ALLOCATION_ERROR
;
85 glyphStorage
.allocateGlyphArray(count
, rightToLeft
, success
);
86 glyphStorage
.allocateAuxData(success
);
88 if (LE_FAILURE(success
)) {
89 LE_DELETE_ARRAY(outChars
);
93 CanonShaping::reorderMarks(&chars
[offset
], count
, rightToLeft
, outChars
, glyphStorage
);
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
);
103 void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
,
104 LEGlyphStorage
&glyphStorage
, LEErrorCode
&success
)
106 if (LE_FAILURE(success
)) {
110 if (chars
== NULL
|| offset
< 0 || count
< 0) {
111 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
115 if (fGPOSTable
!= NULL
) {
116 OpenTypeLayoutEngine::adjustGlyphPositions(chars
, offset
, count
, reverse
, glyphStorage
, success
);
117 } else if (fGDEFTable
!= NULL
) {
118 GDEFMarkFilter
filter(fGDEFTable
);
120 adjustMarkGlyphs(glyphStorage
, &filter
, success
);
122 GlyphDefinitionTableHeader
*gdefTable
= (GlyphDefinitionTableHeader
*) CanonShaping::glyphDefinitionTable
;
123 GDEFMarkFilter
filter(gdefTable
);
125 adjustMarkGlyphs(&chars
[offset
], count
, reverse
, glyphStorage
, &filter
, 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
)
132 fGSUBTable
= (const GlyphSubstitutionTableHeader
*) CanonShaping::glyphSubstitutionTable
;
133 fGDEFTable
= (const GlyphDefinitionTableHeader
*) CanonShaping::glyphDefinitionTable
;
135 fSubstitutionFilter
= new CharSubstitutionFilter(fontInstance
);
138 UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
140 delete fSubstitutionFilter
;
143 // "glyphs", "indices" -> glyphs, indices
144 le_int32
UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage
&tempGlyphStorage
, LEGlyphStorage
&glyphStorage
, LEErrorCode
&success
)
146 if (LE_FAILURE(success
)) {
150 // FIXME: we could avoid the memory allocation and copy if we
151 // made a clone of mapCharsToGlyphs which took the fake glyphs
153 le_int32 tempGlyphCount
= tempGlyphStorage
.getGlyphCount();
154 LEUnicode
*tempChars
= LE_NEW_ARRAY(LEUnicode
, tempGlyphCount
);
156 if (tempChars
== NULL
) {
157 success
= LE_MEMORY_ALLOCATION_ERROR
;
161 for (le_int32 i
= 0; i
< tempGlyphCount
; i
+= 1) {
162 tempChars
[i
] = (LEUnicode
) LE_GET_GLYPH(tempGlyphStorage
[i
]);
165 glyphStorage
.adoptCharIndicesArray(tempGlyphStorage
);
167 ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars
, 0, tempGlyphCount
, FALSE
, TRUE
, glyphStorage
, success
);
169 LE_DELETE_ARRAY(tempChars
);
171 return tempGlyphCount
;
174 void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
, le_bool
/*mirror*/, LEGlyphStorage
&glyphStorage
, LEErrorCode
&success
)
176 if (LE_FAILURE(success
)) {
180 if (chars
== NULL
|| offset
< 0 || count
< 0) {
181 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
185 le_int32 i
, dir
= 1, out
= 0;
192 glyphStorage
.allocateGlyphArray(count
, reverse
, success
);
194 for (i
= 0; i
< count
; i
+= 1, out
+= dir
) {
195 glyphStorage
[out
] = (LEGlyphID
) chars
[offset
+ i
];
199 void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
,
200 LEGlyphStorage
&glyphStorage
, LEErrorCode
&success
)
202 if (LE_FAILURE(success
)) {
206 if (chars
== NULL
|| offset
< 0 || count
< 0) {
207 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
211 GDEFMarkFilter
filter(fGDEFTable
);
213 adjustMarkGlyphs(&chars
[offset
], count
, reverse
, glyphStorage
, &filter
, success
);