1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEScripts.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphFilter.h"
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphStorage.h"
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LayoutEngine.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeLayoutEngine.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ArabicLayoutEngine.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ScriptAndLanguageTags.h"
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "CharSubstitutionFilter.h"
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphSubstitutionTables.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphDefinitionTables.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphPositioningTables.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GDEFMarkFilter.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ArabicShaping.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "CanonShaping.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fFontInstance->canDisplay((LEUnicode) glyph);
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
3785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
3885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFeatureOrder = TRUE;
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho						       le_int32 typoFlags, LEErrorCode &success)
4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // NOTE: We don't need to set fFeatureOrder to TRUE here
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // because this constructor is only called by the constructor
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for UnicodeArabicOpenTypeLayoutEngine, which uses a pre-built
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // GSUB table that has the features in the correct order.
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //fFeatureOrder = TRUE;
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // nothing to do
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Input: characters
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Output: characters, char indices, tags
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Returns: output character count
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_ILLEGAL_ARGUMENT_ERROR;
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outChars = LE_NEW_ARRAY(LEUnicode, count);
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (outChars == NULL) {
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_MEMORY_ALLOCATION_ERROR;
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    glyphStorage.allocateGlyphArray(count, rightToLeft, success);
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    glyphStorage.allocateAuxData(success);
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        LE_DELETE_ARRAY(outChars);
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Note: This processes the *original* character array so we can get context
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for the first and last characters. This is OK because only the marks
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // will have been reordered, and they don't contribute to shaping.
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return count;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                                      LEGlyphStorage &glyphStorage, LEErrorCode &success)
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (chars == NULL || offset < 0 || count < 0) {
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_ILLEGAL_ARGUMENT_ERROR;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fGPOSTable != NULL) {
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (fGDEFTable != NULL) {
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        GDEFMarkFilter filter(fGDEFTable);
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        adjustMarkGlyphs(glyphStorage, &filter, success);
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        GDEFMarkFilter filter(gdefTable);
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
13085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSubstitutionFilter;
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// "glyphs", "indices" -> glyphs, indices
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // FIXME: we could avoid the memory allocation and copy if we
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // made a clone of mapCharsToGlyphs which took the fake glyphs
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // directly.
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (tempChars == NULL) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_MEMORY_ALLOCATION_ERROR;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE, TRUE, glyphStorage, success);
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_DELETE_ARRAY(tempChars);
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return tempGlyphCount;
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (chars == NULL || offset < 0 || count < 0) {
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_ILLEGAL_ARGUMENT_ERROR;
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 i, dir = 1, out = 0;
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (reverse) {
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        out = count - 1;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dir = -1;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    glyphStorage.allocateGlyphArray(count, reverse, success);
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i = 0; i < count; i += 1, out += dir) {
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        glyphStorage[out] = (LEGlyphID) chars[offset + i];
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                                      LEGlyphStorage &glyphStorage, LEErrorCode &success)
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (LE_FAILURE(success)) {
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (chars == NULL || offset < 0 || count < 0) {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = LE_ILLEGAL_ARGUMENT_ERROR;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GDEFMarkFilter filter(fGDEFTable);
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
218