Committed by
David PHAM-VAN
Apply THE BIDIRECTIONAL ALGORITHM using dart_bidi lib
Rename some related references
Showing
8 changed files
with
181 additions
and
477 deletions
pdf/lib/src/pdf/font/arabic.dart
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | - | ||
17 | -/// Arabic shape substitutions: char code => (isolated, final, initial, medial). | ||
18 | -/// Arabic Substition A | ||
19 | -const Map<int, dynamic> _arabicSubstitionA = <int, dynamic>{ | ||
20 | - 0x0640: <int>[0x0640, 0x0640, 0x0640, 0x0640], // ARABIC TATWEEL | ||
21 | - | ||
22 | - 0x0621: <int>[1569], // ARABIC LETTER HAMZA | ||
23 | - 0x0622: <int>[1570, 0xFE82], // ARABIC LETTER ALEF WITH MADDA ABOVE | ||
24 | - 0x0623: <int>[1571, 0xFE84], // ARABIC LETTER ALEF WITH HAMZA ABOVE | ||
25 | - 0x0624: <int>[1572, 0xFE86], // ARABIC LETTER WAW WITH HAMZA ABOVE | ||
26 | - 0x0625: <int>[1573, 0xFE88], // ARABIC LETTER ALEF WITH HAMZA BELOW | ||
27 | - 0x0626: <int>[ | ||
28 | - 1574, | ||
29 | - 0xFE8A, | ||
30 | - 0xFE8B, | ||
31 | - 0xFE8C | ||
32 | - ], // ARABIC LETTER YEH WITH HAMZA ABOVE | ||
33 | - 0x0627: <int>[1575, 0xFE8E], // ARABIC LETTER ALEF | ||
34 | - 0x0628: <int>[1576, 0xFE90, 0xFE91, 0xFE92], // ARABIC LETTER BEH | ||
35 | - 0x0629: <int>[1577, 0xFE94], // ARABIC LETTER TEH MARBUTA | ||
36 | - 0x062A: <int>[1578, 0xFE96, 0xFE97, 0xFE98], // ARABIC LETTER TEH | ||
37 | - 0x062B: <int>[1579, 0xFE9A, 0xFE9B, 0xFE9C], // ARABIC LETTER THEH | ||
38 | - 0x062C: <int>[1580, 0xFE9E, 0xFE9F, 0xFEA0], // ARABIC LETTER JEEM | ||
39 | - 0x062D: <int>[1581, 0xFEA2, 0xFEA3, 0xFEA4], // ARABIC LETTER HAH | ||
40 | - 0x062E: <int>[1582, 0xFEA6, 0xFEA7, 0xFEA8], // ARABIC LETTER KHAH | ||
41 | - 0x062F: <int>[1583, 0xFEAA], // ARABIC LETTER DAL | ||
42 | - 0x0630: <int>[1584, 0xFEAC], // ARABIC LETTER THAL | ||
43 | - 0x0631: <int>[1585, 0xFEAE], // ARABIC LETTER REH | ||
44 | - 0x0632: <int>[1586, 0xFEB0], // ARABIC LETTER ZAIN | ||
45 | - 0x0633: <int>[1587, 0xFEB2, 0xFEB3, 0xFEB4], // ARABIC LETTER SEEN | ||
46 | - 0x0634: <int>[1588, 0xFEB6, 0xFEB7, 0xFEB8], // ARABIC LETTER SHEEN | ||
47 | - 0x0635: <int>[1589, 0xFEBA, 0xFEBB, 0xFEBC], // ARABIC LETTER SAD | ||
48 | - 0x0636: <int>[1590, 0xFEBE, 0xFEBF, 0xFEC0], // ARABIC LETTER DAD | ||
49 | - 0x0637: <int>[1591, 0xFEC2, 0xFEC3, 0xFEC4], // ARABIC LETTER TAH | ||
50 | - 0x0638: <int>[1592, 0xFEC6, 0xFEC7, 0xFEC8], // ARABIC LETTER ZAH | ||
51 | - 0x0639: <int>[1593, 0xFECA, 0xFECB, 0xFECC], // ARABIC LETTER AIN | ||
52 | - 0x063A: <int>[1594, 0xFECE, 0xFECF, 0xFED0], // ARABIC LETTER GHAIN | ||
53 | - 0x0641: <int>[1601, 0xFED2, 0xFED3, 0xFED4], // ARABIC LETTER FEH | ||
54 | - 0x0642: <int>[1602, 0xFED6, 0xFED7, 0xFED8], // ARABIC LETTER QAF | ||
55 | - 0x0643: <int>[1603, 0xFEDA, 0xFEDB, 0xFEDC], // ARABIC LETTER KAF | ||
56 | - 0x0644: <int>[1604, 0xFEDE, 0xFEDF, 0xFEE0], // ARABIC LETTER LAM | ||
57 | - 0x0645: <int>[1605, 0xFEE2, 0xFEE3, 0xFEE4], // ARABIC LETTER MEEM | ||
58 | - 0x0646: <int>[1606, 0xFEE6, 0xFEE7, 0xFEE8], // ARABIC LETTER NOON | ||
59 | - 0x0647: <int>[1607, 0xFEEA, 0xFEEB, 0xFEEC], // ARABIC LETTER HEH | ||
60 | - 0x0648: <int>[1608, 0xFEEE], // ARABIC LETTER WAW | ||
61 | - 0x0649: <int>[1609, 0xFEF0, 64488, 64489], // ARABIC LETTER ALEF MAKSURA | ||
62 | - 0x064A: <int>[1610, 0xFEF2, 0xFEF3, 0xFEF4], // ARABIC LETTER YEH | ||
63 | - 0x0671: <int>[0xFB50, 0xFB51], // ARABIC LETTER ALEF WASLA | ||
64 | - 0x0677: <int>[0xFBDD], // ARABIC LETTER U WITH HAMZA ABOVE | ||
65 | - 0x0679: <int>[0xFB66, 0xFB67, 0xFB68, 0xFB69], // ARABIC LETTER TTEH | ||
66 | - 0x067A: <int>[0xFB5E, 0xFB5F, 0xFB60, 0xFB61], // ARABIC LETTER TTEHEH | ||
67 | - 0x067B: <int>[0xFB52, 0xFB53, 0xFB54, 0xFB55], // ARABIC LETTER BEEH | ||
68 | - 0x067E: <int>[0xFB56, 0xFB57, 0xFB58, 0xFB59], // ARABIC LETTER PEH | ||
69 | - 0x067F: <int>[0xFB62, 0xFB63, 0xFB64, 0xFB65], // ARABIC LETTER TEHEH | ||
70 | - 0x0680: <int>[0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D], // ARABIC LETTER BEHEH | ||
71 | - 0x0683: <int>[0xFB76, 0xFB77, 0xFB78, 0xFB79], // ARABIC LETTER NYEH | ||
72 | - 0x0684: <int>[0xFB72, 0xFB73, 0xFB74, 0xFB75], // ARABIC LETTER DYEH | ||
73 | - 0x0686: <int>[0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D], // ARABIC LETTER TCHEH | ||
74 | - 0x0687: <int>[0xFB7E, 0xFB7F, 0xFB80, 0xFB81], // ARABIC LETTER TCHEHEH | ||
75 | - 0x0688: <int>[0xFB88, 0xFB89], // ARABIC LETTER DDAL | ||
76 | - 0x068C: <int>[0xFB84, 0xFB85], // ARABIC LETTER DAHAL | ||
77 | - 0x068D: <int>[0xFB82, 0xFB83], // ARABIC LETTER DDAHAL | ||
78 | - 0x068E: <int>[0xFB86, 0xFB87], // ARABIC LETTER DUL | ||
79 | - 0x0691: <int>[0xFB8C, 0xFB8D], // ARABIC LETTER RREH | ||
80 | - 0x0698: <int>[0xFB8A, 0xFB8B], // ARABIC LETTER JEH | ||
81 | - 0x06A4: <int>[0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D], // ARABIC LETTER VEH | ||
82 | - 0x06A6: <int>[0xFB6E, 0xFB6F, 0xFB70, 0xFB71], // ARABIC LETTER PEHEH | ||
83 | - 0x06A9: <int>[0xFB8E, 0xFB8F, 0xFB90, 0xFB91], // ARABIC LETTER KEHEH | ||
84 | - 0x06AD: <int>[0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6], // ARABIC LETTER NG | ||
85 | - 0x06AF: <int>[0xFB92, 0xFB93, 0xFB94, 0xFB95], // ARABIC LETTER GAF | ||
86 | - 0x06B1: <int>[0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D], // ARABIC LETTER NGOEH | ||
87 | - 0x06B3: <int>[0xFB96, 0xFB97, 0xFB98, 0xFB99], // ARABIC LETTER GUEH | ||
88 | - 0x06BA: <int>[0xFB9E, 0xFB9F], // ARABIC LETTER NOON GHUNNA | ||
89 | - 0x06BB: <int>[0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3], // ARABIC LETTER RNOON | ||
90 | - 0x06BE: <int>[ | ||
91 | - 0xFBAA, | ||
92 | - 0xFBAB, | ||
93 | - 0xFBAC, | ||
94 | - 0xFBAD | ||
95 | - ], // ARABIC LETTER HEH DOACHASHMEE | ||
96 | - 0x06C0: <int>[0xFBA4, 0xFBA5], // ARABIC LETTER HEH WITH YEH ABOVE | ||
97 | - 0x06C1: <int>[0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9], // ARABIC LETTER HEH GOAL | ||
98 | - 0x06C5: <int>[0xFBE0, 0xFBE1], // ARABIC LETTER KIRGHIZ OE | ||
99 | - 0x06C6: <int>[0xFBD9, 0xFBDA], // ARABIC LETTER OE | ||
100 | - 0x06C7: <int>[0xFBD7, 0xFBD8], // ARABIC LETTER U | ||
101 | - 0x06C8: <int>[0xFBDB, 0xFBDC], // ARABIC LETTER YU | ||
102 | - 0x06C9: <int>[0xFBE2, 0xFBE3], // ARABIC LETTER KIRGHIZ YU | ||
103 | - 0x06CB: <int>[0xFBDE, 0xFBDF], // ARABIC LETTER VE | ||
104 | - 0x06CC: <int>[0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF], // ARABIC LETTER FARSI YEH | ||
105 | - 0x06D0: <int>[0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7], //ARABIC LETTER E | ||
106 | - 0x06D2: <int>[0xFBAE, 0xFBAF], // ARABIC LETTER YEH BARREE | ||
107 | - 0x06D3: <int>[0xFBB0, 0xFBB1], // ARABIC LETTER YEH BARREE WITH HAMZA ABOVE | ||
108 | -}; | ||
109 | - | ||
110 | -/* | ||
111 | - var ligaturesSubstitutionA = { | ||
112 | - 0xFBEA: []// ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM | ||
113 | - }; | ||
114 | - */ | ||
115 | - | ||
116 | -const Map<int, dynamic> _diacriticLigatures = <int, dynamic>{ | ||
117 | - 0x0651: <int, int>{ | ||
118 | - 0x064C: 0xFC5E, // Shadda + Dammatan | ||
119 | - 0x064D: 0xFC5F, // Shadda + Kasratan | ||
120 | - 0x064E: 0xFC60, // Shadda + Fatha | ||
121 | - 0x064F: 0xFC61, // Shadda + Damma | ||
122 | - 0x0650: 0xFC62, // Shadda + Kasra | ||
123 | - 0x0670: 0xFC63, // Shadda + Dagger alif | ||
124 | - }, | ||
125 | -}; | ||
126 | - | ||
127 | -const Map<int, dynamic> _ligatures = <int, dynamic>{ | ||
128 | - 0xFEDF: <int, int>{ | ||
129 | - 0xFE82: | ||
130 | - 0xFEF5, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM | ||
131 | - 0xFE84: | ||
132 | - 0xFEF7, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM | ||
133 | - 0xFE88: | ||
134 | - 0xFEF9, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM | ||
135 | - 0xFE8E: 0xFEFB // ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM | ||
136 | - }, | ||
137 | - 0xFEE0: <int, int>{ | ||
138 | - 0xFE82: 0xFEF6, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM | ||
139 | - 0xFE84: 0xFEF8, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM | ||
140 | - 0xFE88: 0xFEFA, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM | ||
141 | - 0xFE8E: 0xFEFC // ARABIC LIGATURE LAM WITH ALEF FINAL FORM | ||
142 | - }, | ||
143 | - 0xFE8D: <int, dynamic>{ | ||
144 | - 0xFEDF: <int, dynamic>{ | ||
145 | - 0xFEE0: <int, int>{0xFEEA: 0xFDF2} | ||
146 | - } | ||
147 | - }, // ALLAH | ||
148 | -}; | ||
149 | - | ||
150 | -const List<int> _alfletter = <int>[1570, 1571, 1573, 1575]; | ||
151 | - | ||
152 | -const Map<int, int> _arabicDiacritics = <int, int>{ | ||
153 | - 0x064B: 0x064B, // Fathatan | ||
154 | - 0x064C: 0x064C, // Dammatan | ||
155 | - 0x064D: 0x064D, // Kasratan | ||
156 | - 0x064E: 0x064E, // Fatha | ||
157 | - 0x064F: 0x064F, // Damma | ||
158 | - 0x0650: 0x0650, // Kasra | ||
159 | - 0x0651: 0x0651, // Shadda | ||
160 | - 0x0652: 0x0652, // Sukun | ||
161 | - | ||
162 | - 0x0670: 0x0670, // Dagger alif | ||
163 | - | ||
164 | - 0xFC5E: 0xFC5E, // Shadda + Dammatan | ||
165 | - 0xFC5F: 0xFC5F, // Shadda + Kasratan | ||
166 | - 0xFC60: 0xFC60, // Shadda + Fatha | ||
167 | - 0xFC61: 0xFC61, // Shadda + Damma | ||
168 | - 0xFC62: 0xFC62, // Shadda + Kasra | ||
169 | - 0xFC63: 0xFC63, // Shadda + Dagger alif | ||
170 | - // 1548: 1548, | ||
171 | -}; | ||
172 | - | ||
173 | -const int _noChangeInForm = -1; | ||
174 | -const int _isolatedForm = 0; | ||
175 | -const int _finalForm = 1; | ||
176 | -const int _initialForm = 2; | ||
177 | -const int _medialForm = 3; | ||
178 | - | ||
179 | -bool _isInArabicSubstitutionA(int letter) { | ||
180 | - return _arabicSubstitionA.containsKey(letter); | ||
181 | -} | ||
182 | - | ||
183 | -bool _isArabicLetter(int letter) { | ||
184 | - return (letter >= 0x0600 && letter <= 0x06FF) || | ||
185 | - (letter >= 0x0750 && letter <= 0x077F) || | ||
186 | - (letter >= 0x0870 && letter <= 0x089F) || | ||
187 | - (letter >= 0x08A0 && letter <= 0x08FF) || | ||
188 | - (letter >= 0xFB50 && letter <= 0xFDFF) || | ||
189 | - (letter >= 0xFE70 && letter <= 0xFEFF) || | ||
190 | - (letter >= 0x10E60 && letter <= 0x10E7F) || | ||
191 | - (letter >= 0x1EC70 && letter <= 0x1ECBF) || | ||
192 | - (letter >= 0x1ED00 && letter <= 0x1ED4F) || | ||
193 | - (letter >= 0x1EE00 && letter <= 0x1EEFF); | ||
194 | -} | ||
195 | - | ||
196 | -bool _isArabicEndLetter(int letter) { | ||
197 | - return _isArabicLetter(letter) && | ||
198 | - _isInArabicSubstitutionA(letter) && | ||
199 | - _arabicSubstitionA[letter].length <= 2; | ||
200 | -} | ||
201 | - | ||
202 | -bool _isArabicAlfLetter(int letter) { | ||
203 | - return _isArabicLetter(letter) && _alfletter.contains(letter); | ||
204 | -} | ||
205 | - | ||
206 | -bool _arabicLetterHasFinalForm(int letter) { | ||
207 | - return _isArabicLetter(letter) && | ||
208 | - _isInArabicSubstitutionA(letter) && | ||
209 | - (_arabicSubstitionA[letter].length >= 2); | ||
210 | -} | ||
211 | - | ||
212 | -bool _arabicLetterHasMedialForm(int letter) { | ||
213 | - return _isArabicLetter(letter) && | ||
214 | - _isInArabicSubstitutionA(letter) && | ||
215 | - _arabicSubstitionA[letter].length == 4; | ||
216 | -} | ||
217 | - | ||
218 | -bool _isArabicDiacritic(int letter) { | ||
219 | - return _arabicDiacritics.containsKey(letter); | ||
220 | -} | ||
221 | - | ||
222 | -bool isArabicDiacriticValue(int letter) { | ||
223 | - return _arabicDiacritics.containsValue(letter); | ||
224 | -} | ||
225 | - | ||
226 | -List<int> _resolveLigatures(List<int> lettersq) { | ||
227 | - final result = <int>[]; | ||
228 | - dynamic tmpLigatures = _ligatures; | ||
229 | - dynamic tmpDiacritic = _diacriticLigatures; | ||
230 | - final letters = lettersq.reversed.toList(); | ||
231 | - | ||
232 | - final effectedLetters = <int>[]; | ||
233 | - final effectedDiacritics = <int>[]; | ||
234 | - | ||
235 | - final finalDiacritics = <int>[]; | ||
236 | - | ||
237 | - for (var i = 0; i < letters.length; i++) { | ||
238 | - if (isArabicDiacriticValue(letters[i])) { | ||
239 | - effectedDiacritics.insert(0, letters[i]); | ||
240 | - if (tmpDiacritic.containsKey(letters[i])) { | ||
241 | - tmpDiacritic = tmpDiacritic[letters[i]]; | ||
242 | - | ||
243 | - if (tmpDiacritic is int) { | ||
244 | - finalDiacritics.insert(0, tmpDiacritic); | ||
245 | - tmpDiacritic = _diacriticLigatures; | ||
246 | - effectedDiacritics.clear(); | ||
247 | - } | ||
248 | - } else { | ||
249 | - tmpDiacritic = _diacriticLigatures; | ||
250 | - | ||
251 | - // add all Diacritics if there is no letter Ligatures. | ||
252 | - if (effectedLetters.isEmpty) { | ||
253 | - result.insertAll(0, finalDiacritics); | ||
254 | - result.insertAll(0, effectedDiacritics); | ||
255 | - finalDiacritics.clear(); | ||
256 | - effectedDiacritics.clear(); | ||
257 | - } | ||
258 | - } | ||
259 | - } else if (tmpLigatures.containsKey(letters[i])) { | ||
260 | - effectedLetters.insert(0, letters[i]); | ||
261 | - tmpLigatures = tmpLigatures[letters[i]]; | ||
262 | - | ||
263 | - if (tmpLigatures is int) { | ||
264 | - result.insert(0, tmpLigatures); | ||
265 | - tmpLigatures = _ligatures; | ||
266 | - effectedLetters.clear(); | ||
267 | - } | ||
268 | - } else { | ||
269 | - tmpLigatures = _ligatures; | ||
270 | - | ||
271 | - // add effected letters if they aren't ligature. | ||
272 | - if (effectedLetters.isNotEmpty) { | ||
273 | - result.insertAll(0, effectedLetters); | ||
274 | - effectedLetters.clear(); | ||
275 | - } | ||
276 | - | ||
277 | - // add Diacritics after or before letter ligature. | ||
278 | - if (effectedLetters.isEmpty && effectedDiacritics.isNotEmpty) { | ||
279 | - result.insertAll(0, effectedDiacritics); | ||
280 | - effectedDiacritics.clear(); | ||
281 | - } | ||
282 | - | ||
283 | - result.insert(0, letters[i]); | ||
284 | - } | ||
285 | - | ||
286 | - // add Diacritic ligatures. | ||
287 | - if (effectedLetters.isEmpty && finalDiacritics.isNotEmpty) { | ||
288 | - result.insertAll(0, finalDiacritics); | ||
289 | - finalDiacritics.clear(); | ||
290 | - } | ||
291 | - } | ||
292 | - | ||
293 | - return result; | ||
294 | -} | ||
295 | - | ||
296 | -int _getCorrectForm(int currentChar, int beforeChar, int nextChar) { | ||
297 | - if (_isInArabicSubstitutionA(currentChar) == false) { | ||
298 | - return _noChangeInForm; | ||
299 | - } | ||
300 | - if (!_arabicLetterHasFinalForm(currentChar) || | ||
301 | - (!_isArabicLetter(beforeChar) && !_isArabicLetter(nextChar)) || | ||
302 | - (!_isArabicLetter(nextChar) && _isArabicEndLetter(beforeChar)) || | ||
303 | - (_isArabicEndLetter(currentChar) && !_isArabicLetter(beforeChar)) || | ||
304 | - (_isArabicEndLetter(currentChar) && _isArabicAlfLetter(beforeChar)) || | ||
305 | - (_isArabicEndLetter(currentChar) && _isArabicEndLetter(beforeChar))) { | ||
306 | - return _isolatedForm; | ||
307 | - } | ||
308 | - | ||
309 | - if (_arabicLetterHasMedialForm(currentChar) && | ||
310 | - _isArabicLetter(beforeChar) && | ||
311 | - !_isArabicEndLetter(beforeChar) && | ||
312 | - _isArabicLetter(nextChar) && | ||
313 | - _arabicLetterHasFinalForm(nextChar)) { | ||
314 | - return _medialForm; | ||
315 | - } | ||
316 | - | ||
317 | - if (_isArabicEndLetter(currentChar) || (!_isArabicLetter(nextChar))) { | ||
318 | - return _finalForm; | ||
319 | - } | ||
320 | - return _initialForm; | ||
321 | -} | ||
322 | - | ||
323 | -Iterable<String> _parse(String text) sync* { | ||
324 | - final words = text.split(' '); | ||
325 | - | ||
326 | - final notArabicWords = <List<int>>[]; | ||
327 | - | ||
328 | - var first = true; | ||
329 | - for (final word in words) { | ||
330 | - final newWord = <int>[]; | ||
331 | - var isNewWordArabic = false; | ||
332 | - | ||
333 | - var prevLetter = 0; | ||
334 | - | ||
335 | - for (var j = 0; j < word.length; j += 1) { | ||
336 | - final currentLetter = word.codeUnitAt(j); | ||
337 | - | ||
338 | - if (_isArabicDiacritic(currentLetter)) { | ||
339 | - newWord.insert(0, _arabicDiacritics[currentLetter]!); | ||
340 | - continue; | ||
341 | - } | ||
342 | - final nextLetter = word | ||
343 | - .split('') | ||
344 | - .skip(j + 1) | ||
345 | - .map((String e) => e.codeUnitAt(0)) | ||
346 | - .firstWhere( | ||
347 | - (int element) => !_isArabicDiacritic(element), | ||
348 | - orElse: () => 0, | ||
349 | - ); | ||
350 | - | ||
351 | - if (_isArabicLetter(currentLetter)) { | ||
352 | - isNewWordArabic = true; | ||
353 | - | ||
354 | - final position = _getCorrectForm(currentLetter, prevLetter, nextLetter); | ||
355 | - prevLetter = currentLetter; | ||
356 | - if (position != -1) { | ||
357 | - newWord.insert(0, _arabicSubstitionA[currentLetter][position]); | ||
358 | - } else { | ||
359 | - newWord.add(currentLetter); | ||
360 | - } | ||
361 | - } else { | ||
362 | - prevLetter = 0; | ||
363 | - if (isNewWordArabic && currentLetter > 32) { | ||
364 | - newWord.insert(0, currentLetter); | ||
365 | - } else { | ||
366 | - newWord.add(currentLetter); | ||
367 | - } | ||
368 | - } | ||
369 | - } | ||
370 | - | ||
371 | - if (!first && isNewWordArabic) { | ||
372 | - yield ' '; | ||
373 | - } | ||
374 | - first = false; | ||
375 | - | ||
376 | - if (isNewWordArabic) { | ||
377 | - isNewWordArabic = false; | ||
378 | - for (final notArabicNewWord in notArabicWords) { | ||
379 | - yield '${String.fromCharCodes(notArabicNewWord)} '; | ||
380 | - } | ||
381 | - notArabicWords.clear(); | ||
382 | - yield String.fromCharCodes(_resolveLigatures(newWord)); | ||
383 | - } else { | ||
384 | - notArabicWords.insert(0, newWord); | ||
385 | - } | ||
386 | - } | ||
387 | - // if notArabicWords.length != 0, that means all sentence doesn't contain Arabic. | ||
388 | - for (var i = 0; i < notArabicWords.length; i++) { | ||
389 | - if (!first) { | ||
390 | - yield ' '; | ||
391 | - } | ||
392 | - yield String.fromCharCodes(notArabicWords[i]); | ||
393 | - } | ||
394 | -} | ||
395 | - | ||
396 | -/// Apply Arabic shape substitutions | ||
397 | -String convert(String input) { | ||
398 | - final lines = input.split('\n'); | ||
399 | - final parsed = <String>[]; | ||
400 | - for (var i = 0; i < lines.length; i++) { | ||
401 | - if (lines[i].isEmpty) { | ||
402 | - continue; | ||
403 | - } | ||
404 | - parsed.addAll([..._parse(lines[i]), if (i != lines.length - 1) '\n']); | ||
405 | - } | ||
406 | - return parsed.join(); | ||
407 | -} |
pdf/lib/src/pdf/font/bidi_utils.dart
0 → 100644
1 | +import 'package:bidi/bidi.dart' as bidi; | ||
2 | +/* | ||
3 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
4 | + * | ||
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + * you may not use this file except in compliance with the License. | ||
7 | + * You may obtain a copy of the License at | ||
8 | + * | ||
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + * | ||
11 | + * Unless required by applicable law or agreed to in writing, software | ||
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + * See the License for the specific language governing permissions and | ||
15 | + * limitations under the License. | ||
16 | + */ | ||
17 | + | ||
18 | +const Map<int, int> _arabicDiacritics = <int, int>{ | ||
19 | + 0x064B: 0x064B, // Fathatan | ||
20 | + 0x064C: 0x064C, // Dammatan | ||
21 | + 0x064D: 0x064D, // Kasratan | ||
22 | + 0x064E: 0x064E, // Fatha | ||
23 | + 0x064F: 0x064F, // Damma | ||
24 | + 0x0650: 0x0650, // Kasra | ||
25 | + 0x0651: 0x0651, // Shadda | ||
26 | + 0x0652: 0x0652, // Sukun | ||
27 | + 0x0670: 0x0670, // Dagger alif | ||
28 | + 0xFC5E: 0xFC5E, // Shadda + Dammatan | ||
29 | + 0xFC5F: 0xFC5F, // Shadda + Kasratan | ||
30 | + 0xFC60: 0xFC60, // Shadda + Fatha | ||
31 | + 0xFC61: 0xFC61, // Shadda + Damma | ||
32 | + 0xFC62: 0xFC62, // Shadda + Kasra | ||
33 | + 0xFC63: 0xFC63, // Shadda + Dagger alif | ||
34 | + // 1548: 1548, | ||
35 | +}; | ||
36 | + | ||
37 | +bool isArabicDiacriticValue(int letter) { | ||
38 | + return _arabicDiacritics.containsValue(letter); | ||
39 | +} | ||
40 | + | ||
41 | +/// Applies THE BIDIRECTIONAL ALGORITHM using (https://pub.dev/packages/bidi) | ||
42 | +String logicalToVisual(String input) { | ||
43 | + final buffer = StringBuffer(); | ||
44 | + final paragraphs = bidi.splitStringToParagraphs(input); | ||
45 | + for (final paragraph in paragraphs) { | ||
46 | + final endsWithNewLine = paragraph.paragraphSeparator == 10; | ||
47 | + final endIndex = paragraph.bidiText.length - (endsWithNewLine ? 1 : 0); | ||
48 | + final visual = String.fromCharCodes(paragraph.bidiText, 0, endIndex); | ||
49 | + buffer.write(visual.split(' ').reversed.join(' ')); | ||
50 | + if (endsWithNewLine) { | ||
51 | + buffer.writeln(); | ||
52 | + } | ||
53 | + } | ||
54 | + return buffer.toString(); | ||
55 | +} |
@@ -19,7 +19,7 @@ import 'dart:typed_data'; | @@ -19,7 +19,7 @@ import 'dart:typed_data'; | ||
19 | 19 | ||
20 | import '../data_types.dart'; | 20 | import '../data_types.dart'; |
21 | import '../document.dart'; | 21 | import '../document.dart'; |
22 | -import '../font/arabic.dart' as arabic; | 22 | +import '../font/bidi_utils.dart' as bidi; |
23 | import '../font/font_metrics.dart'; | 23 | import '../font/font_metrics.dart'; |
24 | import '../font/ttf_parser.dart'; | 24 | import '../font/ttf_parser.dart'; |
25 | import '../font/ttf_writer.dart'; | 25 | import '../font/ttf_writer.dart'; |
@@ -74,7 +74,7 @@ class PdfTtfFont extends PdfFont { | @@ -74,7 +74,7 @@ class PdfTtfFont extends PdfFont { | ||
74 | return PdfFontMetrics.zero; | 74 | return PdfFontMetrics.zero; |
75 | } | 75 | } |
76 | 76 | ||
77 | - if (arabic.isArabicDiacriticValue(charCode)) { | 77 | + if (bidi.isArabicDiacriticValue(charCode)) { |
78 | final metric = font.glyphInfoMap[g] ?? PdfFontMetrics.zero; | 78 | final metric = font.glyphInfoMap[g] ?? PdfFontMetrics.zero; |
79 | return metric.copyWith(advanceWidth: 0); | 79 | return metric.copyWith(advanceWidth: 0); |
80 | } | 80 | } |
@@ -19,7 +19,7 @@ import 'dart:math' as math; | @@ -19,7 +19,7 @@ import 'dart:math' as math; | ||
19 | import 'package:meta/meta.dart'; | 19 | import 'package:meta/meta.dart'; |
20 | 20 | ||
21 | import '../../pdf.dart'; | 21 | import '../../pdf.dart'; |
22 | -import '../pdf/font/arabic.dart' as arabic; | 22 | +import '../pdf/font/bidi_utils.dart' as bidi; |
23 | import 'annotations.dart'; | 23 | import 'annotations.dart'; |
24 | import 'basic.dart'; | 24 | import 'basic.dart'; |
25 | import 'document.dart'; | 25 | import 'document.dart'; |
@@ -918,7 +918,7 @@ class RichText extends Widget with SpanningWidget { | @@ -918,7 +918,7 @@ class RichText extends Widget with SpanningWidget { | ||
918 | font.stringMetrics(' ') * (style.fontSize! * textScaleFactor); | 918 | font.stringMetrics(' ') * (style.fontSize! * textScaleFactor); |
919 | 919 | ||
920 | final spanLines = (_textDirection == TextDirection.rtl | 920 | final spanLines = (_textDirection == TextDirection.rtl |
921 | - ? arabic.convert(span.text!) | 921 | + ? bidi.logicalToVisual(span.text!) |
922 | : span.text)! | 922 | : span.text)! |
923 | .split('\n'); | 923 | .split('\n'); |
924 | 924 |
@@ -11,6 +11,7 @@ environment: | @@ -11,6 +11,7 @@ environment: | ||
11 | dependencies: | 11 | dependencies: |
12 | archive: ^3.1.0 | 12 | archive: ^3.1.0 |
13 | barcode: ">=2.2.3 <3.0.0" | 13 | barcode: ">=2.2.3 <3.0.0" |
14 | + bidi: ^2.0.2 | ||
14 | crypto: ^3.0.0 | 15 | crypto: ^3.0.0 |
15 | image: ">=3.0.1 <4.0.0" | 16 | image: ">=3.0.1 <4.0.0" |
16 | meta: ">=1.3.0 <2.0.0" | 17 | meta: ">=1.3.0 <2.0.0" |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | 16 | ||
17 | import 'dart:io'; | 17 | import 'dart:io'; |
18 | 18 | ||
19 | -import 'package:pdf/src/pdf/font/arabic.dart' as arabic; | 19 | +import 'package:pdf/src/pdf/font/bidi_utils.dart' as bidi; |
20 | import 'package:pdf/widgets.dart'; | 20 | import 'package:pdf/widgets.dart'; |
21 | import 'package:test/test.dart'; | 21 | import 'package:test/test.dart'; |
22 | 22 | ||
@@ -46,16 +46,16 @@ void main() { | @@ -46,16 +46,16 @@ void main() { | ||
46 | }); | 46 | }); |
47 | 47 | ||
48 | test('Arabic Diacritics', () { | 48 | test('Arabic Diacritics', () { |
49 | - final a = ArabicText('السلام', <int>[1605, 65276, 65204, 65247, 1575]); | 49 | + final a = ArabicText('السلام', <int>[65249, 65276, 65204, 65247, 65165]); |
50 | final b = ArabicText('السَلَاْمٌ', | 50 | final b = ArabicText('السَلَاْمٌ', |
51 | - <int>[1612, 1605, 1618, 1614, 65276, 1614, 65204, 65247, 1575]); | 51 | + <int>[1612, 65249, 1618, 1614, 65276, 1614, 65204, 65247, 65165]); |
52 | 52 | ||
53 | expect( | 53 | expect( |
54 | - arabic.convert(a.original).codeUnits, | 54 | + bidi.logicalToVisual(a.original).codeUnits, |
55 | equals(a.reshaped), | 55 | equals(a.reshaped), |
56 | ); | 56 | ); |
57 | expect( | 57 | expect( |
58 | - arabic.convert(b.original).codeUnits, | 58 | + bidi.logicalToVisual(b.original).codeUnits, |
59 | equals(b.reshaped), | 59 | equals(b.reshaped), |
60 | ); | 60 | ); |
61 | }); | 61 | }); |
@@ -64,7 +64,7 @@ void main() { | @@ -64,7 +64,7 @@ void main() { | ||
64 | final cases = <ArabicText>[ | 64 | final cases = <ArabicText>[ |
65 | ArabicText('الـــسَلاْمُ عَلَيْكُمْ', <int>[ | 65 | ArabicText('الـــسَلاْمُ عَلَيْكُمْ', <int>[ |
66 | 1615, | 66 | 1615, |
67 | - 1605, | 67 | + 65249, |
68 | 1618, | 68 | 1618, |
69 | 65276, | 69 | 65276, |
70 | 1614, | 70 | 1614, |
@@ -73,7 +73,7 @@ void main() { | @@ -73,7 +73,7 @@ void main() { | ||
73 | 1600, | 73 | 1600, |
74 | 1600, | 74 | 1600, |
75 | 65247, | 75 | 65247, |
76 | - 1575, | 76 | + 65165, |
77 | 32, | 77 | 32, |
78 | 1618, | 78 | 1618, |
79 | 65250, | 79 | 65250, |
@@ -94,7 +94,7 @@ void main() { | @@ -94,7 +94,7 @@ void main() { | ||
94 | 1600, | 94 | 1600, |
95 | 1600, | 95 | 1600, |
96 | 65247, | 96 | 65247, |
97 | - 1575, | 97 | + 65165, |
98 | 32, | 98 | 32, |
99 | 65172, | 99 | 65172, |
100 | 64608, | 100 | 64608, |
@@ -105,7 +105,7 @@ void main() { | @@ -105,7 +105,7 @@ void main() { | ||
105 | 1600, | 105 | 1600, |
106 | 65228, | 106 | 65228, |
107 | 65247, | 107 | 65247, |
108 | - 1575, | 108 | + 65165, |
109 | 32, | 109 | 32, |
110 | 65266, | 110 | 65266, |
111 | 65259, | 111 | 65259, |
@@ -114,15 +114,15 @@ void main() { | @@ -114,15 +114,15 @@ void main() { | ||
114 | 65198, | 114 | 65198, |
115 | 65180, | 115 | 65180, |
116 | 65243, | 116 | 65243, |
117 | - 1571, | 117 | + 65155, |
118 | 32, | 118 | 32, |
119 | 1616, | 119 | 1616, |
120 | - 1578, | 120 | + 65173, |
121 | 65166, | 121 | 65166, |
122 | 65232, | 122 | 65232, |
123 | 65248, | 123 | 65248, |
124 | 65247, | 124 | 65247, |
125 | - 1575 | 125 | + 65165 |
126 | ]), | 126 | ]), |
127 | ArabicText('تحدُّثاً ونُطقاً ضِمْنَ مَجمُوعَة', <int>[ | 127 | ArabicText('تحدُّثاً ونُطقاً ضِمْنَ مَجمُوعَة', <int>[ |
128 | 1611, | 128 | 1611, |
@@ -139,7 +139,7 @@ void main() { | @@ -139,7 +139,7 @@ void main() { | ||
139 | 65220, | 139 | 65220, |
140 | 1615, | 140 | 1615, |
141 | 65255, | 141 | 65255, |
142 | - 1608, | 142 | + 65261, |
143 | 32, | 143 | 32, |
144 | 1614, | 144 | 1614, |
145 | 65254, | 145 | 65254, |
@@ -159,12 +159,12 @@ void main() { | @@ -159,12 +159,12 @@ void main() { | ||
159 | 65251 | 159 | 65251 |
160 | ]), | 160 | ]), |
161 | ArabicText('اللغات السامية', <int>[ | 161 | ArabicText('اللغات السامية', <int>[ |
162 | - 1578, | 162 | + 65173, |
163 | 65166, | 163 | 65166, |
164 | 65232, | 164 | 65232, |
165 | 65248, | 165 | 65248, |
166 | 65247, | 166 | 65247, |
167 | - 1575, | 167 | + 65165, |
168 | 32, | 168 | 32, |
169 | 65172, | 169 | 65172, |
170 | 65268, | 170 | 65268, |
@@ -172,7 +172,7 @@ void main() { | @@ -172,7 +172,7 @@ void main() { | ||
172 | 65166, | 172 | 65166, |
173 | 65204, | 173 | 65204, |
174 | 65247, | 174 | 65247, |
175 | - 1575 | 175 | + 65165, |
176 | ]), | 176 | ]), |
177 | ArabicText('العربية لغةٌ رسميةٌ في', <int>[ | 177 | ArabicText('العربية لغةٌ رسميةٌ في', <int>[ |
178 | 65172, | 178 | 65172, |
@@ -181,7 +181,7 @@ void main() { | @@ -181,7 +181,7 @@ void main() { | ||
181 | 65198, | 181 | 65198, |
182 | 65228, | 182 | 65228, |
183 | 65247, | 183 | 65247, |
184 | - 1575, | 184 | + 65165, |
185 | 32, | 185 | 32, |
186 | 1612, | 186 | 1612, |
187 | 65172, | 187 | 65172, |
@@ -193,7 +193,7 @@ void main() { | @@ -193,7 +193,7 @@ void main() { | ||
193 | 65268, | 193 | 65268, |
194 | 65252, | 194 | 65252, |
195 | 65203, | 195 | 65203, |
196 | - 1585, | 196 | + 65197, |
197 | 32, | 197 | 32, |
198 | 65266, | 198 | 65266, |
199 | 65235 | 199 | 65235 |
@@ -204,16 +204,16 @@ void main() { | @@ -204,16 +204,16 @@ void main() { | ||
204 | 65243, | 204 | 65243, |
205 | 32, | 205 | 32, |
206 | 1616, | 206 | 1616, |
207 | - 1604, | ||
208 | - 1608, | ||
209 | - 1583, | 207 | + 65245, |
208 | + 65261, | ||
209 | + 65193, | ||
210 | 32, | 210 | 32, |
211 | 1616, | 211 | 1616, |
212 | 65254, | 212 | 65254, |
213 | 65219, | 213 | 65219, |
214 | 65262, | 214 | 65262, |
215 | 65247, | 215 | 65247, |
216 | - 1575, | 216 | + 65165, |
217 | 32, | 217 | 32, |
218 | 64610, | 218 | 64610, |
219 | 65266, | 219 | 65266, |
@@ -221,19 +221,19 @@ void main() { | @@ -221,19 +221,19 @@ void main() { | ||
221 | 65198, | 221 | 65198, |
222 | 65228, | 222 | 65228, |
223 | 65247, | 223 | 65247, |
224 | - 1575 | 224 | + 65165 |
225 | ]), | 225 | ]), |
226 | ArabicText('إضافة إلىّٰ كونها لغة؟', <int>[ | 226 | ArabicText('إضافة إلىّٰ كونها لغة؟', <int>[ |
227 | 65172, | 227 | 65172, |
228 | 65235, | 228 | 65235, |
229 | 65166, | 229 | 65166, |
230 | 65215, | 230 | 65215, |
231 | - 1573, | 231 | + 65159, |
232 | 32, | 232 | 32, |
233 | 64611, | 233 | 64611, |
234 | 65264, | 234 | 65264, |
235 | 65247, | 235 | 65247, |
236 | - 1573, | 236 | + 65159, |
237 | 32, | 237 | 32, |
238 | 65166, | 238 | 65166, |
239 | 65260, | 239 | 65260, |
@@ -241,22 +241,22 @@ void main() { | @@ -241,22 +241,22 @@ void main() { | ||
241 | 65262, | 241 | 65262, |
242 | 65243, | 242 | 65243, |
243 | 32, | 243 | 32, |
244 | + 1567, | ||
244 | 65172, | 245 | 65172, |
245 | 65232, | 246 | 65232, |
246 | 65247, | 247 | 65247, |
247 | - 1567 | ||
248 | ]), | 248 | ]), |
249 | ArabicText('رسمية في تشاد وإريتريا', <int>[ | 249 | ArabicText('رسمية في تشاد وإريتريا', <int>[ |
250 | 65172, | 250 | 65172, |
251 | 65268, | 251 | 65268, |
252 | 65252, | 252 | 65252, |
253 | 65203, | 253 | 65203, |
254 | - 1585, | 254 | + 65197, |
255 | 32, | 255 | 32, |
256 | 65266, | 256 | 65266, |
257 | 65235, | 257 | 65235, |
258 | 32, | 258 | 32, |
259 | - 1583, | 259 | + 65193, |
260 | 65166, | 260 | 65166, |
261 | 65208, | 261 | 65208, |
262 | 65175, | 262 | 65175, |
@@ -266,36 +266,36 @@ void main() { | @@ -266,36 +266,36 @@ void main() { | ||
266 | 65198, | 266 | 65198, |
267 | 65176, | 267 | 65176, |
268 | 65267, | 268 | 65267, |
269 | - 1585, | ||
270 | - 1573, | ||
271 | - 1608 | 269 | + 65197, |
270 | + 65159, | ||
271 | + 65261 | ||
272 | ]), | 272 | ]), |
273 | ArabicText('وإسرائيل. وهي إحدى اللغات', <int>[ | 273 | ArabicText('وإسرائيل. وهي إحدى اللغات', <int>[ |
274 | 46, | 274 | 46, |
275 | 65246, | 275 | 65246, |
276 | 65268, | 276 | 65268, |
277 | 65163, | 277 | 65163, |
278 | - 1575, | 278 | + 65165, |
279 | 65198, | 279 | 65198, |
280 | 65203, | 280 | 65203, |
281 | - 1573, | ||
282 | - 1608, | 281 | + 65159, |
282 | + 65261, | ||
283 | 32, | 283 | 32, |
284 | 65266, | 284 | 65266, |
285 | 65259, | 285 | 65259, |
286 | - 1608, | 286 | + 65261, |
287 | 32, | 287 | 32, |
288 | - 1609, | 288 | + 65263, |
289 | 65194, | 289 | 65194, |
290 | 65187, | 290 | 65187, |
291 | - 1573, | 291 | + 65159, |
292 | 32, | 292 | 32, |
293 | - 1578, | 293 | + 65173, |
294 | 65166, | 294 | 65166, |
295 | 65232, | 295 | 65232, |
296 | 65248, | 296 | 65248, |
297 | 65247, | 297 | 65247, |
298 | - 1575 | 298 | + 65165 |
299 | ]), | 299 | ]), |
300 | ArabicText('الرسمية الست في منظمة', <int>[ | 300 | ArabicText('الرسمية الست في منظمة', <int>[ |
301 | 65172, | 301 | 65172, |
@@ -304,12 +304,12 @@ void main() { | @@ -304,12 +304,12 @@ void main() { | ||
304 | 65203, | 304 | 65203, |
305 | 65198, | 305 | 65198, |
306 | 65247, | 306 | 65247, |
307 | - 1575, | 307 | + 65165, |
308 | 32, | 308 | 32, |
309 | 65174, | 309 | 65174, |
310 | 65204, | 310 | 65204, |
311 | 65247, | 311 | 65247, |
312 | - 1575, | 312 | + 65165, |
313 | 32, | 313 | 32, |
314 | 65266, | 314 | 65266, |
315 | 65235, | 315 | 65235, |
@@ -324,16 +324,16 @@ void main() { | @@ -324,16 +324,16 @@ void main() { | ||
324 | 65250, | 324 | 65250, |
325 | 65251, | 325 | 65251, |
326 | 65271, | 326 | 65271, |
327 | - 1575, | 327 | + 65165, |
328 | 32, | 328 | 32, |
329 | - 1577, | 329 | + 1548, |
330 | + 65171, | ||
330 | 65194, | 331 | 65194, |
331 | 65188, | 332 | 65188, |
332 | 65176, | 333 | 65176, |
333 | 65252, | 334 | 65252, |
334 | 65247, | 335 | 65247, |
335 | - 1575, | ||
336 | - 1548, | 336 | + 65165, |
337 | 32, | 337 | 32, |
338 | 65246, | 338 | 65246, |
339 | 65236, | 339 | 65236, |
@@ -341,10 +341,10 @@ void main() { | @@ -341,10 +341,10 @@ void main() { | ||
341 | 65188, | 341 | 65188, |
342 | 1615, | 342 | 1615, |
343 | 65267, | 343 | 65267, |
344 | - 1608 | 344 | + 65261 |
345 | ]), | 345 | ]), |
346 | ArabicText('باليوم العالمي للغة العربية', <int>[ | 346 | ArabicText('باليوم العالمي للغة العربية', <int>[ |
347 | - 1605, | 347 | + 65249, |
348 | 65262, | 348 | 65262, |
349 | 65268, | 349 | 65268, |
350 | 65247, | 350 | 65247, |
@@ -357,7 +357,7 @@ void main() { | @@ -357,7 +357,7 @@ void main() { | ||
357 | 65166, | 357 | 65166, |
358 | 65228, | 358 | 65228, |
359 | 65247, | 359 | 65247, |
360 | - 1575, | 360 | + 65165, |
361 | 32, | 361 | 32, |
362 | 65172, | 362 | 65172, |
363 | 65232, | 363 | 65232, |
@@ -370,7 +370,7 @@ void main() { | @@ -370,7 +370,7 @@ void main() { | ||
370 | 65198, | 370 | 65198, |
371 | 65228, | 371 | 65228, |
372 | 65247, | 372 | 65247, |
373 | - 1575 | 373 | + 65165 |
374 | ]), | 374 | ]), |
375 | ArabicText('في 18 ديسمبر كذكرى اعتماد', <int>[ | 375 | ArabicText('في 18 ديسمبر كذكرى اعتماد', <int>[ |
376 | 65266, | 376 | 65266, |
@@ -384,20 +384,20 @@ void main() { | @@ -384,20 +384,20 @@ void main() { | ||
384 | 65252, | 384 | 65252, |
385 | 65204, | 385 | 65204, |
386 | 65267, | 386 | 65267, |
387 | - 1583, | 387 | + 65193, |
388 | 32, | 388 | 32, |
389 | - 1609, | 389 | + 65263, |
390 | 65198, | 390 | 65198, |
391 | 65243, | 391 | 65243, |
392 | 65196, | 392 | 65196, |
393 | 65243, | 393 | 65243, |
394 | 32, | 394 | 32, |
395 | - 1583, | 395 | + 65193, |
396 | 65166, | 396 | 65166, |
397 | 65252, | 397 | 65252, |
398 | 65176, | 398 | 65176, |
399 | 65227, | 399 | 65227, |
400 | - 1575 | 400 | + 65165 |
401 | ]), | 401 | ]), |
402 | ArabicText('العربية بين لغات العمل في', <int>[ | 402 | ArabicText('العربية بين لغات العمل في', <int>[ |
403 | 65172, | 403 | 65172, |
@@ -406,13 +406,13 @@ void main() { | @@ -406,13 +406,13 @@ void main() { | ||
406 | 65198, | 406 | 65198, |
407 | 65228, | 407 | 65228, |
408 | 65247, | 408 | 65247, |
409 | - 1575, | 409 | + 65165, |
410 | 32, | 410 | 32, |
411 | 65254, | 411 | 65254, |
412 | 65268, | 412 | 65268, |
413 | 65169, | 413 | 65169, |
414 | 32, | 414 | 32, |
415 | - 1578, | 415 | + 65173, |
416 | 65166, | 416 | 65166, |
417 | 65232, | 417 | 65232, |
418 | 65247, | 418 | 65247, |
@@ -421,7 +421,7 @@ void main() { | @@ -421,7 +421,7 @@ void main() { | ||
421 | 65252, | 421 | 65252, |
422 | 65228, | 422 | 65228, |
423 | 65247, | 423 | 65247, |
424 | - 1575, | 424 | + 65165, |
425 | 32, | 425 | 32, |
426 | 65266, | 426 | 65266, |
427 | 65235 | 427 | 65235 |
@@ -430,16 +430,16 @@ void main() { | @@ -430,16 +430,16 @@ void main() { | ||
430 | 65250, | 430 | 65250, |
431 | 65251, | 431 | 65251, |
432 | 65271, | 432 | 65271, |
433 | - 1575, | 433 | + 65165, |
434 | 32, | 434 | 32, |
435 | 46, | 435 | 46, |
436 | - 1577, | 436 | + 65171, |
437 | 65194, | 437 | 65194, |
438 | 65188, | 438 | 65188, |
439 | 65176, | 439 | 65176, |
440 | 65252, | 440 | 65252, |
441 | 65247, | 441 | 65247, |
442 | - 1575, | 442 | + 65165, |
443 | ]), | 443 | ]), |
444 | ]; | 444 | ]; |
445 | 445 | ||
@@ -462,7 +462,7 @@ void main() { | @@ -462,7 +462,7 @@ void main() { | ||
462 | 462 | ||
463 | for (final item in cases) { | 463 | for (final item in cases) { |
464 | expect( | 464 | expect( |
465 | - arabic.convert(item.original).codeUnits, | 465 | + bidi.logicalToVisual(item.original).codeUnits, |
466 | equals(item.reshaped), | 466 | equals(item.reshaped), |
467 | ); | 467 | ); |
468 | } | 468 | } |
@@ -481,7 +481,7 @@ void main() { | @@ -481,7 +481,7 @@ void main() { | ||
481 | children: const <TextSpan>[ | 481 | children: const <TextSpan>[ |
482 | TextSpan( | 482 | TextSpan( |
483 | text: | 483 | text: |
484 | - 'القهوة مشروب يعد من بذور الب المحمصة، وينمو في أكثر من 70 لداً. خصوصاً في المناطق الاستوائية في أمريكا الشمالية والجنوبية وجنوب شرق آسيا وشبه القارة الهندية وأفريقيا. ويقال أن البن الأخضر هو ثاني أكثر السلع تداولاً في العالم بعد النفط الخام.', | 484 | + 'القهوة مشروب يعد من بذور الب المحمصة، وينمو في أكثر من 70 بلداً. خصوصاً في المناطق الاستوائية في أمريكا الشمالية والجنوبية وجنوب شرق آسيا وشبه القارة الهندية وأفريقيا. ويقال أن البن الأخضر هو ثاني أكثر السلع تداولاً في العالم بعد النفط الخام.', |
485 | style: TextStyle( | 485 | style: TextStyle( |
486 | fontSize: 20, | 486 | fontSize: 20, |
487 | ), | 487 | ), |
@@ -506,7 +506,7 @@ void main() { | @@ -506,7 +506,7 @@ void main() { | ||
506 | children: const <TextSpan>[ | 506 | children: const <TextSpan>[ |
507 | TextSpan( | 507 | TextSpan( |
508 | text: | 508 | text: |
509 | - 'القهوة مشروب يعد من بذور الب المحمصة، وينمو في أكثر من 70 لداً. خصوصاً في المناطق الاستوائية في أمريكا الشمالية والجنوبية وجنوب شرق آسيا وشبه القارة الهندية وأفريقيا. ويقال أن البن الأخضر هو ثاني أكثر السلع تداولاً في العالم بعد النفط الخام.', | 509 | + 'القهوة مشروب يعد من بذور الب المحمصة، وينمو في أكثر من 70 بلداً. خصوصاً في المناطق الاستوائية في أمريكا الشمالية والجنوبية وجنوب شرق آسيا وشبه القارة الهندية وأفريقيا. ويقال أن البن الأخضر هو ثاني أكثر السلع تداولاً في العالم بعد النفط الخام.', |
510 | style: TextStyle( | 510 | style: TextStyle( |
511 | fontSize: 20, | 511 | fontSize: 20, |
512 | ), | 512 | ), |
@@ -517,8 +517,34 @@ void main() { | @@ -517,8 +517,34 @@ void main() { | ||
517 | )); | 517 | )); |
518 | }); | 518 | }); |
519 | 519 | ||
520 | - test( | ||
521 | - 'Text Widgets, Mixed Arabic and Latin words should be rendered in order ', | 520 | + test('Text Widgets, Arabic Text with Tashkeel', () { |
521 | + pdf.addPage(Page( | ||
522 | + textDirection: TextDirection.rtl, | ||
523 | + build: (Context context) => RichText( | ||
524 | + text: TextSpan( | ||
525 | + text: 'الفَرَاشَةُ\n', | ||
526 | + style: TextStyle( | ||
527 | + font: arabicFont, | ||
528 | + fontSize: 30, | ||
529 | + ), | ||
530 | + children: const <TextSpan>[ | ||
531 | + if (true) | ||
532 | + TextSpan( | ||
533 | + text: | ||
534 | + 'فَرَاشَةٌ مُلَوَّنَةٌ تَطِيْرُ في البُسْتَانِ، حُلْوَةٌ مُهَنْدَمَةٌ تُدْهِشُ الإِنْسَانَ، أَهْدَافُهَا مُحَدَّدَةٌ، حَرَكَاتُها مُرَتَّبَةٌ، تَحُوْمُ بِانْتِظَامٍ،' | ||
535 | + ' تَحُطُّ فِي نُعُومَةٍ تَنْشُرُ السَّلاَمَ. فَرَاشَةٌ مُلَوَّنَةٌ تَطِيرُ بِلا اُنْقِطَاعٍ، بِالنَّهارِ المُشْرِقِ تَمْلَأُ البِقَاعَ، تُحِبُّ الوَرْدَ ' | ||
536 | + 'المَزْرُوعَ، تَلْثُمُهُ فِي وَقْتِ الجُوعِ، تَمْتَصُّ رَحِيْقَ الأَزْهَارِ، تُحْيي جَنْيَ الأَشْجَارِ، مِنْ وَرْدَةٍ لِوَرْدَةٍ، تَطِيْرُ بِانْتِظَامٍ.', | ||
537 | + style: TextStyle( | ||
538 | + fontSize: 18, | ||
539 | + ), | ||
540 | + ), | ||
541 | + ], | ||
542 | + ), | ||
543 | + ), | ||
544 | + )); | ||
545 | + }); | ||
546 | + | ||
547 | + test('Text Widgets, Mixed Arabic and Latin words should be rendered in order', | ||
522 | () { | 548 | () { |
523 | pdf.addPage(Page( | 549 | pdf.addPage(Page( |
524 | textDirection: TextDirection.rtl, | 550 | textDirection: TextDirection.rtl, |
@@ -530,11 +556,11 @@ void main() { | @@ -530,11 +556,11 @@ void main() { | ||
530 | fontSize: 30, | 556 | fontSize: 30, |
531 | ), | 557 | ), |
532 | children: const <TextSpan>[ | 558 | children: const <TextSpan>[ |
559 | + if (true) | ||
533 | TextSpan( | 560 | TextSpan( |
534 | text: r''' | 561 | text: r''' |
535 | الكلمات اللاتينية المضافة إلى نص عربي يجب أن توضع في الترتيب الصحيح Right Order مهما كان موضعها في النص. | 562 | الكلمات اللاتينية المضافة إلى نص عربي يجب أن توضع في الترتيب الصحيح Right Order مهما كان موضعها في النص. |
536 | -At the Beginning of the sentence في بداية الجملة | ||
537 | -أو في منتصفها In the middle of the sentence حيث يكون بعدها كلام عربي | 563 | + في منتصفها In the middle of the sentence حيث يكون بعدها كلام عربي |
538 | أو في نهاية النص At the end of the sentence | 564 | أو في نهاية النص At the end of the sentence |
539 | أيضا ترتيب الأرقام والرموز يجب 1 أن 2 يكون 3 صحيحاً$. | 565 | أيضا ترتيب الأرقام والرموز يجب 1 أن 2 يكون 3 صحيحاً$. |
540 | ولا ننسى أيضا فواصل السطور Line breakers حيث وجودها في موضعها الصحيح مهم جدا في النصوص ثنائية الاتجاه Bidirectional | 566 | ولا ننسى أيضا فواصل السطور Line breakers حيث وجودها في موضعها الصحيح مهم جدا في النصوص ثنائية الاتجاه Bidirectional |
@@ -549,6 +575,34 @@ At the Beginning of the sentence في بداية الجملة | @@ -549,6 +575,34 @@ At the Beginning of the sentence في بداية الجملة | ||
549 | )); | 575 | )); |
550 | }); | 576 | }); |
551 | 577 | ||
578 | + test('Text Widgets Arabic with weak/natural Chars', () { | ||
579 | + pdf.addPage(Page( | ||
580 | + build: (Context context) => SizedBox.expand( | ||
581 | + child: RichText( | ||
582 | + textDirection: TextDirection.rtl, | ||
583 | + text: TextSpan( | ||
584 | + style: TextStyle( | ||
585 | + font: arabicFont, | ||
586 | + fontSize: 18, | ||
587 | + ), | ||
588 | + children: const <TextSpan>[ | ||
589 | + TextSpan( | ||
590 | + text: ''' | ||
591 | +اضف العدد (5) إلى العدد (40) | ||
592 | +ثم اطرح منه العدد (10) | ||
593 | +الناتج = 35 | ||
594 | +جملة (if) الشرطية: | ||
595 | +كلمة عربية (بين قوسين) | ||
596 | +حاصل العملية (5 * 2) + (2 - 4) يساوي 12 | ||
597 | +العدد 9 > 5 والعدد 9 < 10 | ||
598 | + ''', | ||
599 | + ), | ||
600 | + ], | ||
601 | + ), | ||
602 | + )), | ||
603 | + )); | ||
604 | + }); | ||
605 | + | ||
552 | tearDownAll(() async { | 606 | tearDownAll(() async { |
553 | final file = File('arabic.pdf'); | 607 | final file = File('arabic.pdf'); |
554 | await file.writeAsBytes(await pdf.save()); | 608 | await file.writeAsBytes(await pdf.save()); |
No preview for this file type
-
Please register or login to post a comment