mirror of
https://github.com/penpot/penpot.git
synced 2026-07-31 18:36:18 +00:00
WIP
This commit is contained in:
parent
fe6e2b97fa
commit
bdff7730d6
@ -20,10 +20,7 @@ use std::collections::HashMap;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::error::{Error, Result};
|
||||
use crate::{
|
||||
render::{FrameType, RenderFlag},
|
||||
shapes::Frame,
|
||||
};
|
||||
use crate::render::FrameType;
|
||||
|
||||
use globals::{get_design_state, get_gpu_state, get_render_state};
|
||||
|
||||
@ -108,24 +105,12 @@ pub extern "C" fn set_canvas_background(raw_color: u32) -> Result<()> {
|
||||
|
||||
#[no_mangle]
|
||||
#[wasm_error]
|
||||
pub extern "C" fn render2(timestamp: i32, flags: u8) -> Result<FrameType> {
|
||||
pub extern "C" fn render2(timestamp: i32, _flags: u8) -> Result<FrameType> {
|
||||
with_state!(state, {
|
||||
let render_state = get_render_state();
|
||||
|
||||
render_state.prepare_render_loop(&mut state.shapes)?;
|
||||
let frame_type = if flags & RenderFlag::Partial as u8 == RenderFlag::Partial as u8 {
|
||||
// TODO: Meter una flag que lo que haga es indicar
|
||||
// si el render es sync o no y que esto no permita
|
||||
let allow_stop = true;
|
||||
render_state
|
||||
.continue_render_loop(timestamp, allow_stop)
|
||||
.map_err(|_| Error::RecoverableError("Error rendering".to_string()))?
|
||||
} else {
|
||||
let sync_render = false;
|
||||
render_state
|
||||
.start_render_loop(timestamp, sync_render)
|
||||
.map_err(|_| Error::RecoverableError("Error rendering".to_string()))?
|
||||
};
|
||||
let frame_type = render_state
|
||||
.render_backbuffer_vector(&state.shapes, timestamp)
|
||||
.map_err(|_| Error::RecoverableError("Error rendering".to_string()))?;
|
||||
render_state.end_render_loop(&frame_type);
|
||||
return Ok(frame_type);
|
||||
});
|
||||
|
||||
@ -1347,6 +1347,110 @@ impl RenderState {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn render_backbuffer_vector(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
_timestamp: i32,
|
||||
) -> Result<FrameType> {
|
||||
#[cfg(feature = "stats")]
|
||||
self.stats.clear();
|
||||
|
||||
self.surfaces.clear_backbuffer(self.background_color);
|
||||
self.surfaces.clear_target(self.background_color);
|
||||
|
||||
self.pending_nodes.clear();
|
||||
self.nested_fills.clear();
|
||||
self.nested_blurs.clear();
|
||||
self.cached_layer_blur = None;
|
||||
self.nested_shadows.clear();
|
||||
self.focus_mode.reset();
|
||||
|
||||
let tile_render_state = get_tile_render_state();
|
||||
tile_render_state.current = None;
|
||||
|
||||
self.empty_grid_frame_ids.clear();
|
||||
if self.show_grid.is_some() {
|
||||
for shape in tree.iter() {
|
||||
if shape.id.is_nil() || !shape.children.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let Type::Frame(frame) = &shape.shape_type {
|
||||
if matches!(frame.layout, Some(Layout::GridLayout(_, _))) && !shape.deleted() {
|
||||
self.empty_grid_frame_ids.insert(shape.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let scale = self.get_scale();
|
||||
let offset = self.viewbox.get_offset();
|
||||
let pan = self.viewbox.pan();
|
||||
let area = self.viewbox.area;
|
||||
|
||||
println!(
|
||||
"VECTOR: scale={scale} pan=({},{}) area=({},{},{},{}) offset=({},{}) dpr={} zoom={}",
|
||||
pan.x, pan.y,
|
||||
area.left, area.top, area.right, area.bottom,
|
||||
offset.x, offset.y,
|
||||
self.viewbox.dpr, self.viewbox.zoom,
|
||||
);
|
||||
|
||||
// Apply viewbox transform to backbuffer canvas.
|
||||
self.surfaces.canvas(SurfaceId::Backbuffer).save();
|
||||
{
|
||||
let canvas = self.surfaces.canvas(SurfaceId::Backbuffer);
|
||||
canvas.restore_to_count(1);
|
||||
canvas.save();
|
||||
canvas.scale((scale, scale));
|
||||
canvas.translate((-offset.x, -offset.y));
|
||||
}
|
||||
|
||||
// Determine root frames to render.
|
||||
self.viewer_render_root = self.base_object;
|
||||
let root_ids: Vec<Uuid> = {
|
||||
if let Some(shape_id) = self.base_object {
|
||||
vec![shape_id]
|
||||
} else if let Some(root) = tree.get(&Uuid::nil()) {
|
||||
root.children_ids(false)
|
||||
} else {
|
||||
return Err(Error::CriticalError(
|
||||
"Root shape not found".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Render each root directly onto the backbuffer canvas using
|
||||
// the vector renderer (CPU Skia canvas, no GPU surface pipelining).
|
||||
for root_id in &root_ids {
|
||||
let canvas_ptr: *const skia::Canvas = {
|
||||
let canvas: &skia::Canvas = self.surfaces.canvas(SurfaceId::Backbuffer);
|
||||
canvas as *const skia::Canvas
|
||||
};
|
||||
let canvas = unsafe { &*canvas_ptr };
|
||||
vector::render_tree(
|
||||
self,
|
||||
canvas,
|
||||
root_id,
|
||||
tree,
|
||||
scale,
|
||||
vector::VectorTarget::Backbuffer,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Restore the viewbox transform.
|
||||
self.surfaces.canvas(SurfaceId::Backbuffer).restore();
|
||||
|
||||
let saved_preview_mode = self.preview_mode;
|
||||
self.preview_mode = true;
|
||||
//self.present_frame();
|
||||
self.surfaces.copy_backbuffer_to_target();
|
||||
self.flush_and_submit();
|
||||
|
||||
self.preview_mode = saved_preview_mode;
|
||||
|
||||
Ok(FrameType::Full)
|
||||
}
|
||||
|
||||
pub fn start_render_loop(&mut self, timestamp: i32, sync_render: bool) -> Result<FrameType> {
|
||||
let design_state = get_design_state();
|
||||
let tree = &design_state.shapes;
|
||||
|
||||
@ -16,10 +16,11 @@ use super::{get_dest_rect, get_source_rect};
|
||||
// VectorTarget — vector export backend selector
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Vector export backend selector (PDF today; SVG could be added as a variant).
|
||||
/// Vector backend selector (PDF export or realtime backbuffer rendering).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(super) enum VectorTarget {
|
||||
Pdf,
|
||||
Backbuffer,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user