blob: 0c46eed3c5c40ff9bac9e0078780e6784605871d [file]
// Copyright 2025 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::renderer::Renderer;
use vello_common::color::palette::css::{BLUE, YELLOW};
use vello_common::kurbo::Rect;
use vello_common::peniko::{BlendMode, Compose, Mix};
use vello_cpu::peniko::Color;
use vello_dev_macros::vello_test;
fn compose(ctx: &mut impl Renderer, compose: Compose) {
ctx.push_blend_layer(BlendMode::new(Mix::Normal, Compose::SrcOver));
// Draw the destination layer.
ctx.set_paint(YELLOW.with_alpha(1.0));
ctx.fill_rect(&Rect::new(10.0, 10.0, 70.0, 70.0));
// Draw the source layer.
ctx.push_blend_layer(BlendMode::new(Mix::Normal, compose));
ctx.set_paint(BLUE.with_alpha(1.0));
ctx.fill_rect(&Rect::new(30.0, 30.0, 90.0, 90.0));
// Compose.
ctx.pop_layer();
ctx.pop_layer();
}
#[vello_test(height = 8)]
fn compose_wide_tile_nested(ctx: &mut impl Renderer) {
const WIDTH: f64 = 100.0;
const HEIGHT: f64 = 4.0;
const OFFSET: f64 = 20.0;
// Pure colors: max values only
let red = Color::from_rgb8(255, 0, 0);
let green = Color::from_rgb8(0, 255, 0);
let blue = Color::from_rgb8(0, 0, 255);
let cyan = Color::from_rgb8(0, 255, 255); // Green + Blue maxed
ctx.push_blend_layer(BlendMode::new(Mix::Normal, Compose::SrcOver));
// Draw base red rectangle
ctx.set_paint(red);
ctx.fill_rect(&Rect::new(0.0, 0.0, WIDTH, HEIGHT));
// Start nesting - green with Xor
ctx.push_blend_layer(BlendMode::new(Mix::Normal, Compose::SrcOver));
ctx.set_paint(green);
ctx.fill_rect(&Rect::new(OFFSET, 0.0, OFFSET + WIDTH, HEIGHT));
// Nest blue with Plus
ctx.push_blend_layer(BlendMode::new(Mix::Normal, Compose::SrcOver));
ctx.set_paint(blue);
ctx.fill_rect(&Rect::new(OFFSET * 2.0, 0.0, OFFSET * 2.0 + WIDTH, HEIGHT));
// Nest cyan with Multiply
ctx.push_blend_layer(BlendMode::new(Mix::Normal, Compose::SrcOver));
ctx.set_paint(cyan);
ctx.fill_rect(&Rect::new(OFFSET * 3.0, 0.0, OFFSET * 3.0 + WIDTH, HEIGHT));
ctx.pop_layer(); // cyan
ctx.pop_layer(); // blue
ctx.pop_layer(); // green
ctx.pop_layer(); // base
}
#[vello_test]
fn compose_src_over(ctx: &mut impl Renderer) {
compose(ctx, Compose::SrcOver);
}
#[vello_test]
fn compose_xor(ctx: &mut impl Renderer) {
compose(ctx, Compose::Xor);
}
#[vello_test]
fn compose_clear(ctx: &mut impl Renderer) {
compose(ctx, Compose::Clear);
}
#[vello_test]
fn compose_copy(ctx: &mut impl Renderer) {
compose(ctx, Compose::Copy);
}
#[vello_test]
fn compose_dest(ctx: &mut impl Renderer) {
compose(ctx, Compose::Dest);
}
#[vello_test]
fn compose_dest_over(ctx: &mut impl Renderer) {
compose(ctx, Compose::DestOver);
}
#[vello_test]
fn compose_src_in(ctx: &mut impl Renderer) {
compose(ctx, Compose::SrcIn);
}
#[vello_test]
fn compose_src_out(ctx: &mut impl Renderer) {
compose(ctx, Compose::SrcOut);
}
#[vello_test]
fn compose_dest_in(ctx: &mut impl Renderer) {
compose(ctx, Compose::DestIn);
}
#[vello_test]
fn compose_dest_out(ctx: &mut impl Renderer) {
compose(ctx, Compose::DestOut);
}
#[vello_test]
fn compose_src_atop(ctx: &mut impl Renderer) {
compose(ctx, Compose::SrcAtop);
}
#[vello_test]
fn compose_dest_atop(ctx: &mut impl Renderer) {
compose(ctx, Compose::DestAtop);
}
#[vello_test]
fn compose_plus(ctx: &mut impl Renderer) {
compose(ctx, Compose::Plus);
}