diff options
author | Tomer Shalev <shalev.tomer@gmail.com> | 2009-11-24 20:41:42 +0000 |
---|---|---|
committer | Tomer Shalev <shalev.tomer@gmail.com> | 2009-11-24 20:41:42 +0000 |
commit | 7682cb5ca8f201be74dc12c1388cdd69a6c178bc (patch) | |
tree | a59dda85dbc95c9dddd69970ee7bcd36cdbba7c0 /firmware/drivers/lcd-bitmap-common.c | |
parent | 640d98de0fe2d7f5447ce2bdaf435108478e451a (diff) | |
download | rockbox-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.c | 97 |
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 | ||
83 | struct 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 */ |
83 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | 92 | static 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 */ |