AgentSkillsCN

vello-hybrid-api

当您使用 vello_svg crate 渲染 SVG 内容、将 SVG 字符串或 usvg 树转换为 vello 场景,或处理不被支持的 SVG 功能时,可选用此方案。

SKILL.md
--- frontmatter
name: vello-hybrid-api
description: Use when working with vello_hybrid crate - drawing scenes, rendering with wgpu/WebGL, using clipping, gradients, or images

vello_hybrid Reference

Hybrid CPU/GPU 2D vector renderer. CPU handles path processing and strip generation; GPU handles rendering and compositing.

Quick Reference

OperationMethodNotes
Create sceneScene::new(width: u16, height: u16)Dimensions are u16
Reset between framesscene.reset()Required - clears state and encoded paints
Set paintscene.set_paint(impl Into<Paint>)Solid, Gradient, or Image
Fill rectscene.fill_rect(&Rect)Fast path for rectangles
Fill pathscene.fill_path(&BezPath)General path filling
Stroke pathscene.stroke_path(&BezPath)Uses current stroke settings
Set strokescene.set_stroke(Stroke)Width, caps, joins
Set transformscene.set_transform(Affine)Applied to geometry
Set paint transformscene.set_paint_transform(Affine)Applied to paint coordinates

Clipping: Two Mechanisms

code
push_clip_path()     push_clip_layer()
      │                     │
      ▼                     ▼
 Fast, immediate      Uses GPU slots
 No blend modes       Supports blend/opacity
 No layer overhead    Requires slot cleanup
      │                     │
      ▼                     ▼
 pop_clip_path()     pop_clip_layer()

Use push_clip_path() for simple geometric clipping. Use push_clip_layer() only when you need blend modes or layer opacity.

Rendering (wgpu)

rust
use vello_hybrid::{Renderer, RenderTargetConfig, RenderSize};

let config = RenderTargetConfig {
    format: surface.format(),  // or Rgba8Unorm for headless
    width: window_width,       // u32
    height: window_height,     // u32
};
let mut renderer = Renderer::new(&device, &config);

let render_size = RenderSize { width, height };  // u32 values
renderer.render(&scene, &device, &queue, &mut encoder, &render_size, &view)?;

Scene vs RenderSize: Scene uses u16 dimensions (coordinate space). RenderSize uses u32 (output resolution). They can differ for scaling.

Common Patterns

Gradient Fill

rust
use vello_common::peniko::{Gradient, LinearGradientPosition, ColorStop, ColorStops, Extend};

let gradient = Gradient {
    kind: LinearGradientPosition { start, end }.into(),
    stops: ColorStops::from([
        ColorStop::from((0.0, color1)),
        ColorStop::from((1.0, color2)),
    ].as_slice()),
    extend: Extend::Pad,
    ..Default::default()
};
scene.set_paint(gradient);

Image Drawing

rust
use vello_hybrid::{Renderer, Pixmap};
use vello_common::paint::{Image, ImageSource};
use vello_common::peniko::ImageSampler;

// Upload image to atlas (once) - requires encoder
let image_id = renderer.upload_image(&device, &queue, &mut encoder, &pixmap);

// Draw (per frame)
let image = Image {
    image: ImageSource::OpaqueId(image_id),
    sampler: ImageSampler::default(),
};
scene.set_paint(image);
scene.fill_rect(&rect);

// Cleanup when done - also requires encoder
renderer.destroy_image(&device, &queue, &mut encoder, image_id);

AtlasWriter types: Pixmap, Arc<Pixmap>, or wgpu::Texture implement AtlasWriter.

Pitfalls

IssueCauseFix
State bleeds between framesMissing reset()Call scene.reset() before each frame
Nothing rendersPaint alpha = 0Solid colors with alpha=0 are skipped as optimization
SlotsExhausted errorToo many nested clip layersReduce nesting or use push_clip_path() instead
Filter effects panicNot implementedpush_layer() with filter and set_filter_effect() are unimplemented
GPU memory leakForgot destroy_image()Always destroy images when no longer needed

Imports

rust
// Scene and rendering
use vello_hybrid::{Scene, Renderer, RenderTargetConfig, RenderSize};

// Geometry (from kurbo via vello_common)
use vello_common::kurbo::{Affine, BezPath, Circle, Point, Rect, Shape};

// Paint types (from peniko via vello_common)
use vello_common::peniko::{
    BlendMode, Color, Fill, Gradient, Image, Stroke,
    ColorStop, ColorStops, Extend, LinearGradientPosition, RadialGradientPosition,
};
use vello_common::peniko::color::palette::css::*;  // Named colors

WebGL Backend (WASM only)

rust
#[cfg(target_arch = "wasm32")]
use vello_hybrid::WebGlRenderer;

let mut renderer = WebGlRenderer::new(canvas_element);
renderer.render(&scene, &render_size)?;