2023-01-09 03:15:51 +11:00
|
|
|
// Copyright 2022 The vello authors.
|
2022-04-11 19:30:08 +10:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2023-01-07 08:52:41 +11:00
|
|
|
use peniko::kurbo::{Affine, Rect, Shape};
|
|
|
|
use peniko::{BlendMode, BrushRef, Fill, Stroke};
|
2022-12-10 05:23:03 +11:00
|
|
|
|
2023-01-07 08:52:41 +11:00
|
|
|
use crate::encoding::{Encoding, Transform};
|
2022-12-10 05:23:03 +11:00
|
|
|
|
|
|
|
/// Encoded definition of a scene and associated resources.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Scene {
|
2023-01-07 08:52:41 +11:00
|
|
|
data: Encoding,
|
2022-12-10 05:23:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Scene {
|
|
|
|
/// Creates a new scene.
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the raw encoded scene data streams.
|
2023-01-07 08:52:41 +11:00
|
|
|
pub fn data(&self) -> &Encoding {
|
2022-12-10 05:23:03 +11:00
|
|
|
&self.data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Encoded definition of a scene fragment and associated resources.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct SceneFragment {
|
2023-01-07 08:52:41 +11:00
|
|
|
data: Encoding,
|
2022-12-10 05:23:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SceneFragment {
|
|
|
|
/// Creates a new scene fragment.
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if the fragment does not contain any paths.
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.data.is_empty()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the the entire sequence of points in the scene fragment.
|
|
|
|
pub fn points(&self) -> &[[f32; 2]] {
|
|
|
|
if self.is_empty() {
|
|
|
|
&[]
|
|
|
|
} else {
|
2023-01-07 08:52:41 +11:00
|
|
|
bytemuck::cast_slice(&self.data.path_data)
|
2022-12-10 05:23:03 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 19:30:08 +10:00
|
|
|
/// Builder for constructing a scene or scene fragment.
|
2022-08-12 05:29:15 +10:00
|
|
|
pub struct SceneBuilder<'a> {
|
2023-01-07 08:52:41 +11:00
|
|
|
scene: &'a mut Encoding,
|
2022-11-30 05:28:25 +11:00
|
|
|
layer_depth: u32,
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
2022-08-12 05:29:15 +10:00
|
|
|
impl<'a> SceneBuilder<'a> {
|
|
|
|
/// Creates a new builder for filling a scene. Any current content in the scene
|
|
|
|
/// will be cleared.
|
2022-08-12 08:00:53 +10:00
|
|
|
pub fn for_scene(scene: &'a mut Scene) -> Self {
|
|
|
|
Self::new(&mut scene.data, false)
|
2022-08-12 05:29:15 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new builder for filling a scene fragment. Any current content in
|
|
|
|
/// the fragment will be cleared.
|
|
|
|
pub fn for_fragment(fragment: &'a mut SceneFragment) -> Self {
|
2022-08-12 08:00:53 +10:00
|
|
|
Self::new(&mut fragment.data, true)
|
2022-08-12 05:29:15 +10:00
|
|
|
}
|
|
|
|
|
2022-04-11 19:30:08 +10:00
|
|
|
/// Creates a new builder for constructing a scene.
|
2023-01-07 08:52:41 +11:00
|
|
|
fn new(scene: &'a mut Encoding, is_fragment: bool) -> Self {
|
2022-04-18 17:48:10 +10:00
|
|
|
scene.reset(is_fragment);
|
2022-04-11 20:14:58 +10:00
|
|
|
Self {
|
|
|
|
scene,
|
2022-11-30 05:28:25 +11:00
|
|
|
layer_depth: 0,
|
2022-04-11 20:14:58 +10:00
|
|
|
}
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Pushes a new layer bound by the specifed shape and composed with
|
|
|
|
/// previous layers using the specified blend mode.
|
2022-11-24 04:50:28 +11:00
|
|
|
pub fn push_layer(
|
|
|
|
&mut self,
|
|
|
|
blend: impl Into<BlendMode>,
|
2022-11-30 05:28:25 +11:00
|
|
|
alpha: f32,
|
2022-11-24 04:50:28 +11:00
|
|
|
transform: Affine,
|
|
|
|
shape: &impl Shape,
|
|
|
|
) {
|
|
|
|
let blend = blend.into();
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_transform(Transform::from_kurbo(&transform));
|
|
|
|
self.scene.encode_linewidth(-1.0);
|
|
|
|
if !self.scene.encode_shape(shape, true) {
|
2022-11-24 08:51:30 +11:00
|
|
|
// If the layer shape is invalid, encode a valid empty path. This suppresses
|
|
|
|
// all drawing until the layer is popped.
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_shape(&Rect::new(0.0, 0.0, 0.0, 0.0), true);
|
2022-11-23 07:17:50 +11:00
|
|
|
}
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.encode_begin_clip(blend, alpha.clamp(0.0, 1.0));
|
2022-11-30 05:28:25 +11:00
|
|
|
self.layer_depth += 1;
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Pops the current layer.
|
2022-04-11 20:05:40 +10:00
|
|
|
pub fn pop_layer(&mut self) {
|
2022-11-30 05:28:25 +11:00
|
|
|
if self.layer_depth > 0 {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.encode_end_clip();
|
2022-11-30 05:28:25 +11:00
|
|
|
self.layer_depth -= 1;
|
2022-04-11 20:05:40 +10:00
|
|
|
}
|
|
|
|
}
|
2022-04-11 19:30:08 +10:00
|
|
|
|
|
|
|
/// Fills a shape using the specified style and brush.
|
2022-11-24 04:50:28 +11:00
|
|
|
pub fn fill<'b>(
|
2022-04-11 19:30:08 +10:00
|
|
|
&mut self,
|
2023-01-11 07:22:04 +11:00
|
|
|
style: Fill,
|
2022-08-17 04:52:04 +10:00
|
|
|
transform: Affine,
|
2022-11-24 04:50:28 +11:00
|
|
|
brush: impl Into<BrushRef<'b>>,
|
2022-04-11 19:30:08 +10:00
|
|
|
brush_transform: Option<Affine>,
|
2022-11-23 06:49:51 +11:00
|
|
|
shape: &impl Shape,
|
|
|
|
) {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_transform(Transform::from_kurbo(&transform));
|
2023-01-11 07:22:04 +11:00
|
|
|
self.scene.encode_linewidth(match style {
|
|
|
|
Fill::NonZero => -1.0,
|
|
|
|
Fill::EvenOdd => -2.0,
|
|
|
|
});
|
2023-01-07 08:52:41 +11:00
|
|
|
if self.scene.encode_shape(shape, true) {
|
2022-08-12 05:29:15 +10:00
|
|
|
if let Some(brush_transform) = brush_transform {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_transform(Transform::from_kurbo(&(transform * brush_transform)));
|
|
|
|
self.scene.swap_last_path_tags();
|
|
|
|
self.scene.encode_brush(brush, 1.0);
|
2022-07-16 04:36:20 +10:00
|
|
|
} else {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.encode_brush(brush, 1.0);
|
2022-07-16 04:36:20 +10:00
|
|
|
}
|
2022-04-11 20:05:40 +10:00
|
|
|
}
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Strokes a shape using the specified style and brush.
|
2022-11-24 04:50:28 +11:00
|
|
|
pub fn stroke<'b>(
|
2022-04-11 19:30:08 +10:00
|
|
|
&mut self,
|
2022-11-23 06:49:51 +11:00
|
|
|
style: &Stroke,
|
2022-08-17 04:52:04 +10:00
|
|
|
transform: Affine,
|
2022-11-24 04:50:28 +11:00
|
|
|
brush: impl Into<BrushRef<'b>>,
|
2022-04-11 19:30:08 +10:00
|
|
|
brush_transform: Option<Affine>,
|
2022-11-23 06:49:51 +11:00
|
|
|
shape: &impl Shape,
|
|
|
|
) {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_transform(Transform::from_kurbo(&transform));
|
|
|
|
self.scene.encode_linewidth(style.width);
|
|
|
|
if self.scene.encode_shape(shape, false) {
|
2022-08-12 05:29:15 +10:00
|
|
|
if let Some(brush_transform) = brush_transform {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene
|
|
|
|
.encode_transform(Transform::from_kurbo(&(transform * brush_transform)));
|
|
|
|
self.scene.swap_last_path_tags();
|
|
|
|
self.scene.encode_brush(brush, 1.0);
|
2022-07-16 04:36:20 +10:00
|
|
|
} else {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.encode_brush(brush, 1.0);
|
2022-07-16 04:36:20 +10:00
|
|
|
}
|
2022-04-11 20:05:40 +10:00
|
|
|
}
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Appends a fragment to the scene.
|
2022-08-12 05:29:15 +10:00
|
|
|
pub fn append(&mut self, fragment: &SceneFragment, transform: Option<Affine>) {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.append(
|
|
|
|
&fragment.data,
|
|
|
|
&transform.map(|xform| Transform::from_kurbo(&xform)),
|
|
|
|
);
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Completes construction and finalizes the underlying scene.
|
2023-01-07 08:52:41 +11:00
|
|
|
pub fn finish(self) {
|
2022-11-30 05:28:25 +11:00
|
|
|
for _ in 0..self.layer_depth {
|
2023-01-07 08:52:41 +11:00
|
|
|
self.scene.encode_end_clip();
|
2022-04-11 19:30:08 +10:00
|
|
|
}
|
|
|
|
}
|
2022-12-10 05:23:03 +11:00
|
|
|
}
|