Support setting initial pen position & retrieving final pen position in font text shaping

This commit is contained in:
Nikita Lisitsa 2022-05-21 19:51:07 +03:00
parent a9de6232de
commit 98b8a324d0
5 changed files with 39 additions and 28 deletions

View file

@ -57,8 +57,20 @@ namespace psemek::ui
virtual bool supports_character(char32_t c) const = 0;
virtual util::span<character_range const> supported_characters() const = 0;
virtual std::vector<glyph> shape(std::string_view str, shape_options const & options) const = 0;
virtual std::vector<glyph> shape(std::u32string_view str, shape_options const & options) const = 0;
virtual std::vector<glyph> shape(std::string_view str, shape_options const & options, geom::point<float, 2> & pen) const = 0;
virtual std::vector<glyph> shape(std::u32string_view str, shape_options const & options, geom::point<float, 2> & pen) const = 0;
virtual std::vector<glyph> shape(std::string_view str, shape_options const & options) const
{
geom::point<float, 2> pen{0.f, 0.f};
return shape(str, options, pen);
}
virtual std::vector<glyph> shape(std::u32string_view str, shape_options const & options) const
{
geom::point<float, 2> pen{0.f, 0.f};
return shape(str, options, pen);
}
virtual gfx::texture_2d const & atlas() const = 0;

View file

@ -31,8 +31,8 @@ namespace psemek::ui
bool supports_character(char32_t c) const override;
util::span<character_range const> supported_characters() const override { return ranges_; }
std::vector<glyph> shape(std::string_view str, shape_options const & options) const override;
std::vector<glyph> shape(std::u32string_view str, shape_options const & options) const override;
std::vector<glyph> shape(std::string_view str, shape_options const & options, geom::point<float, 2> & pen) const override;
std::vector<glyph> shape(std::u32string_view str, shape_options const & options, geom::point<float, 2> & pen) const override;
gfx::texture_2d const & atlas() const override { return atlas_; };
@ -47,7 +47,7 @@ namespace psemek::ui
std::unordered_map<char32_t, glyph_data> glyphs_;
template <typename String>
std::vector<glyph> shape_impl(String const & str, shape_options const & options) const;
std::vector<glyph> shape_impl(String const & str, shape_options const & options, geom::point<float, 2> & pen) const;
};
}

View file

@ -19,8 +19,8 @@ namespace psemek::ui
bool supports_character(char32_t c) const override;
util::span<character_range const> supported_characters() const override { return {&range_, &range_ + 1}; }
std::vector<glyph> shape(std::string_view str, shape_options const & options) const override;
std::vector<glyph> shape(std::u32string_view str, shape_options const & options) const override;
std::vector<glyph> shape(std::string_view str, shape_options const & options, geom::point<float, 2> & pen) const override;
std::vector<glyph> shape(std::u32string_view str, shape_options const & options, geom::point<float, 2> & pen) const override;
gfx::texture_2d const & atlas() const override { return atlas_; };
@ -34,7 +34,7 @@ namespace psemek::ui
std::vector<geom::box<float, 2>> texcoords_;
template <typename String>
std::vector<glyph> shape_impl(String const & str, shape_options const & options) const;
std::vector<glyph> shape_impl(String const & str, shape_options const & options, geom::point<float, 2> & pen) const;
};
}

View file

@ -50,25 +50,25 @@ namespace psemek::ui
return std::isspace(c) || glyphs_.contains(c);
}
std::vector<glyph> kerned_font::shape(std::string_view str, shape_options const & options) const
std::vector<glyph> kerned_font::shape(std::string_view str, shape_options const & options, geom::point<float, 2> & pen) const
{
return shape_impl(util::utf8_range(str), options);
return shape_impl(util::utf8_range(str), options, pen);
}
std::vector<glyph> kerned_font::shape(std::u32string_view str, shape_options const & options) const
std::vector<glyph> kerned_font::shape(std::u32string_view str, shape_options const & options, geom::point<float, 2> & pen) const
{
return shape_impl(str, options);
return shape_impl(str, options, pen);
}
template <typename String>
std::vector<glyph> kerned_font::shape_impl(String const & str, shape_options const & options) const
std::vector<glyph> kerned_font::shape_impl(String const & str, shape_options const & options, geom::point<float, 2> & pen) const
{
char32_t const unknown = supports_character(options.unknown_character) ? options.unknown_character : '?';
geom::vector<float, 2> const advance_mask = advance_dir(options.direction);
std::vector<glyph> result;
geom::vector<float, 2> pos{0.f, (size_[1] - baseline_offset_) * options.scale};
float const offset_to_baseline = (size_[1] - baseline_offset_) * options.scale;
for (char32_t c : str)
{
if (!supports_character(c))
@ -82,15 +82,15 @@ namespace psemek::ui
glyph g;
g.character = c;
g.position[0].min = pos[0] + data.offset_x * options.scale;
g.position[1].min = pos[1] - (data.offset_y + data.size_y) * options.scale;
g.position[0].max = pos[0] + (data.offset_x + data.size_x) * options.scale;
g.position[1].max = pos[1] - data.offset_y * options.scale;
g.position[0].min = pen[0] + data.offset_x * options.scale;
g.position[1].min = pen[1] + offset_to_baseline - (data.offset_y + data.size_y) * options.scale;
g.position[0].max = pen[0] + (data.offset_x + data.size_x) * options.scale;
g.position[1].max = pen[1] + offset_to_baseline - data.offset_y * options.scale;
result.push_back(g);
geom::vector<float, 2> advance{data.advance * options.scale, size_[1] * options.scale};
pos += geom::pointwise_mult(advance_mask, advance);
pen += geom::pointwise_mult(advance_mask, advance);
}
return result;

View file

@ -37,18 +37,18 @@ namespace psemek::ui
return std::isspace(c) || (c >= range_.begin && c < range_.end);
}
std::vector<glyph> monospace_font::shape(std::string_view str, shape_options const & options) const
std::vector<glyph> monospace_font::shape(std::string_view str, shape_options const & options, geom::point<float, 2> & pen) const
{
return shape_impl(util::utf8_range(str), options);
return shape_impl(util::utf8_range(str), options, pen);
}
std::vector<glyph> monospace_font::shape(std::u32string_view str, shape_options const & options) const
std::vector<glyph> monospace_font::shape(std::u32string_view str, shape_options const & options, geom::point<float, 2> & pen) const
{
return shape_impl(str, options);
return shape_impl(str, options, pen);
}
template <typename String>
std::vector<glyph> monospace_font::shape_impl(String const & str, shape_options const & options) const
std::vector<glyph> monospace_font::shape_impl(String const & str, shape_options const & options, geom::point<float, 2> & pen) const
{
char32_t const unknown = supports_character(options.unknown_character) ? options.unknown_character : '?';
geom::vector<float, 2> const size = geom::cast<float>(this->size()) * options.scale;
@ -56,22 +56,21 @@ namespace psemek::ui
std::vector<glyph> result;
geom::vector<float, 2> pos{0.f, 0.f};
for (char32_t c : str)
{
glyph g;
if (std::isspace(c))
{
g.character = c;
g.position = {{{pos[0], pos[0]}, {pos[1], pos[1]}}};
g.position = {{{pen[0], pen[0]}, {pen[1], pen[1]}}};
}
else
{
g.character = supports_character(c) ? c : unknown;
g.position = {{{pos[0], pos[0] + size[0]}, {pos[1], pos[1] + size[1]}}};
g.position = {{{pen[0], pen[0] + size[0]}, {pen[1], pen[1] + size[1]}}};
}
result.push_back(g);
pos += advance;
pen += advance;
}
return result;