@@ -499,6 +499,7 @@ PyFT2Font_init(py::object filename, long hinting_factor = 8,
499499
500500 self->x = new FT2Font (open_args, hinting_factor, fallback_fonts, ft_glyph_warn,
501501 warn_if_used);
502+ self->x ->set_parent (self);
502503
503504 self->x ->set_kerning_factor (kerning_factor);
504505
@@ -1471,6 +1472,81 @@ PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
14711472 return indices;
14721473}
14731474
1475+ /* *********************************************************************
1476+ * Layout items
1477+ * */
1478+
1479+ struct LayoutItem {
1480+ PyFT2Font *ft_object;
1481+ std::u32string character;
1482+ int glyph_idx;
1483+ double x;
1484+ double y;
1485+ double prev_kern;
1486+
1487+ LayoutItem (PyFT2Font *f, std::u32string c, int i, double x, double y, double k) :
1488+ ft_object (f), character(c), glyph_idx(i), x(x), y(y), prev_kern(k) {}
1489+
1490+ std::string to_string ()
1491+ {
1492+ std::ostringstream out;
1493+ out << " LayoutItem(ft_object=" << PyFT2Font_fname (ft_object);
1494+ out << " , char=" << character[0 ];
1495+ out << " , glyph_idx=" << glyph_idx;
1496+ out << " , x=" << x;
1497+ out << " , y=" << y;
1498+ out << " , prev_kern=" << prev_kern;
1499+ out << " )" ;
1500+ return out.str ();
1501+ }
1502+ };
1503+
1504+ const char *PyFT2Font_layout__doc__ = R"""(
1505+ Layout a string and yield information about each used glyph.
1506+
1507+ .. warning::
1508+ This API uses the fallback list and is both private and provisional: do not use
1509+ it directly.
1510+
1511+ Parameters
1512+ ----------
1513+ text : str
1514+ The characters for which to find fonts.
1515+
1516+ Returns
1517+ -------
1518+ list[LayoutItem]
1519+ )""" ;
1520+
1521+ static auto
1522+ PyFT2Font_layout (PyFT2Font *self, std::u32string text, LoadFlags flags)
1523+ {
1524+ auto load_flags = static_cast <FT_Int32>(flags);
1525+
1526+ std::set<FT_String*> glyph_seen_fonts;
1527+ std::vector<raqm_glyph_t > glyphs;
1528+ self->x ->layout (text, load_flags, glyph_seen_fonts, glyphs);
1529+
1530+ std::vector<LayoutItem> items;
1531+
1532+ double x = 0.0 ;
1533+ double y = 0.0 ;
1534+ for (auto &glyph : glyphs) {
1535+ auto ft_object = static_cast <FT2Font *>(glyph.ftface ->generic .data );
1536+ auto pyft_object = static_cast <PyFT2Font *>(ft_object->get_parent ());
1537+ items.emplace_back (pyft_object, text.substr (glyph.cluster , 1 ), glyph.index ,
1538+ (x + glyph.x_offset ) / 64 , (y + glyph.y_offset ) / 64 , 0 );
1539+ x += glyph.x_advance ;
1540+ y += glyph.y_advance ;
1541+ }
1542+
1543+ return items;
1544+ }
1545+
1546+ /* *********************************************************************
1547+ * Deprecations
1548+ * */
1549+
14741550static py::object
14751551ft2font__getattr__ (std::string name) {
14761552 auto api = py::module_::import (" matplotlib._api" );
@@ -1601,6 +1677,21 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16011677 .def_property_readonly (" bbox" , &PyGlyph_get_bbox,
16021678 " The control box of the glyph." );
16031679
1680+ py::class_<LayoutItem>(m, " LayoutItem" , py::is_final ())
1681+ .def_readonly (" ft_object" , &LayoutItem::ft_object,
1682+ " The FT_Face of the item." )
1683+ .def_readonly (" char" , &LayoutItem::character,
1684+ " The character code for the item." )
1685+ .def_readonly (" glyph_idx" , &LayoutItem::glyph_idx,
1686+ " The glyph index for the item." )
1687+ .def_readonly (" x" , &LayoutItem::x,
1688+ " The x position of the item." )
1689+ .def_readonly (" y" , &LayoutItem::y,
1690+ " The y position of the item." )
1691+ .def_readonly (" prev_kern" , &LayoutItem::prev_kern,
1692+ " The kerning between this item and the previous one." )
1693+ .def (" __str__" , &LayoutItem::to_string);
1694+
16041695 py::class_<PyFT2Font>(m, " FT2Font" , py::is_final (), py::buffer_protocol (),
16051696 PyFT2Font__doc__)
16061697 .def (py::init (&PyFT2Font_init),
@@ -1617,6 +1708,8 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
16171708 PyFT2Font_select_charmap__doc__)
16181709 .def (" get_kerning" , &PyFT2Font_get_kerning, " left" _a, " right" _a, " mode" _a,
16191710 PyFT2Font_get_kerning__doc__)
1711+ .def (" _layout" , &PyFT2Font_layout, " string" _a, " flags" _a,
1712+ PyFT2Font_layout__doc__)
16201713 .def (" set_text" , &PyFT2Font_set_text,
16211714 " string" _a, " angle" _a=0.0 , " flags" _a=LoadFlags::FORCE_AUTOHINT,
16221715 PyFT2Font_set_text__doc__)
0 commit comments