mirror of https://github.com/kivy/kivy.git
Pango text provider: Initial commit
This commit is contained in:
parent
8841927f64
commit
f1835deacf
|
@ -22,6 +22,7 @@ examples/*/bin
|
|||
examples/*/.buildozer
|
||||
kivy/*.c
|
||||
kivy/*.pyd
|
||||
kivy/core/text/_text_pango.c
|
||||
kivy/core/text/text_layout.c
|
||||
kivy/core/text/text_layout.pyd
|
||||
kivy/core/window/window_info.c
|
||||
|
|
|
@ -778,6 +778,9 @@ class LabelBase(object):
|
|||
|
||||
# Load the appropriate provider
|
||||
label_libs = []
|
||||
if platform in ('linux', ):
|
||||
label_libs += [('pango', 'text_pango', 'LabelPango')]
|
||||
|
||||
if USE_SDL2:
|
||||
label_libs += [('sdl2', 'text_sdl2', 'LabelSDL2')]
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
# NOTE: We could probably use a single global FcConfig, but it's not obvious
|
||||
# how since adding a font doesn't give you back something that can be directly
|
||||
# used to render with. Apparently you must look it up via a font description.
|
||||
# Where do you get that from? I don't know... maybe FcConfigGetFonts then
|
||||
# pango_fc_font_description_from_pattern(), somehow?
|
||||
#
|
||||
# The current implementation uses pango_fc_font_map_set_config() to force the
|
||||
# loaded TTF to be used, seems to work. As far as I can tell alternative is:
|
||||
#
|
||||
# cdef FcConfig *oldconfig = FcConfigGetCurrent()
|
||||
# FcConfigSetCurrent(context.fc_config)
|
||||
# <-- render -->
|
||||
# FcConfigSetCurrent(oldconfig)
|
||||
#
|
||||
|
||||
cimport cython
|
||||
from libc.stdint cimport uint32_t
|
||||
from libc.string cimport memset
|
||||
from cpython.mem cimport PyMem_Malloc, PyMem_Free
|
||||
|
||||
include "../../lib/pangoft2.pxi"
|
||||
from kivy.logger import Logger
|
||||
from kivy.core.image import ImageData
|
||||
|
||||
# Cached contexts; dict key + list value is font filename ("font_name_r")
|
||||
# Dict values are ContextContainer instances, one for each font.
|
||||
cdef dict kivy_pango_cache = {}
|
||||
cdef list kivy_pango_cache_order = []
|
||||
|
||||
# Map text direction to pango constant - neutral is considered auto, anything
|
||||
# else will call pango_layout_set_auto_dir(the_layout, FALSE)
|
||||
cdef dict kivy_pango_text_direction = {
|
||||
'ltr': PANGO_DIRECTION_LTR,
|
||||
'rtl': PANGO_DIRECTION_RTL,
|
||||
'weak_ltr': PANGO_DIRECTION_WEAK_LTR,
|
||||
'weak_rtl': PANGO_DIRECTION_WEAK_RTL,
|
||||
'neutral': PANGO_DIRECTION_NEUTRAL,
|
||||
'auto': PANGO_DIRECTION_NEUTRAL}
|
||||
|
||||
|
||||
# Fontconfig and pango structures (one per loaded font). Can't use
|
||||
# ctypedef struct here, because that won't fit in the cache dict
|
||||
cdef class ContextContainer:
|
||||
cdef PangoContext *context
|
||||
cdef PangoFontMap *fontmap
|
||||
cdef PangoFontDescription *fontdesc
|
||||
cdef PangoLayout *layout
|
||||
cdef FcConfig *fc_config
|
||||
|
||||
# Called explicitly on malloc fail to release as fast as possible
|
||||
# Note: calling a method from __dealloc__ can lead to revived object
|
||||
def __dealloc__(self):
|
||||
if self.fontdesc:
|
||||
pango_font_description_free(self.fontdesc)
|
||||
if self.layout:
|
||||
g_object_unref(self.layout)
|
||||
if self.context:
|
||||
g_object_unref(self.context)
|
||||
if self.fontmap:
|
||||
g_object_unref(self.fontmap)
|
||||
if self.fc_config:
|
||||
FcConfigDestroy(self.fc_config)
|
||||
|
||||
|
||||
# Add a contextcontainer to cache + keep max 64 open fonts
|
||||
cdef inline _add_pango_cache(unicode fontid, ContextContainer cc):
|
||||
global kivy_pango_cache, kivy_pango_cache_order
|
||||
|
||||
cdef unicode popid
|
||||
while len(kivy_pango_cache_order) >= 64:
|
||||
popid = kivy_pango_cache_order.pop(0)
|
||||
del kivy_pango_cache[popid]
|
||||
|
||||
kivy_pango_cache[fontid] = cc
|
||||
kivy_pango_cache_order.append(fontid)
|
||||
|
||||
|
||||
# NOTE: for future, this applies to font selection, irrelevant with one font
|
||||
#cdef _configure_pattern_destroy_data(gpointer data):
|
||||
# print("_configure_pattern_destroy_data()!")
|
||||
|
||||
#cdef _configure_pattern_callback(FcPattern *pattern, gpointer data):
|
||||
# cdef unsigned int flags = GPOINTER_TO_UINT(data)
|
||||
# print("_configure_pattern_callback()!")
|
||||
# FcPatternDel(pattern, FC_HINTING)
|
||||
# FcPatternAddBool(pattern, FC_HINTING, ...)
|
||||
# FcPatternDel(pattern, FC_AUTOHINT)
|
||||
# FcPatternAddBool(pattern, FC_AUTOHINT, ...)
|
||||
# FcPatternDel(pattern, FC_HINT_STYLE)
|
||||
# FcPatternAddInteger(pattern, FC_HINT_STYLE, ...)
|
||||
# FcPatternDel(pattern, FC_ANTIALIAS)
|
||||
# FcPatternAddBool(pattern, FC_ANTIALIAS, ...)
|
||||
|
||||
|
||||
# Creates a ContextContainer for the font_name_r of the label
|
||||
cdef _get_context_container(kivylabel):
|
||||
global kivy_pango_text_direction
|
||||
cdef dict options = kivylabel.options
|
||||
cdef unicode fontid = <unicode>options['font_name_r']
|
||||
if fontid in kivy_pango_cache:
|
||||
return kivy_pango_cache.get(fontid)
|
||||
|
||||
# Creat a new context
|
||||
cdef ContextContainer cc = ContextContainer()
|
||||
|
||||
# Create blank FcConfig (fontconfig), and load the TTF file
|
||||
cc.fc_config = FcConfigCreate()
|
||||
cdef bytes filename = options['font_name_r'].encode('UTF-8')
|
||||
if FcConfigAppFontAddFile(cc.fc_config, <FcChar8 *>filename) == FcFalse:
|
||||
Logger.warn("_text_pango: Error loadinging font '{}'".format(filename))
|
||||
cc.__dealloc__()
|
||||
return
|
||||
|
||||
# Create a blank font map and assign the config from above (one TTF file)
|
||||
cc.fontmap = pango_ft2_font_map_new()
|
||||
if not cc.fontmap:
|
||||
Logger.warn("_text_pango: Could not create new font map")
|
||||
cc.__dealloc__()
|
||||
return
|
||||
pango_fc_font_map_set_config(PANGO_FC_FONT_MAP(cc.fontmap), cc.fc_config)
|
||||
|
||||
# FIXME: should we configure this?
|
||||
#pango_ft2_font_map_set_resolution(cc.fontmap, n, n)
|
||||
|
||||
# FIXME: This may become relevant, leaving for now
|
||||
#cc.callback_data_ptr = GUINT_TO_POINTER(flags)
|
||||
#pango_ft2_font_map_set_default_substitute(
|
||||
# PANGO_FT2_FONT_MAP(cc.fontmap),
|
||||
# &_configure_pattern_callback,
|
||||
# cc.callback_data_ptr,
|
||||
# &_configure_pattern_destroy_data)
|
||||
|
||||
# Finally create our pango context from the fontmap
|
||||
cc.context = pango_font_map_create_context(cc.fontmap)
|
||||
if not cc.context:
|
||||
Logger.warn("_text_pango: Could not create pango context")
|
||||
cc.__dealloc__()
|
||||
return
|
||||
|
||||
# Configure the context's base direction. If user specified something
|
||||
# explicit, force it. Otherwise (auto/neutral), let pango decide.
|
||||
# FIXME: add text_direction externally so it's available.
|
||||
cdef PangoDirection text_dir = kivy_pango_text_direction.get(
|
||||
options.get('text_direction', 'neutral'), PANGO_DIRECTION_NEUTRAL)
|
||||
pango_context_set_base_dir(cc.context, text_dir)
|
||||
|
||||
# Create layout from context
|
||||
cc.layout = pango_layout_new(cc.context)
|
||||
if not cc.layout:
|
||||
Logger.warn("_text_pango: Could not create pango layout")
|
||||
cc.__dealloc__()
|
||||
return
|
||||
|
||||
# If autodir is false, the context's base direction is used (set above)
|
||||
if text_dir == PANGO_DIRECTION_NEUTRAL:
|
||||
pango_layout_set_auto_dir(cc.layout, TRUE)
|
||||
else:
|
||||
pango_layout_set_auto_dir(cc.layout, FALSE)
|
||||
|
||||
# The actual font size is specified in pango markup, and the
|
||||
# actual font is whatever TTF is loaded in this context. This
|
||||
# may not be needed at all.
|
||||
cc.fontdesc = pango_font_description_from_string("Arial")
|
||||
pango_layout_set_font_description(cc.layout, cc.fontdesc)
|
||||
|
||||
# FIXME: does this need to change w/label settings?
|
||||
pango_layout_set_alignment(cc.layout, PANGO_ALIGN_LEFT)
|
||||
#pango_layout_set_spacing(cc.layout, n)
|
||||
|
||||
_add_pango_cache(fontid, cc)
|
||||
return cc
|
||||
|
||||
|
||||
# Renders the pango layout to a grayscale bitmap, and blits RGBA at x, y
|
||||
cdef _render_context(ContextContainer cc, unsigned char *dstbuf,
|
||||
int x, int y, int final_w, int final_h,
|
||||
unsigned char textcolor[]):
|
||||
if not dstbuf or final_w == 0 or final_h == 0 or x > final_w or y > final_h:
|
||||
Logger.warn('_text_pango: Invalid blit: final={}x{} x={} y={}'
|
||||
.format(final_w, final_h, x, y))
|
||||
return
|
||||
|
||||
# Note, w/h refers to the current subimage size, final_w/h is end result
|
||||
cdef int w, h
|
||||
pango_layout_get_pixel_size(cc.layout, &w, &h)
|
||||
if w == 0 or h == 0 or x + w > final_w or y + h > final_h:
|
||||
Logger.warn('_text_pango: Invalid blit: final={}x{} x={} y={} w={} h={}'
|
||||
.format(final_w, final_h, x, y, w, h))
|
||||
return
|
||||
|
||||
cdef FT_Bitmap bitmap
|
||||
cdef int xi, yi
|
||||
cdef unsigned char graysrc
|
||||
cdef unsigned long grayidx
|
||||
cdef unsigned long yi_w
|
||||
cdef unsigned long offset
|
||||
cdef unsigned long offset_fixed = x + (y * final_w)
|
||||
cdef unsigned long offset_yi = final_w - w
|
||||
cdef unsigned long maxpos = final_w * final_h
|
||||
with nogil:
|
||||
# Prepare ft2 bitmap for pango's grayscale data
|
||||
FT_Bitmap_Init(&bitmap)
|
||||
bitmap.width = w
|
||||
bitmap.rows = h
|
||||
bitmap.pitch = w # 1-byte grayscale
|
||||
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY # no BGRA in pango (ft2 has it)
|
||||
bitmap.num_grays = 256
|
||||
bitmap.buffer = <unsigned char *>g_malloc0(w * h)
|
||||
if not bitmap.buffer:
|
||||
with gil:
|
||||
Logger.warn('_text_pango: Could not malloc FT_Bitmap.buffer')
|
||||
return
|
||||
|
||||
# Render the layout as 1 byte per pixel grayscale bitmap
|
||||
# FIXME: does render_layout_subpixel() do us any good?
|
||||
pango_ft2_render_layout(&bitmap, cc.layout, 0, 0)
|
||||
|
||||
# Blit the bitmap as RGBA at x, y in dstbuf (w/h is the ft2 bitmap)
|
||||
for yi in range(0, h):
|
||||
offset = offset_fixed + (yi * offset_yi)
|
||||
yi_w = yi * w
|
||||
if offset + yi_w + w - 1 > maxpos:
|
||||
with gil:
|
||||
Logger.warn('_text_pango: OOB blit: yi={} final={}x{} '
|
||||
'x={} y={} w={} h={} maxpos={}'.format(
|
||||
yi, final_w, final_h, x, y, w, h, maxpos))
|
||||
break
|
||||
|
||||
# FIXME: Handle big endian - either use variable shifts here, or
|
||||
# return as abgr + handle elsewhere
|
||||
for xi in range(0, w):
|
||||
grayidx = yi_w + xi
|
||||
graysrc = (bitmap.buffer)[grayidx]
|
||||
(<uint32_t *>dstbuf)[offset + grayidx] = (
|
||||
<int>(((textcolor[0] * graysrc) / 255)) |
|
||||
<int>(((textcolor[1] * graysrc) / 255) << 8) |
|
||||
<int>(((textcolor[2] * graysrc) / 255) << 16) |
|
||||
<int>(((textcolor[3] * graysrc) / 255) << 24) )
|
||||
g_free(bitmap.buffer)
|
||||
# /nogil blit
|
||||
|
||||
|
||||
cdef class KivyPangoRenderer:
|
||||
# w, h is the final bitmap size, drawn by 1+ render() calls in *pixels
|
||||
cdef int w, h, canary
|
||||
cdef unsigned char *pixels
|
||||
|
||||
def __cinit__(self, int w, int h):
|
||||
self.canary = 1
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.pixels = <unsigned char *>PyMem_Malloc(w * h * 4)
|
||||
if self.pixels:
|
||||
memset(self.pixels, 0, w * h * 4)
|
||||
|
||||
# Kivy's markup system breaks labels down to smaller chunks and render
|
||||
# separately. In that case, we get several calls to render() with misc
|
||||
# options and x/y positions. End result is stored in self.pixels.
|
||||
def render(self, kivylabel, text, x, y):
|
||||
if not self.pixels:
|
||||
Logger.warn('_text_pango: render() called, but self.pixels is NULL')
|
||||
return
|
||||
cdef ContextContainer cc = _get_context_container(kivylabel)
|
||||
if not cc:
|
||||
Logger.warn('_text_pango: Could not get context container, aborting')
|
||||
return
|
||||
|
||||
# Set markup, this could use kivylabel.options + attrs
|
||||
markup = <bytes>text.encode('UTF-8')
|
||||
pango_layout_set_markup(cc.layout, markup, len(markup))
|
||||
|
||||
# Kivy normalized text color -> 0-255 rgba
|
||||
cdef unsigned char textcolor[4]
|
||||
textcolor[:] = [ min(255, int(c * 255)) for c in kivylabel.options['color'] ]
|
||||
|
||||
# Finally render the layout and blit it to self.pixels
|
||||
_render_context(cc, self.pixels, x, y, self.w, self.h, textcolor)
|
||||
self.canary = 0
|
||||
|
||||
# Return ImageData instance with the rendered pixels
|
||||
def get_ImageData(self):
|
||||
if not self.pixels:
|
||||
Logger.warn('_text_pango: get_ImageData() self.pixels == NULL')
|
||||
return
|
||||
|
||||
if self.canary:
|
||||
Logger.warn("_text_pango: Dead canary in get_ImageData()")
|
||||
return
|
||||
self.canary = 1
|
||||
|
||||
try:
|
||||
b_pixels = <bytes>self.pixels[:self.w * self.h * 4]
|
||||
return ImageData(self.w, self.h, 'rgba', b_pixels)
|
||||
finally:
|
||||
PyMem_Free(self.pixels)
|
||||
|
||||
|
||||
def kpango_get_extents(kivylabel, text):
|
||||
cdef ContextContainer cc = _get_context_container(kivylabel)
|
||||
cdef int w, h
|
||||
if not cc:
|
||||
Logger.warn('_text_pango: Could not get container for extents: {}'
|
||||
.format(kivylabel.options['font_name_r']))
|
||||
return 0, 0
|
||||
|
||||
markup = <bytes>text.encode('UTF-8')
|
||||
pango_layout_set_markup(cc.layout, markup, len(markup))
|
||||
pango_layout_get_pixel_size(cc.layout, &w, &h)
|
||||
return w, h
|
||||
|
||||
|
||||
def kpango_get_ascent(kivylabel):
|
||||
cdef ContextContainer cc = _get_context_container(kivylabel)
|
||||
if not cc:
|
||||
Logger.warn('_text_pango: Could not get container for ascent: {}'
|
||||
.format(kivylabel.options['font_name_r']))
|
||||
return 0
|
||||
|
||||
# FIXME: pango_language_from_string(kivylabel.text_language)
|
||||
cdef PangoFontMetrics *fm = pango_context_get_metrics(
|
||||
cc.context, cc.fontdesc, pango_language_get_default())
|
||||
try:
|
||||
return <double>(pango_font_metrics_get_ascent(fm) / PANGO_SCALE)
|
||||
finally:
|
||||
pango_font_metrics_unref(fm)
|
||||
|
||||
|
||||
def kpango_get_descent(kivylabel):
|
||||
cdef ContextContainer cc = _get_context_container(kivylabel)
|
||||
if not cc:
|
||||
Logger.warn('_text_pango: Could not get container for decent: {}'
|
||||
.format(kivylabel.options['font_name_r']))
|
||||
return 0
|
||||
|
||||
# FIXME: pango_language_from_string(kivylabel.text_language)
|
||||
cdef PangoFontMetrics *fm = pango_context_get_metrics(
|
||||
cc.context, cc.fontdesc, pango_language_get_default())
|
||||
try:
|
||||
return <double>(pango_font_metrics_get_descent(fm) / PANGO_SCALE)
|
||||
finally:
|
||||
pango_font_metrics_unref(fm)
|
|
@ -0,0 +1,63 @@
|
|||
'''
|
||||
Pango text provider
|
||||
===================
|
||||
|
||||
'''
|
||||
|
||||
__all__ = ('LabelPango', )
|
||||
|
||||
from kivy.compat import PY2
|
||||
from kivy.core.text import LabelBase
|
||||
from kivy.core.text._text_pango import (KivyPangoRenderer, kpango_get_extents,
|
||||
kpango_get_ascent, kpango_get_descent)
|
||||
|
||||
|
||||
class LabelPango(LabelBase):
|
||||
|
||||
# This is a hack to avoid dealing with glib attrs to configure layout,
|
||||
# we just create markup out of the options and let pango set attrs
|
||||
def _pango_markup(self, text):
|
||||
markup = text.replace('<', '<').replace('>', '>')
|
||||
options = self.options
|
||||
tags = []
|
||||
if options['bold']:
|
||||
markup = '<b>{}</b>'.format(markup)
|
||||
if options['underline']:
|
||||
markup = '<u>{}</u>'.format(markup)
|
||||
if options['strikethrough']:
|
||||
markup = '<s>{}</s>'.format(markup)
|
||||
if options['font_hinting'] == 'mono':
|
||||
markup = '<tt>{}</tt>'.format(markup)
|
||||
|
||||
# FIXME: does this do the right thing? .. don't see much w/roboto
|
||||
weight_attr = ''
|
||||
if options['font_hinting'] in ('light', 'normal'):
|
||||
weight_attr = ' weight="{}"'.format(options['font_hinting'])
|
||||
|
||||
return b'<span font="{}"{}>{}</span>'.format(
|
||||
int(self.options['font_size']),
|
||||
weight_attr,
|
||||
markup)
|
||||
|
||||
def get_extents(self, text):
|
||||
if not text:
|
||||
return (0, 0)
|
||||
w, h = kpango_get_extents(self, self._pango_markup(text))
|
||||
return (w, h)
|
||||
|
||||
def get_ascent(self):
|
||||
return kpango_get_ascent(self)
|
||||
|
||||
def get_descent(self):
|
||||
return kpango_get_descent(self)
|
||||
|
||||
def _render_begin(self):
|
||||
self._rdr = KivyPangoRenderer(self._size[0], self._size[1])
|
||||
|
||||
def _render_text(self, text, x, y):
|
||||
self._rdr.render(self, self._pango_markup(text), x, y)
|
||||
|
||||
def _render_end(self):
|
||||
imgdata = self._rdr.get_ImageData()
|
||||
del self._rdr
|
||||
return imgdata
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef KIVY_PANGOFT2_HEADER
|
||||
#define KIVY_PANGOFT2_HEADER
|
||||
|
||||
// FreeType2 headers must be included via macros in ft2build.h
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_BITMAP_H
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
cdef extern from "glib.h" nogil:
|
||||
ctypedef void *gpointer
|
||||
ctypedef int gint
|
||||
ctypedef unsigned int guint
|
||||
ctypedef unsigned long gsize
|
||||
ctypedef gint gboolean
|
||||
gboolean TRUE
|
||||
gboolean FALSE
|
||||
|
||||
void *g_malloc(gsize n_bytes)
|
||||
void *g_malloc0(gsize n_bytes)
|
||||
void g_free(gpointer mem)
|
||||
void g_object_unref(gpointer obj)
|
||||
# gpointer GUINT_TO_POINTER(guint u)
|
||||
# guint GPOINTER_TO_UINT(gpointer p)
|
||||
|
||||
|
||||
# https://www.freetype.org/freetype2/docs/reference/ft2-index.html
|
||||
cdef extern from "../../lib/pangoft2.h" nogil:
|
||||
ctypedef struct FT_Library:
|
||||
pass
|
||||
|
||||
ctypedef enum FT_Pixel_Mode:
|
||||
FT_PIXEL_MODE_NONE = 0
|
||||
FT_PIXEL_MODE_MONO
|
||||
FT_PIXEL_MODE_GRAY
|
||||
FT_PIXEL_MODE_GRAY2
|
||||
FT_PIXEL_MODE_GRAY4
|
||||
FT_PIXEL_MODE_LCD
|
||||
FT_PIXEL_MODE_LCD_V
|
||||
FT_PIXEL_MODE_BGRA
|
||||
FT_PIXEL_MODE_MAX
|
||||
|
||||
ctypedef struct FT_Bitmap:
|
||||
unsigned int rows
|
||||
unsigned int width
|
||||
int pitch
|
||||
unsigned char* buffer
|
||||
unsigned short num_grays
|
||||
unsigned char pixel_mode
|
||||
unsigned char palette_mode
|
||||
void* palette
|
||||
|
||||
void FT_Bitmap_Init(FT_Bitmap *bitmap)
|
||||
void FT_Bitmap_Done(FT_Library library, FT_Bitmap *bitmap)
|
||||
|
||||
|
||||
# https://www.freedesktop.org/software/fontconfig/fontconfig-devel/t1.html
|
||||
cdef extern from "fontconfig/fontconfig.h" nogil:
|
||||
ctypedef struct FcConfig:
|
||||
pass
|
||||
ctypedef struct FcPattern:
|
||||
pass
|
||||
# ctypedef struct FcFontSet:
|
||||
# int nfont
|
||||
# int sfont
|
||||
# FcPattern **fonts
|
||||
|
||||
ctypedef bint FcBool
|
||||
ctypedef unsigned char FcChar8
|
||||
bint FcTrue
|
||||
bint FcFalse
|
||||
|
||||
FcConfig *FcConfigCreate()
|
||||
void FcConfigDestroy(FcConfig *config)
|
||||
FcConfig *FcConfigGetCurrent()
|
||||
FcBool FcConfigSetCurrent(FcConfig *config)
|
||||
FcBool FcConfigAppFontAddFile(FcConfig *config, const FcChar8 *file)
|
||||
|
||||
# FcPattern *FcPatternCreate()
|
||||
# void FcPatternDestroy(FcPattern *p)
|
||||
# FcBool FcPatternDel(FcPattern *p, const char *object)
|
||||
# FcBool FcPatternAddInteger (FcPattern *p, const char *object, int i)
|
||||
# FcBool FcPatternAddDouble (FcPattern *p, const char *object, double d)
|
||||
# FcBool FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
|
||||
# FcBool FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *m)
|
||||
# FcBool FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
|
||||
# FcBool FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
|
||||
# FcBool FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Facef)
|
||||
# FcBool FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *l)
|
||||
# FcBool FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Glyph-Storage.html
|
||||
cdef extern from "pango/pango-types.h" nogil:
|
||||
# ctypedef struct PangoRectangle:
|
||||
# int x
|
||||
# int y
|
||||
# int width
|
||||
# int height
|
||||
unsigned int PANGO_SCALE
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Scripts-and-Languages.html
|
||||
cdef extern from "pango/pango-language.h" nogil:
|
||||
ctypedef struct PangoLanguage:
|
||||
pass
|
||||
|
||||
PangoLanguage *pango_language_get_default()
|
||||
PangoLanguage *pango_language_from_string(const char *language)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-FreeType-Fonts-and-Rendering.html
|
||||
cdef extern from "pango/pangoft2.h" nogil:
|
||||
ctypedef struct PangoFT2FontMap:
|
||||
pass
|
||||
ctypedef void *PangoFT2SubstituteFunc
|
||||
ctypedef void *GDestroyNotify
|
||||
|
||||
PangoFT2FontMap *PANGO_FT2_FONT_MAP(PangoFontMap *fontmap)
|
||||
void pango_ft2_render_layout(FT_Bitmap *bitmap, PangoLayout *layout, int x, int y)
|
||||
void pango_ft2_render_layout_subpixel(FT_Bitmap *bitmap, PangoLayout *layout, int x, int y)
|
||||
void pango_ft2_font_map_set_default_substitute(PangoFT2FontMap *fontmap, PangoFT2SubstituteFunc func, gpointer data, GDestroyNotify notify)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Text-Processing.html
|
||||
cdef extern from "pango/pango-context.h" nogil:
|
||||
ctypedef struct PangoContext:
|
||||
pass
|
||||
|
||||
void pango_context_set_base_dir(PangoContext *context, PangoDirection direction)
|
||||
PangoFontMetrics *pango_context_get_metrics(PangoContext *context, const PangoFontDescription *desc, PangoLanguage *language)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Bidirectional-Text.html
|
||||
cdef extern from "pango/pango-bidi-type.h" nogil:
|
||||
ctypedef enum PangoDirection:
|
||||
PANGO_DIRECTION_LTR
|
||||
PANGO_DIRECTION_RTL
|
||||
PANGO_DIRECTION_TTB_LTR # deprecated
|
||||
PANGO_DIRECTION_TTB_RTL # deprecated
|
||||
PANGO_DIRECTION_WEAK_LTR
|
||||
PANGO_DIRECTION_WEAK_RTL
|
||||
PANGO_DIRECTION_NEUTRAL
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Fonts.html
|
||||
cdef extern from "pango/pango-font.h" nogil:
|
||||
ctypedef struct PangoFontMap:
|
||||
pass
|
||||
ctypedef struct PangoFontDescription:
|
||||
pass
|
||||
ctypedef struct PangoFontMetrics:
|
||||
pass
|
||||
|
||||
PangoFontDescription* pango_font_description_from_string(const char *string)
|
||||
void pango_font_description_free(PangoFontDescription *desc)
|
||||
# void pango_font_description_set_size(PangoFontDescription *desc, gint size)
|
||||
PangoContext *pango_font_map_create_context(PangoFontMap *fontmap)
|
||||
PangoFontMap *pango_ft2_font_map_new()
|
||||
int pango_font_metrics_get_ascent(PangoFontMetrics *metrics)
|
||||
int pango_font_metrics_get_descent(PangoFontMetrics *metrics)
|
||||
void pango_font_metrics_unref(PangoFontMetrics *metrics)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/PangoFcFontMap.html
|
||||
cdef extern from "pango/pangofc-fontmap.h" nogil:
|
||||
ctypedef struct PangoFcFontMap:
|
||||
pass
|
||||
|
||||
PangoFcFontMap *PANGO_FC_FONT_MAP(PangoFontMap *fontmap)
|
||||
void pango_fc_font_map_set_config(PangoFcFontMap *fontmap, FcConfig *config)
|
||||
|
||||
|
||||
# https://developer.gnome.org/pango/stable/pango-Layout-Objects.html
|
||||
cdef extern from "pango/pango-layout.h" nogil:
|
||||
ctypedef struct PangoLayout:
|
||||
pass
|
||||
|
||||
ctypedef enum PangoAlignment:
|
||||
PANGO_ALIGN_LEFT
|
||||
PANGO_ALIGN_CENTER
|
||||
PANGO_ALIGN_RIGHT
|
||||
|
||||
PangoLayout *pango_layout_new(PangoContext *context)
|
||||
void pango_layout_get_pixel_size(PangoLayout *layout, int *width, int *height)
|
||||
void pango_layout_get_size(PangoLayout *layout, int *width, int *height)
|
||||
void pango_layout_set_alignment(PangoLayout *layout, PangoAlignment alignment)
|
||||
void pango_layout_set_auto_dir(PangoLayout *layout, gboolean auto_dir)
|
||||
void pango_layout_set_markup(PangoLayout *layout, const char *markup, int length)
|
||||
void pango_layout_set_font_description(PangoLayout *layout, const PangoFontDescription *desc)
|
||||
void pango_layout_set_text(PangoLayout *layout, const char *text, int length)
|
||||
void pango_layout_set_width(PangoLayout *layout, int width)
|
||||
void pango_layout_set_height(PangoLayout *layout, int height)
|
||||
void pango_layout_set_spacing(PangoLayout *layout, int spacing)
|
||||
|
8
setup.py
8
setup.py
|
@ -811,11 +811,19 @@ if c_options['use_sdl2'] and sdl2_flags:
|
|||
for source_file in ('core/window/_window_sdl2.pyx',
|
||||
'core/image/_img_sdl2.pyx',
|
||||
'core/text/_text_sdl2.pyx',
|
||||
'core/text/_text_pango.pyx',
|
||||
'core/audio/audio_sdl2.pyx',
|
||||
'core/clipboard/_clipboard_sdl2.pyx'):
|
||||
sources[source_file] = merge(
|
||||
base_flags, sdl2_flags, sdl2_depends)
|
||||
|
||||
pango_flags = pkgconfig('pangoft2')
|
||||
if pango_flags:
|
||||
pango_depends = {'depends': ['lib/pangoft2.pxi',
|
||||
'lib/pangoft2.h']}
|
||||
sources['core/text/_text_pango.pyx'] = merge(
|
||||
base_flags, pango_flags, pango_depends)
|
||||
|
||||
if platform in ('darwin', 'ios'):
|
||||
# activate ImageIO provider for our core image
|
||||
if platform == 'ios':
|
||||
|
|
Loading…
Reference in New Issue