-
-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Overview
While building a Kivy SVG widget that uses thorvg-python to rasterize and manipulate SVG elements at runtime, I found three related issues with the Accessor API. They are reported together because they all affect the same workflow: traversing a loaded Picture to identify which paint nodes carry SVG id attributes. See: thorvg/thorvg#4217 for background.
Issue 1 — Accessor is not exported from the top-level namespace
Accessor lives in thorvg_python.accessor but is not re-exported in __init__.py. It does not appear in dir(tvg) and cannot be imported as tvg.Accessor.
All other major classes (Picture, Scene, Shape, Engine, etc.) are available directly from import thorvg_python as tvg. It would seen natural that Accessor should follow the same convention.
Issue 2 — accessor_generate_id() crashes with AttributeError
Calling Accessor.accessor_generate_id() raises: AttributeError: 'int' object has no attribute 'value'
The method calls .value on the return of tvg_accessor_generate_id, but the ctypes restype is set to ctypes.c_uint32 which on some platforms returns a plain Python int rather than a ctypes instance. Removing the .value call, or switching the restype to ctypes.c_uint32 and reading it correctly, would fix this.
Minimal Reproducer:
from thorvg_python.accessor import Accessor
import thorvg_python as tvg
engine = tvg.Engine(threads=0)
acc = Accessor(engine, None)
acc.accessor_generate_id('my-element') # raises AttributeErrorIssue 3 — Paint.id (the uint32_t SVG element hash) is not exposed
The ThorVG C++ Paint struct carries a uint32_t id field that, since PR thorvg/thorvg#2827 (merged Oct 2024), is populated with a hash of the SVG id attribute when an SVG is loaded. This field is not exposed by thorvg_python's Paint class.
Without it, calling Accessor.set() to traverse the paint tree is of limited use: the callback visits every node but there is no way to determine which nodes carry an SVG id and what their hash value is. This makes it impossible to enumerate named elements from Python, even though the data is present in ThorVG's internal representation.
Environment
thorvg-python version: latest from PyPI
Python: 3.13 (32-bit, Windows)
ThorVG upstream: latest main
Test case:
from thorvg_python.accessor import Accessor
import thorvg_python as tvg
SVG = (
b'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">'
b'<circle id="ring" r="40" cx="50" cy="50" fill="red"/>'
b'<rect id="box" x="10" y="10" width="30" height="30" fill="blue"/>'
b'<circle r="20" cx="50" cy="50" fill="green"/>'
b'</svg>'
)
engine = tvg.Engine(threads=0)
acc = Accessor(engine, None)
pic = tvg.Picture(engine)
pic.load_data(SVG, 'svg', None, False)
found = []
def visitor(paint_ptr, data_ptr):
p = tvg.Paint(engine, paint_ptr)
attrs = [x for x in dir(p) if 'id' in x.lower() or 'name' in x.lower()]
print(f' Paint attrs with id/name: {attrs}')
found.append(paint_ptr)
return True
print('Traversing with Accessor.set()...')
result = acc.set(pic, visitor, b'x')
print(f'Result: {result}')
print(f'Nodes visited: {len(found)}')
print()
print('Can we get the uint32 id from a Paint via get_paint(hash)?')
hash_ring = acc.accessor_generate_id('ring')
hash_box = acc.accessor_generate_id('box')
print(f' hash("ring") = {hash_ring}')
print(f' hash("box") = {hash_box}')
node = pic.get_paint(hash_ring)
print(f' pic.get_paint(hash_ring) = {node}')Thanks!