summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorTomer Shalev <shalev.tomer@gmail.com>2009-11-24 20:41:42 +0000
committerTomer Shalev <shalev.tomer@gmail.com>2009-11-24 20:41:42 +0000
commit7682cb5ca8f201be74dc12c1388cdd69a6c178bc (patch)
treea59dda85dbc95c9dddd69970ee7bcd36cdbba7c0 /firmware
parent640d98de0fe2d7f5447ce2bdaf435108478e451a (diff)
downloadrockbox-7682cb5ca8f201be74dc12c1388cdd69a6c178bc.tar.gz
rockbox-7682cb5ca8f201be74dc12c1388cdd69a6c178bc.zip
FS#10720 - Support for displaying diacritic characters
This commit corrects the display of diacritic characters, which exist in many languages. Hopefully, it will make Rockbox much more usable for users of these languages. Diacritic information (which used to decide whether a given character is diacritic or not) is taken from the Unicode Standard, Version 5.2. This feature does not affect drawing performance much, as the diacritic database is cached (simple MRU mechanism). There may be room for further performance, footprint, and code-reuse wise improvements, that could be worked on in the future. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23742 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/drivers/diacritic.c378
-rw-r--r--firmware/drivers/lcd-bitmap-common.c97
-rw-r--r--firmware/font.c3
-rw-r--r--firmware/include/diacritic.h26
5 files changed, 494 insertions, 11 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 18106df2cf..5221d3fb8d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -95,6 +95,7 @@ drivers/lcd-16bit-vert.c
95drivers/lcd-16bit.c 95drivers/lcd-16bit.c
96#endif 96#endif
97#endif /* LCD_DEPTH */ 97#endif /* LCD_DEPTH */
98drivers/diacritic.c
98#endif /* HAVE_LCD_BITMAP */ 99#endif /* HAVE_LCD_BITMAP */
99 100
100#ifdef HAVE_REMOTE_LCD 101#ifdef HAVE_REMOTE_LCD
diff --git a/firmware/drivers/diacritic.c b/firmware/drivers/diacritic.c
new file mode 100644
index 0000000000..5074beb2ad
--- /dev/null
+++ b/firmware/drivers/diacritic.c
@@ -0,0 +1,378 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 Phinitnun Chanasabaeng
11 * Initial work
12 * Copyright (C) 2009 Tomer Shalev
13 *
14 * Rockbox diacritic positioning
15 * Based on initial work by Phinitnun Chanasabaeng
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
21 *
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
24 *
25 ****************************************************************************/
26#include "diacritic.h"
27#include "system.h"
28
29#define DIAC_FLAG_DIACRITIC (1 << 31)
30#define DIAC_FLAG_RTL (1 << 30)
31#define DIAC_MASK 0x000FFFFF
32
33#define DIAC_VAL(i) (diac_range[(i)] & DIAC_MASK)
34#define DIAC_IS_DIACRITIC(i) ((diac_range[(i)] & DIAC_FLAG_DIACRITIC) ? 1 : 0)
35#define DIAC_IS_RTL(i) ((diac_range[(i)] & DIAC_FLAG_RTL) ? 1 : 0)
36#define DIAC_NUM_RANGES (ARRAYLEN(diac_range))
37
38/* Sorted by Unicode value */
39static const int diac_range[] =
40{
41 0x00000,
42 0x002ff,
43 0x0036f | DIAC_FLAG_DIACRITIC, /* Combining Diacritical Marks */
44 0x00482,
45 0x00489 | DIAC_FLAG_DIACRITIC, /* Cyrillic */
46 0x00590,
47 0x005bd | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Hebrew */
48 0x005be | DIAC_FLAG_RTL,
49 0x005bf | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Hebrew */
50 0x005c0 | DIAC_FLAG_RTL,
51 0x005c2 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Hebrew */
52 0x005c3 | DIAC_FLAG_RTL,
53 0x005c5 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Hebrew */
54 0x005c6 | DIAC_FLAG_RTL,
55 0x005c7 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Hebrew */
56 0x0060f | DIAC_FLAG_RTL,
57 0x0061a | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
58 0x0064a | DIAC_FLAG_RTL,
59 0x0065e | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
60 0x0066f | DIAC_FLAG_RTL,
61 0x00670 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
62 0x006d5 | DIAC_FLAG_RTL,
63 0x006dc | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
64 0x006de | DIAC_FLAG_RTL,
65 0x006e4 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
66 0x006e6 | DIAC_FLAG_RTL,
67 0x006e8 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
68 0x006e9 | DIAC_FLAG_RTL,
69 0x006ed | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Arabic */
70 0x00710 | DIAC_FLAG_RTL,
71 0x00711 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Syriac */
72 0x0072f | DIAC_FLAG_RTL,
73 0x0074a | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Syriac */
74 0x007a5 | DIAC_FLAG_RTL,
75 0x007b0 | DIAC_FLAG_DIACRITIC | DIAC_FLAG_RTL, /* Thaana */
76 0x007c0 | DIAC_FLAG_RTL,
77 0x007ea,
78 0x007f3 | DIAC_FLAG_DIACRITIC, /* NKo */
79 0x00815,
80 0x00819 | DIAC_FLAG_DIACRITIC, /* Samaritan */
81 0x0081a,
82 0x00823 | DIAC_FLAG_DIACRITIC, /* Samaritan */
83 0x00824,
84 0x00827 | DIAC_FLAG_DIACRITIC, /* Samaritan */
85 0x00828,
86 0x0082d | DIAC_FLAG_DIACRITIC, /* Samaritan */
87 0x008ff,
88 0x00903 | DIAC_FLAG_DIACRITIC, /* Devanagari */
89 0x0093b,
90 0x0093c | DIAC_FLAG_DIACRITIC, /* Devanagari */
91 0x0093d,
92 0x0094e | DIAC_FLAG_DIACRITIC, /* Devanagari */
93 0x00950,
94 0x00955 | DIAC_FLAG_DIACRITIC, /* Devanagari */
95 0x00961,
96 0x00963 | DIAC_FLAG_DIACRITIC, /* Devanagari */
97 0x00980,
98 0x00983 | DIAC_FLAG_DIACRITIC, /* Bengali */
99 0x009bb,
100 0x009bc | DIAC_FLAG_DIACRITIC, /* Bengali */
101 0x009bd,
102 0x009cd | DIAC_FLAG_DIACRITIC, /* Bengali */
103 0x009d6,
104 0x009d7 | DIAC_FLAG_DIACRITIC, /* Bengali */
105 0x009e1,
106 0x009e3 | DIAC_FLAG_DIACRITIC, /* Bengali */
107 0x00a00,
108 0x00a03 | DIAC_FLAG_DIACRITIC, /* Gurmukhi */
109 0x00a3b,
110 0x00a51 | DIAC_FLAG_DIACRITIC, /* Gurmukhi */
111 0x00a6f,
112 0x00a71 | DIAC_FLAG_DIACRITIC, /* Gurmukhi */
113 0x00a74,
114 0x00a75 | DIAC_FLAG_DIACRITIC, /* Gurmukhi */
115 0x00a80,
116 0x00a83 | DIAC_FLAG_DIACRITIC, /* Gujarati */
117 0x00abb,
118 0x00abc | DIAC_FLAG_DIACRITIC, /* Gujarati */
119 0x00abd,
120 0x00acd | DIAC_FLAG_DIACRITIC, /* Gujarati */
121 0x00ae1,
122 0x00ae3 | DIAC_FLAG_DIACRITIC, /* Gujarati */
123 0x00b00,
124 0x00b03 | DIAC_FLAG_DIACRITIC, /* Oriya */
125 0x00b3b,
126 0x00b3c | DIAC_FLAG_DIACRITIC, /* Oriya */
127 0x00b3d,
128 0x00b57 | DIAC_FLAG_DIACRITIC, /* Oriya */
129 0x00b81,
130 0x00b82 | DIAC_FLAG_DIACRITIC, /* Tamil */
131 0x00bbd,
132 0x00bcd | DIAC_FLAG_DIACRITIC, /* Tamil */
133 0x00bd6,
134 0x00bd7 | DIAC_FLAG_DIACRITIC, /* Tamil */
135 0x00c00,
136 0x00c03 | DIAC_FLAG_DIACRITIC, /* Telugu */
137 0x00c3d,
138 0x00c56 | DIAC_FLAG_DIACRITIC, /* Telugu */
139 0x00c61,
140 0x00c63 | DIAC_FLAG_DIACRITIC, /* Telugu */
141 0x00c81,
142 0x00c83 | DIAC_FLAG_DIACRITIC, /* Kannada */
143 0x00cbb,
144 0x00cbc | DIAC_FLAG_DIACRITIC, /* Kannada */
145 0x00cbd,
146 0x00cd6 | DIAC_FLAG_DIACRITIC, /* Kannada */
147 0x00ce1,
148 0x00ce3 | DIAC_FLAG_DIACRITIC, /* Kannada */
149 0x00d01,
150 0x00d03 | DIAC_FLAG_DIACRITIC, /* Malayalam */
151 0x00d3d,
152 0x00d57 | DIAC_FLAG_DIACRITIC, /* Malayalam */
153 0x00d61,
154 0x00d63 | DIAC_FLAG_DIACRITIC, /* Malayalam */
155 0x00d81,
156 0x00d83 | DIAC_FLAG_DIACRITIC, /* Sinhala */
157 0x00dc9,
158 0x00df3 | DIAC_FLAG_DIACRITIC, /* Sinhala */
159 0x00e30,
160 0x00e31 | DIAC_FLAG_DIACRITIC, /* Thai */
161 0x00e33,
162 0x00e3a | DIAC_FLAG_DIACRITIC, /* Thai */
163 0x00e46,
164 0x00e4e | DIAC_FLAG_DIACRITIC, /* Thai */
165 0x00eb0,
166 0x00eb1 | DIAC_FLAG_DIACRITIC, /* Lao */
167 0x00eb3,
168 0x00ebc | DIAC_FLAG_DIACRITIC, /* Lao */
169 0x00ec7,
170 0x00ecd | DIAC_FLAG_DIACRITIC, /* Lao */
171 0x00f17,
172 0x00f19 | DIAC_FLAG_DIACRITIC, /* Tibetan */
173 0x00f34,
174 0x00f35 | DIAC_FLAG_DIACRITIC, /* Tibetan */
175 0x00f36,
176 0x00f37 | DIAC_FLAG_DIACRITIC, /* Tibetan */
177 0x00f38,
178 0x00f39 | DIAC_FLAG_DIACRITIC, /* Tibetan */
179 0x00f3d,
180 0x00f3f | DIAC_FLAG_DIACRITIC, /* Tibetan */
181 0x00f70,
182 0x00f84 | DIAC_FLAG_DIACRITIC, /* Tibetan */
183 0x00f85,
184 0x00f87 | DIAC_FLAG_DIACRITIC, /* Tibetan */
185 0x00f8f,
186 0x00fbc | DIAC_FLAG_DIACRITIC, /* Tibetan */
187 0x0102a,
188 0x0103e | DIAC_FLAG_DIACRITIC, /* Myanmar */
189 0x01055,
190 0x01059 | DIAC_FLAG_DIACRITIC, /* Myanmar */
191 0x0105d,
192 0x01060 | DIAC_FLAG_DIACRITIC, /* Myanmar */
193 0x01061,
194 0x01064 | DIAC_FLAG_DIACRITIC, /* Myanmar */
195 0x01066,
196 0x0106d | DIAC_FLAG_DIACRITIC, /* Myanmar */
197 0x01070,
198 0x01074 | DIAC_FLAG_DIACRITIC, /* Myanmar */
199 0x01081,
200 0x0108d | DIAC_FLAG_DIACRITIC, /* Myanmar */
201 0x0108e,
202 0x0108f | DIAC_FLAG_DIACRITIC, /* Myanmar */
203 0x01099,
204 0x0109d | DIAC_FLAG_DIACRITIC, /* Myanmar */
205 0x0135e,
206 0x0135f | DIAC_FLAG_DIACRITIC, /* Ethiopic */
207 0x01711,
208 0x01714 | DIAC_FLAG_DIACRITIC, /* Tagalog */
209 0x01731,
210 0x01734 | DIAC_FLAG_DIACRITIC, /* Hanunoo */
211 0x01751,
212 0x01753 | DIAC_FLAG_DIACRITIC, /* Buhid */
213 0x01771,
214 0x01773 | DIAC_FLAG_DIACRITIC, /* Tagbanwa */
215 0x017b5,
216 0x017d3 | DIAC_FLAG_DIACRITIC, /* Khmer */
217 0x017dc,
218 0x017dd | DIAC_FLAG_DIACRITIC, /* Khmer */
219 0x018a8,
220 0x018a9 | DIAC_FLAG_DIACRITIC, /* Mongolian */
221 0x0191f,
222 0x0193b | DIAC_FLAG_DIACRITIC, /* Limbu */
223 0x019af,
224 0x019c0 | DIAC_FLAG_DIACRITIC, /* New Tai Lue */
225 0x019c7,
226 0x019c9 | DIAC_FLAG_DIACRITIC, /* New Tai Lue */
227 0x01a16,
228 0x01a1b | DIAC_FLAG_DIACRITIC, /* Buginese */
229 0x01a54,
230 0x01a7f | DIAC_FLAG_DIACRITIC, /* Tai Tham */
231 0x01aff,
232 0x01b04 | DIAC_FLAG_DIACRITIC, /* Balinese */
233 0x01b33,
234 0x01b44 | DIAC_FLAG_DIACRITIC, /* Balinese */
235 0x01b6a,
236 0x01b73 | DIAC_FLAG_DIACRITIC, /* Balinese */
237 0x01b7f,
238 0x01b82 | DIAC_FLAG_DIACRITIC, /* Sundanese */
239 0x01ba0,
240 0x01baa | DIAC_FLAG_DIACRITIC, /* Sundanese */
241 0x01c23,
242 0x01c37 | DIAC_FLAG_DIACRITIC, /* Lepcha */
243 0x01ccf,
244 0x01cd2 | DIAC_FLAG_DIACRITIC, /* Vedic Extensions */
245 0x01cd3,
246 0x01ce8 | DIAC_FLAG_DIACRITIC, /* Vedic Extensions */
247 0x01cec,
248 0x01ced | DIAC_FLAG_DIACRITIC, /* Vedic Extensions */
249 0x01cf1,
250 0x01cf2 | DIAC_FLAG_DIACRITIC, /* Vedic Extensions */
251 0x01dbf,
252 0x01dff | DIAC_FLAG_DIACRITIC, /* Combining Diacritical Marks Supplement */
253 0x020cf,
254 0x020f0 | DIAC_FLAG_DIACRITIC, /* Combining Diacritical Marks for Symbols */
255 0x02cee,
256 0x02cf1 | DIAC_FLAG_DIACRITIC, /* Coptic */
257 0x02ddf,
258 0x02dff | DIAC_FLAG_DIACRITIC, /* Coptic */
259 0x03029,
260 0x0302f | DIAC_FLAG_DIACRITIC, /* CJK Symbols and Punctuation */
261 0x03098,
262 0x0309a | DIAC_FLAG_DIACRITIC, /* Hiragana */
263 0x0a66e,
264 0x0a672 | DIAC_FLAG_DIACRITIC, /* Hiragana */
265 0x0a67b,
266 0x0a67d | DIAC_FLAG_DIACRITIC, /* Hiragana */
267 0x0a6ef,
268 0x0a6f1 | DIAC_FLAG_DIACRITIC, /* Bamum */
269 0x0a801,
270 0x0a802 | DIAC_FLAG_DIACRITIC, /* Syloti Nagri */
271 0x0a805,
272 0x0a806 | DIAC_FLAG_DIACRITIC, /* Syloti Nagri */
273 0x0a80a,
274 0x0a80b | DIAC_FLAG_DIACRITIC, /* Syloti Nagri */
275 0x0a822,
276 0x0a827 | DIAC_FLAG_DIACRITIC, /* Syloti Nagri */
277 0x0a87f,
278 0x0a881 | DIAC_FLAG_DIACRITIC, /* Saurashtra */
279 0x0a8b3,
280 0x0a8c4 | DIAC_FLAG_DIACRITIC, /* Saurashtra */
281 0x0a8df,
282 0x0a8f1 | DIAC_FLAG_DIACRITIC, /* Devanagari Extended */
283 0x0a925,
284 0x0a92d | DIAC_FLAG_DIACRITIC, /* Kayah Li */
285 0x0a946,
286 0x0a953 | DIAC_FLAG_DIACRITIC, /* Rejang */
287 0x0a97f,
288 0x0a983 | DIAC_FLAG_DIACRITIC, /* Javanese */
289 0x0a9b2,
290 0x0a9c0 | DIAC_FLAG_DIACRITIC, /* Javanese */
291 0x0aa28,
292 0x0aa36 | DIAC_FLAG_DIACRITIC, /* Cham */
293 0x0aa42,
294 0x0aa43 | DIAC_FLAG_DIACRITIC, /* Cham */
295 0x0aa4b,
296 0x0aa4d | DIAC_FLAG_DIACRITIC, /* Cham */
297 0x0aa7a,
298 0x0aa7b | DIAC_FLAG_DIACRITIC, /* Cham */
299 0x0aaaf,
300 0x0aab0 | DIAC_FLAG_DIACRITIC, /* Tai Viet */
301 0x0aab1,
302 0x0aab4 | DIAC_FLAG_DIACRITIC, /* Tai Viet */
303 0x0aab6,
304 0x0aab8 | DIAC_FLAG_DIACRITIC, /* Tai Viet */
305 0x0aabd,
306 0x0aabf | DIAC_FLAG_DIACRITIC, /* Tai Viet */
307 0x0aac0,
308 0x0aac1 | DIAC_FLAG_DIACRITIC, /* Tai Viet */
309 0x0abe2,
310 0x0abea | DIAC_FLAG_DIACRITIC, /* Meetei Mayek */
311 0x0abeb,
312 0x0abed | DIAC_FLAG_DIACRITIC, /* Meetei Mayek */
313 0x0fb1d,
314 0x0fb1e | DIAC_FLAG_DIACRITIC, /* Alphabetic Presentation Forms */
315 0x0fe1f,
316 0x0fe26 | DIAC_FLAG_DIACRITIC, /* Combining Half Marks */
317 0x1107f,
318 0x11082 | DIAC_FLAG_DIACRITIC, /* Kaithi */
319 0x110af,
320 0x110ba | DIAC_FLAG_DIACRITIC, /* Kaithi */
321 0x1d164,
322 0x1d169 | DIAC_FLAG_DIACRITIC, /* Musical Symbols */
323 0x1d16c,
324 0x1d182 | DIAC_FLAG_DIACRITIC, /* Musical Symbols */
325 0x1d184,
326 0x1d18b | DIAC_FLAG_DIACRITIC, /* Musical Symbols */
327 0x1d1a9,
328 0x1d1ad | DIAC_FLAG_DIACRITIC, /* Musical Symbols */
329 0x1d241,
330 0x1d244 | DIAC_FLAG_DIACRITIC, /* Ancient Greek Musical Notation */
331 0xe01ef,
332};
333
334#define MRU_MAX_LEN 32
335
336static unsigned short mru_len = 0;
337static unsigned short diacritic_mru[MRU_MAX_LEN];
338
339int is_diacritic(unsigned short char_code, bool *is_rtl)
340{
341 unsigned short mru, i;
342
343 /* Search in MRU */
344 for (mru = 0; mru < mru_len; mru++)
345 {
346 i = diacritic_mru[mru];
347
348 /* Found in MRU */
349 if (DIAC_VAL(i - 1) < char_code && char_code <= DIAC_VAL(i))
350 goto Found;
351 }
352
353 /* Search in DB */
354 for (i = 1; i < DIAC_NUM_RANGES; i++)
355 {
356 /* Found */
357 if (char_code < DIAC_VAL(i))
358 break;
359 }
360
361 /* Add MRU entry, or overwrite LRU if MRU array is full */
362 if (mru_len < MRU_MAX_LEN)
363 mru_len++;
364 else
365 mru--;
366
367Found:
368 /* Promote MRU item to top of MRU */
369 for ( ; mru > 0; mru--)
370 diacritic_mru[mru] = diacritic_mru[mru - 1];
371 diacritic_mru[0] = i;
372
373 /* Update RTL */
374 if (is_rtl)
375 *is_rtl = DIAC_IS_RTL(i);
376
377 return DIAC_IS_DIACRITIC(i);
378}
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c
index 70ae00ba84..5b79879d70 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -29,6 +29,7 @@
29 ****************************************************************************/ 29 ****************************************************************************/
30#include "stdarg.h" 30#include "stdarg.h"
31#include "sprintf.h" 31#include "sprintf.h"
32#include "diacritic.h"
32 33
33#ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */ 34#ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
34#define LCDFN(fn) lcd_ ## fn 35#define LCDFN(fn) lcd_ ## fn
@@ -79,15 +80,22 @@ static void lcd_gradient_rect(int x1, int x2, int y, unsigned h,
79} 80}
80#endif 81#endif
81 82
83struct lcd_bitmap_char
84{
85 bool is_rtl;
86 bool is_diacritic;
87 int width;
88 int base_width;
89};
90
82/* put a string at a given pixel position, skipping first ofs pixel columns */ 91/* put a string at a given pixel position, skipping first ofs pixel columns */
83static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) 92static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
84{ 93{
85 unsigned short ch;
86 unsigned short *ucs; 94 unsigned short *ucs;
87 struct font* pf = font_get(current_vp->font); 95 struct font* pf = font_get(current_vp->font);
88 int vp_flags = current_vp->flags; 96 int vp_flags = current_vp->flags;
89 97 int i, len;
90 ucs = bidi_l2v(str, 1); 98 static struct lcd_bitmap_char chars[SCROLL_LINE_SIZE];
91 99
92 if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) 100 if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0)
93 { 101 {
@@ -109,13 +117,59 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
109 } 117 }
110 } 118 }
111 119
112 while ((ch = *ucs++) != 0 && x < current_vp->width) 120 ucs = bidi_l2v(str, 1);
121 /* Mark diacritic and rtl flags for each character */
122 for (i = 0; i < SCROLL_LINE_SIZE && ucs[i]; i++)
123 chars[i].is_diacritic = is_diacritic(ucs[i], &chars[i].is_rtl);
124 len = i;
125
126 /* Get proportional width and glyph bits */
127 for (i = 0; i < len; i++)
128 chars[i].width = font_get_width(pf, ucs[i]);
129
130 /* Calculate base width for each character */
131 for (i = 0; i < len; i++)
132 {
133 if (chars[i].is_rtl)
134 {
135 /* Forward-seek the next non-diacritic character for base width */
136 if (chars[i].is_diacritic)
137 {
138 int j;
139
140 /* Jump to next non-diacritic character, and calc its width */
141 for (j = i; j < len && chars[j].is_diacritic; j++);
142
143 /* Set all related diacritic char's base-width accordingly */
144 for (; i <= j; i++)
145 chars[i].base_width = chars[j].width;
146 }
147 else
148 {
149 chars[i].base_width = chars[i].width;
150 }
151 }
152 else
153 {
154 static int last_non_diacritic_width = 0;
155
156 if (!chars[i].is_diacritic)
157 last_non_diacritic_width = chars[i].width;
158
159 chars[i].base_width = last_non_diacritic_width;
160 }
161 }
162
163 for (i = 0; i < len; i++)
113 { 164 {
114 int width;
115 const unsigned char *bits; 165 const unsigned char *bits;
166 unsigned short ch = ucs[i];
167 int width = chars[i].width;
168 int drawmode = 0, base_ofs = 0;
169 bool next_is_diacritic;
116 170
117 /* get proportional width and glyph bits */ 171 if (x >= current_vp->width)
118 width = font_get_width(pf, ch); 172 break;
119 173
120 if (ofs > width) 174 if (ofs > width)
121 { 175 {
@@ -123,13 +177,34 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
123 continue; 177 continue;
124 } 178 }
125 179
180 if (chars[i].is_diacritic)
181 {
182 drawmode = current_vp->drawmode;
183 current_vp->drawmode = DRMODE_FG;
184
185 base_ofs = (chars[i].base_width - width) / 2;
186 }
187
126 bits = font_get_bits(pf, ch); 188 bits = font_get_bits(pf, ch);
189 LCDFN(mono_bitmap_part)(bits, ofs, 0, width,
190 x + base_ofs, y, width - ofs, pf->height);
191
192 if (chars[i].is_diacritic)
193 {
194 current_vp->drawmode = drawmode;
195 }
127 196
128 LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, 197 /* Increment if next char is not diacritic (non-rtl),
129 pf->height); 198 * or current char is non-diacritic and next char is diacritic (rtl)*/
199 next_is_diacritic = (ucs[i + 1] && chars[i + 1].is_diacritic);
130 200
131 x += width - ofs; 201 if (ucs[i + 1] &&
132 ofs = 0; 202 ((chars[i].is_rtl && !chars[i].is_diacritic) ||
203 (!chars[i].is_rtl && (chars[i + 1].is_rtl || !chars[i + 1].is_diacritic))))
204 {
205 x += chars[i].base_width - ofs;
206 ofs = 0;
207 }
133 } 208 }
134} 209}
135/* put a string at a given pixel position */ 210/* put a string at a given pixel position */
diff --git a/firmware/font.c b/firmware/font.c
index e02f276efe..624e0de9a7 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -35,6 +35,7 @@
35#include "debug.h" 35#include "debug.h"
36#include "panic.h" 36#include "panic.h"
37#include "rbunicode.h" 37#include "rbunicode.h"
38#include "diacritic.h"
38 39
39#ifndef BOOTLOADER 40#ifndef BOOTLOADER
40/* Font cache includes */ 41/* Font cache includes */
@@ -604,6 +605,8 @@ int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
604 605
605 for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch)) 606 for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch))
606 { 607 {
608 if (is_diacritic(ch, NULL))
609 continue;
607 610
608 /* get proportional width and glyph bits*/ 611 /* get proportional width and glyph bits*/
609 width += font_get_width(pf,ch); 612 width += font_get_width(pf,ch);
diff --git a/firmware/include/diacritic.h b/firmware/include/diacritic.h
new file mode 100644
index 0000000000..ebcb3bb79a
--- /dev/null
+++ b/firmware/include/diacritic.h
@@ -0,0 +1,26 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 Tomer Shalev
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _DIACRITIC_H_
22#define _DIACRITIC_H_
23#include "system.h"
24
25int is_diacritic(unsigned short char_code, bool *is_rtl);
26#endif