Giter VIP home page Giter VIP logo

pangocffi's People

Contributors

andy-mortimer avatar cattte avatar georgeharker avatar leifgehrmann avatar naveen521kk avatar promyloph avatar raffienficiaud avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pangocffi's Issues

Question about "font_description"

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:

  • I am pretty sure there is an easier way to achieve this, however I am a bit confused by pango in general. Would you please give me a hint?
  • what happens to the pointer font_description_pointer after this? Is this garbage collected or should I free it explicitly?

Thank you for your time.

Specify the DLL file to load using Environment Variable

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.

Using properties instead of getters/setters

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!

Fix critical messages in tests

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
        )
  • Thirdly, when calling functions like 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:

  • Users of pangocffi shouldn't normally see these critical messages since they mostly only apply to artificial instances of PangoContext.
  • If someone uses 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.

Use properties

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.

ModuleNotFoundError: No module named 'pangocffi._generated'

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.

Rectangle needs setter methods if Attribute.from_shape() is to be used

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:

  • Setter methods for width, height, x, y should be added.
  • width, height, x, y should be added as optional parameters to Rectangle.__init__

SegFault when applying AttrList to Layout

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.

Internal Improvement: Fix pango_color_copy() usage for Color.copy()

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.

Support Logging

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?

Questions about pangocontext

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)
  • How does this 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.
  • how does this pangocontext relate to the cairo context? As I am creating the pango context out of the cairo context, I imagine that they are linked somehow, but does the set_resolution call on the pango context impact the cairo context?
  • I then later tried this 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.

Attribute's end_index is not set correctly

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.

Add acceptance tests to properly test pango API calls

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.