如何用Cairo实现填充形状外部区域(保留透明孔洞)
如何用Cairo实现带透明圆形孔洞的蓝色背景?
嘿,我刚好能解决你这个问题!你需要的是“在蓝色背景上挖一个透明圆形洞”的效果,Cairo里有两种非常实用的实现方式,我给你详细拆解并附上C和Python的代码示例:
方法1:利用奇偶填充规则(Even-Odd Fill Rule)
Cairo默认的填充规则是WINDING,它会填充所有路径包围的区域;而EVEN_ODD规则会交替填充——路径重叠偶数次的区域不会被填充,刚好可以用来做“挖洞”效果。
C语言示例
#include <cairo.h> #include <math.h> int main() { // 创建300x300的ARGB32格式surface(支持透明) cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300); cairo_t *cr = cairo_create(surface); // 先把整个surface初始化为透明 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_paint(cr); // 切换到奇偶填充规则 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); // 设置蓝色背景的颜色(不透明蓝) cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0); // 绘制覆盖整个surface的矩形 cairo_rectangle(cr, 0, 0, 300, 300); // 在中心绘制一个半径80的圆形(这就是我们要的孔洞) cairo_arc(cr, 150, 150, 80, 0, 2 * M_PI); // 填充路径:奇偶规则会让圆形区域(两层路径重叠)不被填充,保持透明 cairo_fill(cr); // 保存为PNG文件 cairo_surface_write_to_png(surface, "transparent_hole_bg.png"); // 清理资源 cairo_destroy(cr); cairo_surface_destroy(surface); return 0; }
Python(Pycairo)示例
import cairo # 创建300x300的透明surface surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300) cr = cairo.Context(surface) # 初始化透明背景 cr.set_source_rgba(0.0, 0.0, 0.0, 0.0) cr.paint() # 设置奇偶填充规则 cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) # 绘制蓝色背景矩形 cr.set_source_rgba(0.0, 0.0, 1.0, 1.0) cr.rectangle(0, 0, 300, 300) # 绘制中心圆形孔洞 cr.arc(150, 150, 80, 0, 2 * 3.14159265) # 填充路径 cr.fill() # 保存结果 surface.write_to_png("transparent_hole_bg_python.png")
方法2:使用DEST_OUT绘图操作符
另一种更直接的思路是:先铺满蓝色背景,然后用DEST_OUT操作符绘制圆形——这个操作符会把圆形区域的内容清除为透明,相当于直接“挖洞”。
C语言示例
#include <cairo.h> #include <math.h> int main() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300); cairo_t *cr = cairo_create(surface); // 先绘制整个蓝色背景 cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0); cairo_paint(cr); // 设置操作符为DEST_OUT:保留目标(蓝色背景)中不在源路径内的部分,源路径内变透明 cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OUT); // 绘制中心圆形,这里的颜色不影响,操作符决定最终效果 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_arc(cr, 150, 150, 80, 0, 2 * M_PI); cairo_fill(cr); // 保存并清理 cairo_surface_write_to_png(surface, "transparent_hole_operator.png"); cairo_destroy(cr); cairo_surface_destroy(surface); return 0; }
Python(Pycairo)示例
import cairo surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300) cr = cairo.Context(surface) # 绘制蓝色背景 cr.set_source_rgba(0.0, 0.0, 1.0, 1.0) cr.paint() # 设置DEST_OUT操作符,用于清除圆形区域为透明 cr.set_operator(cairo.OPERATOR_DEST_OUT) # 绘制圆形孔洞 cr.arc(150, 150, 80, 0, 2 * 3.14159265) cr.fill() # 保存结果 surface.write_to_png("transparent_hole_operator_python.png")
两种方法的适用场景
- 如果需要创建多个不规则孔洞,方法1的奇偶填充规则会更灵活——你只需要在矩形内部添加更多路径即可。
- 如果只是单个简单孔洞,方法2的代码更简洁,逻辑也更直观。
两种方法都能完美实现你要的“蓝色背景+透明圆形孔洞”效果,你可以根据自己的实际需求选择~
内容的提问来源于stack exchange,提问作者BobMorane
相关产品推荐
相关产品推荐

