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

Commitd5f19e7

Browse files
committed
ft2font: Add a wrapper around layouting for vector usage
1 parent8d651a6 commitd5f19e7

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

‎ci/mypy-stubtest-allowlist.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ matplotlib\._.*
66
matplotlib\.rcsetup\._listify_validator
77
matplotlib\.rcsetup\._validate_linestyle
88
matplotlib\.ft2font\.Glyph
9+
matplotlib\.ft2font\.LayoutItem
910
matplotlib\.testing\.jpl_units\..*
1011
matplotlib\.sphinxext(\..*)?
1112

‎lib/matplotlib/ft2font.pyi‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ class _SfntPcltDict(TypedDict):
191191
widthType:int
192192
serifStyle:int
193193

194+
@final
195+
classLayoutItem:
196+
@property
197+
defft_object(self)->FT2Font: ...
198+
@property
199+
defchar(self)->str: ...
200+
@property
201+
defglyph_index(self)->GlyphIndexType: ...
202+
@property
203+
defx(self)->float: ...
204+
@property
205+
defy(self)->float: ...
206+
@property
207+
defprev_kern(self)->float: ...
208+
def__str__(self)->str: ...
209+
194210
@final
195211
classFT2Font(Buffer):
196212
def__init__(
@@ -204,6 +220,13 @@ class FT2Font(Buffer):
204220
ifsys.version_info[:2]>= (3,12):
205221
def__buffer__(self,flags:int)->memoryview: ...
206222
def_get_fontmap(self,string:str)->dict[str,FT2Font]: ...
223+
def_layout(
224+
self,
225+
text:str,
226+
flags:LoadFlags,
227+
features:tuple[str, ...]|None= ...,
228+
language:str|tuple[tuple[str,int,int], ...]|None= ...,
229+
)->list[LayoutItem]: ...
207230
defclear(self)->None: ...
208231
defdraw_glyph_to_bitmap(
209232
self,image:NDArray[np.uint8],x:int,y:int,glyph:Glyph,antialiased:bool= ...

‎src/ft2font_wrapper.cpp‎

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,119 @@ PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
14091409
return indices;
14101410
}
14111411

1412+
/**********************************************************************
1413+
* Layout items
1414+
**/
1415+
1416+
structLayoutItem {
1417+
PyFT2Font *ft_object;
1418+
std::u32string character;
1419+
int glyph_index;
1420+
double x;
1421+
double y;
1422+
double prev_kern;
1423+
1424+
LayoutItem(PyFT2Font *f, std::u32string c,int i,double x,double y,double k) :
1425+
ft_object(f), character(c), glyph_index(i), x(x), y(y), prev_kern(k) {}
1426+
};
1427+
1428+
constchar *PyFT2Font_layout__doc__ =R"""(
1429+
Layout a string and yield information about each used glyph.
1430+
1431+
.. warning::
1432+
This API uses the fallback list and is both private and provisional: do not use
1433+
it directly.
1434+
1435+
.. versionadded:: 3.11
1436+
1437+
Parameters
1438+
----------
1439+
text : str
1440+
The characters for which to find fonts.
1441+
flags : LoadFlags, default: `.LoadFlags.FORCE_AUTOHINT`
1442+
Any bitwise-OR combination of the `.LoadFlags` flags.
1443+
features : tuple[str, ...], optional
1444+
The font feature tags to use for the font.
1445+
1446+
Available font feature tags may be found at
1447+
https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
1448+
language : str, optional
1449+
The language of the text in a format accepted by libraqm, namely `a BCP47
1450+
language code <https://www.w3.org/International/articles/language-tags/>`_.
1451+
1452+
Returns
1453+
-------
1454+
list[LayoutItem]
1455+
)""";
1456+
1457+
staticauto
1458+
PyFT2Font_layout(PyFT2Font *self, std::u32string text, LoadFlags flags,
1459+
std::optional<std::vector<std::string>> features = std::nullopt,
1460+
std::variant<FT2Font::LanguageType, std::string> languages_or_str =nullptr)
1461+
{
1462+
constauto hinting_factor = self->get_hinting_factor();
1463+
constauto load_flags =static_cast<FT_Int32>(flags);
1464+
1465+
FT2Font::LanguageType languages;
1466+
if (auto value = std::get_if<FT2Font::LanguageType>(&languages_or_str)) {
1467+
languages =std::move(*value);
1468+
}elseif (auto value = std::get_if<std::string>(&languages_or_str)) {
1469+
languages = std::vector<FT2Font::LanguageRange>{
1470+
FT2Font::LanguageRange{*value,0, text.size()}
1471+
};
1472+
}else {
1473+
// NOTE: this can never happen as pybind11 would have checked the type in the
1474+
// Python wrapper before calling this function, but we need to keep the
1475+
// std::get_if instead of std::get for macOS 10.12 compatibility.
1476+
throwpy::type_error("languages must be str or list of tuple");
1477+
}
1478+
1479+
std::set<FT_String*> glyph_seen_fonts;
1480+
auto glyphs = self->layout(text, load_flags, features, languages, glyph_seen_fonts);
1481+
1482+
std::set<decltype(raqm_glyph_t::cluster)> clusters;
1483+
for (auto &glyph : glyphs) {
1484+
clusters.emplace(glyph.cluster);
1485+
}
1486+
1487+
std::vector<LayoutItem> items;
1488+
1489+
double x =0.0;
1490+
double y =0.0;
1491+
std::optional<double> prev_advance = std::nullopt;
1492+
double prev_x =0.0;
1493+
for (auto &glyph : glyphs) {
1494+
auto ft_object =static_cast<PyFT2Font *>(glyph.ftface->generic.data);
1495+
1496+
ft_object->load_glyph(glyph.index, load_flags);
1497+
1498+
double prev_kern =0.0;
1499+
if (prev_advance) {
1500+
double actual_advance = (x + glyph.x_offset) - prev_x;
1501+
prev_kern = actual_advance - *prev_advance;
1502+
}
1503+
1504+
auto next = clusters.upper_bound(glyph.cluster);
1505+
auto end = (next != clusters.end()) ? *next : text.size();
1506+
auto substr = text.substr(glyph.cluster, end - glyph.cluster);
1507+
1508+
items.emplace_back(ft_object, substr, glyph.index,
1509+
(x + glyph.x_offset) /64.0, (y + glyph.y_offset) /64.0,
1510+
prev_kern /64.0);
1511+
prev_x = x + glyph.x_offset;
1512+
x += glyph.x_advance;
1513+
y += glyph.y_advance;
1514+
// Note, linearHoriAdvance is a 16.16 instead of 26.6 fixed-point value.
1515+
prev_advance = ft_object->get_face()->glyph->linearHoriAdvance /1024.0 / hinting_factor;
1516+
}
1517+
1518+
return items;
1519+
}
1520+
1521+
/**********************************************************************
1522+
* Deprecations
1523+
**/
1524+
14121525
static py::object
14131526
ft2font__getattr__(std::string name) {
14141527
auto api =py::module_::import("matplotlib._api");
@@ -1543,6 +1656,32 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
15431656
.def_property_readonly("bbox", &PyGlyph_get_bbox,
15441657
"The control box of the glyph.");
15451658

1659+
py::class_<LayoutItem>(m,"LayoutItem",py::is_final())
1660+
.def(py::init<>([]() -> LayoutItem {
1661+
// LayoutItem is not useful from Python, so mark it as not constructible.
1662+
throwstd::runtime_error("LayoutItem is not constructible");
1663+
}))
1664+
.def_readonly("ft_object", &LayoutItem::ft_object,
1665+
"The FT_Face of the item.")
1666+
.def_readonly("char", &LayoutItem::character,
1667+
"The character code for the item.")
1668+
.def_readonly("glyph_index", &LayoutItem::glyph_index,
1669+
"The glyph index for the item.")
1670+
.def_readonly("x", &LayoutItem::x,
1671+
"The x position of the item.")
1672+
.def_readonly("y", &LayoutItem::y,
1673+
"The y position of the item.")
1674+
.def_readonly("prev_kern", &LayoutItem::prev_kern,
1675+
"The kerning between this item and the previous one.")
1676+
.def("__str__",
1677+
[](const LayoutItem& item) {
1678+
return
1679+
"LayoutItem(ft_object={}, char={!r}, glyph_index={},"_s
1680+
"x={}, y={}, prev_kern={})"_s.format(
1681+
PyFT2Font_fname(item.ft_object), item.character,
1682+
item.glyph_index, item.x, item.y, item.prev_kern);
1683+
});
1684+
15461685
auto cls = py::class_<PyFT2Font>(m,"FT2Font",py::is_final(),py::buffer_protocol(),
15471686
PyFT2Font__doc__)
15481687
.def(py::init(&PyFT2Font_init),
@@ -1559,6 +1698,9 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
15591698
PyFT2Font_select_charmap__doc__)
15601699
.def("get_kerning", &PyFT2Font_get_kerning,"left"_a,"right"_a,"mode"_a,
15611700
PyFT2Font_get_kerning__doc__)
1701+
.def("_layout", &PyFT2Font_layout,"string"_a,"flags"_a,py::kw_only(),
1702+
"features"_a=nullptr,"language"_a=nullptr,
1703+
PyFT2Font_layout__doc__)
15621704
.def("set_text", &PyFT2Font_set_text,
15631705
"string"_a,"angle"_a=0.0,"flags"_a=LoadFlags::FORCE_AUTOHINT,py::kw_only(),
15641706
"features"_a=nullptr,"language"_a=nullptr,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp