Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Layouter reverse-mapping to characters #11060

Merged
merged 2 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/gfx_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,19 @@ Dimension Layouter::GetBounds()
return d;
}

/**
* Test whether a character is a non-printable formatting code
*/
static bool IsConsumedFormattingCode(WChar ch)
{
if (ch >= SCC_BLUE && ch <= SCC_BLACK) return true;
if (ch == SCC_PUSH_COLOUR) return true;
if (ch == SCC_POP_COLOUR) return true;
if (ch >= SCC_FIRST_FONT && ch <= SCC_LAST_FONT) return true;
// All other characters defined in Unicode standard are assumed to be non-consumed.
return false;
}

/**
* Get the position of a character in the layout.
* @param ch Character to get the position of. Must be an iterator of the string passed to the constructor.
Expand All @@ -228,7 +241,7 @@ Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const
auto str = this->string.begin();
while (str < ch) {
WChar c = Utf8Consume(str);
index += line->GetInternalCharLength(c);
if (!IsConsumedFormattingCode(c)) index += line->GetInternalCharLength(c);
}

/* We couldn't find the code point index. */
Expand Down Expand Up @@ -282,7 +295,7 @@ ptrdiff_t Layouter::GetCharAtPosition(int x) const
if (cur_idx == index) return str - this->string.begin();

WChar c = Utf8Consume(str);
cur_idx += line->GetInternalCharLength(c);
if (!IsConsumedFormattingCode(c)) cur_idx += line->GetInternalCharLength(c);
}
}
}
Expand Down
21 changes: 11 additions & 10 deletions src/gfx_layout_fallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class FallbackParagraphLayout : public ParagraphLayouter {
int glyph_count; ///< The number of glyphs.

public:
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x);
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int char_offset, int x);
FallbackVisualRun(FallbackVisualRun &&other) noexcept;
~FallbackVisualRun() override;
const Font *GetFont() const override;
Expand Down Expand Up @@ -104,12 +104,13 @@ class FallbackParagraphLayout : public ParagraphLayouter {

/**
* Create the visual run.
* @param font The font to use for this run.
* @param chars The characters to use for this run.
* @param char_count The number of characters in this run.
* @param x The initial x position for this run.
* @param font The font to use for this run.
* @param chars The characters to use for this run.
* @param char_count The number of characters in this run.
* @param char_offset This run's offset from the start of the layout input string.
* @param x The initial x position for this run.
*/
FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const WChar *chars, int char_count, int x) :
FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const WChar *chars, int char_count, int char_offset, int x) :
font(font), glyph_count(char_count)
{
const bool isbuiltin = font->fc->IsBuiltInFont();
Expand All @@ -131,7 +132,7 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const
this->positions[2 * i + 1] = 0; // No ascender adjustment.
}
this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(this->glyphs[i]);
this->glyph_to_char[i] = i;
this->glyph_to_char[i] = char_offset + i;
}
}

Expand Down Expand Up @@ -295,7 +296,7 @@ std::unique_ptr<const ParagraphLayouter::Line> FallbackParagraphLayout::NextLine
if (*this->buffer == '\0') {
/* Only a newline. */
this->buffer = nullptr;
l->emplace_back(this->runs.begin()->second, this->buffer, 0, 0);
l->emplace_back(this->runs.begin()->second, this->buffer, 0, 0, 0);
return l;
}

Expand Down Expand Up @@ -324,7 +325,7 @@ std::unique_ptr<const ParagraphLayouter::Line> FallbackParagraphLayout::NextLine

if (this->buffer == next_run) {
int w = l->GetWidth();
l->emplace_back(iter->second, begin, this->buffer - begin, w);
l->emplace_back(iter->second, begin, this->buffer - begin, begin - this->buffer_begin, w);
++iter;
assert(iter != this->runs.end());

Expand Down Expand Up @@ -369,7 +370,7 @@ std::unique_ptr<const ParagraphLayouter::Line> FallbackParagraphLayout::NextLine

if (l->size() == 0 || last_char - begin > 0) {
int w = l->GetWidth();
l->emplace_back(iter->second, begin, last_char - begin, w);
l->emplace_back(iter->second, begin, last_char - begin, begin - this->buffer_begin, w);
}
return l;
}