Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 19 additions & 27 deletions src/ft2font_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#endif

#include "ft2font.h"
#include "mplutils.h"

#include <set>
#include <sstream>
Expand Down Expand Up @@ -617,20 +618,15 @@ PyFT2Font_set_text(PyFT2Font *self, std::u32string_view text, double angle = 0.0
std::variant<FT2Font::LanguageType, std::string> languages_or_str = nullptr)
{
std::vector<double> xys;

FT2Font::LanguageType languages;
if (auto value = std::get_if<FT2Font::LanguageType>(&languages_or_str)) {
languages = std::move(*value);
} else if (auto value = std::get_if<std::string>(&languages_or_str)) {
languages = std::vector<FT2Font::LanguageRange>{
FT2Font::LanguageRange{*value, 0, text.size()}
};
} else {
// NOTE: this can never happen as pybind11 would have checked the type in the
// Python wrapper before calling this function, but we need to keep the
// std::get_if instead of std::get for macOS 10.12 compatibility.
throw py::type_error("languages must be str or list of tuple");
}
FT2Font::LanguageType languages = std::visit(overloaded {
[](FT2Font::LanguageType languages) {
return languages;
},
[&](std::string value) {
return FT2Font::LanguageType{{
FT2Font::LanguageRange{value, 0, text.size()}}};
}
}, languages_or_str);

self->set_text(text, angle, static_cast<FT_Int32>(flags), features, languages, xys);

Expand Down Expand Up @@ -1340,19 +1336,15 @@ PyFT2Font_layout(PyFT2Font *self, std::u32string text, LoadFlags flags,
{
const auto load_flags = static_cast<FT_Int32>(flags);

FT2Font::LanguageType languages;
if (auto value = std::get_if<FT2Font::LanguageType>(&languages_or_str)) {
languages = std::move(*value);
} else if (auto value = std::get_if<std::string>(&languages_or_str)) {
languages = std::vector<FT2Font::LanguageRange>{
FT2Font::LanguageRange{*value, 0, text.size()}
};
} else {
// NOTE: this can never happen as pybind11 would have checked the type in the
// Python wrapper before calling this function, but we need to keep the
// std::get_if instead of std::get for macOS 10.12 compatibility.
throw py::type_error("languages must be str or list of tuple");
}
FT2Font::LanguageType languages = std::visit(overloaded {
[](FT2Font::LanguageType languages) {
return languages;
},
[&](std::string value) {
return FT2Font::LanguageType{{
FT2Font::LanguageRange{value, 0, text.size()}}};
}
}, languages_or_str);

std::set<FT_String*> glyph_seen_fonts;
auto glyphs = self->layout(text, load_flags, features, languages, glyph_seen_fonts);
Expand Down
15 changes: 9 additions & 6 deletions src/mplutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ enum {
};

#ifdef __cplusplus // not for macosx.m
// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs
// so that we don't need to access the NPY_INTP_FMT macro here.
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <array>
Expand All @@ -59,6 +57,12 @@ enum {
namespace py = pybind11;
using namespace pybind11::literals;

// Helper for std::visit.
template<typename... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<typename... Ts> overloaded(Ts...) -> overloaded<Ts...>;

// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs
// so that we don't need to access the NPY_INTP_FMT macro here.
template<typename T>
inline void check_trailing_shape(T array, char const* name, long d1)
{
Expand Down Expand Up @@ -97,11 +101,10 @@ inline void check_trailing_shape(T array, char const* name, long d1, long d2)
}
}

/* In most cases, code should use safe_first_shape(obj) instead of obj.shape(0), since
safe_first_shape(obj) == 0 when any dimension is 0. */
// In most cases, code should use safe_first_shape(obj) instead of
// obj.shape(0), since safe_first_shape(obj) == 0 when any dimension is 0.
template <typename T, py::ssize_t ND>
py::ssize_t
safe_first_shape(const py::detail::unchecked_reference<T, ND> &a)
py::ssize_t safe_first_shape(const py::detail::unchecked_reference<T, ND> &a)
{
bool empty = (ND == 0);
for (py::ssize_t i = 0; i < ND; i++) {
Expand Down
Loading