5 * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
10 #include "LEScripts.h"
11 #include "LEGlyphFilter.h"
12 #include "LayoutEngine.h"
13 #include "OpenTypeLayoutEngine.h"
14 #include "ArabicLayoutEngine.h"
15 #include "ScriptAndLanguageTags.h"
17 #include "GlyphSubstitutionTables.h"
18 #include "GlyphDefinitionTables.h"
19 #include "GlyphPositioningTables.h"
21 #include "GDEFMarkFilter.h"
23 #include "ArabicShaping.h"
24 #include "HebrewShaping.h"
28 class CharSubstitutionFilter
: public UMemory
, public LEGlyphFilter
31 const LEFontInstance
*fFontInstance
;
33 CharSubstitutionFilter(const CharSubstitutionFilter
&other
); // forbid copying of this class
34 CharSubstitutionFilter
&operator=(const CharSubstitutionFilter
&other
); // forbid copying of this class
37 CharSubstitutionFilter(const LEFontInstance
*fontInstance
);
38 le_bool
accept(LEGlyphID glyph
) const;
41 CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance
*fontInstance
)
42 : fFontInstance(fontInstance
)
47 le_bool
CharSubstitutionFilter::accept(LEGlyphID glyph
) const
49 return fFontInstance
->canDisplay((LEUnicode
) glyph
);
52 const char ArabicOpenTypeLayoutEngine::fgClassID
=0;
54 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance
*fontInstance
, le_int32 scriptCode
, le_int32 languageCode
,
55 const GlyphSubstitutionTableHeader
*gsubTable
)
56 : OpenTypeLayoutEngine(fontInstance
, scriptCode
, languageCode
, gsubTable
)
58 // fFeatureOrder = ArabicShaping::getFeatureOrder();
61 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance
*fontInstance
, le_int32 scriptCode
, le_int32 languageCode
)
62 : OpenTypeLayoutEngine(fontInstance
, scriptCode
, languageCode
)
64 // fFeatureOrder = ArabicShaping::getFeatureOrder();
67 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
73 // Output: characters, char indices, tags
74 // Returns: output character count
75 le_int32
ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_int32 max
, le_bool rightToLeft
,
76 LEUnicode
*&/*outChars*/, le_int32
*&/*charIndices*/, const LETag
**&featureTags
, LEErrorCode
&success
)
78 if (LE_FAILURE(success
)) {
82 if (chars
== NULL
|| offset
< 0 || count
< 0 || max
< 0 || offset
>= max
|| offset
+ count
> max
) {
83 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
87 featureTags
= LE_NEW_ARRAY(const LETag
*, count
);
89 if (featureTags
== NULL
) {
90 success
= LE_MEMORY_ALLOCATION_ERROR
;
94 switch (fScriptCode
) {
97 GlyphShaper
shaper(featureTags
);
99 // NOTE: may not need seperate shaper if always use tags...
100 // NOTE: shaper could allocate the feature tags...
101 ArabicShaping::shape(chars
, offset
, count
, max
, rightToLeft
, shaper
);
106 HebrewShaping::shape(chars
, offset
, count
, max
, rightToLeft
, featureTags
);
113 void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
,
114 LEGlyphID glyphs
[], le_int32 glyphCount
, float positions
[], LEErrorCode
&success
)
116 if (LE_FAILURE(success
)) {
120 if (chars
== NULL
|| glyphs
== NULL
|| positions
== NULL
|| offset
< 0 || count
< 0) {
121 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
125 if (fGPOSTable
!= NULL
) {
126 OpenTypeLayoutEngine::adjustGlyphPositions(chars
, offset
, count
, reverse
, glyphs
, glyphCount
, positions
, success
);
127 } else if (fGDEFTable
!= NULL
) {
128 GDEFMarkFilter
filter(fGDEFTable
);
130 adjustMarkGlyphs(glyphs
, glyphCount
, false, &filter
, positions
, success
);
132 GlyphDefinitionTableHeader
*gdefTable
= (GlyphDefinitionTableHeader
*) ArabicShaping::glyphDefinitionTable
;
133 GDEFMarkFilter
filter(gdefTable
);
134 LEGlyphID
*tempGlyphs
;
136 // FIXME: we could avoid the memory allocation and copying here by
137 // making a clone of the adjustMarkGlyphs method which took characters
139 tempGlyphs
= LE_NEW_ARRAY(LEGlyphID
, count
);
141 if (tempGlyphs
== NULL
) {
142 success
= LE_MEMORY_ALLOCATION_ERROR
;
146 for (le_int32 i
= 0; i
< count
; i
+= 1) {
147 tempGlyphs
[i
] = (LEGlyphID
) chars
[offset
+ i
];
150 adjustMarkGlyphs(tempGlyphs
, count
, reverse
, &filter
, positions
, success
);
152 LE_DELETE_ARRAY(tempGlyphs
);
156 UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance
*fontInstance
, le_int32 scriptCode
, le_int32 languageCode
)
157 : ArabicOpenTypeLayoutEngine(fontInstance
, scriptCode
, languageCode
)
159 switch (scriptCode
) {
161 fGSUBTable
= (const GlyphSubstitutionTableHeader
*) ArabicShaping::glyphSubstitutionTable
;
162 fGDEFTable
= (const GlyphDefinitionTableHeader
*) ArabicShaping::glyphDefinitionTable
;
166 fGSUBTable
= (const GlyphSubstitutionTableHeader
*) HebrewShaping::glyphSubstitutionTable
;
167 fGDEFTable
= (const GlyphDefinitionTableHeader
*) HebrewShaping::glyphDefinitionTable
;
172 fSubstitutionFilter
= new CharSubstitutionFilter(fontInstance
);
175 UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
177 delete fSubstitutionFilter
;
180 // "glyphs", "indices" -> glyphs, indices
181 le_int32
UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphID tempGlyphs
[], le_int32 tempCharIndices
[], le_int32 tempGlyphCount
,
182 LEGlyphID
*&glyphs
, le_int32
*&charIndices
, LEErrorCode
&success
)
184 if (LE_FAILURE(success
)) {
188 if (tempGlyphs
== NULL
|| tempCharIndices
== NULL
||tempGlyphCount
< 0) {
189 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
193 // FIXME: we could avoid the memory allocation and copy if we
194 // made a clone of mapCharsToGlyphs which took the fake glyphs
196 LEUnicode
*tempChars
= LE_NEW_ARRAY(LEUnicode
, tempGlyphCount
);
198 if (tempChars
== NULL
) {
199 success
= LE_MEMORY_ALLOCATION_ERROR
;
203 for (le_int32 i
= 0; i
< tempGlyphCount
; i
+= 1) {
204 tempChars
[i
] = (LEUnicode
) LE_GET_GLYPH(tempGlyphs
[i
]);
207 charIndices
= tempCharIndices
;
209 ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars
, 0, tempGlyphCount
, false, true, glyphs
, charIndices
, success
);
211 LE_DELETE_ARRAY(tempChars
);
213 return tempGlyphCount
;
216 void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
, le_bool
/*mirror*/, LEGlyphID
*&glyphs
, le_int32
*&charIndices
, LEErrorCode
&success
)
218 if (LE_FAILURE(success
)) {
222 if (chars
== NULL
|| offset
< 0 || count
< 0) {
223 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
227 le_int32 i
, dir
, out
;
237 glyphs
= LE_NEW_ARRAY(LEGlyphID
, count
);
239 if (glyphs
== NULL
) {
240 success
= LE_MEMORY_ALLOCATION_ERROR
;
244 charIndices
= LE_NEW_ARRAY(le_int32
, count
);
246 if (charIndices
== NULL
) {
247 LE_DELETE_ARRAY(glyphs
);
248 success
= LE_MEMORY_ALLOCATION_ERROR
;
252 for (i
= 0; i
< count
; i
+= 1, out
+= dir
) {
253 glyphs
[out
] = (LEGlyphID
) chars
[offset
+ i
];
254 charIndices
[out
] = i
;
258 void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars
[], le_int32 offset
, le_int32 count
, le_bool reverse
,
259 LEGlyphID glyphs
[], le_int32 glyphCount
, float positions
[], LEErrorCode
&success
)
261 if (LE_FAILURE(success
)) {
265 if (chars
== NULL
|| glyphs
== NULL
|| positions
== NULL
|| offset
< 0 || count
< 0 || glyphCount
< 0) {
266 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
270 GDEFMarkFilter
filter(fGDEFTable
);
272 // FIXME: we could avoid the memory allocation and copying here by
273 // making a clone of the adjustMarkGlyphs method which took characters
275 LEGlyphID
*tempGlyphs
= LE_NEW_ARRAY(LEGlyphID
, count
);
277 if (tempGlyphs
== NULL
) {
278 success
= LE_MEMORY_ALLOCATION_ERROR
;
282 for (le_int32 i
= 0; i
< count
; i
+= 1) {
283 tempGlyphs
[i
] = (LEGlyphID
) chars
[offset
+ i
];
286 adjustMarkGlyphs(tempGlyphs
, count
, reverse
, &filter
, positions
, success
);
288 LE_DELETE_ARRAY(tempGlyphs
);