mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-12 10:30:28 +00:00
(svn r26017) -Change: allow the fallback and ICU layouter to exist in unison
-Fix [FS#5711]: crash when the ICU layouter thinks a font is corrupted
This commit is contained in:
parent
6449e96f1a
commit
ddc0026712
@ -13,6 +13,7 @@
|
|||||||
#include "gfx_layout.h"
|
#include "gfx_layout.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "strings_func.h"
|
#include "strings_func.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#include "table/control_codes.h"
|
#include "table/control_codes.h"
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &poin
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Layouter::AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
|
static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
|
||||||
{
|
{
|
||||||
/* Transform from UTF-32 to internal ICU format of UTF-16. */
|
/* Transform from UTF-32 to internal ICU format of UTF-16. */
|
||||||
int32 length = 0;
|
int32 length = 0;
|
||||||
@ -119,7 +120,63 @@ size_t Layouter::AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphLayout *Layouter::GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
|
/**
|
||||||
|
* Wrapper for doing layouts with ICU.
|
||||||
|
*/
|
||||||
|
class ICUParagraphLayout : public AutoDeleteSmallVector<ParagraphLayouter::Line *, 4>, public ParagraphLayouter {
|
||||||
|
ParagraphLayout *p; ///< The actual ICU paragraph layout.
|
||||||
|
public:
|
||||||
|
/** Helper for GetLayouter, to get the right type. */
|
||||||
|
typedef UChar CharType;
|
||||||
|
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||||
|
static const bool SUPPORTS_RTL = true;
|
||||||
|
|
||||||
|
/** Visual run contains data about the bit of text with the same font. */
|
||||||
|
class ICUVisualRun : public ParagraphLayouter::VisualRun {
|
||||||
|
const ParagraphLayout::VisualRun *vr; ///< The actual ICU vr.
|
||||||
|
|
||||||
|
public:
|
||||||
|
ICUVisualRun(const ParagraphLayout::VisualRun *vr) : vr(vr) { }
|
||||||
|
|
||||||
|
const Font *getFont() const { return (const Font*)vr->getFont(); }
|
||||||
|
int getGlyphCount() const { return vr->getGlyphCount(); }
|
||||||
|
const GlyphID *getGlyphs() const { return vr->getGlyphs(); }
|
||||||
|
const float *getPositions() const { return vr->getPositions(); }
|
||||||
|
int getLeading() const { return vr->getLeading(); }
|
||||||
|
const int *getGlyphToCharMap() const { return vr->getGlyphToCharMap(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A single line worth of VisualRuns. */
|
||||||
|
class ICULine : public AutoDeleteSmallVector<ICUVisualRun *, 4>, public ParagraphLayouter::Line {
|
||||||
|
ParagraphLayout::Line *l; ///< The actual ICU line.
|
||||||
|
|
||||||
|
public:
|
||||||
|
ICULine(ParagraphLayout::Line *l) : l(l)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < l->countRuns(); i++) {
|
||||||
|
*this->Append() = new ICUVisualRun(l->getVisualRun(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~ICULine() { delete l; }
|
||||||
|
|
||||||
|
int getLeading() const { return l->getLeading(); }
|
||||||
|
int getWidth() const { return l->getWidth(); }
|
||||||
|
int countRuns() const { return l->countRuns(); }
|
||||||
|
const ParagraphLayouter::VisualRun *getVisualRun(int run) const { return *this->Get(run); }
|
||||||
|
};
|
||||||
|
|
||||||
|
ICUParagraphLayout(ParagraphLayout *p) : p(p) { }
|
||||||
|
~ICUParagraphLayout() { delete p; }
|
||||||
|
void reflow() { p->reflow(); }
|
||||||
|
|
||||||
|
ParagraphLayouter::Line *nextLine(int max_width)
|
||||||
|
{
|
||||||
|
ParagraphLayout::Line *l = p->nextLine(max_width);
|
||||||
|
return l == NULL ? NULL : new ICULine(l);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
|
||||||
{
|
{
|
||||||
int32 length = buff_end - buff;
|
int32 length = buff_end - buff;
|
||||||
|
|
||||||
@ -139,12 +196,79 @@ ParagraphLayout *Layouter::GetParagraphLayout(UChar *buff, UChar *buff_end, Font
|
|||||||
LEErrorCode status = LE_NO_ERROR;
|
LEErrorCode status = LE_NO_ERROR;
|
||||||
/* ParagraphLayout does not copy "buff", so it must stay valid.
|
/* ParagraphLayout does not copy "buff", so it must stay valid.
|
||||||
* "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
|
* "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
|
||||||
return new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
|
ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
|
||||||
|
if (status != LE_NO_ERROR) {
|
||||||
|
delete p;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* WITH_ICU */
|
return new ICUParagraphLayout(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_ICU */
|
||||||
|
|
||||||
/*** Paragraph layout ***/
|
/*** Paragraph layout ***/
|
||||||
|
/**
|
||||||
|
* Class handling the splitting of a paragraph of text into lines and
|
||||||
|
* visual runs.
|
||||||
|
*
|
||||||
|
* One constructs this class with the text that needs to be split into
|
||||||
|
* lines. Then nextLine is called with the maximum width until NULL is
|
||||||
|
* returned. Each nextLine call creates VisualRuns which contain the
|
||||||
|
* length of text that are to be drawn with the same font. In other
|
||||||
|
* words, the result of this class is a list of sub strings with their
|
||||||
|
* font. The sub strings are then already fully laid out, and only
|
||||||
|
* need actual drawing.
|
||||||
|
*
|
||||||
|
* The positions in a visual run are sequential pairs of X,Y of the
|
||||||
|
* begin of each of the glyphs plus an extra pair to mark the end.
|
||||||
|
*
|
||||||
|
* @note This variant does not handle left-to-right properly. This
|
||||||
|
* is supported in the one ParagraphLayout coming from ICU.
|
||||||
|
*/
|
||||||
|
class FallbackParagraphLayout : public ParagraphLayouter {
|
||||||
|
public:
|
||||||
|
/** Helper for GetLayouter, to get the right type. */
|
||||||
|
typedef WChar CharType;
|
||||||
|
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||||
|
static const bool SUPPORTS_RTL = false;
|
||||||
|
|
||||||
|
/** Visual run contains data about the bit of text with the same font. */
|
||||||
|
class FallbackVisualRun : public ParagraphLayouter::VisualRun {
|
||||||
|
Font *font; ///< The font used to layout these.
|
||||||
|
GlyphID *glyphs; ///< The glyphs we're drawing.
|
||||||
|
float *positions; ///< The positions of the glyphs.
|
||||||
|
int *glyph_to_char; ///< The char index of the glyphs.
|
||||||
|
int glyph_count; ///< The number of glyphs.
|
||||||
|
|
||||||
|
public:
|
||||||
|
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x);
|
||||||
|
~FallbackVisualRun();
|
||||||
|
const Font *getFont() const;
|
||||||
|
int getGlyphCount() const;
|
||||||
|
const GlyphID *getGlyphs() const;
|
||||||
|
const float *getPositions() const;
|
||||||
|
int getLeading() const;
|
||||||
|
const int *getGlyphToCharMap() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A single line worth of VisualRuns. */
|
||||||
|
class FallbackLine : public AutoDeleteSmallVector<FallbackVisualRun *, 4>, public ParagraphLayouter::Line {
|
||||||
|
public:
|
||||||
|
int getLeading() const;
|
||||||
|
int getWidth() const;
|
||||||
|
int countRuns() const;
|
||||||
|
const ParagraphLayouter::VisualRun *getVisualRun(int run) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
const WChar *buffer_begin; ///< Begin of the buffer.
|
||||||
|
const WChar *buffer; ///< The current location in the buffer.
|
||||||
|
FontMap &runs; ///< The fonts we have to use for this paragraph.
|
||||||
|
|
||||||
|
FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs);
|
||||||
|
void reflow();
|
||||||
|
const ParagraphLayouter::Line *nextLine(int max_width);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the visual run.
|
* Create the visual run.
|
||||||
@ -261,7 +385,7 @@ int FallbackParagraphLayout::FallbackLine::getWidth() const
|
|||||||
* Since there is no left-to-right support, taking this value of
|
* Since there is no left-to-right support, taking this value of
|
||||||
* the last run gives us the end of the line and thus the width.
|
* the last run gives us the end of the line and thus the width.
|
||||||
*/
|
*/
|
||||||
const FallbackVisualRun *run = this->getVisualRun(this->countRuns() - 1);
|
const ParagraphLayouter::VisualRun *run = this->getVisualRun(this->countRuns() - 1);
|
||||||
return (int)run->getPositions()[run->getGlyphCount() * 2];
|
return (int)run->getPositions()[run->getGlyphCount() * 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +533,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::nextLine(int max_width)
|
|||||||
* @param c The character to add.
|
* @param c The character to add.
|
||||||
* @return The number of buffer spaces that were used.
|
* @return The number of buffer spaces that were used.
|
||||||
*/
|
*/
|
||||||
size_t Layouter::AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
|
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
|
||||||
{
|
{
|
||||||
*buff = c;
|
*buff = c;
|
||||||
return 1;
|
return 1;
|
||||||
@ -422,11 +546,74 @@ size_t Layouter::AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
|
|||||||
* @param fontMapping THe mapping of the fonts.
|
* @param fontMapping THe mapping of the fonts.
|
||||||
* @return The ParagraphLayout instance.
|
* @return The ParagraphLayout instance.
|
||||||
*/
|
*/
|
||||||
ParagraphLayouter *Layouter::GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
|
static FallbackParagraphLayout *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
|
||||||
{
|
{
|
||||||
return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
|
return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
|
||||||
}
|
}
|
||||||
#endif /* !WITH_ICU */
|
|
||||||
|
/**
|
||||||
|
* Helper for getting a ParagraphLayouter of the given type.
|
||||||
|
*
|
||||||
|
* @note In case no ParagraphLayouter could be constructed, line.layout will be NULL.
|
||||||
|
* @param line The cache item to store our layouter in.
|
||||||
|
* @param str The string to create a layouter for.
|
||||||
|
* @param state The state of the font and color.
|
||||||
|
* @tparam T The type of layouter we want.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static inline void GetLayouter(Layouter::LineCacheItem &line, const char *str, FontState state)
|
||||||
|
{
|
||||||
|
if (line.buffer != NULL) free(line.buffer);
|
||||||
|
|
||||||
|
typename T::CharType *buff_begin = MallocT<typename T::CharType>(DRAW_STRING_BUFFER);
|
||||||
|
const typename T::CharType *buffer_last = buff_begin + DRAW_STRING_BUFFER;
|
||||||
|
typename T::CharType *buff = buff_begin;
|
||||||
|
FontMap &fontMapping = line.runs;
|
||||||
|
Font *f = Layouter::GetFont(state.fontsize, state.cur_colour);
|
||||||
|
|
||||||
|
line.buffer = buff_begin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go through the whole string while adding Font instances to the font map
|
||||||
|
* whenever the font changes, and convert the wide characters into a format
|
||||||
|
* usable by ParagraphLayout.
|
||||||
|
*/
|
||||||
|
for (; buff < buffer_last;) {
|
||||||
|
WChar c = Utf8Consume(const_cast<const char **>(&str));
|
||||||
|
if (c == '\0' || c == '\n') {
|
||||||
|
break;
|
||||||
|
} else if (c >= SCC_BLUE && c <= SCC_BLACK) {
|
||||||
|
state.SetColour((TextColour)(c - SCC_BLUE));
|
||||||
|
} else if (c == SCC_PREVIOUS_COLOUR) { // Revert to the previous colour.
|
||||||
|
state.SetPreviousColour();
|
||||||
|
} else if (c == SCC_TINYFONT) {
|
||||||
|
state.SetFontSize(FS_SMALL);
|
||||||
|
} else if (c == SCC_BIGFONT) {
|
||||||
|
state.SetFontSize(FS_LARGE);
|
||||||
|
} else {
|
||||||
|
/* Filter out text direction characters that shouldn't be drawn, and
|
||||||
|
* will not be handled in the fallback non ICU case because they are
|
||||||
|
* mostly needed for RTL languages which need more ICU support. */
|
||||||
|
if (!T::SUPPORTS_RTL && IsTextDirectionChar(c)) continue;
|
||||||
|
buff += AppendToBuffer(buff, buffer_last, c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fontMapping.Contains(buff - buff_begin)) {
|
||||||
|
fontMapping.Insert(buff - buff_begin, f);
|
||||||
|
}
|
||||||
|
f = Layouter::GetFont(state.fontsize, state.cur_colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Better safe than sorry. */
|
||||||
|
*buff = '\0';
|
||||||
|
|
||||||
|
if (!fontMapping.Contains(buff - buff_begin)) {
|
||||||
|
fontMapping.Insert(buff - buff_begin, f);
|
||||||
|
}
|
||||||
|
line.layout = GetParagraphLayout(buff_begin, buff, fontMapping);
|
||||||
|
line.state_after = state;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new layouter.
|
* Create a new layouter.
|
||||||
@ -457,54 +644,19 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
|
|||||||
line.layout->reflow();
|
line.layout->reflow();
|
||||||
} else {
|
} else {
|
||||||
/* Line is new, layout it */
|
/* Line is new, layout it */
|
||||||
const CharType *buffer_last = lastof(line.buffer);
|
#ifdef WITH_ICU
|
||||||
CharType *buff_begin = line.buffer;
|
GetLayouter<ICUParagraphLayout>(line, str, state);
|
||||||
CharType *buff = buff_begin;
|
if (line.layout == NULL) {
|
||||||
FontMap &fontMapping = line.runs;
|
static bool warned = false;
|
||||||
Font *f = GetFont(state.fontsize, state.cur_colour);
|
if (!warned) {
|
||||||
|
DEBUG(misc, 0, "ICU layouter bailed on the font. Falling back to the fallback layouter");
|
||||||
/*
|
warned = true;
|
||||||
* Go through the whole string while adding Font instances to the font map
|
}
|
||||||
* whenever the font changes, and convert the wide characters into a format
|
GetLayouter<FallbackParagraphLayout>(line, str, state);
|
||||||
* usable by ParagraphLayout.
|
}
|
||||||
*/
|
#else
|
||||||
for (; buff < buffer_last;) {
|
GetLayouter<FallbackParagraphLayout>(line, str, state);
|
||||||
c = Utf8Consume(const_cast<const char **>(&str));
|
|
||||||
if (c == '\0' || c == '\n') {
|
|
||||||
break;
|
|
||||||
} else if (c >= SCC_BLUE && c <= SCC_BLACK) {
|
|
||||||
state.SetColour((TextColour)(c - SCC_BLUE));
|
|
||||||
} else if (c == SCC_PREVIOUS_COLOUR) { // Revert to the previous colour.
|
|
||||||
state.SetPreviousColour();
|
|
||||||
} else if (c == SCC_TINYFONT) {
|
|
||||||
state.SetFontSize(FS_SMALL);
|
|
||||||
} else if (c == SCC_BIGFONT) {
|
|
||||||
state.SetFontSize(FS_LARGE);
|
|
||||||
} else {
|
|
||||||
#ifndef WITH_ICU
|
|
||||||
/* Filter out text direction characters that shouldn't be drawn, and
|
|
||||||
* will not be handled in the fallback non ICU case because they are
|
|
||||||
* mostly needed for RTL languages which need more ICU support. */
|
|
||||||
if (IsTextDirectionChar(c)) continue;
|
|
||||||
#endif
|
#endif
|
||||||
buff += AppendToBuffer(buff, buffer_last, c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fontMapping.Contains(buff - buff_begin)) {
|
|
||||||
fontMapping.Insert(buff - buff_begin, f);
|
|
||||||
}
|
|
||||||
f = GetFont(state.fontsize, state.cur_colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Better safe than sorry. */
|
|
||||||
*buff = '\0';
|
|
||||||
|
|
||||||
if (!fontMapping.Contains(buff - buff_begin)) {
|
|
||||||
fontMapping.Insert(buff - buff_begin, f);
|
|
||||||
}
|
|
||||||
line.layout = GetParagraphLayout(buff_begin, buff, fontMapping);
|
|
||||||
line.state_after = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
@ -24,11 +24,7 @@
|
|||||||
#define ICU_FONTINSTANCE : public LEFontInstance
|
#define ICU_FONTINSTANCE : public LEFontInstance
|
||||||
#else /* WITH_ICU */
|
#else /* WITH_ICU */
|
||||||
#define ICU_FONTINSTANCE
|
#define ICU_FONTINSTANCE
|
||||||
#define FallbackParagraphLayout ParagraphLayout
|
|
||||||
#define FallbackVisualRun VisualRun
|
|
||||||
#define FallbackLine Line
|
|
||||||
#endif /* WITH_ICU */
|
#endif /* WITH_ICU */
|
||||||
#define ParagraphLayouter ParagraphLayout
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text drawing parameters, which can change while drawing a line, but are kept between multiple parts
|
* Text drawing parameters, which can change while drawing a line, but are kept between multiple parts
|
||||||
@ -101,66 +97,38 @@ public:
|
|||||||
/** Mapping from index to font. */
|
/** Mapping from index to font. */
|
||||||
typedef SmallMap<int, Font *> FontMap;
|
typedef SmallMap<int, Font *> FontMap;
|
||||||
|
|
||||||
#ifndef WITH_ICU
|
|
||||||
/**
|
/**
|
||||||
* Class handling the splitting of a paragraph of text into lines and
|
* Interface to glue fallback and normal layouter into one.
|
||||||
* visual runs.
|
|
||||||
*
|
|
||||||
* One constructs this class with the text that needs to be split into
|
|
||||||
* lines. Then nextLine is called with the maximum width until NULL is
|
|
||||||
* returned. Each nextLine call creates VisualRuns which contain the
|
|
||||||
* length of text that are to be drawn with the same font. In other
|
|
||||||
* words, the result of this class is a list of sub strings with their
|
|
||||||
* font. The sub strings are then already fully laid out, and only
|
|
||||||
* need actual drawing.
|
|
||||||
*
|
|
||||||
* The positions in a visual run are sequential pairs of X,Y of the
|
|
||||||
* begin of each of the glyphs plus an extra pair to mark the end.
|
|
||||||
*
|
|
||||||
* @note This variant does not handle left-to-right properly. This
|
|
||||||
* is supported in the one ParagraphLayout coming from ICU.
|
|
||||||
* @note Does not conform to function naming style as it provides a
|
|
||||||
* fallback for the ICU class.
|
|
||||||
*/
|
*/
|
||||||
class FallbackParagraphLayout {
|
class ParagraphLayouter {
|
||||||
public:
|
public:
|
||||||
/** Visual run contains data about the bit of text with the same font. */
|
virtual ~ParagraphLayouter() {}
|
||||||
class FallbackVisualRun {
|
|
||||||
Font *font; ///< The font used to layout these.
|
|
||||||
GlyphID *glyphs; ///< The glyphs we're drawing.
|
|
||||||
float *positions; ///< The positions of the glyphs.
|
|
||||||
int *glyph_to_char; ///< The char index of the glyphs.
|
|
||||||
int glyph_count; ///< The number of glyphs.
|
|
||||||
|
|
||||||
|
/** Visual run contains data about the bit of text with the same font. */
|
||||||
|
class VisualRun {
|
||||||
public:
|
public:
|
||||||
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x);
|
virtual ~VisualRun() {}
|
||||||
~FallbackVisualRun();
|
virtual const Font *getFont() const = 0;
|
||||||
const Font *getFont() const;
|
virtual int getGlyphCount() const = 0;
|
||||||
int getGlyphCount() const;
|
virtual const GlyphID *getGlyphs() const = 0;
|
||||||
const GlyphID *getGlyphs() const;
|
virtual const float *getPositions() const = 0;
|
||||||
const float *getPositions() const;
|
virtual int getLeading() const = 0;
|
||||||
int getLeading() const;
|
virtual const int *getGlyphToCharMap() const = 0;
|
||||||
const int *getGlyphToCharMap() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A single line worth of VisualRuns. */
|
/** A single line worth of VisualRuns. */
|
||||||
class FallbackLine : public AutoDeleteSmallVector<FallbackVisualRun *, 4> {
|
class Line {
|
||||||
public:
|
public:
|
||||||
int getLeading() const;
|
virtual ~Line() {}
|
||||||
int getWidth() const;
|
virtual int getLeading() const = 0;
|
||||||
int countRuns() const;
|
virtual int getWidth() const = 0;
|
||||||
const FallbackVisualRun *getVisualRun(int run) const;
|
virtual int countRuns() const = 0;
|
||||||
|
virtual const VisualRun *getVisualRun(int run) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const WChar *buffer_begin; ///< Begin of the buffer.
|
virtual void reflow() = 0;
|
||||||
const WChar *buffer; ///< The current location in the buffer.
|
virtual const Line *nextLine(int max_width) = 0;
|
||||||
FontMap &runs; ///< The fonts we have to use for this paragraph.
|
|
||||||
|
|
||||||
FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs);
|
|
||||||
void reflow();
|
|
||||||
const Line *nextLine(int max_width);
|
|
||||||
};
|
};
|
||||||
#endif /* !WITH_ICU */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layouter performs all the layout work.
|
* The layouter performs all the layout work.
|
||||||
@ -168,17 +136,8 @@ public:
|
|||||||
* It also accounts for the memory allocations and frees.
|
* It also accounts for the memory allocations and frees.
|
||||||
*/
|
*/
|
||||||
class Layouter : public AutoDeleteSmallVector<const ParagraphLayouter::Line *, 4> {
|
class Layouter : public AutoDeleteSmallVector<const ParagraphLayouter::Line *, 4> {
|
||||||
#ifdef WITH_ICU
|
|
||||||
typedef UChar CharType; ///< The type of character used within the layouter.
|
|
||||||
#else /* WITH_ICU */
|
|
||||||
typedef WChar CharType; ///< The type of character used within the layouter.
|
|
||||||
#endif /* WITH_ICU */
|
|
||||||
|
|
||||||
const char *string; ///< Pointer to the original string.
|
const char *string; ///< Pointer to the original string.
|
||||||
|
|
||||||
size_t AppendToBuffer(CharType *buff, const CharType *buffer_last, WChar c);
|
|
||||||
ParagraphLayouter *GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping);
|
|
||||||
|
|
||||||
/** Key into the linecache */
|
/** Key into the linecache */
|
||||||
struct LineCacheKey {
|
struct LineCacheKey {
|
||||||
FontState state_before; ///< Font state at the beginning of the line.
|
FontState state_before; ///< Font state at the beginning of the line.
|
||||||
@ -193,18 +152,20 @@ class Layouter : public AutoDeleteSmallVector<const ParagraphLayouter::Line *, 4
|
|||||||
return this->str < other.str;
|
return this->str < other.str;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
public:
|
||||||
/** Item in the linecache */
|
/** Item in the linecache */
|
||||||
struct LineCacheItem {
|
struct LineCacheItem {
|
||||||
/* Stuff that cannot be freed until the ParagraphLayout is freed */
|
/* Stuff that cannot be freed until the ParagraphLayout is freed */
|
||||||
CharType buffer[DRAW_STRING_BUFFER]; ///< Accessed by both ICU's and our ParagraphLayout::nextLine.
|
void *buffer; ///< Accessed by both ICU's and our ParagraphLayout::nextLine.
|
||||||
FontMap runs; ///< Accessed by our ParagraphLayout::nextLine.
|
FontMap runs; ///< Accessed by our ParagraphLayout::nextLine.
|
||||||
|
|
||||||
FontState state_after; ///< Font state after the line.
|
FontState state_after; ///< Font state after the line.
|
||||||
ParagraphLayouter *layout; ///< Layout of the line.
|
ParagraphLayouter *layout; ///< Layout of the line.
|
||||||
|
|
||||||
LineCacheItem() : layout(NULL) {}
|
LineCacheItem() : buffer(NULL), layout(NULL) {}
|
||||||
~LineCacheItem() { delete layout; }
|
~LineCacheItem() { delete layout; free(buffer); }
|
||||||
};
|
};
|
||||||
|
private:
|
||||||
typedef std::map<LineCacheKey, LineCacheItem> LineCache;
|
typedef std::map<LineCacheKey, LineCacheItem> LineCache;
|
||||||
static LineCache *linecache;
|
static LineCache *linecache;
|
||||||
|
|
||||||
@ -212,9 +173,9 @@ class Layouter : public AutoDeleteSmallVector<const ParagraphLayouter::Line *, 4
|
|||||||
|
|
||||||
typedef SmallMap<TextColour, Font *> FontColourMap;
|
typedef SmallMap<TextColour, Font *> FontColourMap;
|
||||||
static FontColourMap fonts[FS_END];
|
static FontColourMap fonts[FS_END];
|
||||||
|
public:
|
||||||
static Font *GetFont(FontSize size, TextColour colour);
|
static Font *GetFont(FontSize size, TextColour colour);
|
||||||
|
|
||||||
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);
|
||||||
Dimension GetBounds();
|
Dimension GetBounds();
|
||||||
Point GetCharPosition(const char *ch) const;
|
Point GetCharPosition(const char *ch) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user