diff options
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 */ |