Skip to content

Commit

Permalink
Initial commit of piet-next API sketch
Browse files Browse the repository at this point in the history
Ideas for what an API might look like. We'll use the CPU sparse strip implementation to test those ideas.

Currently lots of TODO and very likely things will change, but this should give an idea.
  • Loading branch information
raphlinus committed Dec 3, 2024
1 parent aef3254 commit 7d90b93
Show file tree
Hide file tree
Showing 5 changed files with 532 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ members = [
"piet-web",
"piet-web/examples/basic",
"piet-svg"
]
, "piet-next"]

default-members = [
"piet",
Expand Down
12 changes: 12 additions & 0 deletions piet-next/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "piet-next"
version = "0.1.0"
authors = ["Raph Levien <[email protected]>"]
description = "A testbend for next-generation 2D renderer ideas"
license = "Apache-2.0 OR MIT"
edition = "2021"
keywords = ["graphics", "2d"]
categories = ["graphics"]

[dependencies]
peniko = { git = "https://github.com/linebender/peniko", rev = "aeded39" }
245 changes: 245 additions & 0 deletions piet-next/src/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
// Copyright 2024 the Piet Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

#![allow(unused)]
use std::{any::Any, sync::Arc};

use peniko::{kurbo::Affine, BrushRef};

use crate::{Id, Path, Record, RenderCtx, ResourceCtx};

#[derive(Clone)]
pub struct AnyImage {
// TODO: move id into trait
id: Id,
body: Arc<dyn Any + Send + Sync>,
}

pub trait AnyRecord: Send {
fn as_any(&mut self) -> &mut dyn std::any::Any;

fn dyn_finish(&mut self) -> Arc<dyn Any + Send>;
}

impl<R: Record + Send + 'static> AnyRecord for R
where
<<R as RenderCtx>::Resource as ResourceCtx>::Recording: Sync,
{
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}

fn dyn_finish(&mut self) -> Arc<dyn Any + Send> {
let recording = self.finish();
Arc::new(recording)
}
}

pub trait AnyRenderCtx {
fn as_any(&mut self) -> &mut dyn std::any::Any;

fn dyn_playback(&mut self, recording: &Arc<dyn Any + Send>);

fn dyn_fill(&mut self, path: &Path, brush: BrushRef);
}

impl<RC: RenderCtx + 'static> AnyRenderCtx for RC {
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}

fn dyn_playback(&mut self, recording: &Arc<dyn Any + Send>) {
if let Some(recording) = recording.downcast_ref() {
self.playback(recording)
} else {
panic!("downcast error on playback");
}
}

fn dyn_fill(&mut self, path: &Path, brush: BrushRef) {
self.fill(path, brush)
}
}

pub type BoxedRenderCtx = Box<dyn AnyRenderCtx>;

impl RenderCtx for BoxedRenderCtx {
type Resource = Box<dyn AnyResourceCtx>;

fn playback(&mut self, recording: &Arc<<Self::Resource as ResourceCtx>::Recording>) {
self.dyn_playback(recording);
}

fn fill(&mut self, path: &Path, brush: BrushRef) {
self.dyn_fill(path, brush);
}

fn stroke(&mut self, path: &Path, stroke: &peniko::kurbo::Stroke, brush: BrushRef) {
todo!()
}

fn draw_image(
&mut self,
image: &<Self::Resource as ResourceCtx>::Image,
dst_rect: peniko::kurbo::Rect,
interp: crate::InterpolationMode,
) {
todo!()
}

fn clip(&mut self, path: &Path) {
todo!()
}

fn save(&mut self) {
todo!()
}

fn restore(&mut self) {
todo!()
}

fn transform(&mut self, affine: Affine) {
todo!()
}

fn begin_draw_glyphs(&mut self, font: &peniko::Font) {
todo!()
}

fn font_size(&mut self, size: f32) {
todo!()
}

fn hint(&mut self, hint: bool) {
todo!()
}

fn glyph_brush(&mut self, brush: BrushRef) {
todo!()
}

fn draw_glyphs(&mut self, style: peniko::StyleRef, glyphs: &dyn Iterator<Item = crate::Glyph>) {
todo!()
}

fn end_draw_glyphs(&mut self) {
todo!()
}
}

pub trait AnyResourceCtx {
fn as_any(&mut self) -> &mut dyn std::any::Any;

fn dyn_record(&mut self) -> Box<dyn AnyRecord + Send>;

fn dyn_make_image_with_stride(
&mut self,
width: usize,
height: usize,
stride: usize,
buf: &[u8],
format: crate::ImageFormat,
) -> Result<AnyImage, crate::Error>;
}

impl ResourceCtx for Box<dyn AnyResourceCtx> {
type Image = AnyImage;

type Recording = dyn Any + Send;

type Record = Box<dyn AnyRecord>;

fn record(&mut self) -> Self::Record {
self.dyn_record()
}

fn make_image_with_stride(
&mut self,
width: usize,
height: usize,
stride: usize,
buf: &[u8],
format: crate::ImageFormat,
) -> Result<Self::Image, crate::Error> {
let image = self.dyn_make_image_with_stride(width, height, stride, buf, format)?;
let id = Id::get();
Ok(AnyImage {
id,
body: Arc::new(image),
})
}
}

pub struct BoxedAnyRecord(Option<Box<dyn AnyRecord>>);

impl RenderCtx for Box<dyn AnyRecord> {
type Resource = Box<dyn AnyResourceCtx>;

fn playback(&mut self, recording: &Arc<<Self::Resource as ResourceCtx>::Recording>) {
self.dyn_playback(recording);
}

fn fill(&mut self, path: &Path, brush: BrushRef) {
self.dyn_fill(path, brush);
}

fn stroke(&mut self, path: &Path, stroke: &peniko::kurbo::Stroke, brush: BrushRef) {
todo!()
}

fn draw_image(
&mut self,
image: &<Self::Resource as ResourceCtx>::Image,
dst_rect: peniko::kurbo::Rect,
interp: crate::InterpolationMode,
) {
todo!()
}

fn clip(&mut self, path: &Path) {
todo!()
}

fn save(&mut self) {
todo!()
}

fn restore(&mut self) {
todo!()
}

fn transform(&mut self, affine: Affine) {
todo!()
}

fn begin_draw_glyphs(&mut self, font: &peniko::Font) {
todo!()
}

fn font_size(&mut self, size: f32) {
todo!()
}

fn hint(&mut self, hint: bool) {
todo!()
}

fn glyph_brush(&mut self, brush: BrushRef) {
todo!()
}

fn draw_glyphs(&mut self, style: peniko::StyleRef, glyphs: &dyn Iterator<Item = crate::Glyph>) {
todo!()
}

fn end_draw_glyphs(&mut self) {
todo!()
}
}

impl Record for Box<dyn AnyRecord> {
fn finish(&mut self) -> Arc<<Self::Resource as ResourceCtx>::Recording> {
self.dyn_finish()
}
}
Loading

0 comments on commit 7d90b93

Please sign in to comment.