summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
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