mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Address review feedback.
* remove area clamp in fine (now in #241) * make DrawTag::info_size() const fn * document DrawColor rgba field * change Monoid type parameter to an associated type and describe the additional Default constraint * consistent parens in PathTag::is_subpath_end * add comments for 32-bit path segment types in PathTag * also adds low level encoding functions for the three currently supported brushes
This commit is contained in:
parent
dbe7f27768
commit
520f6d0d41
|
@ -138,7 +138,7 @@ fn fill_path(tile: Tile, xy: vec2<f32>) -> array<f32, PIXELS_PER_THREAD> {
|
||||||
}
|
}
|
||||||
// nonzero winding rule
|
// nonzero winding rule
|
||||||
for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) {
|
for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) {
|
||||||
area[i] = min(abs(area[i]), 1.0);
|
area[i] = abs(area[i]);
|
||||||
}
|
}
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ impl DrawTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrawTag {
|
impl DrawTag {
|
||||||
/// Returns the size of the info buffer used by this tag.
|
/// Returns the size of the info buffer (in u32s) used by this tag.
|
||||||
pub fn info_size(self) -> u32 {
|
pub const fn info_size(self) -> u32 {
|
||||||
(self.0 >> 6) & 0xf
|
(self.0 >> 6) & 0xf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,8 @@ impl DrawTag {
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DrawColor {
|
pub struct DrawColor {
|
||||||
/// Packed RGBA color.
|
/// Packed little endian RGBA premultiplied color with the alpha component
|
||||||
|
/// in the low byte.
|
||||||
pub rgba: u32,
|
pub rgba: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +144,9 @@ pub struct DrawMonoid {
|
||||||
pub info_offset: u32,
|
pub info_offset: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Monoid<DrawTag> for DrawMonoid {
|
impl Monoid for DrawMonoid {
|
||||||
|
type SourceValue = DrawTag;
|
||||||
|
|
||||||
fn new(tag: DrawTag) -> Self {
|
fn new(tag: DrawTag) -> Self {
|
||||||
Self {
|
Self {
|
||||||
path_ix: (tag != DrawTag::NOP) as u32,
|
path_ix: (tag != DrawTag::NOP) as u32,
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
// Also licensed under MIT license, at your choice.
|
// Also licensed under MIT license, at your choice.
|
||||||
|
|
||||||
use super::resource::Patch;
|
use super::resource::Patch;
|
||||||
use super::{DrawTag, PathEncoder, PathTag, Transform};
|
use super::{
|
||||||
|
DrawColor, DrawLinearGradient, DrawRadialGradient, DrawTag, PathEncoder, PathTag, Transform,
|
||||||
|
};
|
||||||
|
|
||||||
use peniko::{kurbo::Shape, BlendMode, BrushRef, Color, ColorStop};
|
use peniko::{kurbo::Shape, BlendMode, BrushRef, Color, ColorStop, Extend};
|
||||||
|
|
||||||
/// Encoded data streams for a scene.
|
/// Encoded data streams for a scene.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -148,44 +150,79 @@ impl Encoding {
|
||||||
/// Encodes a brush with an optional alpha modifier.
|
/// Encodes a brush with an optional alpha modifier.
|
||||||
pub fn encode_brush<'b>(&mut self, brush: impl Into<BrushRef<'b>>, alpha: f32) {
|
pub fn encode_brush<'b>(&mut self, brush: impl Into<BrushRef<'b>>, alpha: f32) {
|
||||||
use super::math::point_to_f32;
|
use super::math::point_to_f32;
|
||||||
use super::{DrawColor, DrawLinearGradient, DrawRadialGradient};
|
|
||||||
match brush.into() {
|
match brush.into() {
|
||||||
BrushRef::Solid(color) => {
|
BrushRef::Solid(color) => {
|
||||||
self.draw_tags.push(DrawTag::COLOR);
|
|
||||||
let color = if alpha != 1.0 {
|
let color = if alpha != 1.0 {
|
||||||
color_with_alpha(color, alpha)
|
color_with_alpha(color, alpha)
|
||||||
} else {
|
} else {
|
||||||
color
|
color
|
||||||
};
|
};
|
||||||
self.draw_data
|
self.encode_color(DrawColor::new(color));
|
||||||
.extend_from_slice(bytemuck::bytes_of(&DrawColor::new(color)));
|
|
||||||
}
|
}
|
||||||
BrushRef::LinearGradient(gradient) => {
|
BrushRef::LinearGradient(gradient) => {
|
||||||
self.add_ramp(&gradient.stops, alpha);
|
self.encode_linear_gradient(
|
||||||
self.draw_tags.push(DrawTag::LINEAR_GRADIENT);
|
DrawLinearGradient {
|
||||||
self.draw_data
|
|
||||||
.extend_from_slice(bytemuck::bytes_of(&DrawLinearGradient {
|
|
||||||
index: 0,
|
index: 0,
|
||||||
p0: point_to_f32(gradient.start),
|
p0: point_to_f32(gradient.start),
|
||||||
p1: point_to_f32(gradient.end),
|
p1: point_to_f32(gradient.end),
|
||||||
}));
|
},
|
||||||
|
gradient.stops.iter().copied(),
|
||||||
|
alpha,
|
||||||
|
gradient.extend,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
BrushRef::RadialGradient(gradient) => {
|
BrushRef::RadialGradient(gradient) => {
|
||||||
self.add_ramp(&gradient.stops, alpha);
|
self.encode_radial_gradient(
|
||||||
self.draw_tags.push(DrawTag::RADIAL_GRADIENT);
|
DrawRadialGradient {
|
||||||
self.draw_data
|
|
||||||
.extend_from_slice(bytemuck::bytes_of(&DrawRadialGradient {
|
|
||||||
index: 0,
|
index: 0,
|
||||||
p0: point_to_f32(gradient.start_center),
|
p0: point_to_f32(gradient.start_center),
|
||||||
p1: point_to_f32(gradient.end_center),
|
p1: point_to_f32(gradient.end_center),
|
||||||
r0: gradient.start_radius,
|
r0: gradient.start_radius,
|
||||||
r1: gradient.end_radius,
|
r1: gradient.end_radius,
|
||||||
}));
|
},
|
||||||
|
gradient.stops.iter().copied(),
|
||||||
|
alpha,
|
||||||
|
gradient.extend,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
BrushRef::SweepGradient(_gradient) => todo!("sweep gradients aren't done yet!"),
|
BrushRef::SweepGradient(_gradient) => todo!("sweep gradients aren't done yet!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encodes a solid color brush.
|
||||||
|
pub fn encode_color(&mut self, color: DrawColor) {
|
||||||
|
self.draw_tags.push(DrawTag::COLOR);
|
||||||
|
self.draw_data.extend_from_slice(bytemuck::bytes_of(&color));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes a linear gradient brush.
|
||||||
|
pub fn encode_linear_gradient(
|
||||||
|
&mut self,
|
||||||
|
gradient: DrawLinearGradient,
|
||||||
|
color_stops: impl Iterator<Item = ColorStop>,
|
||||||
|
alpha: f32,
|
||||||
|
_extend: Extend,
|
||||||
|
) {
|
||||||
|
self.add_ramp(color_stops, alpha);
|
||||||
|
self.draw_tags.push(DrawTag::LINEAR_GRADIENT);
|
||||||
|
self.draw_data
|
||||||
|
.extend_from_slice(bytemuck::bytes_of(&gradient));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes a radial gradient brush.
|
||||||
|
pub fn encode_radial_gradient(
|
||||||
|
&mut self,
|
||||||
|
gradient: DrawRadialGradient,
|
||||||
|
color_stops: impl Iterator<Item = ColorStop>,
|
||||||
|
alpha: f32,
|
||||||
|
_extend: Extend,
|
||||||
|
) {
|
||||||
|
self.add_ramp(color_stops, alpha);
|
||||||
|
self.draw_tags.push(DrawTag::RADIAL_GRADIENT);
|
||||||
|
self.draw_data
|
||||||
|
.extend_from_slice(bytemuck::bytes_of(&gradient));
|
||||||
|
}
|
||||||
|
|
||||||
/// Encodes a begin clip command.
|
/// Encodes a begin clip command.
|
||||||
pub fn encode_begin_clip(&mut self, blend_mode: BlendMode, alpha: f32) {
|
pub fn encode_begin_clip(&mut self, blend_mode: BlendMode, alpha: f32) {
|
||||||
use super::DrawBeginClip;
|
use super::DrawBeginClip;
|
||||||
|
@ -211,16 +248,16 @@ impl Encoding {
|
||||||
self.path_tags.swap(len - 1, len - 2);
|
self.path_tags.swap(len - 1, len - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_ramp(&mut self, stops: &[ColorStop], alpha: f32) {
|
fn add_ramp(&mut self, color_stops: impl Iterator<Item = ColorStop>, alpha: f32) {
|
||||||
let offset = self.draw_data.len();
|
let offset = self.draw_data.len();
|
||||||
let stops_start = self.color_stops.len();
|
let stops_start = self.color_stops.len();
|
||||||
if alpha != 1.0 {
|
if alpha != 1.0 {
|
||||||
self.color_stops.extend(stops.iter().map(|s| ColorStop {
|
self.color_stops.extend(color_stops.map(|s| ColorStop {
|
||||||
offset: s.offset,
|
offset: s.offset,
|
||||||
color: color_with_alpha(s.color, alpha),
|
color: color_with_alpha(s.color, alpha),
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
self.color_stops.extend_from_slice(stops);
|
self.color_stops.extend(color_stops);
|
||||||
}
|
}
|
||||||
self.patches.push(Patch::Ramp {
|
self.patches.push(Patch::Ramp {
|
||||||
offset,
|
offset,
|
||||||
|
|
|
@ -14,10 +14,15 @@
|
||||||
//
|
//
|
||||||
// Also licensed under MIT license, at your choice.
|
// Also licensed under MIT license, at your choice.
|
||||||
|
|
||||||
/// Interface for a monoid.
|
/// Interface for a monoid. The default value must be the identity of
|
||||||
pub trait Monoid<T>: Default {
|
/// the monoid.
|
||||||
|
pub trait Monoid: Default {
|
||||||
|
/// The source value for constructing the monoid.
|
||||||
|
type SourceValue;
|
||||||
|
|
||||||
/// Creates a monoid from a given value.
|
/// Creates a monoid from a given value.
|
||||||
fn new(value: T) -> Self;
|
fn new(value: Self::SourceValue) -> Self;
|
||||||
|
|
||||||
/// Combines two monoids. This operation must be associative.
|
/// Combines two monoids. This operation must be associative.
|
||||||
fn combine(&self, other: &Self) -> Self;
|
fn combine(&self, other: &Self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ pub struct PathSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Path segment type.
|
/// Path segment type.
|
||||||
|
///
|
||||||
|
/// The values of the segment types are equivalent to the number of associated
|
||||||
|
/// points for each segment in the path data stream.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Pod, Zeroable)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Pod, Zeroable)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PathSegmentType(pub u8);
|
pub struct PathSegmentType(pub u8);
|
||||||
|
@ -52,12 +55,18 @@ pub struct PathTag(pub u8);
|
||||||
|
|
||||||
impl PathTag {
|
impl PathTag {
|
||||||
/// 32-bit floating point line segment.
|
/// 32-bit floating point line segment.
|
||||||
|
///
|
||||||
|
/// This is equivalent to (PathSegmentType::LINE_TO | PathTag::F32_BIT).
|
||||||
pub const LINE_TO_F32: Self = Self(0x9);
|
pub const LINE_TO_F32: Self = Self(0x9);
|
||||||
|
|
||||||
/// 32-bit floating point quadratic segment.
|
/// 32-bit floating point quadratic segment.
|
||||||
|
///
|
||||||
|
/// This is equivalent to (PathSegmentType::QUAD_TO | PathTag::F32_BIT).
|
||||||
pub const QUAD_TO_F32: Self = Self(0xa);
|
pub const QUAD_TO_F32: Self = Self(0xa);
|
||||||
|
|
||||||
/// 32-bit floating point cubic segment.
|
/// 32-bit floating point cubic segment.
|
||||||
|
///
|
||||||
|
/// This is equivalent to (PathSegmentType::CUBIC_TO | PathTag::F32_BIT).
|
||||||
pub const CUBIC_TO_F32: Self = Self(0xb);
|
pub const CUBIC_TO_F32: Self = Self(0xb);
|
||||||
|
|
||||||
/// 16-bit integral line segment.
|
/// 16-bit integral line segment.
|
||||||
|
@ -78,8 +87,14 @@ impl PathTag {
|
||||||
/// Line width setting.
|
/// Line width setting.
|
||||||
pub const LINEWIDTH: Self = Self(0x40);
|
pub const LINEWIDTH: Self = Self(0x40);
|
||||||
|
|
||||||
|
/// Bit for path segments that are represented as f32 values. If unset
|
||||||
|
/// they are represented as i16.
|
||||||
const F32_BIT: u8 = 0x8;
|
const F32_BIT: u8 = 0x8;
|
||||||
|
|
||||||
|
/// Bit that marks a segment that is the end of a subpath.
|
||||||
const SUBPATH_END_BIT: u8 = 0x4;
|
const SUBPATH_END_BIT: u8 = 0x4;
|
||||||
|
|
||||||
|
/// Mask for bottom 3 bits that contain the [PathSegmentType].
|
||||||
const SEGMENT_MASK: u8 = 0x3;
|
const SEGMENT_MASK: u8 = 0x3;
|
||||||
|
|
||||||
/// Returns true if the tag is a segment.
|
/// Returns true if the tag is a segment.
|
||||||
|
@ -94,7 +109,7 @@ impl PathTag {
|
||||||
|
|
||||||
/// Returns true if this segment ends a subpath.
|
/// Returns true if this segment ends a subpath.
|
||||||
pub fn is_subpath_end(self) -> bool {
|
pub fn is_subpath_end(self) -> bool {
|
||||||
(self.0 & Self::SUBPATH_END_BIT) != 0
|
self.0 & Self::SUBPATH_END_BIT != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the subpath end bit.
|
/// Sets the subpath end bit.
|
||||||
|
@ -124,7 +139,9 @@ pub struct PathMonoid {
|
||||||
pub path_ix: u32,
|
pub path_ix: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Monoid<u32> for PathMonoid {
|
impl Monoid for PathMonoid {
|
||||||
|
type SourceValue = u32;
|
||||||
|
|
||||||
/// Reduces a packed 32-bit word containing 4 tags.
|
/// Reduces a packed 32-bit word containing 4 tags.
|
||||||
fn new(tag_word: u32) -> Self {
|
fn new(tag_word: u32) -> Self {
|
||||||
let mut c = Self::default();
|
let mut c = Self::default();
|
||||||
|
|
Loading…
Reference in a new issue