leifgehrmann / pangocffi Goto Github PK
View Code? Open in Web Editor NEWCFFI-based pango bindings for Python.
Home Page: https://pangocffi.readthedocs.io
License: GNU Lesser General Public License v2.1
CFFI-based pango bindings for Python.
Home Page: https://pangocffi.readthedocs.io
License: GNU Lesser General Public License v2.1
Hi again,
In order to get a particular font and attach it to the layout, I am doing currently this:
font_description_pointer = pangocairo.font_map.pango.pango_font_description_from_string(
b"Steradian Extralight 25"
)
font_description = pango.FontDescription.from_pointer(font_description_pointer)
and then passing the font_description
to a layout
layout.set_font_description(font_description)
A couple of question:
font_description_pointer
after this? Is this garbage collected or should I free it explicitly?Thank you for your time.
I would like to specify exactly what should be the binary to load and not search using ctypes.util.find_library()
because each time I need to manipulate my PATH variable for this. I would like to a variable PANGO_LOCATION or something similar where I can specify the DLL file to load. This will make sure that there is no python crash because of wrong DLL being loaded. Also, I would use it in Manim so that there is no crash, caused so many issues. If this looks ok then I will make a PR. This would help prevent DLL HELL.
Same for pangocairocffi
and cairocffi
also.
Thanks.
hey! first of all, thanks for creating this library, it's been really useful lately.
while using the various interfaces, i noticed that a lot of them use get_...()
and set_...()
methods. this is fine, and it makes sense considering the underlying C API, but, IMO, it would be much more pythonic if the library used property()
instead. something like this:
class Layout(object):
def set_text(...):
def get_text(...):
could be turned into this, which would simplify the usage and documentation a lot:
class Layout(object):
def _get_text(...):
def _set_text(...):
text = property(_get_text, _set_text)
i also see that a lot of the classes use the @property
decorator instead of the function, which is fine:
class Layout(object):
@property text
def get_text(...):
@text.setter
def set_text(...):
it would be much better if either one of these was (consistently) used across all classes, not just some.
of course, if this change was to be implemented we'd have to keep the original getters/setters for back-compat (unless it was immediately released as a major), and eventually deprecate/underscore them... i'm 100% up for making this change, so just let me know and i'll make a PR!
In #28 it was discovered the tests are displaying critical messages.
tests/functional/test_attr_list.py .........
tests/functional/test_attribute.py ...........................<class 'pangocffi.attribute.Attribute'>
...
tests/functional/test_colors.py ......
tests/functional/test_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.135: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
....
tests/functional/test_convert.py ..
tests/functional/test_ffi_instance_builder.py .
tests/functional/test_font_description.py ....
tests/functional/test_glyph_item_iter_with_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.802: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
tests/functional/test_glyph_item_with_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.830: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.878: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.906: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
tests/functional/test_item.py .
tests/functional/test_item_with_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.936: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
tests/functional/test_layout.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.937: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
..
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.939: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
...
(process:30432): Pango-CRITICAL **: 13:42:22.942: pango_context_load_font: assertion 'context->font_map != NULL' failed
(process:30432): Pango-CRITICAL **: 13:42:22.942: pango_context_load_font: assertion 'context->font_map != NULL' failed
...
tests/functional/test_layout_iter.py
(process:30432): Pango-CRITICAL **: 13:42:22.964: pango_context_load_font: assertion 'context->font_map != NULL' failed
.
(process:30432): Pango-CRITICAL **: 13:42:22.965: pango_context_load_font: assertion 'context->font_map != NULL' failed
..
(process:30432): Pango-CRITICAL **: 13:42:22.968: pango_context_load_font: assertion 'context->font_map != NULL' failed
.
tests/functional/test_layout_run_with_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:22.996: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
(process:30432): GLib-GObject-CRITICAL **: 13:42:23.025: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
(process:30432): GLib-GObject-CRITICAL **: 13:42:23.055: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
tests/functional/test_layout_with_context.py
(process:30432): GLib-GObject-CRITICAL **: 13:42:23.086: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
.
tests/functional/test_rectangle.py ..
tests/functional/test_version.py ..
After some brief investigation, it appears there are three issues.
Most of these critical messages are because I'm cheating when creating a pango context. Normally they are supposed to be created from a pangocairo context, rather than being instantiated from nothing (i.e. pango.pango_context_new()
).
Secondly, in tests with a real pango context (tests/functional/test_[x]_with_context.py
), we are applying a redundant gc
call, which can be removed.
pango_pointer = pangocffi.ffi.gc(
pango_pointer,
pangocffi.gobject.g_object_unref
)
layout.get_context()
, and layout.from_pointer()
, to which we are applying an unnecessary gc via gobject.g_object_unref
on the pointers.What this effectively means is:
PangoContext
.layout.get_context()
or layout.from_pointer()
they will likely see a critical message appear when their script finishes. To be honest, it would be surprising to see anyone even using these methods in practice, so this isn't a serious issue for now.There should be no getters and setters. Instead of using it, @property
decorator should be used. I could see it is used on some files. like get_text
and set_text
. Instead, it should be managing a text attributes inside layout.
Documentation at https://pangocffi.readthedocs.io is no longer generating. This is because readthedocs.org now require a new configuration file.
Error
The configuration file required to build documentation is missing from your project. Add a configuration file to your project to make it build successfully. Read more at https://docs.readthedocs.io/en/stable/config-file/v2.html
OS: macOS Catalina
OS version: 10.15.7
While installing using [email protected], It is throwing the error:
ERROR: Command errored out with exit status 1:
command: /usr/local/opt/python@3.9/bin/python3.9 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/tx/3w2tbvmn64n0xd6ktnxf1yqc0000gn/T/pip-install-p5relybu/pangocairocffi/setup.py'"'"'; __file__='"'"'/private/var/folders/tx/3w2tbvmn64n0xd6ktnxf1yqc0000gn/T/pip-install-p5relybu/pangocairocffi/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/tx/3w2tbvmn64n0xd6ktnxf1yqc0000gn/T/pip-pip-egg-info-ce9ywn4e
cwd: /private/var/folders/tx/3w2tbvmn64n0xd6ktnxf1yqc0000gn/T/pip-install-p5relybu/pangocairocffi/
Complete output (27 lines):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/tx/3w2tbvmn64n0xd6ktnxf1yqc0000gn/T/pip-install-p5relybu/pangocairocffi/setup.py", line 9, in <module>
setup(
File "/usr/local/lib/python3.9/site-packages/setuptools/__init__.py", line 153, in setup
return distutils.core.setup(**attrs)
File "/usr/local/Cellar/[email protected]/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/distutils/core.py", line 108, in setup
_setup_distribution = dist = klass(attrs)
File "/usr/local/lib/python3.9/site-packages/setuptools/dist.py", line 423, in __init__
_Distribution.__init__(self, {
File "/usr/local/Cellar/[email protected]/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/distutils/dist.py", line 292, in __init__
self.finalize_options()
File "/usr/local/lib/python3.9/site-packages/setuptools/dist.py", line 695, in finalize_options
ep(self)
File "/usr/local/lib/python3.9/site-packages/setuptools/dist.py", line 702, in _finalize_setup_keywords
ep.load()(self, ep.name, value)
File "/usr/local/lib/python3.9/site-packages/cffi/setuptools_ext.py", line 219, in cffi_modules
add_cffi_module(dist, cffi_module)
File "/usr/local/lib/python3.9/site-packages/cffi/setuptools_ext.py", line 49, in add_cffi_module
execfile(build_file_name, mod_vars)
File "/usr/local/lib/python3.9/site-packages/cffi/setuptools_ext.py", line 25, in execfile
exec(code, glob, glob)
File "pangocairocffi/ffi_build.py", line 11, in <module>
from pangocffi.ffi_instance_builder import \
File "/usr/local/lib/python3.9/site-packages/pangocffi/__init__.py", line 2, in <module>
from ._generated.ffi import ffi
ModuleNotFoundError: No module named 'pangocffi._generated'
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
Currently it's not possible to create rectangle objects without directly accessing the pointer via get_pointer()
and setting the width
, height
, x
, y
properties.
Two things should probably be done:
width
, height
, x
, y
should be added.width
, height
, x
, y
should be added as optional parameters to Rectangle.__init__
The following error occurs when attempting to instantiate Attributes, insert them to the AttrList, then set it against a layout, then finally attempting to render the layout.
layout.set_text('Hi from Παν語')
attr_list = AttrList()
attr_list.insert(Attribute.from_foreground_color(65535, 0, 0, 3, 7))
layout.set_attributes(attr_list)
pangocairocffi.show_layout(ctx, layout) # <-- Fails on this line
The SegFault can be seen below:
Process: Python [84873]
Path: /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/Resources/Python.app/Contents/MacOS/Python
Identifier: Python
Version: 3.8.5 (3.8.5)
Code Type: X86-64 (Native)
Parent Process: make [84872]
Responsible: pycharm [1751]
User ID: 501
Date/Time: 2020-12-28 23:10:03.590 +0000
OS Version: macOS 11.1 (20C69)
Report Version: 12
System Integrity Protection: enabled
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
VM Regions Near 0:
-->
__TEXT 107732000-107734000 [ 8K] r-x/r-x SM=COW /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/Resources/Python.app/Contents/MacOS/Python
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff2034f462 __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff2037d610 pthread_kill + 263
2 libsystem_c.dylib 0x00007fff2025fba3 raise + 26
3 libsystem_platform.dylib 0x00007fff203c1d7d _sigtramp + 29
4 ??? 000000000000000000 0 + 0
5 libglib-2.0.0.dylib 0x00000001089cb0ee g_ptr_array_copy + 94
6 libpango-1.0.0.dylib 0x0000000108983337 pango_attr_list_copy + 71
7 libpango-1.0.0.dylib 0x00000001089957cb pango_layout_get_effective_attributes + 27
8 libpango-1.0.0.dylib 0x000000010898c7e9 pango_layout_check_lines + 121
9 libpango-1.0.0.dylib 0x0000000108991e6f _pango_layout_get_iter + 127
10 libpango-1.0.0.dylib 0x000000010899c90c pango_renderer_draw_layout + 332
11 libpangocairo-1.0.0.dylib 0x00000001096cf795 _pango_cairo_do_layout + 133
12 libffi.dylib 0x00007fff2d9af8e5 ffi_call_unix64 + 85
13 libffi.dylib 0x00007fff2d9af22a ffi_call_int + 692
14 libffi.dylib 0x00007fff2d9af22a ffi_call_int + 692
15 libffi.dylib 0x00007fff2d9af22a ffi_call_int + 692
16 libffi.dylib 0x00007fff2d9af22a ffi_call_int + 692
etc....
After doing some quick tests, it appears to be related to ffi.gc(pointer, pango.pango_attribute_destroy)
in Attribute.py
. Changing it to just pointer
resolves the issue, but we could be running into memory issues if there are heavy usages of attributes. Therefore we might need to provide direct access to pango.pango_attribute_destroy
by adding a new function like destroy()
, and write in the documentation for Attribute
that destroy()
MUST be called to avoid memory leaks.
The copy()
method for the Color object is currently broken. This was discovered in #47 by cAttte while refactoring all the classes. The blue component is not copied by pango_color_copy()
and always defaults to 0.
A workaround for now is to manually copy the red
, green
, and blue
components and instantiate a new object. Functionally this is identical to pango_color_copy()
, so it's not a terrible compromise. But it does make the code in color.py
a bit ugly.
The issue is not due to the Pango library itself. I've confirmed this by 1. confirming that a test for this exists, and 2. attempting to replicate the issue in C. See below for the program and commands I ran:
#include <pango/pango.h>
int main (int argc, gchar **argv) {
printf("%d\n", pango_version());
PangoColor color = { 1, 2, 3 };
printf("%d, %d, %d\n", color.red, color.green, color.blue);
PangoColor *copy = pango_color_copy(&color);
printf("%d, %d, %d\n", copy->red, copy->green, copy->blue);
}
% gcc example.c -o example `pkg-config --cflags --libs pango`
% ./example
15010
1, 2, 3
1, 2, 3
So the next layer up the chain that could be causing problems is the C-FFI.
So the next steps are to create a small proof of concept which implements PangoColor
and some of the Pango functions and see if the issue can be replicated outside of pangocffi.
Forked from ManimCommunity/manim#757
I would like to access the logger of Pango(I think it uses the one from glib) and convert it to things understandable by Python's logger, so that it would be easy to view the DEBUG logs as well as WARNING printed correctly. As in that issue, the font is not there but it doesn't create(or maybe not show) the warning message explicitly as reported by @leotrs . It does shows those messages but it looks like we don't have any control over it. Is it possible to be wrapped around so that our need fulfill?
Hi,
First of all, thank you for your work on the pango library, it is really helpful.
I would like to ask about a confusion I currently have concerning the pango context and the cairo context.
I currently create a layout
from a context object I have from cairo
, like this
layout = pangocairo.create_layout(context)
where
import pangocffi as pango
import pangocairocffi as pangocairo
cairo = pangocairo.cairocffi
I would like now to set the resolution of the font. The set_resolution
here applies to a pangocontext
object. I can create one by using
pangocontext = pangocairo.create_context(cairo_context=context)
and then set the resolution like
pangocairo.set_resolution(context=pangocontext, dpi=300)
pangocontext
relate to the layout? I am new to this, and I am not sure to understand how they are linked. Inspecting the code of the library, it looks to me that the layout __init__
creates each time a new context, and I have not found a way to create the layout with a given pango context.set_resolution
call on the pango context impact the cairo context?pangocairo.update_layout(cairo_context=layout.get_context(), layout=layout)
and it makes the application crash (some infinite loop). However pangocairo.update_layout(cairo_context=context, layout=layout)
works (the passed contexts are different in nature). I am not sure to understand on which type of context the function update_layout
should be applied.Sorry if my questions are confused, as I said I am discovering pango and your bindings.
It appears the ranges are not being correctly set when instantiating Attribute objects.
After a quick look it appears the setter for end_index
is incorrectly setting the start_index
. It should probably be end_index
.
A lot of functionality is not being properly tested because we are not actively using methods that can only be found by using pangocairo.
We currently do have tests that instantiate a pango context to create Layout objects, but we never actually use the layout for rendering. Without these tests, we run into issues like #38 and #39.
Acceptance tests should be added to make sure the output is correct and that the code doesn't cause SegFaults.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.