blob: 1ddaeadf11b2dab0ba8bbf2f0267d45d38a45b65 [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Also licensed under MIT license, at your choice.
use bytemuck::{Pod, Zeroable};
use peniko::{BlendMode, Color};
use super::Monoid;
/// Draw tag representation.
#[derive(Copy, Clone, PartialEq, Eq, Pod, Zeroable)]
#[repr(C)]
pub struct DrawTag(pub u32);
impl DrawTag {
/// No operation.
pub const NOP: Self = Self(0);
/// Color fill.
pub const COLOR: Self = Self(0x44);
/// Linear gradient fill.
pub const LINEAR_GRADIENT: Self = Self(0x114);
/// Radial gradient fill.
pub const RADIAL_GRADIENT: Self = Self(0x2dc);
/// Image fill.
pub const IMAGE: Self = Self(0x48);
/// Begin layer/clip.
pub const BEGIN_CLIP: Self = Self(0x9);
/// End layer/clip.
pub const END_CLIP: Self = Self(0x21);
}
impl DrawTag {
/// Returns the size of the info buffer (in u32s) used by this tag.
pub const fn info_size(self) -> u32 {
(self.0 >> 6) & 0xf
}
}
/// Draw data for a solid color.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)]
pub struct DrawColor {
/// Packed little endian RGBA premultiplied color with the alpha component
/// in the low byte.
pub rgba: u32,
}
impl DrawColor {
/// Creates new solid color draw data.
pub fn new(color: Color) -> Self {
Self {
rgba: color.to_premul_u32(),
}
}
}
/// Draw data for a linear gradient.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)]
pub struct DrawLinearGradient {
/// Ramp index.
pub index: u32,
/// Start point.
pub p0: [f32; 2],
/// End point.
pub p1: [f32; 2],
}
/// Draw data for a radial gradient.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)]
pub struct DrawRadialGradient {
/// Ramp index.
pub index: u32,
/// Start point.
pub p0: [f32; 2],
/// End point.
pub p1: [f32; 2],
/// Start radius.
pub r0: f32,
/// End radius.
pub r1: f32,
}
/// Draw data for an image.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)]
pub struct DrawImage {
/// Image index.
pub index: u32,
/// Packed image offset.
pub offset: u32,
}
/// Draw data for a clip or layer.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)]
pub struct DrawBeginClip {
/// Blend mode.
pub blend_mode: u32,
/// Group alpha.
pub alpha: f32,
}
impl DrawBeginClip {
/// Creates new clip draw data.
pub fn new(blend_mode: BlendMode, alpha: f32) -> Self {
Self {
blend_mode: (blend_mode.mix as u32) << 8 | blend_mode.compose as u32,
alpha,
}
}
}
/// Monoid for the draw tag stream.
#[derive(Copy, Clone, PartialEq, Eq, Pod, Zeroable, Default)]
#[repr(C)]
pub struct DrawMonoid {
// The number of paths preceding this draw object.
pub path_ix: u32,
// The number of clip operations preceding this draw object.
pub clip_ix: u32,
// The offset of the encoded draw object in the scene (u32s).
pub scene_offset: u32,
// The offset of the associated info.
pub info_offset: u32,
}
impl Monoid for DrawMonoid {
type SourceValue = DrawTag;
fn new(tag: DrawTag) -> Self {
Self {
path_ix: (tag != DrawTag::NOP) as u32,
clip_ix: tag.0 & 1,
scene_offset: (tag.0 >> 2) & 0x7,
info_offset: (tag.0 >> 6) & 0xf,
}
}
fn combine(&self, other: &Self) -> Self {
Self {
path_ix: self.path_ix + other.path_ix,
clip_ix: self.clip_ix + other.clip_ix,
scene_offset: self.scene_offset + other.scene_offset,
info_offset: self.info_offset + other.info_offset,
}
}
}