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

Commit669ba8f

Browse files
committed
Add language parameter to Text objects
1 parenta7c08c8 commit669ba8f

17 files changed

+175
-17
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Specifying text language
2+
------------------------
3+
4+
OpenType fonts may support language systems which can be used to select different
5+
typographic conventions, e.g., localized variants of letters that share a single Unicode
6+
code point, or different default font features. The text API now supports setting a
7+
language to be used and may be set/get with:
8+
9+
- `matplotlib.text.Text.set_language` / `matplotlib.text.Text.get_language`
10+
- Any API that creates a `.Text` object by passing the *language* argument (e.g.,
11+
``plt.xlabel(..., language=...)``)
12+
13+
The language of the text must be in a format accepted by libraqm, namely `a BCP47
14+
language code <https://www.w3.org/International/articles/language-tags/>`_. If None or
15+
unset, then no particular language will be implied, and default font settings will be
16+
used.
17+
18+
For example, the default font ``DejaVu Sans`` supports language-specific glyphs in the
19+
Serbian and Macedonian languages in the Cyrillic alphabet, or the Sámi family of
20+
languages in the Latin alphabet.
21+
22+
..plot::
23+
:include-source:
24+
25+
fig = plt.figure(figsize=(7, 3))
26+
27+
char = '\U00000431'
28+
fig.text(0.5, 0.8, f'\\U{ord(char):08x}', fontsize=40, horizontalalignment='center')
29+
fig.text(0, 0.6, f'Serbian: {char}', fontsize=40, language='sr')
30+
fig.text(1, 0.6, f'Russian: {char}', fontsize=40, language='ru',
31+
horizontalalignment='right')
32+
33+
char = '\U0000014a'
34+
fig.text(0.5, 0.3, f'\\U{ord(char):08x}', fontsize=40, horizontalalignment='center')
35+
fig.text(0, 0.1, f'English: {char}', fontsize=40, language='en')
36+
fig.text(1, 0.1, f'Inari Sámi: {char}', fontsize=40, language='smn',
37+
horizontalalignment='right')

‎lib/matplotlib/_text_helpers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def warn_on_missing_glyph(codepoint, fontnames):
4343
f"Matplotlib currently does not support{block} natively.")
4444

4545

46-
deflayout(string,font,*,kern_mode=Kerning.DEFAULT):
46+
deflayout(string,font,*,language=None,kern_mode=Kerning.DEFAULT):
4747
"""
4848
Render *string* with *font*.
4949
@@ -56,6 +56,9 @@ def layout(string, font, *, kern_mode=Kerning.DEFAULT):
5656
The string to be rendered.
5757
font : FT2Font
5858
The font.
59+
language : str or list of tuples of (str, int, int), optional
60+
The language of the text in a format accepted by libraqm, namely `a BCP47
61+
language code <https://www.w3.org/International/articles/language-tags/>`_.
5962
kern_mode : Kerning
6063
A FreeType kerning mode.
6164
@@ -65,7 +68,7 @@ def layout(string, font, *, kern_mode=Kerning.DEFAULT):
6568
"""
6669
x=0
6770
prev_glyph_idx=None
68-
char_to_font=font._get_fontmap(string)
71+
char_to_font=font._get_fontmap(string)# TODO: Pass in language.
6972
base_font=font
7073
forcharinstring:
7174
# This has done the fallback logic

‎lib/matplotlib/backends/backend_agg.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
189189
font=self._prepare_font(prop)
190190
# We pass '0' for angle here, since it will be rotated (in raster
191191
# space) in the following call to draw_text_image).
192-
font.set_text(s,0,flags=get_hinting_flag())
192+
font.set_text(s,0,flags=get_hinting_flag(),
193+
language=mtext.get_language()ifmtextisnotNoneelseNone)
193194
font.draw_glyphs_to_bitmap(
194195
antialiased=gc.get_antialiased())
195196
d=font.get_descent()/64.0

‎lib/matplotlib/backends/backend_pdf.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
23382338
returnself.draw_mathtext(gc,x,y,s,prop,angle)
23392339

23402340
fontsize=prop.get_size_in_points()
2341+
language=mtext.get_language()ifmtextisnotNoneelseNone
23412342

23422343
ifmpl.rcParams['pdf.use14corefonts']:
23432344
font=self._get_font_afm(prop)
@@ -2348,7 +2349,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
23482349
fonttype=mpl.rcParams['pdf.fonttype']
23492350

23502351
ifgc.get_url()isnotNone:
2351-
font.set_text(s)
2352+
font.set_text(s,language=language)
23522353
width,height=font.get_width_height()
23532354
self.file._annotations[-1][1].append(_get_link_annotation(
23542355
gc,x,y,width/64,height/64,angle))
@@ -2382,7 +2383,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
23822383
multibyte_glyphs= []
23832384
prev_was_multibyte=True
23842385
prev_font=font
2385-
foritemin_text_helpers.layout(s,font,kern_mode=Kerning.UNFITTED):
2386+
foritemin_text_helpers.layout(s,font,language=language,
2387+
kern_mode=Kerning.UNFITTED):
23862388
if_font_supports_glyph(fonttype,ord(item.char)):
23872389
ifprev_was_multibyteoritem.ft_object!=prev_font:
23882390
singlebyte_chunks.append((item.ft_object,item.x, []))

‎lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,9 +795,10 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
795795
thisx+=width*scale
796796

797797
else:
798+
language=mtext.get_language()ifmtextisnotNoneelseNone
798799
font=self._get_font_ttf(prop)
799800
self._character_tracker.track(font,s)
800-
foritemin_text_helpers.layout(s,font):
801+
foritemin_text_helpers.layout(s,font,language=language):
801802
ps_name= (item.ft_object.postscript_name
802803
.encode("ascii","replace").decode("ascii"))
803804
glyph_name=item.ft_object.get_glyph_name(item.glyph_idx)

‎lib/matplotlib/ft2font.pyi

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,12 @@ class FT2Font(Buffer):
236236
defset_charmap(self,i:int)->None: ...
237237
defset_size(self,ptsize:float,dpi:float)->None: ...
238238
defset_text(
239-
self,string:str,angle:float= ...,flags:LoadFlags= ...
239+
self,
240+
string:str,
241+
angle:float= ...,
242+
flags:LoadFlags= ...,
243+
*,
244+
language:str|list[tuple[str,int,int]]|None= ...,
240245
)->NDArray[np.float64]: ...
241246
@property
242247
defascender(self)->int: ...

‎lib/matplotlib/mpl-data/matplotlibrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@
292292
## for more information on text properties
293293
#text.color: black
294294

295+
## The language of the text in a format accepted by libraqm, namely `a BCP47 language
296+
## code <https://www.w3.org/International/articles/language-tags/>`_. If None, then no
297+
## particular language will be implied, and default font settings will be used.
298+
#text.language: None
299+
295300
## FreeType hinting flag ("foo" corresponds to FT_LOAD_FOO); may be one of the
296301
## following (Proprietary Matplotlib-specific synonyms are given in parentheses,
297302
## but their use is discouraged):

‎lib/matplotlib/rcsetup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,7 @@ def _convert_validator_spec(key, conv):
10581058
"text.kerning_factor":validate_int,
10591059
"text.antialiased":validate_bool,
10601060
"text.parse_math":validate_bool,
1061+
"text.language":validate_string_or_None,
10611062

10621063
"mathtext.cal":validate_font_properties,
10631064
"mathtext.rm":validate_font_properties,

‎lib/matplotlib/tests/test_ft2font.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,27 @@ def test_ft2font_set_text():
774774
assertfont.get_bitmap_offset()== (6,0)
775775

776776

777+
deftest_ft2font_language_invalid():
778+
file=fm.findfont('DejaVu Sans')
779+
font=ft2font.FT2Font(file,hinting_factor=1,_kerning_factor=0)
780+
withpytest.raises(TypeError):
781+
font.set_text('foo',language=[1,2,3])
782+
withpytest.raises(TypeError):
783+
font.set_text('foo',language=[(1,2)])
784+
withpytest.raises(TypeError):
785+
font.set_text('foo',language=[('en','foo',2)])
786+
withpytest.raises(TypeError):
787+
font.set_text('foo',language=[('en',1,'foo')])
788+
789+
790+
deftest_ft2font_language():
791+
file=fm.findfont('DejaVu Sans')
792+
font=ft2font.FT2Font(file,hinting_factor=1,_kerning_factor=0)
793+
font.set_text('foo')
794+
font.set_text('foo',language='en')
795+
font.set_text('foo',language=[('en',1,2)])
796+
797+
777798
deftest_ft2font_loading():
778799
file=fm.findfont('DejaVu Sans')
779800
font=ft2font.FT2Font(file,hinting_factor=1,_kerning_factor=0)

‎lib/matplotlib/tests/test_text.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,3 +1190,19 @@ def test_ytick_rotation_mode():
11901190
tick.set_rotation(angle)
11911191

11921192
plt.subplots_adjust(left=0.4,right=0.6,top=.99,bottom=.01)
1193+
1194+
1195+
deftest_text_language_invalid():
1196+
withpytest.raises(TypeError,match='must be list of tuple'):
1197+
Text(0,0,'foo',language=[1,2,3])
1198+
withpytest.raises(TypeError,match='must be list of tuple'):
1199+
Text(0,0,'foo',language=[(1,2)])
1200+
withpytest.raises(TypeError,match='start location must be int'):
1201+
Text(0,0,'foo',language=[('en','foo',2)])
1202+
withpytest.raises(TypeError,match='end location must be int'):
1203+
Text(0,0,'foo',language=[('en',1,'foo')])
1204+
1205+
1206+
deftest_text_language():
1207+
Text(0,0,'foo',language='en')
1208+
Text(0,0,'foo',language=[('en',1,2)])

‎lib/matplotlib/text.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def __init__(self,
136136
super().__init__()
137137
self._x,self._y=x,y
138138
self._text=''
139+
self._language=None
139140
self._reset_visual_defaults(
140141
text=text,
141142
color=color,
@@ -1422,6 +1423,41 @@ def _va_for_angle(self, angle):
14221423
return'baseline'ifanchor_at_leftelse'top'
14231424
return'top'ifanchor_at_leftelse'baseline'
14241425

1426+
defget_language(self):
1427+
"""Return the language this Text is in."""
1428+
returnself._language
1429+
1430+
defset_language(self,language):
1431+
"""
1432+
Set the language of the text.
1433+
1434+
Parameters
1435+
----------
1436+
language : str or list[tuple[str, int, int]] or None
1437+
The language of the text in a format accepted by libraqm, namely `a BCP47
1438+
language code <https://www.w3.org/International/articles/language-tags/>`_.
1439+
1440+
If None, then defaults to :rc:`text.language`.
1441+
"""
1442+
_api.check_isinstance((list,str,None),language=language)
1443+
language=mpl._val_or_rc(language,'text.language')
1444+
1445+
ifisinstance(language,list):
1446+
forvalinlanguage:
1447+
ifnotisinstance(val,tuple)orlen(val)!=3:
1448+
raiseTypeError('language must be list of tuple, not {language!r}')
1449+
sublang,start,end=val
1450+
ifnotisinstance(sublang,str):
1451+
raiseTypeError(
1452+
'sub-language specification must be str, not {sublang!r}')
1453+
ifnotisinstance(start,int):
1454+
raiseTypeError('start location must be int, not {start!r}')
1455+
ifnotisinstance(end,int):
1456+
raiseTypeError('end location must be int, not {end!r}')
1457+
1458+
self._language=language
1459+
self.stale=True
1460+
14251461

14261462
classOffsetFrom:
14271463
"""Callable helper class for working with `Annotation`."""

‎lib/matplotlib/text.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class Text(Artist):
108108
defset_antialiased(self,antialiased:bool)->None: ...
109109
def_ha_for_angle(self,angle:Any)->Literal['center','right','left']|None: ...
110110
def_va_for_angle(self,angle:Any)->Literal['center','top','baseline']|None: ...
111+
defget_language(self)->str|list[tuple[str,int,int]]|None: ...
112+
defset_language(self,language:str|list[tuple[str,int,int]]|None)->None: ...
111113

112114
classOffsetFrom:
113115
def__init__(

‎lib/matplotlib/textpath.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def get_text_width_height_descent(self, s, prop, ismath):
6969
d/=64.0
7070
returnw*scale,h*scale,d*scale
7171

72-
defget_text_path(self,prop,s,ismath=False):
72+
defget_text_path(self,prop,s,ismath=False,*,language=None):
7373
"""
7474
Convert text *s* to path (a tuple of vertices and codes for
7575
matplotlib.path.Path).
@@ -82,6 +82,9 @@ def get_text_path(self, prop, s, ismath=False):
8282
The text to be converted.
8383
ismath : {False, True, "TeX"}
8484
If True, use mathtext parser. If "TeX", use tex for rendering.
85+
language : str or list of tuples of (str, int, int), optional
86+
The language of the text in a format accepted by libraqm, namely `a BCP47
87+
language code <https://www.w3.org/International/articles/language-tags/>`_.
8588
8689
Returns
8790
-------
@@ -109,7 +112,8 @@ def get_text_path(self, prop, s, ismath=False):
109112
glyph_info,glyph_map,rects=self.get_glyphs_tex(prop,s)
110113
elifnotismath:
111114
font=self._get_font(prop)
112-
glyph_info,glyph_map,rects=self.get_glyphs_with_font(font,s)
115+
glyph_info,glyph_map,rects=self.get_glyphs_with_font(font,s,
116+
language=language)
113117
else:
114118
glyph_info,glyph_map,rects=self.get_glyphs_mathtext(prop,s)
115119

@@ -130,7 +134,7 @@ def get_text_path(self, prop, s, ismath=False):
130134
returnverts,codes
131135

132136
defget_glyphs_with_font(self,font,s,glyph_map=None,
133-
return_new_glyphs_only=False):
137+
return_new_glyphs_only=False,*,language=None):
134138
"""
135139
Convert string *s* to vertices and codes using the provided ttf font.
136140
"""
@@ -145,7 +149,7 @@ def get_glyphs_with_font(self, font, s, glyph_map=None,
145149

146150
xpositions= []
147151
glyph_ids= []
148-
foritemin_text_helpers.layout(s,font):
152+
foritemin_text_helpers.layout(s,font,language=language):
149153
char_id=self._get_char_id(item.ft_object,ord(item.char))
150154
glyph_ids.append(char_id)
151155
xpositions.append(item.x)

‎lib/matplotlib/textpath.pyi

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ class TextToPath:
1616
self,s:str,prop:FontProperties,ismath:bool|Literal["TeX"]
1717
)->tuple[float,float,float]: ...
1818
defget_text_path(
19-
self,prop:FontProperties,s:str,ismath:bool|Literal["TeX"]= ...
19+
self,prop:FontProperties,s:str,ismath:bool|Literal["TeX"]= ...,*,
20+
language:str|list[tuple[str,int,int]]|None= ...,
2021
)->list[np.ndarray]: ...
2122
defget_glyphs_with_font(
2223
self,
2324
font:FT2Font,
2425
s:str,
2526
glyph_map:dict[str,tuple[np.ndarray,np.ndarray]]|None= ...,
2627
return_new_glyphs_only:bool= ...,
28+
*,
29+
language:str|list[tuple[str,int,int]]|None= ...,
2730
)->tuple[
2831
list[tuple[str,float,float,float]],
2932
dict[str,tuple[np.ndarray,np.ndarray]],

‎src/ft2font.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,8 @@ void FT2Font::set_kerning_factor(int factor)
397397
}
398398

399399
voidFT2Font::set_text(
400-
std::u32string_view text,double angle, FT_Int32 flags, std::vector<double> &xys)
400+
std::u32string_view text,double angle, FT_Int32 flags, LanguageType languages,
401+
std::vector<double> &xys)
401402
{
402403
FT_Matrix matrix;/* transformation matrix*/
403404

‎src/ft2font.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef MPL_FT2FONT_H
77
#defineMPL_FT2FONT_H
88

9+
#include<optional>
910
#include<set>
1011
#include<string>
1112
#include<string_view>
@@ -70,6 +71,9 @@ class FT2Font
7071
typedefvoid (*WarnFunc)(FT_ULong charcode, std::set<FT_String*> family_names);
7172

7273
public:
74+
using LanguageRange = std::tuple<std::string,int,int>;
75+
using LanguageType = std::optional<std::vector<LanguageRange>>;
76+
7377
FT2Font(FT_Open_Args &open_args,long hinting_factor,
7478
std::vector<FT2Font *> &fallback_list,
7579
WarnFunc warn,bool warn_if_used);
@@ -79,7 +83,7 @@ class FT2Font
7983
voidset_charmap(int i);
8084
voidselect_charmap(unsignedlong i);
8185
voidset_text(std::u32string_view codepoints,double angle, FT_Int32 flags,
82-
std::vector<double> &xys);
86+
LanguageType languages,std::vector<double> &xys);
8387
intget_kerning(FT_UInt left, FT_UInt right, FT_Kerning_Mode mode,bool fallback);
8488
intget_kerning(FT_UInt left, FT_UInt right, FT_Kerning_Mode mode, FT_Vector &delta);
8589
voidset_kerning_factor(int factor);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp