summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-bitmap-common.c
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/drivers/lcd-bitmap-common.c
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/drivers/lcd-bitmap-common.c')
-rw-r--r--firmware/drivers/lcd-bitmap-common.c97
1 files changed, 86 insertions, 11 deletions
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 */