1
0
Fork 0

Codechange: Store both left and right glyph positions in a run.

This also allows the end of a run to be known without using an extra position entry.
pull/12771/head
Peter Nelson 2024-05-22 20:36:18 +01:00 committed by Peter Nelson
parent 80ddcb9d7d
commit 5cd81a980e
10 changed files with 68 additions and 61 deletions

View File

@ -349,10 +349,10 @@ struct IConsoleWindow : Window
{ {
int delta = std::min<int>(this->width - this->line_offset - _iconsole_cmdline.pixels - ICON_RIGHT_BORDERWIDTH, 0); int delta = std::min<int>(this->width - this->line_offset - _iconsole_cmdline.pixels - ICON_RIGHT_BORDERWIDTH, 0);
Point p1 = GetCharPosInString(_iconsole_cmdline.buf, from, FS_NORMAL); const auto p1 = GetCharPosInString(_iconsole_cmdline.buf, from, FS_NORMAL);
Point p2 = from != to ? GetCharPosInString(_iconsole_cmdline.buf, to, FS_NORMAL) : p1; const auto p2 = from != to ? GetCharPosInString(_iconsole_cmdline.buf, to, FS_NORMAL) : p1;
Rect r = {this->line_offset + delta + p1.x, this->height - this->line_height, this->line_offset + delta + p2.x, this->height}; Rect r = {this->line_offset + delta + p1.left, this->height - this->line_height, this->line_offset + delta + p2.right, this->height};
return r; return r;
} }

View File

@ -605,9 +605,9 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
/* Not a valid glyph (empty) */ /* Not a valid glyph (empty) */
if (glyph == 0xFFFF) continue; if (glyph == 0xFFFF) continue;
int begin_x = positions[i].x + left - offset_x; int begin_x = positions[i].left + left - offset_x;
int end_x = positions[i + 1].x + left - offset_x - 1; int end_x = positions[i].right + left - offset_x;
int top = positions[i].y + y; int top = positions[i].top + y;
/* Truncated away. */ /* Truncated away. */
if (truncation && (begin_x < min_x || end_x > max_x)) continue; if (truncation && (begin_x < min_x || end_x > max_x)) continue;

View File

@ -225,7 +225,7 @@ static bool IsConsumedFormattingCode(char32_t ch)
* @return Upper left corner of the character relative to the start of the string. * @return Upper left corner of the character relative to the start of the string.
* @note Will only work right for single-line strings. * @note Will only work right for single-line strings.
*/ */
Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const ParagraphLayouter::Position Layouter::GetCharPosition(std::string_view::const_iterator ch) const
{ {
const auto &line = this->front(); const auto &line = this->front();
@ -245,8 +245,8 @@ Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const
} }
/* Initial position, returned if character not found. */ /* Initial position, returned if character not found. */
const Point initial_position = {_current_text_dir == TD_LTR ? 0 : line->GetWidth(), 0}; const ParagraphLayouter::Position initial_position = Point{_current_text_dir == TD_LTR ? 0 : line->GetWidth(), 0};
const Point *position = &initial_position; const ParagraphLayouter::Position *position = &initial_position;
/* We couldn't find the code point index. */ /* We couldn't find the code point index. */
if (str != ch) return *position; if (str != ch) return *position;
@ -303,8 +303,8 @@ ptrdiff_t Layouter::GetCharAtPosition(int x, size_t line_index) const
/* Not a valid glyph (empty). */ /* Not a valid glyph (empty). */
if (glyphs[i] == 0xFFFF) continue; if (glyphs[i] == 0xFFFF) continue;
int begin_x = positions[i].x; int begin_x = positions[i].left;
int end_x = positions[i + 1].x; int end_x = positions[i].right + 1;
if (IsInsideMM(x, begin_x, end_x)) { if (IsInsideMM(x, begin_x, end_x)) {
/* Found our glyph, now convert to UTF-8 string index. */ /* Found our glyph, now convert to UTF-8 string index. */
@ -418,7 +418,7 @@ void Layouter::ReduceLineCache()
* @param start_fontsize Font size to start the text with. * @param start_fontsize Font size to start the text with.
* @return Upper left corner of the glyph associated with the character. * @return Upper left corner of the glyph associated with the character.
*/ */
Point GetCharPosInString(std::string_view str, const char *ch, FontSize start_fontsize) ParagraphLayouter::Position GetCharPosInString(std::string_view str, const char *ch, FontSize start_fontsize)
{ {
/* Ensure "ch" is inside "str" or at the exact end. */ /* Ensure "ch" is inside "str" or at the exact end. */
assert(ch >= str.data() && (ch - str.data()) <= static_cast<ptrdiff_t>(str.size())); assert(ch >= str.data() && (ch - str.data()) <= static_cast<ptrdiff_t>(str.size()));

View File

@ -90,6 +90,19 @@ class ParagraphLayouter {
public: public:
virtual ~ParagraphLayouter() = default; virtual ~ParagraphLayouter() = default;
/** Position of a glyph within a VisualRun. */
class Position {
public:
int16_t left; ///< Left-most position of glyph.
int16_t right; ///< Right-most position of glyph.
int16_t top; ///< Top-most position of glyph.
constexpr inline Position(int16_t left, int16_t right, int16_t top) : left(left), right(right), top(top) { }
/** Conversion from a single point to a Position. */
constexpr inline Position(const Point &pt) : left(pt.x), right(pt.x), top(pt.y) { }
};
/** Visual run contains data about the bit of text with the same font. */ /** Visual run contains data about the bit of text with the same font. */
class VisualRun { class VisualRun {
public: public:
@ -97,7 +110,7 @@ public:
virtual const Font *GetFont() const = 0; virtual const Font *GetFont() const = 0;
virtual int GetGlyphCount() const = 0; virtual int GetGlyphCount() const = 0;
virtual std::span<const GlyphID> GetGlyphs() const = 0; virtual std::span<const GlyphID> GetGlyphs() const = 0;
virtual std::span<const Point> GetPositions() const = 0; virtual std::span<const Position> GetPositions() const = 0;
virtual int GetLeading() const = 0; virtual int GetLeading() const = 0;
virtual std::span<const int> GetGlyphToCharMap() const = 0; virtual std::span<const int> GetGlyphToCharMap() const = 0;
}; };
@ -176,7 +189,7 @@ public:
Layouter(std::string_view str, int maxw = INT32_MAX, FontSize fontsize = FS_NORMAL); Layouter(std::string_view str, int maxw = INT32_MAX, FontSize fontsize = FS_NORMAL);
Dimension GetBounds(); Dimension GetBounds();
Point GetCharPosition(std::string_view::const_iterator ch) const; ParagraphLayouter::Position GetCharPosition(std::string_view::const_iterator ch) const;
ptrdiff_t GetCharAtPosition(int x, size_t line_index) const; ptrdiff_t GetCharAtPosition(int x, size_t line_index) const;
static void Initialize(); static void Initialize();
@ -185,7 +198,7 @@ public:
static void ReduceLineCache(); static void ReduceLineCache();
}; };
Point GetCharPosInString(std::string_view str, const char *ch, FontSize start_fontsize = FS_NORMAL); ParagraphLayouter::Position GetCharPosInString(std::string_view str, const char *ch, FontSize start_fontsize = FS_NORMAL);
ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize = FS_NORMAL); ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize = FS_NORMAL);
#endif /* GFX_LAYOUT_H */ #endif /* GFX_LAYOUT_H */

View File

@ -40,7 +40,7 @@ public:
/** Visual run contains data about the bit of text with the same font. */ /** Visual run contains data about the bit of text with the same font. */
class FallbackVisualRun : public ParagraphLayouter::VisualRun { class FallbackVisualRun : public ParagraphLayouter::VisualRun {
std::vector<GlyphID> glyphs; ///< The glyphs we're drawing. std::vector<GlyphID> glyphs; ///< The glyphs we're drawing.
std::vector<Point> positions; ///< The positions of the glyphs. std::vector<Position> positions; ///< The positions of the glyphs.
std::vector<int> glyph_to_char; ///< The char index of the glyphs. std::vector<int> glyph_to_char; ///< The char index of the glyphs.
Font *font; ///< The font used to layout these. Font *font; ///< The font used to layout these.
@ -50,7 +50,7 @@ public:
const Font *GetFont() const override { return this->font; } const Font *GetFont() const override { return this->font; }
int GetGlyphCount() const override { return static_cast<int>(this->glyphs.size()); } int GetGlyphCount() const override { return static_cast<int>(this->glyphs.size()); }
std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; } std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; }
std::span<const Point> GetPositions() const override { return this->positions; } std::span<const Position> GetPositions() const override { return this->positions; }
int GetLeading() const override { return this->GetFont()->fc->GetHeight(); } int GetLeading() const override { return this->GetFont()->fc->GetHeight(); }
std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; } std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; }
}; };
@ -116,25 +116,22 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const
this->glyphs.reserve(char_count); this->glyphs.reserve(char_count);
this->glyph_to_char.reserve(char_count); this->glyph_to_char.reserve(char_count);
this->positions.reserve(char_count);
/* Positions contains the location of the begin of each of the glyphs, and the end of the last one. */
this->positions.reserve(char_count + 1);
int advance = x; int advance = x;
for (int i = 0; i < char_count; i++) { for (int i = 0; i < char_count; i++) {
const GlyphID &glyph_id = this->glyphs.emplace_back(font->fc->MapCharToGlyph(chars[i])); const GlyphID &glyph_id = this->glyphs.emplace_back(font->fc->MapCharToGlyph(chars[i]));
int x_advance = font->fc->GetGlyphWidth(glyph_id);
if (isbuiltin) { if (isbuiltin) {
this->positions.emplace_back(advance, font->fc->GetAscender()); // Apply sprite font's ascender. this->positions.emplace_back(advance, advance + x_advance - 1, font->fc->GetAscender()); // Apply sprite font's ascender.
} else if (chars[i] >= SCC_SPRITE_START && chars[i] <= SCC_SPRITE_END) { } else if (chars[i] >= SCC_SPRITE_START && chars[i] <= SCC_SPRITE_END) {
this->positions.emplace_back(advance, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre this->positions.emplace_back(advance, advance + x_advance - 1, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre
} else { } else {
this->positions.emplace_back(advance, 0); // No ascender adjustment. this->positions.emplace_back(advance, advance + x_advance - 1, 0); // No ascender adjustment.
} }
advance += font->fc->GetGlyphWidth(glyph_id); advance += x_advance;
this->glyph_to_char.push_back(char_offset + i); this->glyph_to_char.push_back(char_offset + i);
} }
/* End-of-run position. */
this->positions.emplace_back(advance, 0);
} }
/** /**
@ -165,7 +162,9 @@ int FallbackParagraphLayout::FallbackLine::GetWidth() const
* 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 auto &run = this->GetVisualRun(this->CountRuns() - 1); const auto &run = this->GetVisualRun(this->CountRuns() - 1);
return run.GetPositions().back().x; const auto &positions = run.GetPositions();
if (positions.empty()) return 0;
return positions.back().right + 1;
} }
/** /**

View File

@ -45,7 +45,7 @@ public:
std::vector<GlyphID> glyphs; ///< The glyphs of the run. Valid after Shape() is called. std::vector<GlyphID> glyphs; ///< The glyphs of the run. Valid after Shape() is called.
std::vector<int> advance; ///< The advance (width) of the glyphs. Valid after Shape() is called. std::vector<int> advance; ///< The advance (width) of the glyphs. Valid after Shape() is called.
std::vector<int> glyph_to_char; ///< The mapping from glyphs to characters. Valid after Shape() is called. std::vector<int> glyph_to_char; ///< The mapping from glyphs to characters. Valid after Shape() is called.
std::vector<Point> positions; ///< The positions of the glyphs. Valid after Shape() is called. std::vector<ParagraphLayouter::Position> positions; ///< The positions of the glyphs. Valid after Shape() is called.
int total_advance = 0; ///< The total advance of the run. Valid after Shape() is called. int total_advance = 0; ///< The total advance of the run. Valid after Shape() is called.
ICURun(int start, int length, UBiDiLevel level, UScriptCode script = USCRIPT_UNKNOWN, Font *font = nullptr) : start(start), length(length), level(level), script(script), font(font) {} ICURun(int start, int length, UBiDiLevel level, UScriptCode script = USCRIPT_UNKNOWN, Font *font = nullptr) : start(start), length(length), level(level), script(script), font(font) {}
@ -62,7 +62,7 @@ public:
class ICUVisualRun : public ParagraphLayouter::VisualRun { class ICUVisualRun : public ParagraphLayouter::VisualRun {
private: private:
std::vector<GlyphID> glyphs; std::vector<GlyphID> glyphs;
std::vector<Point> positions; std::vector<Position> positions;
std::vector<int> glyph_to_char; std::vector<int> glyph_to_char;
int total_advance; int total_advance;
@ -72,7 +72,7 @@ public:
ICUVisualRun(const ICURun &run, int x); ICUVisualRun(const ICURun &run, int x);
std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; } std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; }
std::span<const Point> GetPositions() const override { return this->positions; } std::span<const Position> GetPositions() const override { return this->positions; }
std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; } std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; }
const Font *GetFont() const override { return this->font; } const Font *GetFont() const override { return this->font; }
@ -136,8 +136,8 @@ ICUParagraphLayout::ICUVisualRun::ICUVisualRun(const ICURun &run, int x) :
this->positions.reserve(run.positions.size()); this->positions.reserve(run.positions.size());
/* Copy positions, moving x coordinate by x offset. */ /* Copy positions, moving x coordinate by x offset. */
for (const Point &pt : run.positions) { for (const auto &pos : run.positions) {
this->positions.emplace_back(pt.x + x, pt.y); this->positions.emplace_back(pos.left + x, pos.right + x, pos.top);
} }
} }
@ -179,7 +179,7 @@ void ICURun::Shape(UChar *buff, size_t buff_length)
/* Reserve space, as we already know the size. */ /* Reserve space, as we already know the size. */
this->glyphs.reserve(glyph_count); this->glyphs.reserve(glyph_count);
this->glyph_to_char.reserve(glyph_count); this->glyph_to_char.reserve(glyph_count);
this->positions.reserve(glyph_count + 1); this->positions.reserve(glyph_count);
this->advance.reserve(glyph_count); this->advance.reserve(glyph_count);
/* Prepare the glyphs/position. ICUVisualRun will give the position an offset if needed. */ /* Prepare the glyphs/position. ICUVisualRun will give the position an offset if needed. */
@ -189,14 +189,13 @@ void ICURun::Shape(UChar *buff, size_t buff_length)
if (buff[glyph_info[i].cluster] >= SCC_SPRITE_START && buff[glyph_info[i].cluster] <= SCC_SPRITE_END && glyph_info[i].codepoint == 0) { if (buff[glyph_info[i].cluster] >= SCC_SPRITE_START && buff[glyph_info[i].cluster] <= SCC_SPRITE_END && glyph_info[i].codepoint == 0) {
auto glyph = this->font->fc->MapCharToGlyph(buff[glyph_info[i].cluster]); auto glyph = this->font->fc->MapCharToGlyph(buff[glyph_info[i].cluster]);
this->glyphs.push_back(glyph);
this->positions.emplace_back(advance, (this->font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->font->fc->GetSize()))) / 2); // Align sprite font to centre
x_advance = this->font->fc->GetGlyphWidth(glyph); x_advance = this->font->fc->GetGlyphWidth(glyph);
this->glyphs.push_back(glyph);
this->positions.emplace_back(advance, advance + x_advance - 1, (this->font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->font->fc->GetSize()))) / 2); // Align sprite font to centre
} else { } else {
this->glyphs.push_back(glyph_info[i].codepoint);
this->positions.emplace_back(glyph_pos[i].x_offset / FONT_SCALE + advance, glyph_pos[i].y_offset / FONT_SCALE);
x_advance = glyph_pos[i].x_advance / FONT_SCALE; x_advance = glyph_pos[i].x_advance / FONT_SCALE;
this->glyphs.push_back(glyph_info[i].codepoint);
this->positions.emplace_back(glyph_pos[i].x_offset / FONT_SCALE + advance, glyph_pos[i].x_offset / FONT_SCALE + advance + x_advance - 1, glyph_pos[i].y_offset / FONT_SCALE);
} }
this->glyph_to_char.push_back(glyph_info[i].cluster); this->glyph_to_char.push_back(glyph_info[i].cluster);
@ -204,9 +203,6 @@ void ICURun::Shape(UChar *buff, size_t buff_length)
advance += x_advance; advance += x_advance;
} }
/* End-of-run position. */
this->positions.emplace_back(advance, 0);
/* Track the total advancement we made. */ /* Track the total advancement we made. */
this->total_advance = advance; this->total_advance = advance;

View File

@ -902,10 +902,10 @@ Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, const char *fro
r = ScrollEditBoxTextRect(r, *tb); r = ScrollEditBoxTextRect(r, *tb);
/* Get location of first and last character. */ /* Get location of first and last character. */
Point p1 = GetCharPosInString(tb->buf, from, FS_NORMAL); const auto p1 = GetCharPosInString(tb->buf, from, FS_NORMAL);
Point p2 = from != to ? GetCharPosInString(tb->buf, to, FS_NORMAL) : p1; const auto p2 = from != to ? GetCharPosInString(tb->buf, to, FS_NORMAL) : p1;
return { Clamp(r.left + p1.x, r.left, r.right), r.top, Clamp(r.left + p2.x, r.left, r.right), r.bottom }; return { Clamp(r.left + p1.left, r.left, r.right), r.top, Clamp(r.left + p2.right, r.left, r.right), r.bottom };
} }
/** /**

View File

@ -71,7 +71,7 @@ public:
class CoreTextVisualRun : public ParagraphLayouter::VisualRun { class CoreTextVisualRun : public ParagraphLayouter::VisualRun {
private: private:
std::vector<GlyphID> glyphs; std::vector<GlyphID> glyphs;
std::vector<Point> positions; std::vector<Position> positions;
std::vector<int> glyph_to_char; std::vector<int> glyph_to_char;
int total_advance = 0; int total_advance = 0;
@ -82,7 +82,7 @@ public:
CoreTextVisualRun(CoreTextVisualRun &&other) = default; CoreTextVisualRun(CoreTextVisualRun &&other) = default;
std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; } std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; }
std::span<const Point> GetPositions() const override { return this->positions; } std::span<const Position> GetPositions() const override { return this->positions; }
std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; } std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; }
const Font *GetFont() const override { return this->font; } const Font *GetFont() const override { return this->font; }
@ -241,7 +241,9 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font
CGPoint pts[this->glyphs.size()]; CGPoint pts[this->glyphs.size()];
CTRunGetPositions(run, CFRangeMake(0, 0), pts); CTRunGetPositions(run, CFRangeMake(0, 0), pts);
this->positions.reserve(this->glyphs.size() + 1); CGSize advs[this->glyphs.size()];
CTRunGetAdvances(run, CFRangeMake(0, 0), advs);
this->positions.reserve(this->glyphs.size());
/* Convert glyph array to our data type. At the same time, substitute /* Convert glyph array to our data type. At the same time, substitute
* the proper glyphs for our private sprite glyphs. */ * the proper glyphs for our private sprite glyphs. */
@ -251,15 +253,13 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font
if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && (gl[i] == 0 || gl[i] == 3)) { if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && (gl[i] == 0 || gl[i] == 3)) {
/* A glyph of 0 indidicates not found, while apparently 3 is what char 0xFFFC maps to. */ /* A glyph of 0 indidicates not found, while apparently 3 is what char 0xFFFC maps to. */
this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]); this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]);
this->positions.emplace_back(pts[i].x, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre this->positions.emplace_back(pts[i].x, pts[i].x + advs[i].width - 1, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre
} else { } else {
this->glyphs[i] = gl[i]; this->glyphs[i] = gl[i];
this->positions.emplace_back(pts[i].x, pts[i].y); this->positions.emplace_back(pts[i].x, pts[i].x + advs[i].width - 1, pts[i].y);
} }
} }
this->total_advance = (int)std::ceil(CTRunGetTypographicBounds(run, CFRangeMake(0, 0), nullptr, nullptr, nullptr)); this->total_advance = (int)std::ceil(CTRunGetTypographicBounds(run, CFRangeMake(0, 0), nullptr, nullptr, nullptr));
/* End-of-run position. */
this->positions.emplace_back(this->positions.front().x + this->total_advance, 0);
} }
/** /**

View File

@ -74,7 +74,7 @@ public:
class UniscribeVisualRun : public ParagraphLayouter::VisualRun { class UniscribeVisualRun : public ParagraphLayouter::VisualRun {
private: private:
std::vector<GlyphID> glyphs; std::vector<GlyphID> glyphs;
std::vector<Point> positions; std::vector<Position> positions;
std::vector<WORD> char_to_glyph; std::vector<WORD> char_to_glyph;
int start_pos; int start_pos;
@ -89,7 +89,7 @@ public:
UniscribeVisualRun(UniscribeVisualRun &&other) noexcept; UniscribeVisualRun(UniscribeVisualRun &&other) noexcept;
std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; } std::span<const GlyphID> GetGlyphs() const override { return this->glyphs; }
std::span<const Point> GetPositions() const override { return this->positions; } std::span<const Position> GetPositions() const override { return this->positions; }
std::span<const int> GetGlyphToCharMap() const override; std::span<const int> GetGlyphToCharMap() const override;
const Font *GetFont() const override { return this->font; } const Font *GetFont() const override { return this->font; }
@ -474,16 +474,15 @@ int UniscribeParagraphLayout::UniscribeLine::GetWidth() const
UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const UniscribeRun &range, int x) : glyphs(range.ft_glyphs), char_to_glyph(range.char_to_glyph), start_pos(range.pos), total_advance(range.total_advance), font(range.font) UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const UniscribeRun &range, int x) : glyphs(range.ft_glyphs), char_to_glyph(range.char_to_glyph), start_pos(range.pos), total_advance(range.total_advance), font(range.font)
{ {
this->num_glyphs = (int)glyphs.size(); this->num_glyphs = (int)glyphs.size();
this->positions.reserve(this->num_glyphs + 1); this->positions.reserve(this->num_glyphs);
int advance = x; int advance = x;
for (int i = 0; i < this->num_glyphs; i++) { for (int i = 0; i < this->num_glyphs; i++) {
this->positions.emplace_back(range.offsets[i].du + advance, range.offsets[i].dv); int x_advance = range.advances[i];
this->positions.emplace_back(range.offsets[i].du + advance - 1, range.offsets[i].du + advance + x_advance, range.offsets[i].dv);
advance += range.advances[i]; advance += x_advance;
} }
/* End-of-run position. */
this->positions.emplace_back(advance, 0);
} }
UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept

View File

@ -309,15 +309,15 @@ void Textbuf::UpdateWidth()
/** Update pixel position of the caret. */ /** Update pixel position of the caret. */
void Textbuf::UpdateCaretPosition() void Textbuf::UpdateCaretPosition()
{ {
this->caretxoffs = this->chars > 1 ? GetCharPosInString(this->buf, this->buf + this->caretpos, FS_NORMAL).x : 0; this->caretxoffs = this->chars > 1 ? GetCharPosInString(this->buf, this->buf + this->caretpos, FS_NORMAL).left : 0;
} }
/** Update pixel positions of the marked text area. */ /** Update pixel positions of the marked text area. */
void Textbuf::UpdateMarkedText() void Textbuf::UpdateMarkedText()
{ {
if (this->markend != 0) { if (this->markend != 0) {
this->markxoffs = GetCharPosInString(this->buf, this->buf + this->markpos, FS_NORMAL).x; this->markxoffs = GetCharPosInString(this->buf, this->buf + this->markpos, FS_NORMAL).left;
this->marklength = GetCharPosInString(this->buf, this->buf + this->markend, FS_NORMAL).x - this->markxoffs; this->marklength = GetCharPosInString(this->buf, this->buf + this->markend, FS_NORMAL).left - this->markxoffs;
} else { } else {
this->markxoffs = this->marklength = 0; this->markxoffs = this->marklength = 0;
} }