(svn r25482) -Fix [FS#5620]: forced newlines were not properly handled

This commit is contained in:
rubidium 2013-06-27 16:24:19 +00:00
parent bd2f4b9a24
commit 569eaf0e11
2 changed files with 79 additions and 60 deletions

View File

@ -105,25 +105,25 @@ size_t Layouter::AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
return length; return length;
} }
ParagraphLayout *Layouter::GetParagraphLayout(UChar *buff) ParagraphLayout *Layouter::GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
{ {
int32 length = buff - this->buffer; int32 length = buff_end - buff;
if (length == 0) { if (length == 0) {
/* ICU's ParagraphLayout cannot handle empty strings, so fake one. */ /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
this->buffer[0] = ' '; buff[0] = ' ';
length = 1; length = 1;
this->fonts.End()[-1].first++; fontMapping.End()[-1].first++;
} }
/* Fill ICU's FontRuns with the right data. */ /* Fill ICU's FontRuns with the right data. */
FontRuns runs(this->fonts.Length()); FontRuns runs(fontMapping.Length());
for (FontMap::iterator iter = this->fonts.Begin(); iter != this->fonts.End(); iter++) { for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
runs.add(iter->second, iter->first); runs.add(iter->second, iter->first);
} }
LEErrorCode status = LE_NO_ERROR; LEErrorCode status = LE_NO_ERROR;
return new ParagraphLayout(this->buffer, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status); return new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
} }
#else /* WITH_ICU */ #else /* WITH_ICU */
@ -277,20 +277,27 @@ ParagraphLayout::Line *ParagraphLayout::nextLine(int max_width)
* - split a line at a newline character, or at a space where we can break a line. * - split a line at a newline character, or at a space where we can break a line.
* - split for a visual run whenever a new line happens, or the font changes. * - split for a visual run whenever a new line happens, or the font changes.
*/ */
if (this->buffer == NULL|| *this->buffer == '\0') return NULL; if (this->buffer == NULL) return NULL;
Line *l = new Line(); Line *l = new Line();
if (*this->buffer == '\0') {
/* Only a newline. */
this->buffer = NULL;
*l->Append() = new VisualRun(this->runs.Begin()->second, this->buffer, 0, 0);
return l;
}
const WChar *begin = this->buffer; const WChar *begin = this->buffer;
WChar *last_space = NULL; WChar *last_space = NULL;
const WChar *last_char = begin; const WChar *last_char = begin;
int width = 0; int width = 0;
int offset = this->buffer - this->buffer_begin; int offset = this->buffer - this->buffer_begin;
FontMap::iterator iter = runs.Begin(); FontMap::iterator iter = this->runs.Begin();
while (iter->first <= offset) { while (iter->first <= offset) {
iter++; iter++;
assert(iter != runs.End()); assert(iter != this->runs.End());
} }
const FontCache *fc = iter->second->fc; const FontCache *fc = iter->second->fc;
@ -303,12 +310,11 @@ ParagraphLayout::Line *ParagraphLayout::nextLine(int max_width)
this->buffer = NULL; this->buffer = NULL;
break; break;
} }
if (c == '\n') break;
if (this->buffer == next_run) { if (this->buffer == next_run) {
*l->Append() = new VisualRun(iter->second, begin, this->buffer - begin, l->getWidth()); *l->Append() = new VisualRun(iter->second, begin, this->buffer - begin, l->getWidth());
iter++; iter++;
assert(iter != runs.End()); assert(iter != this->runs.End());
next_run = this->buffer_begin + iter->first + 1; next_run = this->buffer_begin + iter->first + 1;
begin = this->buffer; begin = this->buffer;
@ -350,7 +356,7 @@ ParagraphLayout::Line *ParagraphLayout::nextLine(int max_width)
} }
} }
if (last_char - begin != 0) { if (l->Length() == 0 || last_char - begin != 0) {
*l->Append() = new VisualRun(iter->second, begin, last_char - begin, l->getWidth()); *l->Append() = new VisualRun(iter->second, begin, last_char - begin, l->getWidth());
} }
return l; return l;
@ -371,12 +377,14 @@ size_t Layouter::AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
/** /**
* Get the actual ParagraphLayout for the given buffer. * Get the actual ParagraphLayout for the given buffer.
* @param buff The begin of the buffer.
* @param buff_end The location after the last element in the buffer. * @param buff_end The location after the last element in the buffer.
* @param fontMapping THe mapping of the fonts.
* @return The ParagraphLayout instance. * @return The ParagraphLayout instance.
*/ */
ParagraphLayout *Layouter::GetParagraphLayout(WChar *buff_end) ParagraphLayout *Layouter::GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
{ {
return new ParagraphLayout(this->buffer, buff_end - this->buffer, this->fonts); return new ParagraphLayout(buff, buff_end - buff, fontMapping);
} }
#endif /* !WITH_ICU */ #endif /* !WITH_ICU */
@ -393,7 +401,12 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
CharType *buff = this->buffer; CharType *buff = this->buffer;
TextColour cur_colour = colour, prev_colour = colour; TextColour cur_colour = colour, prev_colour = colour;
WChar c;
do {
Font *f = new Font(fontsize, cur_colour); Font *f = new Font(fontsize, cur_colour);
CharType *buff_begin = buff;
FontMap fontMapping;
/* /*
* Go through the whole string while adding Font instances to the font map * Go through the whole string while adding Font instances to the font map
@ -401,8 +414,8 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
* usable by ParagraphLayout. * usable by ParagraphLayout.
*/ */
for (; buff < buffer_last;) { for (; buff < buffer_last;) {
WChar c = Utf8Consume(const_cast<const char **>(&str)); c = Utf8Consume(const_cast<const char **>(&str));
if (c == 0) { if (c == '\0' || c == '\n') {
break; break;
} else if (c >= SCC_BLUE && c <= SCC_BLACK) { } else if (c >= SCC_BLUE && c <= SCC_BLACK) {
prev_colour = cur_colour; prev_colour = cur_colour;
@ -418,8 +431,9 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
continue; continue;
} }
if (!this->fonts.Contains(buff - this->buffer)) { if (!fontMapping.Contains(buff - buff_begin)) {
this->fonts.Insert(buff - this->buffer, f); fontMapping.Insert(buff - buff_begin, f);
*this->fonts.Append() = f;
} else { } else {
delete f; delete f;
} }
@ -429,10 +443,11 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
/* Better safe than sorry. */ /* Better safe than sorry. */
*buff = '\0'; *buff = '\0';
if (!this->fonts.Contains(buff - this->buffer)) { if (!fontMapping.Contains(buff - buff_begin)) {
this->fonts.Insert(buff - this->buffer, f); fontMapping.Insert(buff - buff_begin, f);
*this->fonts.Append() = f;
} }
ParagraphLayout *p = GetParagraphLayout(buff); ParagraphLayout *p = GetParagraphLayout(buff_begin, buff, fontMapping);
/* Copy all lines into a local cache so we can reuse them later on more easily. */ /* Copy all lines into a local cache so we can reuse them later on more easily. */
ParagraphLayout::Line *l; ParagraphLayout::Line *l;
@ -441,13 +456,15 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
} }
delete p; delete p;
} while (c != '\0' && buff < buffer_last);
} }
/** Free everything we allocated. */ /** Free everything we allocated. */
Layouter::~Layouter() Layouter::~Layouter()
{ {
for (FontMap::iterator iter = this->fonts.Begin(); iter != this->fonts.End(); iter++) { for (Font **iter = this->fonts.Begin(); iter != this->fonts.End(); iter++) {
delete iter->second; delete *iter;
} }
} }

View File

@ -16,6 +16,8 @@
#include "gfx_func.h" #include "gfx_func.h"
#include "core/smallmap_type.hpp" #include "core/smallmap_type.hpp"
#undef WITH_ICU
#ifdef WITH_ICU #ifdef WITH_ICU
#include "layout/ParagraphLayout.h" #include "layout/ParagraphLayout.h"
#define ICU_FONTINSTANCE : public LEFontInstance #define ICU_FONTINSTANCE : public LEFontInstance
@ -125,10 +127,10 @@ class Layouter : public AutoDeleteSmallVector<ParagraphLayout::Line *, 4> {
#endif /* WITH_ICU */ #endif /* WITH_ICU */
size_t AppendToBuffer(CharType *buff, const CharType *buffer_last, WChar c); size_t AppendToBuffer(CharType *buff, const CharType *buffer_last, WChar c);
ParagraphLayout *GetParagraphLayout(CharType *buff); ParagraphLayout *GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping);
CharType buffer[DRAW_STRING_BUFFER]; ///< Buffer for the text that is going to be drawn. CharType buffer[DRAW_STRING_BUFFER]; ///< Buffer for the text that is going to be drawn.
FontMap fonts; ///< The fonts needed for drawing. SmallVector<Font *, 4> fonts; ///< The fonts needed for drawing.
public: public:
Layouter(const char *str, int maxw = INT32_MAX, TextColour colour = TC_FROMSTRING, FontSize fontsize = FS_NORMAL); Layouter(const char *str, int maxw = INT32_MAX, TextColour colour = TC_FROMSTRING, FontSize fontsize = FS_NORMAL);