srctree

Robin Linden parent 018228a2 282b4849
type: Take font weight into account when measuring text

inlinesplit
layout/layout.cpp added: 41, removed: 22, total 19
@@ -223,10 +223,11 @@ void Layouter::layout_inline(LayoutBox &box, geom::Rect const &bounds) const {
if (auto text = box.text()) {
auto font = find_font(font_families);
if (font) {
box.dimensions.content.width = (*font)->measure(*text, type::Px{font_size}).width;
box.dimensions.content.width = (*font)->measure(*text, type::Px{font_size}, type::Weight::Normal).width;
} else {
spdlog::warn("No font found for font-families: {}", fmt::join(font_families, ", "));
box.dimensions.content.width = type::NaiveFont{}.measure(*text, type::Px{font_size}).width;
box.dimensions.content.width =
type::NaiveFont{}.measure(*text, type::Px{font_size}, type::Weight::Normal).width;
}
}
 
@@ -285,7 +286,9 @@ void Layouter::layout_anonymous_block(LayoutBox &box, geom::Rect const &bounds)
std::size_t best_split_point = std::string_view::npos;
for (auto split_point = text->find(' '); split_point != std::string_view::npos;
split_point = text->find(' ', split_point + 1)) {
if (last_child_end + font->measure(text->substr(0, split_point), font_size).width > bounds.width) {
if (last_child_end
+ font->measure(text->substr(0, split_point), font_size, type::Weight::Normal).width
> bounds.width) {
break;
}
 
@@ -293,7 +296,8 @@ void Layouter::layout_anonymous_block(LayoutBox &box, geom::Rect const &bounds)
}
 
if (best_split_point != std::string_view::npos) {
child->dimensions.content.width = font->measure(text->substr(0, best_split_point), font_size).width;
child->dimensions.content.width =
font->measure(text->substr(0, best_split_point), font_size, type::Weight::Normal).width;
auto bonus_child = *child;
bonus_child.layout_text = std::string{text->substr(best_split_point + 1)};
box.children.insert(box.children.begin() + i + 1, std::move(bonus_child));
@@ -304,7 +308,7 @@ void Layouter::layout_anonymous_block(LayoutBox &box, geom::Rect const &bounds)
child = &box.children[i];
child->layout_text = std::string{text->substr(0, best_split_point)};
} else {
child->dimensions.content.width = font->measure(*text, font_size).width;
child->dimensions.content.width = font->measure(*text, font_size, type::Weight::Normal).width;
last_child_end += child->dimensions.margin_box().width;
}
}
 
type/naive.h added: 41, removed: 22, total 19
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2023-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -15,7 +15,7 @@ namespace type {
 
class NaiveFont : public IFont {
public:
Size measure(std::string_view text, Px font_size) const override {
Size measure(std::string_view text, Px font_size, Weight) const override {
return Size{static_cast<int>(text.size()) * font_size.v / 2, font_size.v};
}
};
 
type/naive_test.cpp added: 41, removed: 22, total 19
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2023-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -15,12 +15,12 @@ int main() {
type::NaiveType type{};
 
auto font10px = type.font("a").value();
a.expect_eq(font10px->measure("a", type::Px{10}), type::Size{5, 10});
a.expect_eq(font10px->measure("hello", type::Px{10}), type::Size{25, 10});
a.expect_eq(font10px->measure("a", type::Px{10}, type::Weight::Normal), type::Size{5, 10});
a.expect_eq(font10px->measure("hello", type::Px{10}, type::Weight::Normal), type::Size{25, 10});
 
auto font20px = type.font("a").value();
a.expect_eq(font20px->measure("a", type::Px{20}), type::Size{10, 20});
a.expect_eq(font20px->measure("hello", type::Px{20}), type::Size{50, 20});
a.expect_eq(font20px->measure("a", type::Px{20}, type::Weight::Normal), type::Size{10, 20});
a.expect_eq(font20px->measure("hello", type::Px{20}, type::Weight::Normal), type::Size{50, 20});
});
 
s.add_test("NaiveType::font_cache", [](etest::IActions &a) {
 
type/sfml.cpp added: 41, removed: 22, total 19
@@ -54,9 +54,19 @@ std::optional<std::string> find_path_to_font(std::string_view font_filename) {
 
} // namespace
 
Size SfmlFont::measure(std::string_view text, Px font_size) const {
Size SfmlFont::measure(std::string_view text, Px font_size, Weight weight) const {
sf::Text sf_text{
sf::String::fromUtf8(text.data(), text.data() + text.size()), font_, static_cast<unsigned>(font_size.v)};
 
switch (weight) {
case Weight::Normal:
sf_text.setStyle(sf::Text::Regular);
break;
case Weight::Bold:
sf_text.setStyle(sf::Text::Bold);
break;
}
 
auto bounds = sf_text.getLocalBounds();
return Size{static_cast<int>(bounds.width), static_cast<int>(bounds.height)};
}
 
type/sfml.h added: 41, removed: 22, total 19
@@ -23,7 +23,7 @@ class SfmlFont : public IFont {
public:
explicit SfmlFont(sf::Font const &font) : font_{font} {}
 
Size measure(std::string_view text, Px font_size) const override;
Size measure(std::string_view text, Px font_size, Weight) const override;
 
sf::Font const &sf_font() const { return font_; }
 
 
type/type.h added: 41, removed: 22, total 19
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2023-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -22,10 +22,15 @@ struct Px {
[[nodiscard]] bool operator==(Px const &) const = default;
};
 
enum class Weight {
Normal,
Bold,
};
 
class IFont {
public:
virtual ~IFont() = default;
[[nodiscard]] virtual Size measure(std::string_view, Px font_size) const = 0;
[[nodiscard]] virtual Size measure(std::string_view, Px font_size, Weight) const = 0;
};
 
class IType {