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

Commite545bb2

Browse files
committed
Rasterize dvi files without dvipng.
This patch drops the reliance on dvipng to rasterize dvi files prior toinclusion by agg, instead performing the rasterization ourselves (as aconsequence, the rasterization output also becomes dependent of thefreetype version used). Note that this approach will be needed anywaysto support xetex and luatex, as dvipng doesn't support dvi filesgenerated by these engines.Baseline images change slightly, for the better or the worse. Thetop-left blue cross text in test_rotation.py ("Myrt0") seems to bebetter top-aligned against the blue line (the old version overshot abit); the bounding box of the formulas in test_usetex.py seems a bitworse.
1 parentdef8fa4 commite545bb2

File tree

7 files changed

+129
-13
lines changed

7 files changed

+129
-13
lines changed

‎lib/matplotlib/backends/backend_agg.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"""
2323

2424
fromcontextlibimportnullcontext
25+
importmath
2526
frommathimportradians,cos,sin
2627

2728
importnumpyasnp
@@ -30,8 +31,9 @@
3031
frommatplotlibimport_api,cbook
3132
frommatplotlib.backend_basesimport (
3233
_Backend,FigureCanvasBase,FigureManagerBase,RendererBase)
34+
frommatplotlib.dvireadimportDvi
3335
frommatplotlib.font_managerimportfontManageras_fontManager,get_font
34-
frommatplotlib.ft2fontimportLoadFlags
36+
frommatplotlib.ft2fontimportFT2Image,LoadFlags
3537
frommatplotlib.mathtextimportMathTextParser
3638
frommatplotlib.pathimportPath
3739
frommatplotlib.transformsimportBbox,BboxBase
@@ -208,7 +210,8 @@ def get_text_width_height_descent(self, s, prop, ismath):
208210

209211
_api.check_in_list(["TeX",True,False],ismath=ismath)
210212
ifismath=="TeX":
211-
returnsuper().get_text_width_height_descent(s,prop,ismath)
213+
return [*map(
214+
math.ceil,super().get_text_width_height_descent(s,prop,ismath))]
212215

213216
ifismath:
214217
ox,oy,width,height,descent,font_image= \
@@ -227,19 +230,45 @@ def get_text_width_height_descent(self, s, prop, ismath):
227230
defdraw_tex(self,gc,x,y,s,prop,angle,*,mtext=None):
228231
# docstring inherited
229232
# todo, handle props, angle, origins
230-
size=prop.get_size_in_points()
231-
232-
texmanager=self.get_texmanager()
233233

234-
Z=texmanager.get_grey(s,size,self.dpi)
235-
Z=np.array(Z*255.0,np.uint8)
234+
size=prop.get_size_in_points()
235+
dvifile=self.get_texmanager().make_dvi(s,size)
236+
withDvi(dvifile,self.dpi)asdvi:
237+
page,=dvi
238+
w=math.ceil(page.width)
239+
h=math.ceil(page.height)
240+
d=math.ceil(page.descent)
241+
242+
image=np.zeros((h+d,w),np.uint8)
243+
244+
fortextinpage.text:
245+
hf=mpl.rcParams["text.hinting_factor"]
246+
font=get_font(text.font_path)
247+
font.set_size(text.font_size,self.dpi)
248+
slant=text.font_effects.get("slant",0)
249+
extend=text.font_effects.get("extend",1)
250+
matrix= [
251+
[round(65536*extend/hf),round(65536*extend*slant)],
252+
[0,65536],
253+
]
254+
font._set_transform(matrix, [0,0])
255+
glyph=font.load_glyph(text.index)
256+
# text.y is upwards from baseline, _draw_glyph_at wants upwards from bottom.
257+
font._draw_glyph_at(image,text.x,d+text.y,glyph,
258+
antialiased=gc.get_antialiased())
259+
260+
forboxinpage.boxes:
261+
x0=round(box.x)
262+
x1=x0+max(round(box.width),1)
263+
y1=round(h-box.y)
264+
y0=y1-max(round(box.height),1)
265+
image[y0:y1,x0:x1]=0xff
236266

237-
w,h,d=self.get_text_width_height_descent(s,prop,ismath="TeX")
238267
xd=d*sin(radians(angle))
239268
yd=d*cos(radians(angle))
240269
x=round(x+xd)
241270
y=round(y+yd)
242-
self._renderer.draw_text_image(Z,x,y,angle,gc)
271+
self._renderer.draw_text_image(image,x,y,angle,gc)
243272

244273
defget_canvas_width_height(self):
245274
# docstring inherited
Loading

‎src/ft2font.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,17 @@ void FT2Font::set_size(double ptsize, double dpi)
306306
}
307307
}
308308

309+
voidFT2Font::set_transform(
310+
std::array<std::array<FT_Fixed,2>,2> matrix, std::array<FT_Fixed,2> delta)
311+
{
312+
FT_Matrix m = {matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1]};
313+
FT_Vector d = {delta[0], delta[1]};
314+
FT_Set_Transform(face, &m, &d);
315+
for (auto & fallback : fallbacks) {
316+
fallback->set_transform(matrix, delta);
317+
}
318+
}
319+
309320
voidFT2Font::set_charmap(int i)
310321
{
311322
if (i >= face->num_charmaps) {
@@ -696,6 +707,27 @@ void FT2Font::draw_glyph_to_bitmap(
696707
draw_bitmap(im, &bitmap->bitmap, x + bitmap->left, y);
697708
}
698709

710+
voidFT2Font::draw_glyph_at(
711+
py::array_t<uint8_t, py::array::c_style> im,
712+
double x,double y,size_t glyphInd,bool antialiased)
713+
{
714+
if (glyphInd >= glyphs.size()) {
715+
throwstd::runtime_error("glyph num is out of range");
716+
}
717+
FT_Vector sub_offset = {FT_Fixed(x *64 + .5),FT_Fixed(y *64 + .5)};
718+
FT_Error error =FT_Glyph_To_Bitmap(
719+
&glyphs[glyphInd],
720+
antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
721+
&sub_offset,// additional translation
722+
1// destroy image
723+
);
724+
if (error) {
725+
throw_ft_error("Could not convert glyph to bitmap", error);
726+
}
727+
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[glyphInd];
728+
draw_bitmap(im, &bitmap->bitmap, bitmap->left, im.shape(0) - bitmap->top);
729+
}
730+
699731
voidFT2Font::get_glyph_name(unsignedint glyph_number, std::string &buffer,
700732
bool fallback =false)
701733
{

‎src/ft2font.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class FT2Font
7979
virtual~FT2Font();
8080
voidclear();
8181
voidset_size(double ptsize,double dpi);
82+
voidset_transform(
83+
std::array<std::array<FT_Fixed,2>,2> matrix, std::array<FT_Fixed,2> delta);
8284
voidset_charmap(int i);
8385
voidselect_charmap(unsignedlong i);
8486
voidset_text(std::u32string_view codepoints,double angle, FT_Int32 flags,
@@ -107,6 +109,9 @@ class FT2Font
107109
voiddraw_glyph_to_bitmap(
108110
py::array_t<uint8_t, py::array::c_style> im,
109111
int x,int y,size_t glyphInd,bool antialiased);
112+
voiddraw_glyph_at(
113+
py::array_t<uint8_t, py::array::c_style> im,
114+
double x,double y,size_t glyphInd,bool antialiased);
110115
voidget_glyph_name(unsignedint glyph_number, std::string &buffer,bool fallback);
111116
longget_name_index(char *name);
112117
FT_UIntget_char_index(FT_ULong charcode,bool fallback);

‎src/ft2font_wrapper.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,25 @@ PyFT2Font_set_size(PyFT2Font *self, double ptsize, double dpi)
541541
self->x->set_size(ptsize, dpi);
542542
}
543543

544+
constchar *PyFT2Font__set_transform__doc__ =R"""(
545+
Set the transform of the text.
546+
547+
This is a low-level function directly taking inputs in 26.6 format. Refer
548+
to the FreeType docs of FT_Set_Transform for further description.
549+
550+
Parameters
551+
----------
552+
matrix : (2, 2) array of int
553+
delta : (2,) array of int
554+
)""";
555+
556+
staticvoid
557+
PyFT2Font__set_transform(
558+
PyFT2Font *self, std::array<std::array<FT_Fixed,2>,2> matrix, std::array<FT_Fixed,2> delta)
559+
{
560+
self->x->set_transform(matrix, delta);
561+
}
562+
544563
constchar *PyFT2Font_set_charmap__doc__ =R"""(
545564
Make the i-th charmap current.
546565
@@ -971,7 +990,7 @@ const char *PyFT2Font_draw_glyph_to_bitmap__doc__ = R"""(
971990
image : 2d array of uint8
972991
The image buffer on which to draw the glyph.
973992
x, y : int
974-
Thepixel location at which to draw the glyph.
993+
Theposition of the glyph's top left corner.
975994
glyph : Glyph
976995
The glyph to draw.
977996
antialiased : bool, default: True
@@ -990,9 +1009,36 @@ PyFT2Font_draw_glyph_to_bitmap(PyFT2Font *self, py::buffer &image,
9901009
auto xd = _double_to_<int>("x", vxd);
9911010
auto yd = _double_to_<int>("y", vyd);
9921011

993-
self->x->draw_glyph_to_bitmap(
994-
py::array_t<uint8_t, py::array::c_style>{image},
995-
xd, yd, glyph->glyphInd, antialiased);
1012+
self->x->draw_glyph_to_bitmap(image, xd, yd, glyph->glyphInd, antialiased);
1013+
}
1014+
1015+
constchar *PyFT2Font__draw_glyph_at__doc__ =R"""(
1016+
Draw a single glyph to the bitmap at pixel locations x, y.
1017+
1018+
Parameters
1019+
----------
1020+
image : FT2Image
1021+
The image buffer on which to draw the glyph. If the buffer is too
1022+
small, the glyph will be cropped.
1023+
x, y : float
1024+
The position of the glyph's origin.
1025+
glyph : Glyph
1026+
The glyph to draw.
1027+
antialiased : bool, default: True
1028+
Whether to render glyphs 8-bit antialiased or in pure black-and-white.
1029+
1030+
See Also
1031+
--------
1032+
.draw_glyphs_to_bitmap
1033+
)""";
1034+
1035+
staticvoid
1036+
PyFT2Font__draw_glyph_at(
1037+
PyFT2Font *self,
1038+
py::buffer &image,double x,double y, PyGlyph *glyph,
1039+
bool antialiased =true)
1040+
{
1041+
self->x->draw_glyph_at(image, x, y, glyph->glyphInd, antialiased);
9961042
}
9971043

9981044
constchar *PyFT2Font_get_glyph_name__doc__ =R"""(
@@ -1615,6 +1661,7 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16151661
.def("clear", &PyFT2Font_clear, PyFT2Font_clear__doc__)
16161662
.def("set_size", &PyFT2Font_set_size,"ptsize"_a,"dpi"_a,
16171663
PyFT2Font_set_size__doc__)
1664+
.def("_set_transform", &PyFT2Font__set_transform,"matrix"_a,"delta"_a)
16181665
.def("set_charmap", &PyFT2Font_set_charmap,"i"_a,
16191666
PyFT2Font_set_charmap__doc__)
16201667
.def("select_charmap", &PyFT2Font_select_charmap,"i"_a,
@@ -1654,6 +1701,9 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16541701
PyFT2Font_draw_glyph_to_bitmap__doc__);
16551702
}
16561703
cls
1704+
.def("_draw_glyph_at", &PyFT2Font__draw_glyph_at,
1705+
"image"_a,"x"_a,"y"_a,"glyph"_a,py::kw_only(),"antialiased"_a=true,
1706+
PyFT2Font__draw_glyph_at__doc__)
16571707
.def("get_glyph_name", &PyFT2Font_get_glyph_name,"index"_a,
16581708
PyFT2Font_get_glyph_name__doc__)
16591709
.def("get_charmap", &PyFT2Font_get_charmap, PyFT2Font_get_charmap__doc__)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp