From ded22eadf10d87828809bd40e61f7e05434924a4 Mon Sep 17 00:00:00 2001 From: ghost Date: Wed, 5 May 2010 01:16:17 +0200 Subject: lib/gdi/font.cpp: call libfribidi for single lines on multi line texts to prevent top/bottom reordering this fixes bug #300 --- lib/gdi/font.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp index dfac144c..2fd9fb69 100644 --- a/lib/gdi/font.cpp +++ b/lib/gdi/font.cpp @@ -595,22 +595,59 @@ int eTextPara::renderString(const char *string, int rflags) shape(uc_shape, uc_string); // now do the usual logical->visual reordering -#ifdef HAVE_FRIBIDI + int size=uc_shape.size(); +#ifdef HAVE_FRIBIDI FriBidiCharType dir=FRIBIDI_TYPE_ON; + int lines=1; + int pos=0, spos=0; + uc_visual.resize(size); + // gaaanz lahm, aber anders geht das leider nicht, sorry. + FriBidiChar array[size], target[size]; + std::copy(uc_shape.begin(), uc_shape.end(), array); + + bool line_open = false; + while(pos < size) { - int size=uc_shape.size(); - uc_visual.resize(size); - // gaaanz lahm, aber anders geht das leider nicht, sorry. - FriBidiChar array[size], target[size]; - std::copy(uc_shape.begin(), uc_shape.end(), array); - fribidi_log2vis(array, size, &dir, target, 0, 0, 0); - uc_visual.assign(target, target+size); + int incr=1; + bool line_end = false; + if (!line_open) + line_open = true; + switch((unsigned long)array[pos]) + { + case '\\': + if (pos+1 == size || (unsigned long)array[pos+1] != 'n') + break; + ++incr; + case 0x8A: + case 0xE08A: + case '\n': + line_end = true; + default: + break; + } + if (line_end || pos+incr >= size) { + int len = pos - spos; + if (len) + fribidi_log2vis(array+spos, len, &dir, target+spos, 0, 0, 0); + target[pos] = array[pos]; + if (incr > 1) + target[pos+1] = array[pos+1]; + spos = pos+incr; + ++lines; + line_open = false; + } + pos += incr; } + + if (lines < 2) + fribidi_log2vis(array, size, &dir, target, 0, 0, 0); + + uc_visual.assign(target, target+size); #else uc_visual=uc_shape; #endif - glyphs.reserve(uc_visual.size()); + glyphs.reserve(size); int nextflags = 0; -- cgit v1.2.3 From 7ab186a904a98842266746d2bd3e479bb1cde06e Mon Sep 17 00:00:00 2001 From: ghost Date: Sat, 8 May 2010 13:15:38 +0200 Subject: lib/gdi/font.cpp: try to fix wrong reordering of some characters --- lib/gdi/font.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp index 2fd9fb69..1d3c34da 100644 --- a/lib/gdi/font.cpp +++ b/lib/gdi/font.cpp @@ -597,8 +597,7 @@ int eTextPara::renderString(const char *string, int rflags) // now do the usual logical->visual reordering int size=uc_shape.size(); #ifdef HAVE_FRIBIDI - FriBidiCharType dir=FRIBIDI_TYPE_ON; - int lines=1; + bool mustRealign=false; int pos=0, spos=0; uc_visual.resize(size); // gaaanz lahm, aber anders geht das leider nicht, sorry. @@ -625,23 +624,25 @@ int eTextPara::renderString(const char *string, int rflags) default: break; } - if (line_end || pos+incr >= size) { + if (line_end || pos+incr >= size) + { int len = pos - spos; if (len) + { + FriBidiCharType dir=FRIBIDI_TYPE_ON; fribidi_log2vis(array+spos, len, &dir, target+spos, 0, 0, 0); + if (!mustRealign && dir&FRIBIDI_MASK_RTL) + mustRealign = true; + } target[pos] = array[pos]; if (incr > 1) target[pos+1] = array[pos+1]; spos = pos+incr; - ++lines; line_open = false; } pos += incr; } - if (lines < 2) - fribidi_log2vis(array, size, &dir, target, 0, 0, 0); - uc_visual.assign(target, target+size); #else uc_visual=uc_shape; @@ -740,7 +741,7 @@ nprint: isprintable=0; bboxValid=false; calc_bbox(); #ifdef HAVE_FRIBIDI - if (dir & FRIBIDI_MASK_RTL) + if (mustRealign) realign(dirRight); #endif return 0; -- cgit v1.2.3 From aec06d4c574979c24e7ef10c352f7a2d22e79177 Mon Sep 17 00:00:00 2001 From: ghost Date: Sat, 8 May 2010 18:42:25 +0200 Subject: Revert "lib/gdi/font.cpp: try to fix wrong reordering of some characters" its not working okay.. we need a better fix This reverts commit 414208c929faa0fc56f9c21c0df572dc0b13d3fe. --- lib/gdi/font.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp index 1d3c34da..2fd9fb69 100644 --- a/lib/gdi/font.cpp +++ b/lib/gdi/font.cpp @@ -597,7 +597,8 @@ int eTextPara::renderString(const char *string, int rflags) // now do the usual logical->visual reordering int size=uc_shape.size(); #ifdef HAVE_FRIBIDI - bool mustRealign=false; + FriBidiCharType dir=FRIBIDI_TYPE_ON; + int lines=1; int pos=0, spos=0; uc_visual.resize(size); // gaaanz lahm, aber anders geht das leider nicht, sorry. @@ -624,25 +625,23 @@ int eTextPara::renderString(const char *string, int rflags) default: break; } - if (line_end || pos+incr >= size) - { + if (line_end || pos+incr >= size) { int len = pos - spos; if (len) - { - FriBidiCharType dir=FRIBIDI_TYPE_ON; fribidi_log2vis(array+spos, len, &dir, target+spos, 0, 0, 0); - if (!mustRealign && dir&FRIBIDI_MASK_RTL) - mustRealign = true; - } target[pos] = array[pos]; if (incr > 1) target[pos+1] = array[pos+1]; spos = pos+incr; + ++lines; line_open = false; } pos += incr; } + if (lines < 2) + fribidi_log2vis(array, size, &dir, target, 0, 0, 0); + uc_visual.assign(target, target+size); #else uc_visual=uc_shape; @@ -741,7 +740,7 @@ nprint: isprintable=0; bboxValid=false; calc_bbox(); #ifdef HAVE_FRIBIDI - if (mustRealign) + if (dir & FRIBIDI_MASK_RTL) realign(dirRight); #endif return 0; -- cgit v1.2.3 From 684910d920f90134ade6dd3b944a749336a47029 Mon Sep 17 00:00:00 2001 From: ghost Date: Sat, 8 May 2010 18:42:56 +0200 Subject: Revert "lib/gdi/font.cpp: call libfribidi for single lines on multi line texts to prevent top/bottom reordering" This reverts commit eea0d8e99edec859a7535966b880b49bd0bba85a. This was not working.. so we revert it --- lib/gdi/font.cpp | 55 +++++++++---------------------------------------------- 1 file changed, 9 insertions(+), 46 deletions(-) diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp index 2fd9fb69..dfac144c 100644 --- a/lib/gdi/font.cpp +++ b/lib/gdi/font.cpp @@ -595,59 +595,22 @@ int eTextPara::renderString(const char *string, int rflags) shape(uc_shape, uc_string); // now do the usual logical->visual reordering - int size=uc_shape.size(); -#ifdef HAVE_FRIBIDI +#ifdef HAVE_FRIBIDI FriBidiCharType dir=FRIBIDI_TYPE_ON; - int lines=1; - int pos=0, spos=0; - uc_visual.resize(size); - // gaaanz lahm, aber anders geht das leider nicht, sorry. - FriBidiChar array[size], target[size]; - std::copy(uc_shape.begin(), uc_shape.end(), array); - - bool line_open = false; - while(pos < size) { - int incr=1; - bool line_end = false; - if (!line_open) - line_open = true; - switch((unsigned long)array[pos]) - { - case '\\': - if (pos+1 == size || (unsigned long)array[pos+1] != 'n') - break; - ++incr; - case 0x8A: - case 0xE08A: - case '\n': - line_end = true; - default: - break; - } - if (line_end || pos+incr >= size) { - int len = pos - spos; - if (len) - fribidi_log2vis(array+spos, len, &dir, target+spos, 0, 0, 0); - target[pos] = array[pos]; - if (incr > 1) - target[pos+1] = array[pos+1]; - spos = pos+incr; - ++lines; - line_open = false; - } - pos += incr; - } - - if (lines < 2) + int size=uc_shape.size(); + uc_visual.resize(size); + // gaaanz lahm, aber anders geht das leider nicht, sorry. + FriBidiChar array[size], target[size]; + std::copy(uc_shape.begin(), uc_shape.end(), array); fribidi_log2vis(array, size, &dir, target, 0, 0, 0); - - uc_visual.assign(target, target+size); + uc_visual.assign(target, target+size); + } #else uc_visual=uc_shape; #endif - glyphs.reserve(size); + glyphs.reserve(uc_visual.size()); int nextflags = 0; -- cgit v1.2.3 From a2fd35579432e777cffd5dc43f1b62e136b95bd4 Mon Sep 17 00:00:00 2001 From: ghost Date: Sat, 8 May 2010 19:01:53 +0200 Subject: lib/gdi/font.h/cpp: another try to fix top/bottom reordering for arabic language --- lib/gdi/font.cpp | 60 +++++++++++++++++++++++++++++++++++++++++--------------- lib/gdi/font.h | 13 +++++++++--- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp index dfac144c..f27a8f77 100644 --- a/lib/gdi/font.cpp +++ b/lib/gdi/font.cpp @@ -341,6 +341,8 @@ int eTextPara::appendGlyph(Font *current_font, FT_Face current_face, FT_UInt gly i->x-=offset.x(); i->y-=offset.y(); i->bbox.moveBy(-offset.x(), -offset.y()); + --lineChars.back(); + ++charCount; } while (i-- != glyphs.rbegin()); // rearrange them into the next line cursor+=ePoint(linelength, 0); // put the cursor after that line } else @@ -378,6 +380,7 @@ int eTextPara::appendGlyph(Font *current_font, FT_Face current_face, FT_UInt gly ng.glyph_index = glyphIndex; ng.flags = flags; glyphs.push_back(ng); + ++charCount; /* when we have a SHY, don't xadvance. It will either be the last in the line (when used for breaking), or not displayed. */ if (!(flags & GS_SOFTHYPHEN)) @@ -425,7 +428,13 @@ void eTextPara::newLine(int flags) cursor.setX(left); previous=0; int linegap=current_face->size->metrics.height-(current_face->size->metrics.ascender+current_face->size->metrics.descender); + + lineOffsets.push_back(cursor.y()); + lineChars.push_back(charCount); + charCount=0; + cursor+=ePoint(0, (current_face->size->metrics.ascender+current_face->size->metrics.descender+linegap)>>6); + if (maximum.height()visual reordering -#ifdef HAVE_FRIBIDI + int size=uc_shape.size(); +#ifdef HAVE_FRIBIDI FriBidiCharType dir=FRIBIDI_TYPE_ON; - { - int size=uc_shape.size(); - uc_visual.resize(size); - // gaaanz lahm, aber anders geht das leider nicht, sorry. - FriBidiChar array[size], target[size]; - std::copy(uc_shape.begin(), uc_shape.end(), array); - fribidi_log2vis(array, size, &dir, target, 0, 0, 0); - uc_visual.assign(target, target+size); - } + uc_visual.resize(size); + // gaaanz lahm, aber anders geht das leider nicht, sorry. + FriBidiChar array[size], target[size]; + std::copy(uc_shape.begin(), uc_shape.end(), array); + fribidi_log2vis(array, size, &dir, target, 0, 0, 0); + uc_visual.assign(target, target+size); #else uc_visual=uc_shape; #endif - glyphs.reserve(uc_visual.size()); + glyphs.reserve(size); int nextflags = 0; @@ -704,8 +711,19 @@ nprint: isprintable=0; calc_bbox(); #ifdef HAVE_FRIBIDI if (dir & FRIBIDI_MASK_RTL) + { realign(dirRight); + doTopBottomReordering=true; + } #endif + + if (charCount) + { + lineOffsets.push_back(cursor.y()); + lineChars.push_back(charCount); + charCount=0; + } + return 0; } @@ -796,11 +814,21 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons gRegion clip = dc.getClip() & area; int buffer_stride=surface->stride; - + for (unsigned int c = 0; c < clip.rects.size(); ++c) { - for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i) + std::list::reverse_iterator line_offs_it(lineOffsets.rbegin()); + std::list::iterator line_chars_it(lineChars.begin()); + int line_offs=0; + int line_chars=0; + for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i, --line_chars) { + while(!line_chars) + { + line_offs = *(line_offs_it++); + line_chars = *(line_chars_it++); + } + if (i->flags & GS_SOFTHYPHEN) continue; @@ -813,13 +841,13 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons lookup8 = lookup8_invert; lookup32 = lookup32_invert; } - + static FTC_SBit glyph_bitmap; if (fontRenderClass::instance->getGlyphBitmap(&i->font->font, i->glyph_index, &glyph_bitmap)) continue; int rx=i->x+glyph_bitmap->left + offset.x(); - int ry=i->y-glyph_bitmap->top + offset.y(); - + int ry=(doTopBottomReordering ? line_offs : i->y) - glyph_bitmap->top + offset.y(); + __u8 *d=(__u8*)(surface->data)+buffer_stride*ry+rx*surface->bypp; __u8 *s=glyph_bitmap->buffer; register int sx=glyph_bitmap->width; diff --git a/lib/gdi/font.h b/lib/gdi/font.h index 2643fda2..7dd9f89a 100644 --- a/lib/gdi/font.h +++ b/lib/gdi/font.h @@ -14,6 +14,7 @@ typedef FTC_ImageTypeRec FTC_Image_Desc; typedef FTC_SBitCache FTC_SBit_Cache; #endif #include +#include #include #include @@ -113,6 +114,10 @@ class eTextPara: public iObject eSize maximum; int left; glyphString glyphs; + std::list lineOffsets; + std::list lineChars; + int charCount; + bool doTopBottomReordering; int appendGlyph(Font *current_font, FT_Face current_face, FT_UInt glyphIndex, int flags, int rflags); void newLine(int flags); @@ -120,10 +125,12 @@ class eTextPara: public iObject eRect boundBox; void calc_bbox(); int bboxValid; + void clear(); public: eTextPara(eRect area, ePoint start=ePoint(-1, -1)) - : current_font(0), replacement_font(0), current_face(0), replacement_face(0), - area(area), cursor(start), maximum(0, 0), left(start.x()), bboxValid(0) + :current_font(0), replacement_font(0), current_face(0), replacement_face(0) + ,area(area), cursor(start), maximum(0, 0), left(start.x()), charCount(0) + ,doTopBottomReordering(false), bboxValid(0) { } virtual ~eTextPara(); @@ -134,7 +141,7 @@ public: void setFont(const gFont *font); int renderString(const char *string, int flags=0); - void clear(); + void blit(gDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground); -- cgit v1.2.3