summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-bitmap-common.c
diff options
context:
space:
mode:
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 70ae00b..5b79879 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -29,6 +29,7 @@
****************************************************************************/
#include "stdarg.h"
#include "sprintf.h"
+#include "diacritic.h"
#ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
#define LCDFN(fn) lcd_ ## fn
@@ -79,15 +80,22 @@ static void lcd_gradient_rect(int x1, int x2, int y, unsigned h,
}
#endif
+struct lcd_bitmap_char
+{
+ bool is_rtl;
+ bool is_diacritic;
+ int width;
+ int base_width;
+};
+
/* put a string at a given pixel position, skipping first ofs pixel columns */
static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
{
- unsigned short ch;
unsigned short *ucs;
struct font* pf = font_get(current_vp->font);
int vp_flags = current_vp->flags;
-
- ucs = bidi_l2v(str, 1);
+ int i, len;
+ static struct lcd_bitmap_char chars[SCROLL_LINE_SIZE];
if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0)
{
@@ -109,13 +117,59 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
}
}
- while ((ch = *ucs++) != 0 && x < current_vp->width)
+ ucs = bidi_l2v(str, 1);
+ /* Mark diacritic and rtl flags for each character */
+ for (i = 0; i < SCROLL_LINE_SIZE && ucs[i]; i++)
+ chars[i].is_diacritic = is_diacritic(ucs[i], &chars[i].is_rtl);
+ len = i;
+
+ /* Get proportional width and glyph bits */
+ for (i = 0; i < len; i++)
+ chars[i].width = font_get_width(pf, ucs[i]);
+
+ /* Calculate base width for each character */
+ for (i = 0; i < len; i++)
+ {
+ if (chars[i].is_rtl)
+ {
+ /* Forward-seek the next non-diacritic character for base width */
+ if (chars[i].is_diacritic)
+ {
+ int j;
+
+ /* Jump to next non-diacritic character, and calc its width */
+ for (j = i; j < len && chars[j].is_diacritic; j++);
+
+ /* Set all related diacritic char's base-width accordingly */
+ for (; i <= j; i++)
+ chars[i].base_width = chars[j].width;
+ }
+ else
+ {
+ chars[i].base_width = chars[i].width;
+ }
+ }
+ else
+ {
+ static int last_non_diacritic_width = 0;
+
+ if (!chars[i].is_diacritic)
+ last_non_diacritic_width = chars[i].width;
+
+ chars[i].base_width = last_non_diacritic_width;
+ }
+ }
+
+ for (i = 0; i < len; i++)
{
- int width;
const unsigned char *bits;
+ unsigned short ch = ucs[i];
+ int width = chars[i].width;
+ int drawmode = 0, base_ofs = 0;
+ bool next_is_diacritic;
- /* get proportional width and glyph bits */
- width = font_get_width(pf, ch);
+ if (x >= current_vp->width)
+ break;
if (ofs > width)
{
@@ -123,13 +177,34 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
continue;
}
+ if (chars[i].is_diacritic)
+ {
+ drawmode = current_vp->drawmode;
+ current_vp->drawmode = DRMODE_FG;
+
+ base_ofs = (chars[i].base_width - width) / 2;
+ }
+
bits = font_get_bits(pf, ch);
+ LCDFN(mono_bitmap_part)(bits, ofs, 0, width,
+ x + base_ofs, y, width - ofs, pf->height);
+
+ if (chars[i].is_diacritic)
+ {
+ current_vp->drawmode = drawmode;
+ }
- LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs,
- pf->height);
+ /* Increment if next char is not diacritic (non-rtl),
+ * or current char is non-diacritic and next char is diacritic (rtl)*/
+ next_is_diacritic = (ucs[i + 1] && chars[i + 1].is_diacritic);
- x += width - ofs;
- ofs = 0;
+ if (ucs[i + 1] &&
+ ((chars[i].is_rtl && !chars[i].is_diacritic) ||
+ (!chars[i].is_rtl && (chars[i + 1].is_rtl || !chars[i + 1].is_diacritic))))
+ {
+ x += chars[i].base_width - ofs;
+ ofs = 0;
+ }
}
}
/* put a string at a given pixel position */