Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdef8fa4

Browse files
authored
Merge pull request#30044 from anntzer/ufi
2 parents948a26f +67b4202 commitdef8fa4

File tree

7 files changed

+78
-73
lines changed

7 files changed

+78
-73
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
``FT2Image``
2+
~~~~~~~~~~~~
3+
... is deprecated. Use 2D uint8 ndarrays instead. In particular:
4+
5+
- The ``FT2Image`` constructor took ``width, height`` as separate parameters
6+
but the ndarray constructor takes ``(height, width)`` as single tuple
7+
parameter.
8+
- `.FT2Font.draw_glyph_to_bitmap` now (also) takes 2D uint8 arrays as input.
9+
- ``FT2Image.draw_rect_filled`` should be replaced by directly setting pixel
10+
values to black.
11+
- The ``image`` attribute of the object returned by ``MathTextParser("agg").parse``
12+
is now a 2D uint8 array.

‎lib/matplotlib/_mathtext.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
importenum
1010
importfunctools
1111
importlogging
12+
importmath
1213
importos
1314
importre
1415
importtypes
@@ -19,6 +20,7 @@
1920
fromtypingimportNamedTuple
2021

2122
importnumpyasnp
23+
fromnumpy.typingimportNDArray
2224
frompyparsingimport (
2325
Empty,Forward,Literal,Group,NotAny,OneOrMore,Optional,
2426
ParseBaseException,ParseException,ParseExpression,ParseFatalException,
@@ -30,7 +32,7 @@
3032
from ._mathtext_dataimport (
3133
latex_to_bakoma,stix_glyph_fixes,stix_virtual_fonts,tex2uni)
3234
from .font_managerimportFontProperties,findfont,get_font
33-
from .ft2fontimportFT2Font,FT2Image,Kerning,LoadFlags
35+
from .ft2fontimportFT2Font,Kerning,LoadFlags
3436

3537

3638
ifT.TYPE_CHECKING:
@@ -99,15 +101,15 @@ class RasterParse(NamedTuple):
99101
The offsets are always zero.
100102
width, height, depth : float
101103
The global metrics.
102-
image :FT2Image
104+
image :2D array of uint8
103105
A raster image.
104106
"""
105107
ox:float
106108
oy:float
107109
width:float
108110
height:float
109111
depth:float
110-
image:FT2Image
112+
image:NDArray[np.uint8]
111113

112114
RasterParse.__module__="matplotlib.mathtext"
113115

@@ -148,7 +150,7 @@ def to_raster(self, *, antialiased: bool) -> RasterParse:
148150
w=xmax-xmin
149151
h=ymax-ymin-self.box.depth
150152
d=ymax-ymin-self.box.height
151-
image=FT2Image(int(np.ceil(w)),int(np.ceil(h+max(d,0))))
153+
image=np.zeros((math.ceil(h+max(d,0)),math.ceil(w)),np.uint8)
152154

153155
# Ideally, we could just use self.glyphs and self.rects here, shifting
154156
# their coordinates by (-xmin, -ymin), but this yields slightly
@@ -167,7 +169,9 @@ def to_raster(self, *, antialiased: bool) -> RasterParse:
167169
y=int(center- (height+1)/2)
168170
else:
169171
y=int(y1)
170-
image.draw_rect_filled(int(x1),y,int(np.ceil(x2)),y+height)
172+
x1=math.floor(x1)
173+
x2=math.ceil(x2)
174+
image[y:y+height+1,x1:x2+1]=0xff
171175
returnRasterParse(0,0,w,h+d,d,image)
172176

173177

‎lib/matplotlib/ft2font.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class FT2Font(Buffer):
198198
def_get_fontmap(self,string:str)->dict[str,FT2Font]: ...
199199
defclear(self)->None: ...
200200
defdraw_glyph_to_bitmap(
201-
self,image:FT2Image,x:int,y:int,glyph:Glyph,antialiased:bool= ...
201+
self,image:NDArray[np.uint8],x:int,y:int,glyph:Glyph,antialiased:bool= ...
202202
)->None: ...
203203
defdraw_glyphs_to_bitmap(self,antialiased:bool= ...)->None: ...
204204
defget_bitmap_offset(self)->tuple[int,int]: ...

‎lib/matplotlib/tests/test_ft2font.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ def test_ft2image_draw_rect_filled():
1818
width=23
1919
height=42
2020
forx0,y0,x1,y1initertools.product([1,100], [2,200], [4,400], [8,800]):
21-
im=ft2font.FT2Image(width,height)
21+
withpytest.warns(mpl.MatplotlibDeprecationWarning):
22+
im=ft2font.FT2Image(width,height)
2223
im.draw_rect_filled(x0,y0,x1,y1)
2324
a=np.asarray(im)
2425
asserta.dtype==np.uint8
@@ -823,7 +824,7 @@ def test_ft2font_drawing():
823824
np.testing.assert_array_equal(image,expected)
824825
font=ft2font.FT2Font(file,hinting_factor=1,_kerning_factor=0)
825826
glyph=font.load_char(ord('M'))
826-
image=ft2font.FT2Image(expected.shape[1],expected.shape[0])
827+
image=np.zeros(expected.shape,np.uint8)
827828
font.draw_glyph_to_bitmap(image,-1,1,glyph,antialiased=False)
828829
np.testing.assert_array_equal(image,expected)
829830

‎src/ft2font.cpp

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -63,51 +63,23 @@ void throw_ft_error(std::string message, FT_Error error) {
6363
throwstd::runtime_error(os.str());
6464
}
6565

66-
FT2Image::FT2Image() :m_buffer(nullptr),m_width(0),m_height(0)
67-
{
68-
}
69-
7066
FT2Image::FT2Image(unsignedlong width,unsignedlong height)
71-
:m_buffer(nullptr),m_width(0),m_height(0)
67+
:m_buffer((unsignedchar *)calloc(width * height,1)),m_width(width),m_height(height)
7268
{
73-
resize(width, height);
7469
}
7570

7671
FT2Image::~FT2Image()
7772
{
78-
delete[]m_buffer;
73+
free(m_buffer);
7974
}
8075

81-
voidFT2Image::resize(long width,long height)
76+
voiddraw_bitmap(
77+
py::array_t<uint8_t, py::array::c_style> im, FT_Bitmap *bitmap, FT_Int x, FT_Int y)
8278
{
83-
if (width <=0) {
84-
width =1;
85-
}
86-
if (height <=0) {
87-
height =1;
88-
}
89-
size_t numBytes = width * height;
90-
91-
if ((unsignedlong)width != m_width || (unsignedlong)height != m_height) {
92-
if (numBytes > m_width * m_height) {
93-
delete[] m_buffer;
94-
m_buffer =nullptr;
95-
m_buffer =newunsignedchar[numBytes];
96-
}
79+
auto buf = im.mutable_data(0);
9780

98-
m_width = (unsignedlong)width;
99-
m_height = (unsignedlong)height;
100-
}
101-
102-
if (numBytes && m_buffer) {
103-
memset(m_buffer,0, numBytes);
104-
}
105-
}
106-
107-
voidFT2Image::draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y)
108-
{
109-
FT_Int image_width = (FT_Int)m_width;
110-
FT_Int image_height = (FT_Int)m_height;
81+
FT_Int image_width = (FT_Int)im.shape(1);
82+
FT_Int image_height = (FT_Int)im.shape(0);
11183
FT_Int char_width = bitmap->width;
11284
FT_Int char_height = bitmap->rows;
11385

@@ -121,14 +93,14 @@ void FT2Image::draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y)
12193

12294
if (bitmap->pixel_mode == FT_PIXEL_MODE_GRAY) {
12395
for (FT_Int i =y1; i < y2; ++i) {
124-
unsignedchar *dst =m_buffer + (i * image_width + x1);
96+
unsignedchar *dst =buf + (i * image_width + x1);
12597
unsignedchar *src = bitmap->buffer + (((i - y_offset) * bitmap->pitch) + x_start);
12698
for (FT_Int j = x1; j < x2; ++j, ++dst, ++src)
12799
*dst |= *src;
128100
}
129101
}elseif (bitmap->pixel_mode == FT_PIXEL_MODE_MONO) {
130102
for (FT_Int i =y1; i < y2; ++i) {
131-
unsignedchar *dst =m_buffer + (i * image_width + x1);
103+
unsignedchar *dst =buf + (i * image_width + x1);
132104
unsignedchar *src = bitmap->buffer + ((i - y_offset) * bitmap->pitch);
133105
for (FT_Int j = x1; j < x2; ++j, ++dst) {
134106
int x = (j - x1 + x_start);
@@ -259,7 +231,7 @@ FT2Font::FT2Font(FT_Open_Args &open_args,
259231
long hinting_factor_,
260232
std::vector<FT2Font *> &fallback_list,
261233
FT2Font::WarnFunc warn,bool warn_if_used)
262-
:ft_glyph_warn(warn),warn_if_used(warn_if_used),image(),face(nullptr),
234+
:ft_glyph_warn(warn),warn_if_used(warn_if_used),image({1,1}),face(nullptr),
263235
hinting_factor(hinting_factor_),
264236
// set default kerning factor to 0, i.e., no kerning manipulation
265237
kerning_factor(0)
@@ -676,7 +648,8 @@ void FT2Font::draw_glyphs_to_bitmap(bool antialiased)
676648
long width = (bbox.xMax - bbox.xMin) /64 +2;
677649
long height = (bbox.yMax - bbox.yMin) /64 +2;
678650

679-
image.resize(width, height);
651+
image = py::array_t<uint8_t>{{height, width}};
652+
std::memset(image.mutable_data(0),0, image.nbytes());
680653

681654
for (auto & glyph : glyphs) {
682655
FT_Error error =FT_Glyph_To_Bitmap(
@@ -692,11 +665,13 @@ void FT2Font::draw_glyphs_to_bitmap(bool antialiased)
692665
FT_Int x = (FT_Int)(bitmap->left - (bbox.xMin * (1. /64.)));
693666
FT_Int y = (FT_Int)((bbox.yMax * (1. /64.)) - bitmap->top +1);
694667

695-
image.draw_bitmap(&bitmap->bitmap, x, y);
668+
draw_bitmap(image,&bitmap->bitmap, x, y);
696669
}
697670
}
698671

699-
voidFT2Font::draw_glyph_to_bitmap(FT2Image &im,int x,int y,size_t glyphInd,bool antialiased)
672+
voidFT2Font::draw_glyph_to_bitmap(
673+
py::array_t<uint8_t, py::array::c_style> im,
674+
int x,int y,size_t glyphInd,bool antialiased)
700675
{
701676
FT_Vector sub_offset;
702677
sub_offset.x =0;// int((xd - (double)x) * 64.0);
@@ -718,7 +693,7 @@ void FT2Font::draw_glyph_to_bitmap(FT2Image &im, int x, int y, size_t glyphInd,
718693

719694
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[glyphInd];
720695

721-
im.draw_bitmap(&bitmap->bitmap, x + bitmap->left, y);
696+
draw_bitmap(im,&bitmap->bitmap, x + bitmap->left, y);
722697
}
723698

724699
voidFT2Font::get_glyph_name(unsignedint glyph_number, std::string &buffer,

‎src/ft2font.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ extern "C" {
2222
#include FT_TRUETYPE_TABLES_H
2323
}
2424

25+
#include<pybind11/pybind11.h>
26+
#include<pybind11/numpy.h>
27+
namespacepy= pybind11;
28+
2529
/*
2630
By definition, FT_FIXED as 2 16bit values stored in a single long.
2731
*/
@@ -32,7 +36,6 @@ extern "C" {
3236
classFT2Image
3337
{
3438
public:
35-
FT2Image();
3639
FT2Image(unsignedlong width,unsignedlong height);
3740
virtual~FT2Image();
3841

@@ -101,7 +104,9 @@ class FT2Font
101104
voidget_bitmap_offset(long *x,long *y);
102105
longget_descent();
103106
voiddraw_glyphs_to_bitmap(bool antialiased);
104-
voiddraw_glyph_to_bitmap(FT2Image &im,int x,int y,size_t glyphInd,bool antialiased);
107+
voiddraw_glyph_to_bitmap(
108+
py::array_t<uint8_t, py::array::c_style> im,
109+
int x,int y,size_t glyphInd,bool antialiased);
105110
voidget_glyph_name(unsignedint glyph_number, std::string &buffer,bool fallback);
106111
longget_name_index(char *name);
107112
FT_UIntget_char_index(FT_ULong charcode,bool fallback);
@@ -113,7 +118,7 @@ class FT2Font
113118
return face;
114119
}
115120

116-
FT2Image &get_image()
121+
py::array_t<uint8_t, py::array::c_style> &get_image()
117122
{
118123
return image;
119124
}
@@ -141,7 +146,7 @@ class FT2Font
141146
private:
142147
WarnFunc ft_glyph_warn;
143148
bool warn_if_used;
144-
FT2Image image;
149+
py::array_t<uint8_t, py::array::c_style> image;
145150
FT_Face face;
146151
FT_Vector pen;/* untransformed origin*/
147152
std::vector<FT_Glyph> glyphs;

‎src/ft2font_wrapper.cpp

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ const char *PyFT2Font_draw_glyph_to_bitmap__doc__ = R"""(
968968
969969
Parameters
970970
----------
971-
image :FT2Image
971+
image :2d array of uint8
972972
The image buffer on which to draw the glyph.
973973
x, y : int
974974
The pixel location at which to draw the glyph.
@@ -983,14 +983,16 @@ const char *PyFT2Font_draw_glyph_to_bitmap__doc__ = R"""(
983983
)""";
984984

985985
staticvoid
986-
PyFT2Font_draw_glyph_to_bitmap(PyFT2Font *self,FT2Image &image,
986+
PyFT2Font_draw_glyph_to_bitmap(PyFT2Font *self,py::buffer &image,
987987
double_or_<int> vxd, double_or_<int> vyd,
988988
PyGlyph *glyph,bool antialiased =true)
989989
{
990990
auto xd = _double_to_<int>("x", vxd);
991991
auto yd = _double_to_<int>("y", vyd);
992992

993-
self->x->draw_glyph_to_bitmap(image, xd, yd, glyph->glyphInd, antialiased);
993+
self->x->draw_glyph_to_bitmap(
994+
py::array_t<uint8_t, py::array::c_style>{image},
995+
xd, yd, glyph->glyphInd, antialiased);
994996
}
995997

996998
constchar *PyFT2Font_get_glyph_name__doc__ =R"""(
@@ -1440,12 +1442,7 @@ const char *PyFT2Font_get_image__doc__ = R"""(
14401442
static py::array
14411443
PyFT2Font_get_image(PyFT2Font *self)
14421444
{
1443-
FT2Image &im = self->x->get_image();
1444-
py::ssize_t dims[] = {
1445-
static_cast<py::ssize_t>(im.get_height()),
1446-
static_cast<py::ssize_t>(im.get_width())
1447-
};
1448-
return py::array_t<unsignedchar>(dims, im.get_buffer());
1445+
return self->x->get_image();
14491446
}
14501447

14511448
constchar *PyFT2Font__get_type1_encoding_vector__doc__ =R"""(
@@ -1565,6 +1562,10 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
15651562
PyFT2Image__doc__)
15661563
.def(py::init(
15671564
[](double_or_<long> width, double_or_<long> height) {
1565+
auto warn =
1566+
py::module_::import("matplotlib._api").attr("warn_deprecated");
1567+
warn("since"_a="3.11","name"_a="FT2Image","obj_type"_a="class",
1568+
"alternative"_a="a 2D uint8 ndarray");
15681569
returnnewFT2Image(
15691570
_double_to_<long>("width", width),
15701571
_double_to_<long>("height", height)
@@ -1604,8 +1605,8 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16041605
.def_property_readonly("bbox", &PyGlyph_get_bbox,
16051606
"The control box of the glyph.");
16061607

1607-
py::class_<PyFT2Font>(m,"FT2Font",py::is_final(),py::buffer_protocol(),
1608-
PyFT2Font__doc__)
1608+
auto cls =py::class_<PyFT2Font>(m,"FT2Font",py::is_final(),py::buffer_protocol(),
1609+
PyFT2Font__doc__)
16091610
.def(py::init(&PyFT2Font_init),
16101611
"filename"_a,"hinting_factor"_a=8,py::kw_only(),
16111612
"_fallback_list"_a=py::none(),"_kerning_factor"_a=0,
@@ -1639,10 +1640,20 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16391640
.def("get_descent", &PyFT2Font_get_descent, PyFT2Font_get_descent__doc__)
16401641
.def("draw_glyphs_to_bitmap", &PyFT2Font_draw_glyphs_to_bitmap,
16411642
py::kw_only(),"antialiased"_a=true,
1642-
PyFT2Font_draw_glyphs_to_bitmap__doc__)
1643-
.def("draw_glyph_to_bitmap", &PyFT2Font_draw_glyph_to_bitmap,
1644-
"image"_a,"x"_a,"y"_a,"glyph"_a,py::kw_only(),"antialiased"_a=true,
1645-
PyFT2Font_draw_glyph_to_bitmap__doc__)
1643+
PyFT2Font_draw_glyphs_to_bitmap__doc__);
1644+
// The generated docstring uses an unqualified "Buffer" as type hint,
1645+
// which causes an error in sphinx. This is fixed as of pybind11
1646+
// master (since #5566) which now uses "collections.abc.Buffer";
1647+
// restore the signature once that version is released.
1648+
{
1649+
py::options options{};
1650+
options.disable_function_signatures();
1651+
cls
1652+
.def("draw_glyph_to_bitmap", &PyFT2Font_draw_glyph_to_bitmap,
1653+
"image"_a,"x"_a,"y"_a,"glyph"_a,py::kw_only(),"antialiased"_a=true,
1654+
PyFT2Font_draw_glyph_to_bitmap__doc__);
1655+
}
1656+
cls
16461657
.def("get_glyph_name", &PyFT2Font_get_glyph_name,"index"_a,
16471658
PyFT2Font_get_glyph_name__doc__)
16481659
.def("get_charmap", &PyFT2Font_get_charmap, PyFT2Font_get_charmap__doc__)
@@ -1760,10 +1771,7 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
17601771
"The original filename for this object.")
17611772

17621773
.def_buffer([](PyFT2Font &self) -> py::buffer_info {
1763-
FT2Image &im = self.x->get_image();
1764-
std::vector<py::size_t> shape { im.get_height(), im.get_width() };
1765-
std::vector<py::size_t> strides { im.get_width(),1 };
1766-
returnpy::buffer_info(im.get_buffer(), shape, strides);
1774+
return self.x->get_image().request();
17671775
});
17681776

17691777
m.attr("__freetype_version__") = version_string;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp