Files
MementoMori/kivy/core/text/text_pango.py
thatscringebro abd15f28b6 Ajout du GUI
2022-08-08 16:31:52 -04:00

146 lines
5.6 KiB
Python

'''
Pango text provider
===================
.. versionadded:: 1.11.0
.. warning::
The low-level Pango API is experimental, and subject to change without
notice for as long as this warning is present.
Installation
------------
1. Install pangoft2 (`apt install libfreetype6-dev libpango1.0-dev
libpangoft2-1.0-0`) or ensure it is available in pkg-config
2. Recompile kivy. Check that pangoft2 is found `use_pangoft2 = 1`
3. Test it! Enforce the text core renderer to pango using environment variable:
`export KIVY_TEXT=pango`
This has been tested on OSX and Linux, Python 3.6.
Font context types for FontConfig+FreeType2 backend
---------------------------------------------------
* `system://` - `FcInitLoadConfigAndFonts()`
* `systemconfig://` - `FcInitLoadConfig()`
* `directory://<PATH>` - `FcInitLoadConfig()` + `FcAppFontAddDir()`
* `fontconfig://<PATH>` - `FcConfigCreate()` + `FcConfigParseAndLoad()`
* Any other context name - `FcConfigCreate()`
Low-level Pango access
----------------------
Since Kivy currently does its own text layout, the Label and TextInput widgets
do not take full advantage of Pango. For example, line breaks do not take
language/script into account, and switching alignment per paragraph (for bi-
directional text) is not supported. For advanced i18n requirements, we provide
a simple wrapper around PangoLayout that you can use to render text.
* https://developer.gnome.org/pango/1.40/pango-Layout-Objects.html
* https://developer.gnome.org/pango/1.40/PangoMarkupFormat.html
* See the `kivy/core/text/_text_pango.pyx` file @ `cdef class KivyPangoLayout`
for more information. Not all features of PangoLayout are implemented.
.. python::
from kivy.core.window import Window # OpenGL must be initialized
from kivy.core.text._text_pango import KivyPangoLayout
layout = KivyPangoLayout('system://')
layout.set_markup('<span font="20">Hello <b>World!</b></span>')
tex = layout.render_as_Texture()
Known limitations
-----------------
* Pango versions older than v1.38 has not been tested. It may work on
some systems with older pango and newer FontConfig/FreeType2 versions.
* Kivy's text layout is used, not Pango. This means we do not use Pango's
line-breaking feature (which is superior to Kivy's), and we can't use
Pango's bidirectional cursor helpers in TextInput.
* Font family collissions can happen. For example, if you use a `system://`
context and add a custom `Arial.ttf`, using `arial` as the `font_family`
may or may not draw with your custom font (depending on whether or not
there is already a system-wide "arial" font installed)
* Rendering is inefficient; the normal way to integrate Pango would be
using a dedicated PangoLayout per widget. This is not currently practical
due to missing abstractions in Kivy core (in the current implementation,
we have a dedicated PangoLayout *per font context,* which is rendered
once for each LayoutWord)
'''
__all__ = ('LabelPango', )
from types import MethodType
from os.path import isfile
from kivy.resources import resource_find
from kivy.core.text import LabelBase, FontContextManagerBase
from kivy.core.text._text_pango import (
KivyPangoRenderer,
kpango_get_extents,
kpango_get_ascent,
kpango_get_descent,
kpango_find_base_dir,
kpango_font_context_exists,
kpango_font_context_create,
kpango_font_context_destroy,
kpango_font_context_add_font,
kpango_font_context_list,
kpango_font_context_list_custom,
kpango_font_context_list_families)
class LabelPango(LabelBase):
_font_family_support = True
def __init__(self, *largs, **kwargs):
self.get_extents = MethodType(kpango_get_extents, self)
self.get_ascent = MethodType(kpango_get_ascent, self)
self.get_descent = MethodType(kpango_get_descent, self)
super(LabelPango, self).__init__(*largs, **kwargs)
find_base_direction = staticmethod(kpango_find_base_dir)
def _render_begin(self):
self._rdr = KivyPangoRenderer(*self._size)
def _render_text(self, text, x, y):
self._rdr.render(self, text, x, y)
def _render_end(self):
imgdata = self._rdr.get_ImageData()
del self._rdr
return imgdata
class PangoFontContextManager(FontContextManagerBase):
create = staticmethod(kpango_font_context_create)
exists = staticmethod(kpango_font_context_exists)
destroy = staticmethod(kpango_font_context_destroy)
list = staticmethod(kpango_font_context_list)
list_families = staticmethod(kpango_font_context_list_families)
list_custom = staticmethod(kpango_font_context_list_custom)
@staticmethod
def add_font(font_context, filename, autocreate=True, family=None):
if not autocreate and not PangoFontContextManager.exists(font_context):
raise Exception("FontContextManager: Attempt to add font file "
"'{}' to non-existing context '{}' without "
"autocreate.".format(filename, font_context))
if not filename:
raise Exception("FontContextManager: Cannot add empty font file")
if not isfile(filename):
filename = resource_find(filename)
if not isfile(filename):
if not filename.endswith('.ttf'):
filename = resource_find('{}.ttf'.format(filename))
if filename and isfile(filename):
return kpango_font_context_add_font(font_context, filename)
raise Exception("FontContextManager: Attempt to add non-existent "
"font file: '{}' to context '{}'"
.format(filename, font_context))