在重绘时放大混乱的Cairo纹理

2 投票
1 回答
588 浏览
提问于 2025-04-16 00:48

我正在使用 python-clutter 1.0

我的问题以挑战的形式提出

写一段代码,让我们可以通过按一个键来放大一个 CairoTexture 对象,放大的步骤要能让这个对象重新绘制(通过 cairo),这样图像保持高清晰度,同时也能按预期缩放,而不是改变这个对象的大小。

可以想象一下 Inkscape,如何在矢量图上进行缩放;在任何放大倍数下,矢量图依然保持清晰。把一条路径(比如一堆 cairo 的 line_to 命令)放到一个 CairoTexture 对象上,然后让同样的效果发生。

更多细节

我想做一个小型的 SVG 编辑器,使用一组对象。每个对象专注于一条路径。我通过使用 SomeGroup.set_depth(z) 来“缩放”,然后让 z 变大或变小。到目前为止都很好。然而,随着对象越来越靠近相机,纹理会被拉伸以适应它们的新大小。

我似乎找不到让 Clutter 同时做到这两点的方法:

  1. 保持对象的实际大小不变(也就是它最开始的样子)。
  2. 在放大时,替换它的底层表面为更大的表面,这样我就可以在上面重新绘制路径(并使用 cairo 矩阵来进行上下文的缩放)。

如果我使用 set_sizeset_surface_size,对象会变得 更大,这不是我想要的。我只想让它的 表面(底层数据)变大。

(我不太确定这个术语是什么,可能是 mipmapping?)

换句话说:一个多边形变大了,增加它的纹理数组的大小,以便它可以映射到更大的多边形上。

我甚至尝试绕过 clutter,保持一个第二个表面(使用 pycairo),我重新创建它以适应对象的实际大小(get_transformed_size),然后我使用 clutter 的 set_from_rgb_data 指向我的第二个表面,强制改变表面的大小,但不改变对象的尺寸。

这样做的问题是 a) clutter 忽略了新大小,只在旧的宽度/高度上绘制,b) RGBA 和 ARGB32 的问题导致颜色混乱。

我对任何替代方案持开放态度,希望我在树林里却看不到树!

\d

1 个回答

2

好吧,尽管我做了很多测试和尝试,但答案其实一直就在我眼前。

感谢Neil在clutter项目列表上的分享,下面是事情的真相:

CT = SomeCairoTextureActor()

# record the old height, once:
old_width, old_height = CT.get_size()

Start a loop:
# Do stuff to the depth of CT (or it's parent)
...

# Get the apparent width and height (absolute size in pixels)
appr_w,appr_h = CT.get_transformed_size()

# Make the new surface to the new size
CT.set_surface_size( appr_w, appr_h )

# Crunch the actor back down to old size 
# but leave the texture surface something other!
CT.set_size(old_width, old_height)

loop back again

表面大小和演员的大小不一定要相同。表面大小默认是演员的首选大小。你可以通过直接设置演员的大小来覆盖这个首选大小。如果演员的大小和表面大小不同,那么纹理会被压缩以适应演员的大小(我想这正是你想要的效果)。

很高兴能把这个小谜团解开。谢谢clutter列表!

\d

撰写回答