srctree

Robin Linden parent 582fb66d 081359e6
type: Add an SFML text-measurement implementation

inlinesplit
type/BUILD added: 137, removed: 3, total 134
@@ -26,3 +26,23 @@ cc_test(
"//etest",
],
)
 
SFML_TYPE_COPTS = HASTUR_COPTS + select({
# SFML leaks this into our code.
"@platforms//os:linux": ["-Wno-implicit-fallthrough"],
"//conditions:default": [],
})
 
cc_library(
name = "sfml",
srcs = ["sfml.cpp"],
hdrs = ["sfml.h"],
copts = SFML_TYPE_COPTS,
visibility = ["//visibility:public"],
deps = [
":type",
"//os:xdg",
"//util:string",
"@sfml//:graphics",
],
)
 
filename was Deleted added: 137, removed: 3, total 134
@@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: 2022-2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2022 Mikael Larsson <c.mikael.larsson@gmail.com>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#include "type/sfml.h"
 
#include "os/xdg.h"
#include "util/string.h"
 
#include <SFML/Graphics/Text.hpp>
 
#include <algorithm>
#include <filesystem>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>
 
namespace type {
namespace {
 
std::filesystem::recursive_directory_iterator get_font_dir_iterator(std::filesystem::path const &path) {
std::error_code errc;
if (auto it = std::filesystem::recursive_directory_iterator(path, errc); !errc) {
return it;
}
 
return {};
}
 
// TODO(robinlinden): We should be looking at font names rather than filenames.
std::optional<std::string> find_path_to_font(std::string_view font_filename) {
for (auto const &path : os::font_paths()) {
for (auto const &entry : get_font_dir_iterator(path)) {
auto name = entry.path().filename().string();
// TODO(robinlinden): std::ranges once Clang supports it. Last tested w/ 15.
if (std::search(begin(name), end(name), begin(font_filename), end(font_filename), [](char a, char b) {
return util::lowercased(a) == util::lowercased(b);
}) != end(name)) {
return std::make_optional(entry.path().string());
}
}
}
 
return std::nullopt;
}
 
} // namespace
 
Size SfmlFont::measure(std::string_view text) const {
sf::Text sf_text{
sf::String::fromUtf8(text.data(), text.data() + text.size()), font_, static_cast<unsigned>(font_size_.v)};
auto bounds = sf_text.getLocalBounds();
return Size{static_cast<int>(bounds.width), static_cast<int>(bounds.height)};
}
 
std::optional<std::shared_ptr<IFont const>> SfmlType::font(std::string_view name, Px size) const {
if (auto font = font_cache_.find(name); font != font_cache_.end()) {
font->second->set_font_size(size);
return font->second;
}
 
sf::Font font;
if (auto path = find_path_to_font(name); !path || !font.loadFromFile(*path)) {
return std::nullopt;
}
 
return font_cache_.insert(std::pair{std::string{name}, std::make_shared<SfmlFont>(font, size)}).first->second;
}
 
} // namespace type
 
filename was Deleted added: 137, removed: 3, total 134
@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#ifndef TYPE_SFML_H_
#define TYPE_SFML_H_
 
#include "type/type.h"
 
#include <SFML/Graphics/Font.hpp>
 
#include <map>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>
 
namespace type {
 
class SfmlFont : public IFont {
public:
SfmlFont(sf::Font const &font, Px font_size) : font_{font}, font_size_{font_size} {}
 
Size measure(std::string_view text) const override;
void set_font_size(Px size) { font_size_ = size; }
 
private:
sf::Font font_{};
Px font_size_{};
};
 
class SfmlType : public IType {
public:
std::optional<std::shared_ptr<IFont const>> font(std::string_view name, Px size) const override;
 
private:
mutable std::map<std::string, std::shared_ptr<SfmlFont>, std::less<>> font_cache_;
};
 
} // namespace type
 
#endif