Skip to content
Open
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
49 changes: 24 additions & 25 deletions src/_backend_agg_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,30 @@ PyRendererAgg_draw_text_image(RendererAgg *self,
double angle,
GCAgg &gc)
{
int x, y;

if (auto value = std::get_if<double>(&vx)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
"alternative"_a="int(x)");
x = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vx)) {
x = *value;
} else {
throw std::runtime_error("Should not happen");
}

if (auto value = std::get_if<double>(&vy)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
"alternative"_a="int(y)");
y = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vy)) {
y = *value;
} else {
throw std::runtime_error("Should not happen");
}
int x = std::visit(overloaded {
[&](double value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
"alternative"_a="int(x)");
return static_cast<int>(value);
},
[](int value) {
return value;
}
}, vx);
int y = std::visit(overloaded {
[&](double value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
"alternative"_a="int(x)");
return static_cast<int>(value);
},
[](int value) {
return value;
}
}, vy);

// TODO: This really shouldn't be mutable, but Agg's renderer buffers aren't const.
auto image = image_obj.mutable_unchecked<2>();
Expand Down
166 changes: 72 additions & 94 deletions src/ft2font_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <pybind11/stl.h>

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

#include <set>
Expand All @@ -18,23 +19,20 @@ using double_or_ = std::variant<double, T>;

template <typename T>
static T
_double_to_(const char *name, double_or_<T> &var)
_double_to_(const char *name, double_or_<T> var)
{
if (auto value = std::get_if<double>(&var)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a=name, "obj_type"_a="parameter as float",
"alternative"_a="int({})"_s.format(name));
return static_cast<T>(*value);
} else if (auto value = std::get_if<T>(&var)) {
return *value;
} else {
// pybind11 will have only allowed types that match the variant, so this `else`
// can't happen. We only have this case because older macOS doesn't support
// `std::get` and using the conditional `std::get_if` means an `else` to silence
// compiler warnings about "unhandled" cases.
throw std::runtime_error("Should not happen");
}
return std::visit(overloaded {
[&](double value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a=name, "obj_type"_a="parameter as float",
"alternative"_a="int({})"_s.format(name));
return static_cast<T>(value);
},
[](T value) {
return value;
}
}, var);
}

/**********************************************************************
Expand Down Expand Up @@ -603,22 +601,18 @@ static int
PyFT2Font_get_kerning(PyFT2Font *self, FT_UInt left, FT_UInt right,
std::variant<FT_Kerning_Mode, FT_UInt> mode_or_int)
{
FT_Kerning_Mode mode;

if (auto value = std::get_if<FT_UInt>(&mode_or_int)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="mode", "obj_type"_a="parameter as int",
"alternative"_a="Kerning enum values");
mode = static_cast<FT_Kerning_Mode>(*value);
} else if (auto value = std::get_if<FT_Kerning_Mode>(&mode_or_int)) {
mode = *value;
} 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("mode must be Kerning or int");
}
FT_Kerning_Mode mode = std::visit(overloaded {
[&](FT_UInt value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="mode", "obj_type"_a="parameter as int",
"alternative"_a="Kerning enum values");
return static_cast<FT_Kerning_Mode>(value);
},
[](FT_Kerning_Mode value) {
return value;
}
}, mode_or_int);

return self->get_kerning(left, right, mode);
}
Expand Down Expand Up @@ -708,36 +702,28 @@ 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;
LoadFlags flags;

if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
flags = static_cast<LoadFlags>(*value);
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
flags = *value;
} 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("flags must be LoadFlags or int");
}

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");
}
LoadFlags flags = std::visit(overloaded {
[&](FT_Int32 value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
return static_cast<LoadFlags>(value);
},
[](LoadFlags value) {
return value;
}
}, flags_or_int);

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 @@ -783,22 +769,18 @@ PyFT2Font_load_char(PyFT2Font *self, long charcode,
{
bool fallback = true;
FT2Font *ft_object = nullptr;
LoadFlags flags;

if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
flags = static_cast<LoadFlags>(*value);
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
flags = *value;
} 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("flags must be LoadFlags or int");
}
LoadFlags flags = std::visit(overloaded {
[&](FT_Int32 value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
return static_cast<LoadFlags>(value);
},
[](LoadFlags value) {
return value;
}
}, flags_or_int);

self->load_char(charcode, static_cast<FT_Int32>(flags), ft_object, fallback);

Expand Down Expand Up @@ -835,22 +817,18 @@ static PyGlyph *
PyFT2Font_load_glyph(PyFT2Font *self, FT_UInt glyph_index,
std::variant<LoadFlags, FT_Int32> flags_or_int = LoadFlags::FORCE_AUTOHINT)
{
LoadFlags flags;

if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
flags = static_cast<LoadFlags>(*value);
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
flags = *value;
} 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("flags must be LoadFlags or int");
}
LoadFlags flags = std::visit(overloaded {
[&](FT_Int32 value) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
"alternative"_a="LoadFlags enum values");
return static_cast<LoadFlags>(value);
},
[](LoadFlags value) {
return value;
}
}, flags_or_int);

self->load_glyph(glyph_index, static_cast<FT_Int32>(flags));

Expand Down
15 changes: 9 additions & 6 deletions src/mplutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ 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>

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 @@ -95,11 +99,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