mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
WIP
This commit is contained in:
@@ -415,6 +415,11 @@ impl RenderState {
|
||||
self.surfaces.canvas(surface_id).restore();
|
||||
}
|
||||
|
||||
pub fn apply_full_render_to_final_canvas(&mut self) {
|
||||
emscripten::log!(emscripten::Log::Default, "apply_full_render_to_final_canvas");
|
||||
self.surfaces.draw_into(SurfaceId::Full, SurfaceId::Target, None);
|
||||
}
|
||||
|
||||
pub fn apply_render_to_final_canvas(&mut self, rect: skia::Rect) {
|
||||
let tile_rect = self.get_current_aligned_tile_bounds();
|
||||
self.surfaces.cache_current_tile_texture(
|
||||
@@ -439,6 +444,58 @@ impl RenderState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_drawing_to_full_render_canvas(&mut self, shape: Option<&Shape>) {
|
||||
performance::begin_measure!("apply_drawing_to_full_render_canvas");
|
||||
|
||||
self.surfaces.draw_into(
|
||||
SurfaceId::DropShadows,
|
||||
SurfaceId::Full,
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
|
||||
self.surfaces.draw_into(
|
||||
SurfaceId::Fills,
|
||||
SurfaceId::Full,
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
|
||||
let mut render_overlay_below_strokes = false;
|
||||
if let Some(shape) = shape {
|
||||
render_overlay_below_strokes = shape.has_fills();
|
||||
}
|
||||
|
||||
if render_overlay_below_strokes {
|
||||
self.surfaces.draw_into(
|
||||
SurfaceId::InnerShadows,
|
||||
SurfaceId::Full,
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
}
|
||||
|
||||
self.surfaces.draw_into(
|
||||
SurfaceId::Strokes,
|
||||
SurfaceId::Full,
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
|
||||
if !render_overlay_below_strokes {
|
||||
self.surfaces.draw_into(
|
||||
SurfaceId::InnerShadows,
|
||||
SurfaceId::Full,
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
}
|
||||
let surface_ids = SurfaceId::Strokes as u32
|
||||
| SurfaceId::Fills as u32
|
||||
| SurfaceId::DropShadows as u32
|
||||
| SurfaceId::InnerShadows as u32;
|
||||
|
||||
self.surfaces.apply_mut(surface_ids, |s| {
|
||||
s.canvas().clear(skia::Color::TRANSPARENT);
|
||||
});
|
||||
performance::end_measure!("apply_drawing_to_full_render_canvas");
|
||||
}
|
||||
|
||||
pub fn apply_drawing_to_render_canvas(&mut self, shape: Option<&Shape>) {
|
||||
performance::begin_measure!("apply_drawing_to_render_canvas");
|
||||
|
||||
@@ -488,6 +545,8 @@ impl RenderState {
|
||||
self.surfaces.apply_mut(surface_ids, |s| {
|
||||
s.canvas().clear(skia::Color::TRANSPARENT);
|
||||
});
|
||||
|
||||
performance::end_measure!("apply_drawing_to_render_canvas");
|
||||
}
|
||||
|
||||
pub fn clear_focus_mode(&mut self) {
|
||||
@@ -983,144 +1042,15 @@ impl RenderState {
|
||||
timestamp: i32,
|
||||
) -> Result<(bool, bool), String> {
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full:begin");
|
||||
let result = self.render_shape_tree_full_uncached(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
scale_content,
|
||||
timestamp,
|
||||
);
|
||||
|
||||
let (is_empty, should_stop_rendering) = result?;
|
||||
emscripten::log!(emscripten::Log::Default, "is_empty {} should_stop_rendering {}", is_empty, should_stop_rendering);
|
||||
if should_stop_rendering {
|
||||
self.render_in_progress = false;
|
||||
self.render_is_full = false;
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "dumping tiles");
|
||||
while let Some(next_tile) = self.pending_tiles.pop() {
|
||||
emscripten::log!(emscripten::Log::Default, "next_tile {} {}", next_tile.0, next_tile.1);
|
||||
if self.surfaces.has_cached_tile_surface(next_tile) {
|
||||
emscripten::log!(emscripten::Log::Default, "cached");
|
||||
performance::begin_measure!("render_shape_tree::cached");
|
||||
let tile_rect = self.get_current_tile_bounds();
|
||||
self.surfaces.draw_cached_tile_surface(
|
||||
next_tile,
|
||||
tile_rect,
|
||||
self.background_color,
|
||||
);
|
||||
performance::end_measure!("render_shape_tree::cached");
|
||||
|
||||
if self.options.is_debug_visible() {
|
||||
debug::render_workspace_current_tile(
|
||||
self,
|
||||
"Cached".to_string(),
|
||||
next_tile,
|
||||
tile_rect,
|
||||
);
|
||||
}
|
||||
}
|
||||
// self.update_render_context(&next_tile);
|
||||
self.render_current_tile_to_final_canvas(false);
|
||||
}
|
||||
|
||||
if self.options.is_debug_visible() {
|
||||
debug::render(self);
|
||||
}
|
||||
debug::render_wasm_label(self);
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full:end");
|
||||
|
||||
Ok((is_empty, should_stop_rendering))
|
||||
}
|
||||
|
||||
pub fn render_shape_tree_full_uncached_shape_tile(
|
||||
&mut self,
|
||||
element: &Shape,
|
||||
node_render_state: &NodeRenderState,
|
||||
tile: &tiles::Tile,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
_structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
) -> bool {
|
||||
let NodeRenderState {
|
||||
id: _node_id,
|
||||
visited_children,
|
||||
clip_bounds: _clip_bounds,
|
||||
visited_mask,
|
||||
mask,
|
||||
} = *node_render_state;
|
||||
|
||||
self.update_render_context(tile);
|
||||
|
||||
self.render_shape_enter(element, mask);
|
||||
if !node_render_state.is_root() {
|
||||
self.render_shape(
|
||||
element,
|
||||
modifiers.get(&element.id),
|
||||
scale_content.get(&element.id)
|
||||
);
|
||||
} else {
|
||||
self.apply_drawing_to_render_canvas(Some(element));
|
||||
}
|
||||
if visited_children {
|
||||
self.render_shape_exit(element, visited_mask, modifiers.get(&element.id), scale_content.get(&element.id));
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn render_shape_tree_full_uncached_shape_tiles(
|
||||
&mut self,
|
||||
element: &Shape,
|
||||
node_render_state: &NodeRenderState,
|
||||
tiles: &HashSet<tiles::Tile>,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
) {
|
||||
// We need to iterate over every tile of the element.
|
||||
for tile in tiles.iter() {
|
||||
emscripten::log!(emscripten::Log::Default,
|
||||
"render_shape_tree_full_uncached::for::start {} {}",
|
||||
tile.0, tile.1
|
||||
);
|
||||
self.render_shape_tree_full_uncached_shape_tile(
|
||||
element,
|
||||
node_render_state,
|
||||
tile,
|
||||
modifiers,
|
||||
structure,
|
||||
scale_content,
|
||||
);
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full_uncached::for::end");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_shape_tree_full_uncached(
|
||||
&mut self,
|
||||
tree: &ShapesPool,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
timestamp: i32,
|
||||
) -> Result<(bool, bool), String> {
|
||||
let mut iteration = 0;
|
||||
let mut is_empty = true;
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full_uncached::while::start");
|
||||
let scale = self.get_scale();
|
||||
while let Some(node_render_state) = self.pending_nodes.next() {
|
||||
emscripten::log!(emscripten::Log::Default,
|
||||
"render_shape_tree_full_uncached::while::pop {} {}",
|
||||
self.pending_nodes.len(),
|
||||
self.pending_nodes.is_empty()
|
||||
);
|
||||
let NodeRenderState {
|
||||
id: node_id,
|
||||
visited_children,
|
||||
clip_bounds: _clip_bounds,
|
||||
visited_mask: _visited_mask,
|
||||
clip_bounds: _,
|
||||
visited_mask,
|
||||
mask,
|
||||
} = node_render_state;
|
||||
|
||||
@@ -1130,71 +1060,74 @@ impl RenderState {
|
||||
.to_string(),
|
||||
)?;
|
||||
|
||||
/*
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_color(Color::from_argb(255, 255, 0, 255));
|
||||
paint.set_style(skia::PaintStyle::Fill);
|
||||
paint.set_anti_alias(false);
|
||||
paint.set_blend_mode(skia::BlendMode::SrcOver);
|
||||
// If the shape is not in the tile set, then we update
|
||||
// it.
|
||||
if self.tiles.get_tiles_of(node_id).is_none() {
|
||||
self.update_tiles_for(element);
|
||||
}
|
||||
|
||||
self.surfaces.draw_rect_to(SurfaceId::Current, element, &paint);
|
||||
*/
|
||||
if visited_children {
|
||||
self.render_shape_exit(
|
||||
element,
|
||||
visited_mask,
|
||||
modifiers.get(&node_id),
|
||||
scale_content.get(&element.id),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "a {} {}", element.id, node_render_state.is_root());
|
||||
if !node_render_state.is_root() {
|
||||
// No necesitamos esto porque en el primer render es imposible
|
||||
// que se estén transformando elementos.
|
||||
/*
|
||||
let mut transformed_element: Cow<Shape> = Cow::Borrowed(element);
|
||||
|
||||
if let Some(modifier) = modifiers.get(&node_id) {
|
||||
transformed_element.to_mut().apply_transform(modifier);
|
||||
}
|
||||
|
||||
// let is_visible = transformed_element.extrect().intersects(self.render_area)
|
||||
// && !transformed_element.hidden
|
||||
// && !transformed_element.visually_insignificant(self.get_scale_mut());
|
||||
|
||||
let is_visible = true;
|
||||
let is_visible = transformed_element.extrect().intersects(self.render_area)
|
||||
&& !transformed_element.hidden
|
||||
&& !transformed_element.visually_insignificant(scale);
|
||||
|
||||
if self.options.is_debug_visible() {
|
||||
debug::render_debug_shape(self, &transformed_element, is_visible);
|
||||
}
|
||||
*/
|
||||
|
||||
let is_visible = !element.hidden
|
||||
&& !element.visually_insignificant(scale);
|
||||
|
||||
if self.options.is_debug_visible() {
|
||||
debug::render_debug_shape(self, element, is_visible);
|
||||
}
|
||||
|
||||
if !is_visible {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "b");
|
||||
// If the shape is not in the tile set, then we update
|
||||
// it.
|
||||
if self.get_tiles_of(node_id).is_none() {
|
||||
emscripten::log!(emscripten::Log::Default, "updating tiles for {}", element.id);
|
||||
self.update_tiles_for(element);
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "c");
|
||||
if !element.is_root() {
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full_uncached_shape_tiles");
|
||||
let mut tiles_opt = self.get_tiles_of(element.id);
|
||||
let tiles = tiles_opt.as_mut().unwrap().clone();
|
||||
self.render_shape_tree_full_uncached_shape_tiles(
|
||||
self.render_shape_enter(element, mask);
|
||||
if !node_render_state.is_root() && self.focus_mode.is_active() {
|
||||
self.render_shape(
|
||||
element,
|
||||
&node_render_state,
|
||||
&tiles,
|
||||
modifiers,
|
||||
structure,
|
||||
scale_content,
|
||||
modifiers.get(&element.id),
|
||||
scale_content.get(&element.id),
|
||||
);
|
||||
|
||||
} else if visited_children {
|
||||
// NOTA: Esto no debería usarse porque esta función utiliza el CURRENT.
|
||||
self.apply_drawing_to_full_render_canvas(Some(element));
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "d {}", element.is_recursive());
|
||||
if !visited_children && element.is_recursive() {
|
||||
// Set the node as visited_children before processing children
|
||||
self.pending_nodes.add_children_safeguard(element, mask);
|
||||
|
||||
if element.is_recursive() {
|
||||
let children_clip_bounds =
|
||||
node_render_state.get_children_clip_bounds(element, modifiers.get(&element.id));
|
||||
|
||||
let mut children_ids = element.modified_children_ids(structure.get(&element.id), false);
|
||||
let mut children_ids =
|
||||
element.modified_children_ids(structure.get(&element.id), false);
|
||||
|
||||
// Z-index ordering on Layouts
|
||||
if element.has_layout() {
|
||||
@@ -1205,26 +1138,22 @@ impl RenderState {
|
||||
});
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "children_ids {}", children_ids.len());
|
||||
for child_id in children_ids.iter() {
|
||||
emscripten::log!(emscripten::Log::Default, "children id {}", child_id);
|
||||
self.pending_nodes.add_child(child_id, children_clip_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "e");
|
||||
// We try to avoid doing too many calls to get_time
|
||||
if self.should_stop_rendering(iteration, timestamp) {
|
||||
emscripten::log!(emscripten::Log::Default, "should_stop_rendering {} {}", self.pending_nodes.is_empty(), self.pending_nodes.len() == 0);
|
||||
return Ok((is_empty, self.pending_nodes.is_empty()));
|
||||
}
|
||||
if iteration == 100 {
|
||||
return Ok((false, true));
|
||||
return Ok((is_empty, true));
|
||||
}
|
||||
iteration += 1;
|
||||
}
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full_uncached::while::end");
|
||||
Ok((is_empty, self.pending_nodes.is_empty()))
|
||||
|
||||
emscripten::log!(emscripten::Log::Default, "render_shape_tree_full:end");
|
||||
self.render_in_progress = false;
|
||||
self.apply_full_render_to_final_canvas();
|
||||
Ok((false, true))
|
||||
}
|
||||
|
||||
pub fn render_shape_tree_partial_uncached(
|
||||
|
||||
@@ -26,6 +26,7 @@ pub enum SurfaceId {
|
||||
InnerShadows = 0b0_0100_0000,
|
||||
UI = 0b0_1000_0000,
|
||||
Debug = 0b1_0000_0000,
|
||||
Full = 0b10_0000_0000,
|
||||
}
|
||||
|
||||
pub struct Surfaces {
|
||||
@@ -46,6 +47,8 @@ pub struct Surfaces {
|
||||
ui: skia::Surface,
|
||||
// for drawing debug info.
|
||||
debug: skia::Surface,
|
||||
// for slicing a full render.
|
||||
full: skia::Surface,
|
||||
// for drawing tiles.
|
||||
tiles: TileTextureCache,
|
||||
sampling_options: skia::SamplingOptions,
|
||||
@@ -80,6 +83,7 @@ impl Surfaces {
|
||||
|
||||
let ui = gpu_state.create_surface_with_dimensions("ui".to_string(), width, height);
|
||||
let debug = gpu_state.create_surface_with_dimensions("debug".to_string(), width, height);
|
||||
let full = gpu_state.create_surface_with_dimensions("full".to_string(), width, height);
|
||||
|
||||
let tiles = TileTextureCache::new();
|
||||
Surfaces {
|
||||
@@ -92,6 +96,7 @@ impl Surfaces {
|
||||
shape_strokes,
|
||||
ui,
|
||||
debug,
|
||||
full,
|
||||
tiles,
|
||||
sampling_options,
|
||||
margins,
|
||||
@@ -172,6 +177,9 @@ impl Surfaces {
|
||||
if ids & SurfaceId::Debug as u32 != 0 {
|
||||
f(self.get_mut(SurfaceId::Debug));
|
||||
}
|
||||
if ids & SurfaceId::Full as u32 != 0 {
|
||||
f(self.get_mut(SurfaceId::Full));
|
||||
}
|
||||
performance::begin_measure!("apply_mut::flags");
|
||||
}
|
||||
|
||||
@@ -205,6 +213,7 @@ impl Surfaces {
|
||||
SurfaceId::Strokes => &mut self.shape_strokes,
|
||||
SurfaceId::Debug => &mut self.debug,
|
||||
SurfaceId::UI => &mut self.ui,
|
||||
SurfaceId::Full => &mut self.full,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +222,7 @@ impl Surfaces {
|
||||
self.target = target;
|
||||
self.debug = self.target.new_surface_with_dimensions(dim).unwrap();
|
||||
self.ui = self.target.new_surface_with_dimensions(dim).unwrap();
|
||||
self.full = self.target.new_surface_with_dimensions(dim).unwrap();
|
||||
// The rest are tile size surfaces
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user