sl@0
|
1 |
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
//
|
sl@0
|
15 |
|
sl@0
|
16 |
/**
|
sl@0
|
17 |
@file
|
sl@0
|
18 |
@internalComponent
|
sl@0
|
19 |
*/
|
sl@0
|
20 |
|
sl@0
|
21 |
|
sl@0
|
22 |
#include <gdi.h>
|
sl@0
|
23 |
#include "FontArabic.h"
|
sl@0
|
24 |
#include "GDIPANIC.h"
|
sl@0
|
25 |
|
sl@0
|
26 |
|
sl@0
|
27 |
//
|
sl@0
|
28 |
// Arabic Presentation Forms.
|
sl@0
|
29 |
//
|
sl@0
|
30 |
|
sl@0
|
31 |
|
sl@0
|
32 |
/**
|
sl@0
|
33 |
The contextual forms of each character in the range 0621 - 064A, in
|
sl@0
|
34 |
the order final, initial, medial; followed by the forms of
|
sl@0
|
35 |
the lam-alef ligatures (lam with 0622, 0623, 0625 and 0627);
|
sl@0
|
36 |
followed by the forms of the characters in the range 0671 - 06D3
|
sl@0
|
37 |
*/
|
sl@0
|
38 |
LOCAL_D const TUint16 TheArabicShapeTable[] =
|
sl@0
|
39 |
{
|
sl@0
|
40 |
// Contextual forms for standard Arabic letters
|
sl@0
|
41 |
0x621, 0x621, 0x621, // 621
|
sl@0
|
42 |
0xfe82, 0x622, 0x622, // 622
|
sl@0
|
43 |
0xfe84, 0x623, 0x623, // 623
|
sl@0
|
44 |
0xfe86, 0x624, 0x624, // 624
|
sl@0
|
45 |
0xfe88, 0x625, 0x625, // 625
|
sl@0
|
46 |
0xfe8a, 0xfe8b, 0xfe8c, // 626
|
sl@0
|
47 |
0xfe8e, 0x627, 0x627, // 627
|
sl@0
|
48 |
0xfe90, 0xfe91, 0xfe92, // 628
|
sl@0
|
49 |
0xfe94, 0x629, 0x629, // 629
|
sl@0
|
50 |
0xfe96, 0xfe97, 0xfe98, // 62a
|
sl@0
|
51 |
0xfe9a, 0xfe9b, 0xfe9c, // 62b
|
sl@0
|
52 |
0xfe9e, 0xfe9f, 0xfea0, // 62c
|
sl@0
|
53 |
0xfea2, 0xfea3, 0xfea4, // 62d
|
sl@0
|
54 |
0xfea6, 0xfea7, 0xfea8, // 62e
|
sl@0
|
55 |
0xfeaa, 0x62f, 0x62f, // 62f
|
sl@0
|
56 |
0xfeac, 0x630, 0x630, // 630
|
sl@0
|
57 |
0xfeae, 0x631, 0x631, // 631
|
sl@0
|
58 |
0xfeb0, 0x632, 0x632, // 632
|
sl@0
|
59 |
0xfeb2, 0xfeb3, 0xfeb4, // 633
|
sl@0
|
60 |
0xfeb6, 0xfeb7, 0xfeb8, // 634
|
sl@0
|
61 |
0xfeba, 0xfebb, 0xfebc, // 635
|
sl@0
|
62 |
0xfebe, 0xfebf, 0xfec0, // 636
|
sl@0
|
63 |
0xfec2, 0xfec3, 0xfec4, // 637
|
sl@0
|
64 |
0xfec6, 0xfec7, 0xfec8, // 638
|
sl@0
|
65 |
0xfeca, 0xfecb, 0xfecc, // 639
|
sl@0
|
66 |
0xfece, 0xfecf, 0xfed0, // 63a
|
sl@0
|
67 |
0x63b, 0x63b, 0x63b, // placeholder
|
sl@0
|
68 |
0x63c, 0x63c, 0x63c, // placeholder
|
sl@0
|
69 |
0x63d, 0x63d, 0x63d, // placeholder
|
sl@0
|
70 |
0x63e, 0x63e, 0x63e, // placeholder
|
sl@0
|
71 |
0x63f, 0x63f, 0x63f, // placeholder
|
sl@0
|
72 |
0x640, 0x640, 0x640, // 640
|
sl@0
|
73 |
0xfed2, 0xfed3, 0xfed4, // 641
|
sl@0
|
74 |
0xfed6, 0xfed7, 0xfed8, // 642
|
sl@0
|
75 |
0xfeda, 0xfedb, 0xfedc, // 643
|
sl@0
|
76 |
0xfede, 0xfedf, 0xfee0, // 644
|
sl@0
|
77 |
0xfee2, 0xfee3, 0xfee4, // 645
|
sl@0
|
78 |
0xfee6, 0xfee7, 0xfee8, // 646
|
sl@0
|
79 |
0xfeea, 0xfeeb, 0xfeec, // 647
|
sl@0
|
80 |
0xfeee, 0x648, 0x648, // 648
|
sl@0
|
81 |
0xfef0, 0xfbe8, 0xfbe9, // 649
|
sl@0
|
82 |
0xfef2, 0xfef3, 0xfef4, // 64A
|
sl@0
|
83 |
|
sl@0
|
84 |
// Contextual forms for lam-alef ligatures
|
sl@0
|
85 |
0xfef6, 0xfef5, 0xfef5, // 644 + 622
|
sl@0
|
86 |
0xfef8, 0xfef7, 0xfef7, // 644 + 623
|
sl@0
|
87 |
0xfefa, 0xfef9, 0xfef9, // 644 + 625
|
sl@0
|
88 |
0xfefc, 0xfefb, 0xfefb, // 644 + 627
|
sl@0
|
89 |
|
sl@0
|
90 |
// Contextual forms for extended Arabic letters for Persian, Urdu, Sindhi, etc.
|
sl@0
|
91 |
0xfb51, 0x0671, 0x0671, // 671
|
sl@0
|
92 |
0x0672, 0x0672, 0x0672, // placeholder
|
sl@0
|
93 |
0x0673, 0x0673, 0x0673, // placeholder
|
sl@0
|
94 |
0x0674, 0x0674, 0x0674, // placeholder
|
sl@0
|
95 |
0x0675, 0x0675, 0x0675, // placeholder
|
sl@0
|
96 |
0x0676, 0x0676, 0x0676, // placeholder
|
sl@0
|
97 |
0x0677, 0x0677, 0x0677, // placeholder
|
sl@0
|
98 |
0x0678, 0x0678, 0x0678, // placeholder
|
sl@0
|
99 |
0xfb67, 0xfb68, 0xfb69, // 679
|
sl@0
|
100 |
0xfb5f, 0xfb60, 0xfb61, // 67a
|
sl@0
|
101 |
0xfb53, 0xfb54, 0xfb55, // 67b
|
sl@0
|
102 |
0x067c, 0x067c, 0x067c, // placeholder
|
sl@0
|
103 |
0x067d, 0x067d, 0x067d, // placeholder
|
sl@0
|
104 |
0xfb57, 0xfb58, 0xfb59, // 67e
|
sl@0
|
105 |
0xfb63, 0xfb64, 0xfb65, // 67f
|
sl@0
|
106 |
|
sl@0
|
107 |
0xfb5b, 0xfb5c, 0xfb5d, // 680
|
sl@0
|
108 |
0x0681, 0x0681, 0x0681, // placeholder
|
sl@0
|
109 |
0x0682, 0x0682, 0x0682, // placeholder
|
sl@0
|
110 |
0xfb77, 0xfb78, 0xfb79, // 683
|
sl@0
|
111 |
0xfb73, 0xfb74, 0xfb75, // 684
|
sl@0
|
112 |
0x0685, 0x0685, 0x0685, // placeholder
|
sl@0
|
113 |
0xfb7b, 0xfb7c, 0xfb7d, // 686
|
sl@0
|
114 |
0xfb7f, 0xfb80, 0xfb81, // 687
|
sl@0
|
115 |
0xfb89, 0x0688, 0x0688, // 688
|
sl@0
|
116 |
0x0689, 0x0689, 0x0689, // placeholder
|
sl@0
|
117 |
0x068a, 0x068a, 0x068a, // placeholder
|
sl@0
|
118 |
0x068b, 0x068b, 0x068b, // placeholder
|
sl@0
|
119 |
0xfb85, 0x068c, 0x068c, // 68c
|
sl@0
|
120 |
0xfb83, 0x068d, 0x068d, // 68d
|
sl@0
|
121 |
0xfb87, 0x068e, 0x068e, // 68e
|
sl@0
|
122 |
0x068f, 0x068f, 0x068f, // placeholder
|
sl@0
|
123 |
|
sl@0
|
124 |
0x0690, 0x0690, 0x0690, // placeholder
|
sl@0
|
125 |
0xfb8d, 0x0691, 0x0691, // 691
|
sl@0
|
126 |
0x0692, 0x0692, 0x0692, // placeholder
|
sl@0
|
127 |
0x0693, 0x0693, 0x0693, // placeholder
|
sl@0
|
128 |
0x0694, 0x0694, 0x0694, // placeholder
|
sl@0
|
129 |
0x0695, 0x0695, 0x0695, // placeholder
|
sl@0
|
130 |
0x0696, 0x0696, 0x0696, // placeholder
|
sl@0
|
131 |
0x0697, 0x0697, 0x0697, // placeholder
|
sl@0
|
132 |
0xfb8b, 0x0698, 0x0698, // 698
|
sl@0
|
133 |
0x0699, 0x0699, 0x0699, // placeholder
|
sl@0
|
134 |
0x069a, 0x069a, 0x069a, // placeholder
|
sl@0
|
135 |
0x069b, 0x069b, 0x069b, // placeholder
|
sl@0
|
136 |
0x069c, 0x069c, 0x069c, // placeholder
|
sl@0
|
137 |
0x069d, 0x069d, 0x069d, // placeholder
|
sl@0
|
138 |
0x069e, 0x069e, 0x069e, // placeholder
|
sl@0
|
139 |
0x069f, 0x069f, 0x069f, // placeholder
|
sl@0
|
140 |
|
sl@0
|
141 |
0x06a0, 0x06a0, 0x06a0, // placeholder
|
sl@0
|
142 |
0x06a1, 0x06a1, 0x06a1, // placeholder
|
sl@0
|
143 |
0x06a2, 0x06a2, 0x06a2, // placeholder
|
sl@0
|
144 |
0x06a3, 0x06a3, 0x06a3, // placeholder
|
sl@0
|
145 |
0xfb6b, 0xfb6c, 0xfb6d, // 6a4
|
sl@0
|
146 |
0x06a5, 0x06a5, 0x06a5, // placeholder
|
sl@0
|
147 |
0xfb6f, 0xfb70, 0xfb71, // 6a6
|
sl@0
|
148 |
0x06a7, 0x06a7, 0x06a7, // placeholder
|
sl@0
|
149 |
0x06a8, 0x06a8, 0x06a8, // placeholder
|
sl@0
|
150 |
0xfb8f, 0xfb90, 0xfb91, // 6a9
|
sl@0
|
151 |
0x06aa, 0x06aa, 0x06aa, // 6aa
|
sl@0
|
152 |
0x06ab, 0x06ab, 0x06ab, // 6ab
|
sl@0
|
153 |
0x06ac, 0x06ac, 0x06ac, // 6ac
|
sl@0
|
154 |
0xfbd4, 0xfbd5, 0xfbd6, // 6ad
|
sl@0
|
155 |
0x06ae, 0x06ae, 0x06ae, // 6ae
|
sl@0
|
156 |
0xfb93, 0xfb94, 0xfb95, // 6af
|
sl@0
|
157 |
|
sl@0
|
158 |
0x06b0, 0x06b0, 0x06b0, // placeholder
|
sl@0
|
159 |
0xfb9b, 0xfb9c, 0xfb9d, // 6b1
|
sl@0
|
160 |
0x06b2, 0x06b2, 0x06b2, // 6b2
|
sl@0
|
161 |
0xfb97, 0xfb98, 0xfb99, // 6b3
|
sl@0
|
162 |
0x06b4, 0x06b4, 0x06b4, // placeholder
|
sl@0
|
163 |
0x06b5, 0x06b5, 0x06b5, // placeholder
|
sl@0
|
164 |
0x06b6, 0x06b6, 0x06b6, // placeholder
|
sl@0
|
165 |
0x06b7, 0x06b7, 0x06b7, // placeholder
|
sl@0
|
166 |
0x06b8, 0x06b8, 0x06b8, // placeholder
|
sl@0
|
167 |
0x06b9, 0x06b9, 0x06b9, // placeholder
|
sl@0
|
168 |
0xfb9f, 0x06ba, 0x06ba, // 6ba
|
sl@0
|
169 |
0xfba1, 0xfba2, 0xfba3, // 6bb
|
sl@0
|
170 |
0x06bc, 0x06bc, 0x06bc, // placeholder
|
sl@0
|
171 |
0x06bd, 0x06bd, 0x06bd, // placeholder
|
sl@0
|
172 |
0xfbab, 0xfbac, 0xfbad, // 6be
|
sl@0
|
173 |
0x06bf, 0x06bf, 0x06bf, // placeholder
|
sl@0
|
174 |
|
sl@0
|
175 |
0xfba5, 0x06c0, 0x06c0, // 6c0
|
sl@0
|
176 |
0xfba7, 0xfba8, 0xfba9, // 6c1
|
sl@0
|
177 |
0x06c2, 0x06c2, 0x06c2, // placeholder
|
sl@0
|
178 |
0x06c3, 0x06c3, 0x06c3, // placeholder
|
sl@0
|
179 |
0x06c4, 0x06c4, 0x06c4, // placeholder
|
sl@0
|
180 |
0xfbe1, 0x06c5, 0x06c5, // 6c5
|
sl@0
|
181 |
0xfbda, 0x06c6, 0x06c6, // 6c6
|
sl@0
|
182 |
0xfbd8, 0x06c7, 0x06c7, // 6c7
|
sl@0
|
183 |
0xfbdc, 0x06c8, 0x06c8, // 6c8
|
sl@0
|
184 |
0xfbe3, 0x06c9, 0x06c9, // 6c9
|
sl@0
|
185 |
0x06ca, 0x06ca, 0x06ca, // placeholder
|
sl@0
|
186 |
0xfbdf, 0x06cb, 0x06cb, // 6cb
|
sl@0
|
187 |
0xfbfd, 0xfbfe, 0xfbff, // 6cc
|
sl@0
|
188 |
0x06cd, 0x06cd, 0x06cd, // placeholder
|
sl@0
|
189 |
0x06ce, 0x06ce, 0x06ce, // placeholder
|
sl@0
|
190 |
0x06cf, 0x06cf, 0x06cf, // placeholder
|
sl@0
|
191 |
|
sl@0
|
192 |
0xfbe5, 0xfbe6, 0xfbe7, // 6d0
|
sl@0
|
193 |
0x06d1, 0x06d1, 0x06d1, // placeholder
|
sl@0
|
194 |
0xfbaf, 0x06d2, 0x06d2, // 6d2
|
sl@0
|
195 |
0xfbb1, 0x06d3, 0x06d3 // 6d3
|
sl@0
|
196 |
};
|
sl@0
|
197 |
|
sl@0
|
198 |
|
sl@0
|
199 |
static const int KFinal = 0;
|
sl@0
|
200 |
static const int KInitial = 1;
|
sl@0
|
201 |
static const int KMedial = 2;
|
sl@0
|
202 |
static const int KStandardShapeTableOffset = 0x621;
|
sl@0
|
203 |
static const int KLamAlefShapeTableStart = 0x64B - 0x621;
|
sl@0
|
204 |
static const int KExtendedShapeTableOffset = 0x671 - (0x64f - 0x621);
|
sl@0
|
205 |
|
sl@0
|
206 |
|
sl@0
|
207 |
static inline TInt ArabicShapeTableIndex(TInt aCode)
|
sl@0
|
208 |
{
|
sl@0
|
209 |
if (aCode >= 0x621 && aCode <= 0x64a)
|
sl@0
|
210 |
return (aCode - KStandardShapeTableOffset) * 3;
|
sl@0
|
211 |
if (aCode >= 0x671 && aCode <= 0x6d3)
|
sl@0
|
212 |
return (aCode - KExtendedShapeTableOffset) * 3;
|
sl@0
|
213 |
return KErrNotFound;
|
sl@0
|
214 |
}
|
sl@0
|
215 |
|
sl@0
|
216 |
|
sl@0
|
217 |
static inline TBool IsArabicPoint(TInt aCode)
|
sl@0
|
218 |
{
|
sl@0
|
219 |
return (aCode >= 0x64B && aCode <= 0x655) || aCode == 0x670;
|
sl@0
|
220 |
}
|
sl@0
|
221 |
|
sl@0
|
222 |
TInt ConsumeCharsAndDeterminePresentationForm(const TUtf32Iterator& aText,
|
sl@0
|
223 |
TUint aFlags, TInt& aLigaturePortionsRemaining)
|
sl@0
|
224 |
/**
|
sl@0
|
225 |
Get the Arabic or other presentation form, consuming as many characters
|
sl@0
|
226 |
as necessary. This function can cope with text that has already been
|
sl@0
|
227 |
reversed.
|
sl@0
|
228 |
@internalComponent
|
sl@0
|
229 |
*/
|
sl@0
|
230 |
{
|
sl@0
|
231 |
TUint c = aText.Get();
|
sl@0
|
232 |
TInt index = ArabicShapeTableIndex(c);
|
sl@0
|
233 |
if (index != -1)
|
sl@0
|
234 |
{
|
sl@0
|
235 |
if (aLigaturePortionsRemaining != 0)
|
sl@0
|
236 |
{
|
sl@0
|
237 |
--aLigaturePortionsRemaining;
|
sl@0
|
238 |
GDI_ASSERT_DEBUG(!aText.AtEnd(), EGdiPanic_Invariant);
|
sl@0
|
239 |
return 0xFFFF;
|
sl@0
|
240 |
}
|
sl@0
|
241 |
|
sl@0
|
242 |
int position = -1;
|
sl@0
|
243 |
|
sl@0
|
244 |
// Find previous and next character, skipping Arabic points.
|
sl@0
|
245 |
TUtf32Iterator tmpText(aText);
|
sl@0
|
246 |
tmpText.Prev();
|
sl@0
|
247 |
TUint prev = 0xFFFF;
|
sl@0
|
248 |
while (!tmpText.BeforeStart() && (prev == 0xFFFF || IsArabicPoint(prev)))
|
sl@0
|
249 |
prev = tmpText.GetThenPrev();
|
sl@0
|
250 |
|
sl@0
|
251 |
tmpText = aText;
|
sl@0
|
252 |
tmpText.Next();
|
sl@0
|
253 |
TUint next = 0xFFFF;
|
sl@0
|
254 |
while (!tmpText.AtEnd() && (next == 0xFFFF || IsArabicPoint(next)))
|
sl@0
|
255 |
next = tmpText.GetThenNext();
|
sl@0
|
256 |
|
sl@0
|
257 |
TInt possible_lam = (aFlags & CFont::TPositionParam::EFLogicalOrder)?
|
sl@0
|
258 |
c : next;
|
sl@0
|
259 |
TInt possible_alef = (aFlags & CFont::TPositionParam::EFLogicalOrder)?
|
sl@0
|
260 |
next : c;
|
sl@0
|
261 |
|
sl@0
|
262 |
// Perform lam-alef ligation if necessary.
|
sl@0
|
263 |
if (possible_lam == 0x644 &&
|
sl@0
|
264 |
(possible_alef == 0x622 || possible_alef == 0x623 || possible_alef == 0x625 || possible_alef == 0x627))
|
sl@0
|
265 |
{
|
sl@0
|
266 |
switch(possible_alef)
|
sl@0
|
267 |
{
|
sl@0
|
268 |
case 0x622:
|
sl@0
|
269 |
{
|
sl@0
|
270 |
c = 0xfef5;
|
sl@0
|
271 |
index = KLamAlefShapeTableStart;
|
sl@0
|
272 |
break;
|
sl@0
|
273 |
}
|
sl@0
|
274 |
case 0x623:
|
sl@0
|
275 |
{
|
sl@0
|
276 |
c = 0xfef7;
|
sl@0
|
277 |
index = KLamAlefShapeTableStart + 1;
|
sl@0
|
278 |
break;
|
sl@0
|
279 |
}
|
sl@0
|
280 |
case 0x625:
|
sl@0
|
281 |
{
|
sl@0
|
282 |
c = 0xfef9;
|
sl@0
|
283 |
index = KLamAlefShapeTableStart + 2;
|
sl@0
|
284 |
break;
|
sl@0
|
285 |
}
|
sl@0
|
286 |
default:
|
sl@0
|
287 |
{
|
sl@0
|
288 |
c = 0xfefb;
|
sl@0
|
289 |
index = KLamAlefShapeTableStart + 3;
|
sl@0
|
290 |
}
|
sl@0
|
291 |
}
|
sl@0
|
292 |
index *= 3;
|
sl@0
|
293 |
aLigaturePortionsRemaining = 2;
|
sl@0
|
294 |
|
sl@0
|
295 |
next = 0xFFFF;
|
sl@0
|
296 |
while (!tmpText.AtEnd() && (next == 0xFFFF || IsArabicPoint(next)))
|
sl@0
|
297 |
{
|
sl@0
|
298 |
next = tmpText.Get();
|
sl@0
|
299 |
tmpText.Next();
|
sl@0
|
300 |
}
|
sl@0
|
301 |
}
|
sl@0
|
302 |
|
sl@0
|
303 |
TInt left = (aFlags & CFont::TPositionParam::EFLogicalOrder)? prev : next;
|
sl@0
|
304 |
TInt right = (aFlags & CFont::TPositionParam::EFLogicalOrder)? next : prev;
|
sl@0
|
305 |
|
sl@0
|
306 |
TBool prefix = FALSE;
|
sl@0
|
307 |
if (left == 0x640 || left == 0x200D) // kashida or Zero-Width Joiner
|
sl@0
|
308 |
prefix = TRUE;
|
sl@0
|
309 |
else
|
sl@0
|
310 |
{
|
sl@0
|
311 |
TInt left_index = ArabicShapeTableIndex(left);
|
sl@0
|
312 |
if (left_index != -1)
|
sl@0
|
313 |
{
|
sl@0
|
314 |
if (static_cast<TInt>(TheArabicShapeTable[left_index + KInitial]) != left ||
|
sl@0
|
315 |
static_cast<TInt>(TheArabicShapeTable[left_index + KMedial]) != left)
|
sl@0
|
316 |
prefix = TRUE;
|
sl@0
|
317 |
}
|
sl@0
|
318 |
}
|
sl@0
|
319 |
TBool suffix = FALSE;
|
sl@0
|
320 |
if (right == 0x640 || right == 0x200D) // kashida or Zero-Width Joiner
|
sl@0
|
321 |
suffix = TRUE;
|
sl@0
|
322 |
else
|
sl@0
|
323 |
{
|
sl@0
|
324 |
TInt right_index = ArabicShapeTableIndex(right);
|
sl@0
|
325 |
if (right_index != -1)
|
sl@0
|
326 |
{
|
sl@0
|
327 |
if (static_cast<TInt>(TheArabicShapeTable[right_index + KFinal]) != right ||
|
sl@0
|
328 |
static_cast<TInt>(TheArabicShapeTable[right_index + KMedial]) != right)
|
sl@0
|
329 |
suffix = TRUE;
|
sl@0
|
330 |
}
|
sl@0
|
331 |
}
|
sl@0
|
332 |
TBool medial = static_cast<TUint>(TheArabicShapeTable[index + KMedial]) != c;
|
sl@0
|
333 |
if (medial)
|
sl@0
|
334 |
{
|
sl@0
|
335 |
if (prefix && suffix)
|
sl@0
|
336 |
position = KMedial;
|
sl@0
|
337 |
else if (prefix)
|
sl@0
|
338 |
position = KFinal;
|
sl@0
|
339 |
else if (suffix)
|
sl@0
|
340 |
position = KInitial;
|
sl@0
|
341 |
}
|
sl@0
|
342 |
else
|
sl@0
|
343 |
{
|
sl@0
|
344 |
if (prefix)
|
sl@0
|
345 |
position = KFinal;
|
sl@0
|
346 |
else if (suffix)
|
sl@0
|
347 |
position = KInitial;
|
sl@0
|
348 |
}
|
sl@0
|
349 |
if (position >= 0)
|
sl@0
|
350 |
c = TheArabicShapeTable[index + position];
|
sl@0
|
351 |
}
|
sl@0
|
352 |
|
sl@0
|
353 |
return c;
|
sl@0
|
354 |
}
|
sl@0
|
355 |
|
sl@0
|
356 |
|
sl@0
|
357 |
//
|
sl@0
|
358 |
//
|
sl@0
|
359 |
// GlyphSelector_Arabic Class definition
|
sl@0
|
360 |
//
|
sl@0
|
361 |
//
|
sl@0
|
362 |
|
sl@0
|
363 |
TBool GlyphSelector_Arabic::Process(TGlyphSelectionState& aGss, RShapeInfo&)
|
sl@0
|
364 |
{
|
sl@0
|
365 |
// Select glyph - use presentation form if applicable.
|
sl@0
|
366 |
TInt ligaturePortions = aGss.iLigaturePortionsRemaining;
|
sl@0
|
367 |
TUint flags = aGss.iParam.iFlags;
|
sl@0
|
368 |
TUint code = ConsumeCharsAndDeterminePresentationForm(aGss.iText,
|
sl@0
|
369 |
flags, ligaturePortions);
|
sl@0
|
370 |
|
sl@0
|
371 |
aGss.iText.Next();
|
sl@0
|
372 |
aGss.iClusterState = !aGss.iText.AtEnd() &&
|
sl@0
|
373 |
(aGss.iText.Get().GetCategory() & 0xF0) == TChar::EMarkGroup?
|
sl@0
|
374 |
TGlyphSelectionState::EGClusterNotComplete
|
sl@0
|
375 |
: TGlyphSelectionState::EGClusterComplete;
|
sl@0
|
376 |
|
sl@0
|
377 |
// If we are beginning a new portion of a ligature, we must set the state.
|
sl@0
|
378 |
if (ligaturePortions != aGss.iLigaturePortionsRemaining)
|
sl@0
|
379 |
{
|
sl@0
|
380 |
if (ligaturePortions != 1)
|
sl@0
|
381 |
aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
|
sl@0
|
382 |
aGss.iLigaturePortionFirstMark = aGss.iParam.iOutputGlyphs;
|
sl@0
|
383 |
if (ligaturePortions < aGss.iLigaturePortionsRemaining)
|
sl@0
|
384 |
{
|
sl@0
|
385 |
aGss.iLigaturePortionsRemaining = ligaturePortions;
|
sl@0
|
386 |
// We have just swallowed a non-initial part of the ligature, which
|
sl@0
|
387 |
// must not be drawn.
|
sl@0
|
388 |
GDI_ASSERT_DEBUG(code == 0xFFFF, EGdiPanic_Invariant);
|
sl@0
|
389 |
return ETrue;
|
sl@0
|
390 |
}
|
sl@0
|
391 |
aGss.iLigaturePortionsRemaining = ligaturePortions;
|
sl@0
|
392 |
}
|
sl@0
|
393 |
|
sl@0
|
394 |
// In this method we always output the glyph code calculate previously.
|
sl@0
|
395 |
if (!aGss.AppendGlyphToCluster(code))
|
sl@0
|
396 |
return EFalse;
|
sl@0
|
397 |
|
sl@0
|
398 |
if (!aGss.IsCombiningClass())
|
sl@0
|
399 |
{
|
sl@0
|
400 |
aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
|
sl@0
|
401 |
return ETrue;
|
sl@0
|
402 |
}
|
sl@0
|
403 |
|
sl@0
|
404 |
// Adjust glyph's bounds further to position this character.
|
sl@0
|
405 |
aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
|
sl@0
|
406 |
TRect baseBounds = aGss.iParam.iOutput[0].iBounds;
|
sl@0
|
407 |
TInt firstMark = 1;
|
sl@0
|
408 |
if (aGss.iLigaturePortionsRemaining != 0)
|
sl@0
|
409 |
{
|
sl@0
|
410 |
TInt centre = (baseBounds.iBr.iX + baseBounds.iTl.iX) >> 1;
|
sl@0
|
411 |
TBool firstHalf = aGss.iLigaturePortionsRemaining == 2;
|
sl@0
|
412 |
TBool rightHandSide = flags & CFont::TPositionParam::EFLogicalOrder?
|
sl@0
|
413 |
firstHalf : !firstHalf;
|
sl@0
|
414 |
if (rightHandSide)
|
sl@0
|
415 |
baseBounds.iTl.iX = centre;
|
sl@0
|
416 |
else
|
sl@0
|
417 |
baseBounds.iBr.iX = centre;
|
sl@0
|
418 |
if (firstHalf)
|
sl@0
|
419 |
aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
|
sl@0
|
420 |
firstMark = aGss.iLigaturePortionFirstMark;
|
sl@0
|
421 |
}
|
sl@0
|
422 |
aGss.CombineLastGlyphToBase(baseBounds, firstMark);
|
sl@0
|
423 |
|
sl@0
|
424 |
return ETrue;
|
sl@0
|
425 |
}
|
sl@0
|
426 |
|
sl@0
|
427 |
|
sl@0
|
428 |
TBool GlyphSelector_Arabic::CharactersJoin(TInt aLeftCharacter, TInt aRightCharacter)
|
sl@0
|
429 |
{
|
sl@0
|
430 |
// All the characters join to the right, so we don't need to look them up.
|
sl@0
|
431 |
// as long as they are there at all, it is OK.
|
sl@0
|
432 |
TBool leftIsFixedJoiner = aLeftCharacter == 0x640 || aLeftCharacter == 0x200D;
|
sl@0
|
433 |
if (!leftIsFixedJoiner)
|
sl@0
|
434 |
{
|
sl@0
|
435 |
TInt leftIndex = ArabicShapeTableIndex(aLeftCharacter);
|
sl@0
|
436 |
if (leftIndex == -1)
|
sl@0
|
437 |
return EFalse;
|
sl@0
|
438 |
if (static_cast<TInt>(TheArabicShapeTable[leftIndex + KFinal])
|
sl@0
|
439 |
== aLeftCharacter)
|
sl@0
|
440 |
return EFalse;
|
sl@0
|
441 |
}
|
sl@0
|
442 |
if (aRightCharacter == 0x640 || aRightCharacter == 0x200D)
|
sl@0
|
443 |
return !leftIsFixedJoiner;
|
sl@0
|
444 |
TInt rightIndex = ArabicShapeTableIndex(aRightCharacter);
|
sl@0
|
445 |
return rightIndex != -1
|
sl@0
|
446 |
&& static_cast<TInt>(TheArabicShapeTable[rightIndex + KInitial])
|
sl@0
|
447 |
!= aRightCharacter;
|
sl@0
|
448 |
}
|
sl@0
|
449 |
|