Index: firmware/bidi.c =================================================================== --- firmware/bidi.c (revision 25435) +++ firmware/bidi.c (working copy) @@ -30,6 +30,7 @@ #include "arabjoin.h" #include "scroll_engine.h" #include "bidi.h" +#include "diacritic.h" /* #define _HEB_BUFFER_LENGTH (MAX_PATH + LCD_WIDTH/2 + 3 + 2 + 2) * 2 */ #define _HEB_BLOCK_TYPE_ENG 1 @@ -61,30 +62,47 @@ { bool connected = false; unsigned short * writeprt = stringprt; - + short diacs = 0; + unsigned short * diac_ptr = 0; const arab_t * prev = 0; const arab_t * cur; const arab_t * ligature = 0; short uchar; - int i; + int i, j; for (i = 0; i <= length; i++) { cur = arab_lookup(uchar = *stringprt++); /* Skip non-arabic chars */ + /* (actually this skips diacritics too as they are commented in + * arabjoin.c) */ if (cur == 0) { - if (prev) { + /* skip diacritics without affecting the shaping algorithm (apply + * joining as if there is no diacritics) */ + if (is_diacritic(uchar, NULL)) { + if(!diacs) + diac_ptr = stringprt - 1; + diacs++; + } + else if (prev) /* non-arabic characters */ + { /* Finish the last char */ if (connected) { *writeprt++ = prev->final; connected = false; - } else + } + else *writeprt++ = prev->isolated; prev = 0; + if (diacs) { /* write the skipped diacritics */ + for (j = 0; j < diacs; j++) + *writeprt++ = *diac_ptr++; + diacs = 0; + } *writeprt++ = uchar; - } else { + } + else *writeprt++ = uchar; - } continue; } @@ -129,6 +147,12 @@ } else *writeprt++ = prev->isolated; } + + if (diacs) { /* write the skipped diacritics */ + for (j = 0; j < diacs; j++) + *writeprt++ = *diac_ptr++; + diacs = 0; + } prev = cur; } } Index: firmware/drivers/lcd-bitmap-common.c =================================================================== --- firmware/drivers/lcd-bitmap-common.c (revision 25435) +++ firmware/drivers/lcd-bitmap-common.c (working copy) @@ -30,6 +30,7 @@ #include "stdarg.h" #include "sprintf.h" #include "diacritic.h" +#include "buffer.h" #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */ #define LCDFN(fn) lcd_ ## fn @@ -84,10 +85,16 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) { unsigned short *ucs; + unsigned char *bits_buf; + int k; + bool draw_now = 1; struct font* pf = font_get(current_vp->font); int vp_flags = current_vp->flags; int rtl_next_non_diac_width, last_non_diacritic_width; + const short glyph_bits_length = pf->height * pf->maxwidth / 8; + bits_buf = buffer_alloc(glyph_bits_length); + memset(bits_buf, 0, glyph_bits_length); if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) { int w; @@ -115,7 +122,7 @@ { bool is_rtl, is_diac; const unsigned char *bits; - int width, base_width, drawmode = 0, base_ofs = 0; + int width, base_width, base_ofs = 0; const unsigned short next_ch = ucs[1]; if (x >= current_vp->width) @@ -165,50 +172,36 @@ if (is_diac) { - /* XXX: Suggested by amiconn: - * This will produce completely wrong results if the original - * drawmode is DRMODE_COMPLEMENT. We need to pre-render the current - * character with all its diacritics at least (in mono) and then - * finally draw that. And we'll need an extra buffer that can hold - * one char's bitmap. Basically we can't just change the draw mode - * to something else irrespective of the original mode and expect - * the result to look as intended and with DRMODE_COMPLEMENT (which - * means XORing pixels), overdrawing this way will cause odd results - * if the diacritics and the base char both have common pixels set. - * So we need to combine the char and its diacritics in a temp - * buffer using OR, and then draw the final bitmap instead of the - * chars, without touching the drawmode - **/ - drawmode = current_vp->drawmode; - current_vp->drawmode = DRMODE_FG; - base_ofs = (base_width - width) / 2; } bits = font_get_bits(pf, *ucs); - LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x + base_ofs, y, - width - ofs, pf->height); - - if (is_diac) - { - current_vp->drawmode = drawmode; - } - + /* Buffer glyph bits and OR them with their diacritics */ + for(k = 0; k < glyph_bits_length; k++) + bits_buf[k] |= bits[k]; if (next_ch) { bool next_is_rtl; bool next_is_diacritic = is_diacritic(next_ch, &next_is_rtl); - /* Increment if: + /* Set draw_now flag if: * LTR: Next char is not diacritic, * RTL: Current char is non-diacritic and next char is diacritic */ if ((is_rtl && !is_diac) || (!is_rtl && (!next_is_diacritic || next_is_rtl))) - { - x += base_width - ofs; - ofs = 0; - } + draw_now = 1; + else + draw_now = 0; } + /* draw buffered diacritized glyph and move x to next */ + if(draw_now | !next_ch) + { + LCDFN(mono_bitmap_part)(bits_buf, ofs, 0, width, x + base_ofs, y, + width - ofs, pf->height); + memset(bits_buf, 0, glyph_bits_length); + x += base_width - ofs; + ofs = 0; + } } }