2021-10-22 10:08:27 +11:00
|
|
|
|
use std::borrow::Cow;
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
2021-12-07 06:08:58 +11:00
|
|
|
|
use crate::encoder::GlyphEncoder;
|
|
|
|
|
use crate::stages::{Config, Transform};
|
2021-08-17 09:54:31 +10:00
|
|
|
|
use crate::MAX_BLEND_STACK;
|
2021-10-22 10:08:27 +11:00
|
|
|
|
use piet::kurbo::{Affine, Insets, PathEl, Point, Rect, Shape};
|
2020-11-15 03:22:56 +11:00
|
|
|
|
use piet::{
|
2021-10-22 10:08:27 +11:00
|
|
|
|
Color, Error, FixedGradient, ImageFormat, InterpolationMode, IntoBrush, RenderContext,
|
|
|
|
|
StrokeStyle,
|
2020-04-23 03:28:38 +10:00
|
|
|
|
};
|
|
|
|
|
|
2021-12-03 10:07:33 +11:00
|
|
|
|
use piet_gpu_hal::BufWrite;
|
2021-04-11 14:20:40 +10:00
|
|
|
|
use piet_gpu_types::encoder::{Encode, Encoder};
|
2021-12-09 05:42:35 +11:00
|
|
|
|
use piet_gpu_types::scene::Element;
|
2021-04-11 14:20:40 +10:00
|
|
|
|
|
2021-06-24 04:50:51 +10:00
|
|
|
|
use crate::gradient::{LinearGradient, RampCache};
|
2021-04-09 03:14:09 +10:00
|
|
|
|
use crate::text::Font;
|
2021-12-07 06:08:58 +11:00
|
|
|
|
pub use crate::text::{PietGpuText, PietGpuTextLayout, PietGpuTextLayoutBuilder};
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
pub struct PietGpuImage;
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
pub struct PietGpuRenderContext {
|
|
|
|
|
encoder: Encoder,
|
2020-05-12 13:01:06 +10:00
|
|
|
|
elements: Vec<Element>,
|
2020-04-23 03:28:38 +10:00
|
|
|
|
// Will probably need direct accesss to hal Device to create images etc.
|
|
|
|
|
inner_text: PietGpuText,
|
2020-05-12 13:01:06 +10:00
|
|
|
|
stroke_width: f32,
|
2020-06-03 10:10:20 +10:00
|
|
|
|
// We're tallying these cpu-side for expedience, but will probably
|
|
|
|
|
// move this to some kind of readback from element processing.
|
2020-11-20 06:53:59 +11:00
|
|
|
|
/// The count of elements that make it through to coarse rasterization.
|
2020-06-03 10:10:20 +10:00
|
|
|
|
path_count: usize,
|
2020-11-20 06:53:59 +11:00
|
|
|
|
/// The count of path segment elements.
|
2020-06-03 10:10:20 +10:00
|
|
|
|
pathseg_count: usize,
|
2021-03-15 22:28:04 +11:00
|
|
|
|
/// The count of transform elements.
|
|
|
|
|
trans_count: usize,
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
|
|
|
|
cur_transform: Affine,
|
|
|
|
|
state_stack: Vec<State>,
|
|
|
|
|
clip_stack: Vec<ClipElement>,
|
2021-06-24 04:50:51 +10:00
|
|
|
|
|
|
|
|
|
ramp_cache: RampCache,
|
2021-12-03 10:07:33 +11:00
|
|
|
|
|
|
|
|
|
// Fields for new element processing pipeline below
|
|
|
|
|
// TODO: delete old encoder, rename
|
|
|
|
|
new_encoder: crate::encoder::Encoder,
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub enum PietGpuBrush {
|
|
|
|
|
Solid(u32),
|
2021-06-24 04:50:51 +10:00
|
|
|
|
LinGradient(LinearGradient),
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-20 06:53:59 +11:00
|
|
|
|
#[derive(Default)]
|
|
|
|
|
struct State {
|
|
|
|
|
/// The transform relative to the parent state.
|
2020-11-21 04:26:02 +11:00
|
|
|
|
rel_transform: Affine,
|
|
|
|
|
/// The transform at the parent state.
|
|
|
|
|
///
|
|
|
|
|
/// This invariant should hold: transform * rel_transform = cur_transform
|
2020-11-20 06:53:59 +11:00
|
|
|
|
transform: Affine,
|
|
|
|
|
n_clip: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ClipElement {
|
2021-12-08 12:24:07 +11:00
|
|
|
|
/// Byte offset of BeginClip element in element vec, for bbox fixup.
|
|
|
|
|
save_point: usize,
|
2020-11-20 06:53:59 +11:00
|
|
|
|
bbox: Option<Rect>,
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-03 02:50:36 +10:00
|
|
|
|
const TOLERANCE: f64 = 0.25;
|
2020-04-25 06:06:47 +10:00
|
|
|
|
|
2020-04-23 03:28:38 +10:00
|
|
|
|
impl PietGpuRenderContext {
|
|
|
|
|
pub fn new() -> PietGpuRenderContext {
|
2020-05-12 13:01:06 +10:00
|
|
|
|
let encoder = Encoder::new();
|
|
|
|
|
let elements = Vec::new();
|
2021-04-09 03:14:09 +10:00
|
|
|
|
let font = Font::new();
|
|
|
|
|
let inner_text = PietGpuText::new(font);
|
2021-12-03 10:07:33 +11:00
|
|
|
|
let stroke_width = -1.0;
|
2020-04-23 03:28:38 +10:00
|
|
|
|
PietGpuRenderContext {
|
|
|
|
|
encoder,
|
2020-05-12 13:01:06 +10:00
|
|
|
|
elements,
|
2020-04-23 03:28:38 +10:00
|
|
|
|
inner_text,
|
2020-05-12 13:01:06 +10:00
|
|
|
|
stroke_width,
|
2020-06-03 10:10:20 +10:00
|
|
|
|
path_count: 0,
|
|
|
|
|
pathseg_count: 0,
|
2021-03-15 22:28:04 +11:00
|
|
|
|
trans_count: 0,
|
2020-11-20 06:53:59 +11:00
|
|
|
|
cur_transform: Affine::default(),
|
|
|
|
|
state_stack: Vec::new(),
|
|
|
|
|
clip_stack: Vec::new(),
|
2021-06-24 04:50:51 +10:00
|
|
|
|
ramp_cache: RampCache::default(),
|
2021-12-03 10:07:33 +11:00
|
|
|
|
new_encoder: crate::encoder::Encoder::new(),
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-03 10:07:33 +11:00
|
|
|
|
pub fn stage_config(&self) -> (Config, usize) {
|
|
|
|
|
self.new_encoder.stage_config()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Number of draw objects.
|
|
|
|
|
///
|
|
|
|
|
/// This is for the new element processing pipeline. It's not necessarily the
|
|
|
|
|
/// same as the number of paths (as in the old pipeline), but it might take a
|
|
|
|
|
/// while to sort that out.
|
|
|
|
|
pub fn n_drawobj(&self) -> usize {
|
|
|
|
|
self.new_encoder.n_drawobj()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Number of paths.
|
|
|
|
|
pub fn n_path(&self) -> u32 {
|
|
|
|
|
self.new_encoder.n_path()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn n_pathseg(&self) -> u32 {
|
|
|
|
|
self.new_encoder.n_pathseg()
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-07 10:59:32 +11:00
|
|
|
|
pub fn n_pathtag(&self) -> usize {
|
|
|
|
|
self.new_encoder.n_pathtag()
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-03 10:07:33 +11:00
|
|
|
|
pub fn n_transform(&self) -> usize {
|
|
|
|
|
self.new_encoder.n_transform()
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 11:25:41 +11:00
|
|
|
|
pub fn n_clip(&self) -> u32 {
|
|
|
|
|
self.new_encoder.n_clip()
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-03 10:07:33 +11:00
|
|
|
|
pub fn write_scene(&self, buf: &mut BufWrite) {
|
|
|
|
|
self.new_encoder.write_scene(buf);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-23 03:28:38 +10:00
|
|
|
|
pub fn get_scene_buf(&mut self) -> &[u8] {
|
2021-09-01 05:46:28 +10:00
|
|
|
|
const ALIGN: usize = 128;
|
|
|
|
|
let padded_size = (self.elements.len() + (ALIGN - 1)) & ALIGN.wrapping_neg();
|
|
|
|
|
self.elements.resize(padded_size, Element::Nop());
|
2020-05-12 13:01:06 +10:00
|
|
|
|
self.elements.encode(&mut self.encoder);
|
2020-04-23 03:28:38 +10:00
|
|
|
|
self.encoder.buf()
|
|
|
|
|
}
|
2020-06-03 10:10:20 +10:00
|
|
|
|
|
|
|
|
|
pub fn path_count(&self) -> usize {
|
|
|
|
|
self.path_count
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pathseg_count(&self) -> usize {
|
|
|
|
|
self.pathseg_count
|
|
|
|
|
}
|
2021-03-15 22:28:04 +11:00
|
|
|
|
|
|
|
|
|
pub fn trans_count(&self) -> usize {
|
|
|
|
|
self.trans_count
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
2021-08-04 02:04:19 +10:00
|
|
|
|
pub fn get_ramp_data(&self) -> Vec<u32> {
|
|
|
|
|
self.ramp_cache.get_ramp_data()
|
|
|
|
|
}
|
2021-03-19 23:49:47 +11:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-23 03:28:38 +10:00
|
|
|
|
impl RenderContext for PietGpuRenderContext {
|
|
|
|
|
type Brush = PietGpuBrush;
|
|
|
|
|
type Image = PietGpuImage;
|
|
|
|
|
type Text = PietGpuText;
|
|
|
|
|
type TextLayout = PietGpuTextLayout;
|
|
|
|
|
|
|
|
|
|
fn status(&mut self) -> Result<(), Error> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn solid_brush(&mut self, color: Color) -> Self::Brush {
|
2021-04-11 14:20:40 +10:00
|
|
|
|
// kernel4 expects colors encoded in alpha-premultiplied sRGB:
|
|
|
|
|
//
|
|
|
|
|
// [α,sRGB(α⋅R),sRGB(α⋅G),sRGB(α⋅B)]
|
|
|
|
|
//
|
|
|
|
|
// See also http://ssp.impulsetrain.com/gamma-premult.html.
|
|
|
|
|
let (r, g, b, a) = color.as_rgba();
|
2021-04-09 03:14:09 +10:00
|
|
|
|
let premul = Color::rgba(
|
|
|
|
|
to_srgb(from_srgb(r) * a),
|
|
|
|
|
to_srgb(from_srgb(g) * a),
|
|
|
|
|
to_srgb(from_srgb(b) * a),
|
|
|
|
|
a,
|
|
|
|
|
);
|
2021-04-11 14:20:40 +10:00
|
|
|
|
PietGpuBrush::Solid(premul.as_rgba_u32())
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-24 04:50:51 +10:00
|
|
|
|
fn gradient(&mut self, gradient: impl Into<FixedGradient>) -> Result<Self::Brush, Error> {
|
|
|
|
|
match gradient.into() {
|
|
|
|
|
FixedGradient::Linear(lin) => {
|
|
|
|
|
let lin = self.ramp_cache.add_linear_gradient(&lin);
|
|
|
|
|
Ok(PietGpuBrush::LinGradient(lin))
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("don't do radial gradients yet"),
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear(&mut self, _color: Color) {}
|
|
|
|
|
|
2020-04-25 06:06:47 +10:00
|
|
|
|
fn stroke(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>, width: f64) {
|
2021-12-03 10:07:33 +11:00
|
|
|
|
self.encode_linewidth(width.abs() as f32);
|
2020-05-12 13:01:06 +10:00
|
|
|
|
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
2021-08-04 02:04:19 +10:00
|
|
|
|
// Note: the bbox contribution of stroke becomes more complicated with miter joins.
|
|
|
|
|
self.accumulate_bbox(|| shape.bounding_box() + Insets::uniform(width * 0.5));
|
|
|
|
|
let path = shape.path_elements(TOLERANCE);
|
|
|
|
|
self.encode_path(path, false);
|
|
|
|
|
self.encode_brush(&brush);
|
2020-04-25 06:06:47 +10:00
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn stroke_styled(
|
|
|
|
|
&mut self,
|
|
|
|
|
_shape: impl Shape,
|
|
|
|
|
_brush: &impl IntoBrush<Self>,
|
|
|
|
|
_width: f64,
|
|
|
|
|
_style: &StrokeStyle,
|
2021-04-09 03:14:09 +10:00
|
|
|
|
) {
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
2020-04-25 06:06:47 +10:00
|
|
|
|
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
2021-08-04 02:04:19 +10:00
|
|
|
|
// Note: we might get a good speedup from using an approximate bounding box.
|
|
|
|
|
// Perhaps that should be added to kurbo.
|
|
|
|
|
self.accumulate_bbox(|| shape.bounding_box());
|
|
|
|
|
let path = shape.path_elements(TOLERANCE);
|
2021-12-03 10:07:33 +11:00
|
|
|
|
self.encode_linewidth(-1.0);
|
2021-08-04 02:04:19 +10:00
|
|
|
|
self.encode_path(path, true);
|
|
|
|
|
self.encode_brush(&brush);
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fill_even_odd(&mut self, _shape: impl Shape, _brush: &impl IntoBrush<Self>) {}
|
|
|
|
|
|
2020-11-20 06:53:59 +11:00
|
|
|
|
fn clip(&mut self, shape: impl Shape) {
|
2021-12-08 12:24:07 +11:00
|
|
|
|
self.encode_linewidth(-1.0);
|
2020-11-20 06:53:59 +11:00
|
|
|
|
let path = shape.path_elements(TOLERANCE);
|
|
|
|
|
self.encode_path(path, true);
|
2021-12-08 12:24:07 +11:00
|
|
|
|
let save_point = self.new_encoder.begin_clip();
|
2021-03-30 14:59:49 +11:00
|
|
|
|
if self.clip_stack.len() >= MAX_BLEND_STACK {
|
|
|
|
|
panic!("Maximum clip/blend stack size {} exceeded", MAX_BLEND_STACK);
|
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
self.clip_stack.push(ClipElement {
|
|
|
|
|
bbox: None,
|
2021-12-08 12:24:07 +11:00
|
|
|
|
save_point,
|
2020-11-20 06:53:59 +11:00
|
|
|
|
});
|
2020-11-21 04:26:02 +11:00
|
|
|
|
if let Some(tos) = self.state_stack.last_mut() {
|
|
|
|
|
tos.n_clip += 1;
|
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn text(&mut self) -> &mut Self::Text {
|
|
|
|
|
&mut self.inner_text
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
fn draw_text(&mut self, layout: &Self::TextLayout, pos: impl Into<Point>) {
|
2021-12-07 06:08:58 +11:00
|
|
|
|
self.encode_linewidth(-1.0);
|
2021-04-09 03:14:09 +10:00
|
|
|
|
layout.draw_text(self, pos.into());
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn save(&mut self) -> Result<(), Error> {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
self.state_stack.push(State {
|
|
|
|
|
rel_transform: Affine::default(),
|
|
|
|
|
transform: self.cur_transform,
|
|
|
|
|
n_clip: 0,
|
|
|
|
|
});
|
2020-04-23 03:28:38 +10:00
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
2020-04-23 03:28:38 +10:00
|
|
|
|
fn restore(&mut self) -> Result<(), Error> {
|
2020-11-20 06:53:59 +11:00
|
|
|
|
if let Some(state) = self.state_stack.pop() {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
if state.rel_transform != Affine::default() {
|
|
|
|
|
let a_inv = state.rel_transform.inverse();
|
2021-12-07 06:08:58 +11:00
|
|
|
|
self.encode_transform(Transform::from_kurbo(a_inv));
|
2020-11-20 06:53:59 +11:00
|
|
|
|
}
|
2020-11-21 04:26:02 +11:00
|
|
|
|
self.cur_transform = state.transform;
|
2020-11-20 06:53:59 +11:00
|
|
|
|
for _ in 0..state.n_clip {
|
|
|
|
|
self.pop_clip();
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
} else {
|
|
|
|
|
Err(Error::StackUnbalance)
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
2020-04-23 03:28:38 +10:00
|
|
|
|
fn finish(&mut self) -> Result<(), Error> {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
for _ in 0..self.clip_stack.len() {
|
|
|
|
|
self.pop_clip();
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
|
|
|
|
fn transform(&mut self, transform: Affine) {
|
2021-12-07 06:08:58 +11:00
|
|
|
|
self.encode_transform(Transform::from_kurbo(transform));
|
2020-11-20 06:53:59 +11:00
|
|
|
|
if let Some(tos) = self.state_stack.last_mut() {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
tos.rel_transform *= transform;
|
2020-11-20 06:53:59 +11:00
|
|
|
|
}
|
|
|
|
|
self.cur_transform *= transform;
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn make_image(
|
|
|
|
|
&mut self,
|
|
|
|
|
_width: usize,
|
|
|
|
|
_height: usize,
|
|
|
|
|
_buf: &[u8],
|
|
|
|
|
_format: ImageFormat,
|
|
|
|
|
) -> Result<Self::Image, Error> {
|
|
|
|
|
Ok(PietGpuImage)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn draw_image(
|
|
|
|
|
&mut self,
|
|
|
|
|
_image: &Self::Image,
|
|
|
|
|
_rect: impl Into<Rect>,
|
|
|
|
|
_interp: InterpolationMode,
|
2021-04-09 03:14:09 +10:00
|
|
|
|
) {
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn draw_image_area(
|
|
|
|
|
&mut self,
|
|
|
|
|
_image: &Self::Image,
|
|
|
|
|
_src_rect: impl Into<Rect>,
|
|
|
|
|
_dst_rect: impl Into<Rect>,
|
|
|
|
|
_interp: InterpolationMode,
|
2021-04-09 03:14:09 +10:00
|
|
|
|
) {
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
|
|
|
|
|
fn blurred_rect(&mut self, _rect: Rect, _blur_radius: f64, _brush: &impl IntoBrush<Self>) {}
|
|
|
|
|
|
|
|
|
|
fn current_transform(&self) -> Affine {
|
2020-11-20 06:53:59 +11:00
|
|
|
|
self.cur_transform
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn with_save(&mut self, f: impl FnOnce(&mut Self) -> Result<(), Error>) -> Result<(), Error> {
|
|
|
|
|
self.save()?;
|
|
|
|
|
// Always try to restore the stack, even if `f` errored.
|
|
|
|
|
f(self).and(self.restore())
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-12 13:01:06 +10:00
|
|
|
|
impl PietGpuRenderContext {
|
2021-04-09 03:14:09 +10:00
|
|
|
|
fn encode_path(&mut self, path: impl Iterator<Item = PathEl>, is_fill: bool) {
|
2021-03-17 02:51:13 +11:00
|
|
|
|
if is_fill {
|
2021-04-03 12:59:07 +11:00
|
|
|
|
self.encode_path_inner(
|
|
|
|
|
path.flat_map(|el| {
|
|
|
|
|
match el {
|
|
|
|
|
PathEl::MoveTo(..) => Some(PathEl::ClosePath),
|
|
|
|
|
_ => None,
|
2021-03-17 02:51:13 +11:00
|
|
|
|
}
|
2021-04-03 12:59:07 +11:00
|
|
|
|
.into_iter()
|
|
|
|
|
.chain(Some(el))
|
|
|
|
|
})
|
|
|
|
|
.chain(Some(PathEl::ClosePath)),
|
|
|
|
|
)
|
2021-03-17 02:51:13 +11:00
|
|
|
|
} else {
|
2021-03-19 23:49:47 +11:00
|
|
|
|
self.encode_path_inner(path)
|
2021-03-17 02:51:13 +11:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
fn encode_path_inner(&mut self, path: impl Iterator<Item = PathEl>) {
|
2021-12-03 10:07:33 +11:00
|
|
|
|
let mut pe = self.new_encoder.path_encoder();
|
|
|
|
|
for el in path {
|
|
|
|
|
match el {
|
|
|
|
|
PathEl::MoveTo(p) => {
|
|
|
|
|
let p = to_f32_2(p);
|
|
|
|
|
pe.move_to(p[0], p[1]);
|
2020-04-25 06:06:47 +10:00
|
|
|
|
}
|
2021-12-03 10:07:33 +11:00
|
|
|
|
PathEl::LineTo(p) => {
|
|
|
|
|
let p = to_f32_2(p);
|
|
|
|
|
pe.line_to(p[0], p[1]);
|
|
|
|
|
}
|
|
|
|
|
PathEl::QuadTo(p1, p2) => {
|
|
|
|
|
let p1 = to_f32_2(p1);
|
|
|
|
|
let p2 = to_f32_2(p2);
|
|
|
|
|
pe.quad_to(p1[0], p1[1], p2[0], p2[1]);
|
2020-04-25 06:06:47 +10:00
|
|
|
|
}
|
2021-12-03 10:07:33 +11:00
|
|
|
|
PathEl::CurveTo(p1, p2, p3) => {
|
|
|
|
|
let p1 = to_f32_2(p1);
|
|
|
|
|
let p2 = to_f32_2(p2);
|
|
|
|
|
let p3 = to_f32_2(p3);
|
|
|
|
|
pe.cubic_to(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);
|
|
|
|
|
}
|
|
|
|
|
PathEl::ClosePath => pe.close_path(),
|
2020-04-25 06:06:47 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-03 10:07:33 +11:00
|
|
|
|
pe.path();
|
|
|
|
|
let n_pathseg = pe.n_pathseg();
|
|
|
|
|
self.new_encoder.finish_path(n_pathseg);
|
2020-05-12 13:01:06 +10:00
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
|
|
|
|
fn pop_clip(&mut self) {
|
|
|
|
|
let tos = self.clip_stack.pop().unwrap();
|
2020-11-21 04:26:02 +11:00
|
|
|
|
let bbox = tos.bbox.unwrap_or_default();
|
|
|
|
|
let bbox_f32_4 = rect_to_f32_4(bbox);
|
2021-12-08 12:24:07 +11:00
|
|
|
|
self.new_encoder.end_clip(bbox_f32_4, tos.save_point);
|
2020-11-20 06:53:59 +11:00
|
|
|
|
if let Some(bbox) = tos.bbox {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
self.union_bbox(bbox);
|
2020-11-20 06:53:59 +11:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 04:26:02 +11:00
|
|
|
|
/// Accumulate a bbox.
|
|
|
|
|
///
|
|
|
|
|
/// The bbox is given lazily as a closure, relative to the current transform.
|
|
|
|
|
/// It's lazy because we don't need to compute it unless we're inside a clip.
|
2020-11-20 06:53:59 +11:00
|
|
|
|
fn accumulate_bbox(&mut self, f: impl FnOnce() -> Rect) {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
if !self.clip_stack.is_empty() {
|
2020-11-20 06:53:59 +11:00
|
|
|
|
let bbox = f();
|
2020-11-21 04:26:02 +11:00
|
|
|
|
let bbox = self.cur_transform.transform_rect_bbox(bbox);
|
|
|
|
|
self.union_bbox(bbox);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Accumulate an absolute bbox.
|
|
|
|
|
///
|
|
|
|
|
/// The bbox is given already transformed into surface coordinates.
|
|
|
|
|
fn union_bbox(&mut self, bbox: Rect) {
|
|
|
|
|
if let Some(tos) = self.clip_stack.last_mut() {
|
2020-11-20 06:53:59 +11:00
|
|
|
|
tos.bbox = if let Some(old_bbox) = tos.bbox {
|
|
|
|
|
Some(old_bbox.union(bbox))
|
|
|
|
|
} else {
|
|
|
|
|
Some(bbox)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-15 03:22:56 +11:00
|
|
|
|
|
2021-12-07 06:08:58 +11:00
|
|
|
|
pub(crate) fn encode_glyph(&mut self, glyph: &GlyphEncoder) {
|
|
|
|
|
self.new_encoder.encode_glyph(glyph);
|
2020-11-15 03:22:56 +11:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
pub(crate) fn fill_glyph(&mut self, rgba_color: u32) {
|
2021-12-07 06:08:58 +11:00
|
|
|
|
self.new_encoder.fill_color(rgba_color);
|
2021-08-26 06:59:26 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
pub(crate) fn encode_transform(&mut self, transform: Transform) {
|
2021-12-07 06:08:58 +11:00
|
|
|
|
self.new_encoder.transform(transform);
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
2021-08-04 02:04:19 +10:00
|
|
|
|
|
2021-12-03 10:07:33 +11:00
|
|
|
|
fn encode_linewidth(&mut self, linewidth: f32) {
|
|
|
|
|
if self.stroke_width != linewidth {
|
|
|
|
|
self.new_encoder.linewidth(linewidth);
|
|
|
|
|
self.stroke_width = linewidth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-04 02:04:19 +10:00
|
|
|
|
fn encode_brush(&mut self, brush: &PietGpuBrush) {
|
|
|
|
|
match brush {
|
|
|
|
|
PietGpuBrush::Solid(rgba_color) => {
|
2021-12-03 10:07:33 +11:00
|
|
|
|
self.new_encoder.fill_color(*rgba_color);
|
2021-08-04 02:04:19 +10:00
|
|
|
|
}
|
|
|
|
|
PietGpuBrush::LinGradient(lin) => {
|
2021-12-08 12:24:07 +11:00
|
|
|
|
self.new_encoder
|
|
|
|
|
.fill_lin_gradient(lin.ramp_id, lin.start, lin.end);
|
2021-08-04 02:04:19 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-23 03:28:38 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl IntoBrush<PietGpuRenderContext> for PietGpuBrush {
|
|
|
|
|
fn make_brush<'b>(
|
|
|
|
|
&'b self,
|
|
|
|
|
_piet: &mut PietGpuRenderContext,
|
|
|
|
|
_bbox: impl FnOnce() -> Rect,
|
|
|
|
|
) -> std::borrow::Cow<'b, PietGpuBrush> {
|
|
|
|
|
Cow::Borrowed(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 03:14:09 +10:00
|
|
|
|
pub(crate) fn to_f32_2(point: Point) -> [f32; 2] {
|
2020-05-12 13:01:06 +10:00
|
|
|
|
[point.x as f32, point.y as f32]
|
2020-04-25 06:06:47 +10:00
|
|
|
|
}
|
2020-11-20 06:53:59 +11:00
|
|
|
|
|
|
|
|
|
fn rect_to_f32_4(rect: Rect) -> [f32; 4] {
|
2020-11-21 04:26:02 +11:00
|
|
|
|
[
|
|
|
|
|
rect.x0 as f32,
|
|
|
|
|
rect.y0 as f32,
|
|
|
|
|
rect.x1 as f32,
|
|
|
|
|
rect.y1 as f32,
|
|
|
|
|
]
|
2020-11-20 06:53:59 +11:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 14:20:40 +10:00
|
|
|
|
fn to_srgb(f: f64) -> f64 {
|
|
|
|
|
if f <= 0.0031308 {
|
|
|
|
|
f * 12.92
|
|
|
|
|
} else {
|
|
|
|
|
let a = 0.055;
|
|
|
|
|
(1. + a) * f64::powf(f, f64::recip(2.4)) - a
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn from_srgb(f: f64) -> f64 {
|
|
|
|
|
if f <= 0.04045 {
|
|
|
|
|
f / 12.92
|
|
|
|
|
} else {
|
|
|
|
|
let a = 0.055;
|
|
|
|
|
f64::powf((f + a) * f64::recip(1. + a), 2.4)
|
|
|
|
|
}
|
2021-04-09 03:14:09 +10:00
|
|
|
|
}
|