|
|
|
@ -138,12 +138,12 @@ public:
|
|
|
|
|
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(); }
|
|
|
|
|
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. */
|
|
|
|
@ -159,17 +159,17 @@ public:
|
|
|
|
|
}
|
|
|
|
|
~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); }
|
|
|
|
|
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(); }
|
|
|
|
|
void Reflow() { p->reflow(); }
|
|
|
|
|
|
|
|
|
|
ParagraphLayouter::Line *nextLine(int max_width)
|
|
|
|
|
ParagraphLayouter::Line *NextLine(int max_width)
|
|
|
|
|
{
|
|
|
|
|
ParagraphLayout::Line *l = p->nextLine(max_width);
|
|
|
|
|
return l == NULL ? NULL : new ICULine(l);
|
|
|
|
@ -244,21 +244,21 @@ public:
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
int GetLeading() const;
|
|
|
|
|
int GetWidth() const;
|
|
|
|
|
int CountRuns() const;
|
|
|
|
|
const ParagraphLayouter::VisualRun *GetVisualRun(int run) const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const WChar *buffer_begin; ///< Begin of the buffer.
|
|
|
|
@ -266,8 +266,8 @@ public:
|
|
|
|
|
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);
|
|
|
|
|
void Reflow();
|
|
|
|
|
const ParagraphLayouter::Line *NextLine(int max_width);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -308,7 +308,7 @@ FallbackParagraphLayout::FallbackVisualRun::~FallbackVisualRun()
|
|
|
|
|
* Get the font associated with this run.
|
|
|
|
|
* @return The font.
|
|
|
|
|
*/
|
|
|
|
|
const Font *FallbackParagraphLayout::FallbackVisualRun::getFont() const
|
|
|
|
|
const Font *FallbackParagraphLayout::FallbackVisualRun::GetFont() const
|
|
|
|
|
{
|
|
|
|
|
return this->font;
|
|
|
|
|
}
|
|
|
|
@ -317,7 +317,7 @@ const Font *FallbackParagraphLayout::FallbackVisualRun::getFont() const
|
|
|
|
|
* Get the number of glyphs in this run.
|
|
|
|
|
* @return The number of glyphs.
|
|
|
|
|
*/
|
|
|
|
|
int FallbackParagraphLayout::FallbackVisualRun::getGlyphCount() const
|
|
|
|
|
int FallbackParagraphLayout::FallbackVisualRun::GetGlyphCount() const
|
|
|
|
|
{
|
|
|
|
|
return this->glyph_count;
|
|
|
|
|
}
|
|
|
|
@ -326,7 +326,7 @@ int FallbackParagraphLayout::FallbackVisualRun::getGlyphCount() const
|
|
|
|
|
* Get the glyphs of this run.
|
|
|
|
|
* @return The glyphs.
|
|
|
|
|
*/
|
|
|
|
|
const GlyphID *FallbackParagraphLayout::FallbackVisualRun::getGlyphs() const
|
|
|
|
|
const GlyphID *FallbackParagraphLayout::FallbackVisualRun::GetGlyphs() const
|
|
|
|
|
{
|
|
|
|
|
return this->glyphs;
|
|
|
|
|
}
|
|
|
|
@ -335,7 +335,7 @@ const GlyphID *FallbackParagraphLayout::FallbackVisualRun::getGlyphs() const
|
|
|
|
|
* Get the positions of this run.
|
|
|
|
|
* @return The positions.
|
|
|
|
|
*/
|
|
|
|
|
const float *FallbackParagraphLayout::FallbackVisualRun::getPositions() const
|
|
|
|
|
const float *FallbackParagraphLayout::FallbackVisualRun::GetPositions() const
|
|
|
|
|
{
|
|
|
|
|
return this->positions;
|
|
|
|
|
}
|
|
|
|
@ -344,7 +344,7 @@ const float *FallbackParagraphLayout::FallbackVisualRun::getPositions() const
|
|
|
|
|
* Get the glyph-to-character map for this visual run.
|
|
|
|
|
* @return The glyph-to-character map.
|
|
|
|
|
*/
|
|
|
|
|
const int *FallbackParagraphLayout::FallbackVisualRun::getGlyphToCharMap() const
|
|
|
|
|
const int *FallbackParagraphLayout::FallbackVisualRun::GetGlyphToCharMap() const
|
|
|
|
|
{
|
|
|
|
|
return this->glyph_to_char;
|
|
|
|
|
}
|
|
|
|
@ -353,20 +353,20 @@ const int *FallbackParagraphLayout::FallbackVisualRun::getGlyphToCharMap() const
|
|
|
|
|
* Get the height of this font.
|
|
|
|
|
* @return The height of the font.
|
|
|
|
|
*/
|
|
|
|
|
int FallbackParagraphLayout::FallbackVisualRun::getLeading() const
|
|
|
|
|
int FallbackParagraphLayout::FallbackVisualRun::GetLeading() const
|
|
|
|
|
{
|
|
|
|
|
return this->getFont()->fc->GetHeight();
|
|
|
|
|
return this->GetFont()->fc->GetHeight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the height of the line.
|
|
|
|
|
* @return The maximum height of the line.
|
|
|
|
|
*/
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::getLeading() const
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::GetLeading() const
|
|
|
|
|
{
|
|
|
|
|
int leading = 0;
|
|
|
|
|
for (const FallbackVisualRun * const *run = this->Begin(); run != this->End(); run++) {
|
|
|
|
|
leading = max(leading, (*run)->getLeading());
|
|
|
|
|
leading = max(leading, (*run)->GetLeading());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return leading;
|
|
|
|
@ -376,7 +376,7 @@ int FallbackParagraphLayout::FallbackLine::getLeading() const
|
|
|
|
|
* Get the width of this line.
|
|
|
|
|
* @return The width of the line.
|
|
|
|
|
*/
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::getWidth() const
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::GetWidth() const
|
|
|
|
|
{
|
|
|
|
|
if (this->Length() == 0) return 0;
|
|
|
|
|
|
|
|
|
@ -385,15 +385,15 @@ int FallbackParagraphLayout::FallbackLine::getWidth() const
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = this->getVisualRun(this->countRuns() - 1);
|
|
|
|
|
return (int)run->getPositions()[run->getGlyphCount() * 2];
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = this->GetVisualRun(this->CountRuns() - 1);
|
|
|
|
|
return (int)run->GetPositions()[run->GetGlyphCount() * 2];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the number of runs in this line.
|
|
|
|
|
* @return The number of runs.
|
|
|
|
|
*/
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::countRuns() const
|
|
|
|
|
int FallbackParagraphLayout::FallbackLine::CountRuns() const
|
|
|
|
|
{
|
|
|
|
|
return this->Length();
|
|
|
|
|
}
|
|
|
|
@ -402,7 +402,7 @@ int FallbackParagraphLayout::FallbackLine::countRuns() const
|
|
|
|
|
* Get a specific visual run.
|
|
|
|
|
* @return The visual run.
|
|
|
|
|
*/
|
|
|
|
|
const ParagraphLayouter::VisualRun *FallbackParagraphLayout::FallbackLine::getVisualRun(int run) const
|
|
|
|
|
const ParagraphLayouter::VisualRun *FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const
|
|
|
|
|
{
|
|
|
|
|
return *this->Get(run);
|
|
|
|
|
}
|
|
|
|
@ -421,7 +421,7 @@ FallbackParagraphLayout::FallbackParagraphLayout(WChar *buffer, int length, Font
|
|
|
|
|
/**
|
|
|
|
|
* Reset the position to the start of the paragraph.
|
|
|
|
|
*/
|
|
|
|
|
void FallbackParagraphLayout::reflow()
|
|
|
|
|
void FallbackParagraphLayout::Reflow()
|
|
|
|
|
{
|
|
|
|
|
this->buffer = this->buffer_begin;
|
|
|
|
|
}
|
|
|
|
@ -431,7 +431,7 @@ void FallbackParagraphLayout::reflow()
|
|
|
|
|
* @param max_width The maximum width of the string.
|
|
|
|
|
* @return A Line, or NULL when at the end of the paragraph.
|
|
|
|
|
*/
|
|
|
|
|
const ParagraphLayouter::Line *FallbackParagraphLayout::nextLine(int max_width)
|
|
|
|
|
const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width)
|
|
|
|
|
{
|
|
|
|
|
/* Simple idea:
|
|
|
|
|
* - split a line at a newline character, or at a space where we can break a line.
|
|
|
|
@ -473,7 +473,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::nextLine(int max_width)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->buffer == next_run) {
|
|
|
|
|
int w = l->getWidth();
|
|
|
|
|
int w = l->GetWidth();
|
|
|
|
|
*l->Append() = new FallbackVisualRun(iter->second, begin, this->buffer - begin, w);
|
|
|
|
|
iter++;
|
|
|
|
|
assert(iter != this->runs.End());
|
|
|
|
@ -520,7 +520,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::nextLine(int max_width)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (l->Length() == 0 || last_char - begin != 0) {
|
|
|
|
|
int w = l->getWidth();
|
|
|
|
|
int w = l->GetWidth();
|
|
|
|
|
*l->Append() = new FallbackVisualRun(iter->second, begin, last_char - begin, w);
|
|
|
|
|
}
|
|
|
|
|
return l;
|
|
|
|
@ -641,7 +641,7 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
|
|
|
|
|
/* Line is in cache */
|
|
|
|
|
str = lineend + 1;
|
|
|
|
|
state = line.state_after;
|
|
|
|
|
line.layout->reflow();
|
|
|
|
|
line.layout->Reflow();
|
|
|
|
|
} else {
|
|
|
|
|
/* Line is new, layout it */
|
|
|
|
|
#ifdef WITH_ICU
|
|
|
|
@ -661,7 +661,7 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
|
|
|
|
|
|
|
|
|
|
/* Copy all lines into a local cache so we can reuse them later on more easily. */
|
|
|
|
|
const ParagraphLayouter::Line *l;
|
|
|
|
|
while ((l = line.layout->nextLine(maxw)) != NULL) {
|
|
|
|
|
while ((l = line.layout->NextLine(maxw)) != NULL) {
|
|
|
|
|
*this->Append() = l;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -676,8 +676,8 @@ Dimension Layouter::GetBounds()
|
|
|
|
|
{
|
|
|
|
|
Dimension d = { 0, 0 };
|
|
|
|
|
for (const ParagraphLayouter::Line **l = this->Begin(); l != this->End(); l++) {
|
|
|
|
|
d.width = max<uint>(d.width, (*l)->getWidth());
|
|
|
|
|
d.height += (*l)->getLeading();
|
|
|
|
|
d.width = max<uint>(d.width, (*l)->GetWidth());
|
|
|
|
|
d.height += (*l)->GetLeading();
|
|
|
|
|
}
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
@ -713,18 +713,18 @@ Point Layouter::GetCharPosition(const char *ch) const
|
|
|
|
|
|
|
|
|
|
/* Pointer to the end-of-string/line marker? Return total line width. */
|
|
|
|
|
if (*ch == '\0' || *ch == '\n') {
|
|
|
|
|
Point p = { line->getWidth(), 0 };
|
|
|
|
|
Point p = { line->GetWidth(), 0 };
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scan all runs until we've found our code point index. */
|
|
|
|
|
for (int run_index = 0; run_index < line->countRuns(); run_index++) {
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = line->getVisualRun(run_index);
|
|
|
|
|
for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < run->getGlyphCount(); i++) {
|
|
|
|
|
for (int i = 0; i < run->GetGlyphCount(); i++) {
|
|
|
|
|
/* Matching glyph? Return position. */
|
|
|
|
|
if ((size_t)run->getGlyphToCharMap()[i] == index) {
|
|
|
|
|
Point p = { (int)run->getPositions()[i * 2], (int)run->getPositions()[i * 2 + 1] };
|
|
|
|
|
if ((size_t)run->GetGlyphToCharMap()[i] == index) {
|
|
|
|
|
Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] };
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -742,21 +742,21 @@ Point Layouter::GetCharPosition(const char *ch) const
|
|
|
|
|
*/
|
|
|
|
|
const char *Layouter::GetCharAtPosition(int x) const
|
|
|
|
|
{
|
|
|
|
|
const ParagraphLayouter::Line *line = *this->Begin();;
|
|
|
|
|
const ParagraphLayouter::Line *line = *this->Begin();
|
|
|
|
|
|
|
|
|
|
for (int run_index = 0; run_index < line->countRuns(); run_index++) {
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = line->getVisualRun(run_index);
|
|
|
|
|
for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
|
|
|
|
|
const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < run->getGlyphCount(); i++) {
|
|
|
|
|
for (int i = 0; i < run->GetGlyphCount(); i++) {
|
|
|
|
|
/* Not a valid glyph (empty). */
|
|
|
|
|
if (run->getGlyphs()[i] == 0xFFFF) continue;
|
|
|
|
|
if (run->GetGlyphs()[i] == 0xFFFF) continue;
|
|
|
|
|
|
|
|
|
|
int begin_x = (int)run->getPositions()[i * 2];
|
|
|
|
|
int end_x = (int)run->getPositions()[i * 2 + 2];
|
|
|
|
|
int begin_x = (int)run->GetPositions()[i * 2];
|
|
|
|
|
int end_x = (int)run->GetPositions()[i * 2 + 2];
|
|
|
|
|
|
|
|
|
|
if (IsInsideMM(x, begin_x, end_x)) {
|
|
|
|
|
/* Found our glyph, now convert to UTF-8 string index. */
|
|
|
|
|
size_t index = run->getGlyphToCharMap()[i];
|
|
|
|
|
size_t index = run->GetGlyphToCharMap()[i];
|
|
|
|
|
|
|
|
|
|
size_t cur_idx = 0;
|
|
|
|
|
for (const char *str = this->string; *str != '\0'; ) {
|
|
|
|
|