mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 05:41:37 +02:00
🐛 Fix drawing shapes when dpr > 1
This commit is contained in:
parent
6831acb71d
commit
300e24b403
4 changed files with 45 additions and 39 deletions
|
@ -34,16 +34,16 @@ const VIEWPORT_INTEREST_AREA_THRESHOLD: i32 = 1;
|
||||||
const MAX_BLOCKING_TIME_MS: i32 = 32;
|
const MAX_BLOCKING_TIME_MS: i32 = 32;
|
||||||
const NODE_BATCH_THRESHOLD: i32 = 10;
|
const NODE_BATCH_THRESHOLD: i32 = 10;
|
||||||
|
|
||||||
pub struct NodeRenderState {
|
struct NodeRenderState {
|
||||||
pub id: Uuid,
|
id: Uuid,
|
||||||
// We use this bool to keep that we've traversed all the children inside this node.
|
// We use this bool to keep that we've traversed all the children inside this node.
|
||||||
pub visited_children: bool,
|
visited_children: bool,
|
||||||
// This is used to clip the content of frames.
|
// This is used to clip the content of frames.
|
||||||
pub clip_bounds: Option<(Rect, Option<Corners>, Matrix)>,
|
clip_bounds: Option<(Rect, Option<Corners>, Matrix)>,
|
||||||
// This is a flag to indicate that we've already drawn the mask of a masked group.
|
// This is a flag to indicate that we've already drawn the mask of a masked group.
|
||||||
pub visited_mask: bool,
|
visited_mask: bool,
|
||||||
// This bool indicates that we're drawing the mask shape.
|
// This bool indicates that we're drawing the mask shape.
|
||||||
pub mask: bool,
|
mask: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeRenderState {
|
impl NodeRenderState {
|
||||||
|
@ -90,7 +90,7 @@ pub(crate) struct RenderState {
|
||||||
// Indicates whether the rendering process has pending frames.
|
// Indicates whether the rendering process has pending frames.
|
||||||
pub render_in_progress: bool,
|
pub render_in_progress: bool,
|
||||||
// Stack of nodes pending to be rendered.
|
// Stack of nodes pending to be rendered.
|
||||||
pub pending_nodes: Vec<NodeRenderState>,
|
pending_nodes: Vec<NodeRenderState>,
|
||||||
pub current_tile: Option<tiles::Tile>,
|
pub current_tile: Option<tiles::Tile>,
|
||||||
pub sampling_options: skia::SamplingOptions,
|
pub sampling_options: skia::SamplingOptions,
|
||||||
pub render_area: Rect,
|
pub render_area: Rect,
|
||||||
|
@ -98,10 +98,10 @@ pub(crate) struct RenderState {
|
||||||
pub pending_tiles: Vec<tiles::TileWithDistance>,
|
pub pending_tiles: Vec<tiles::TileWithDistance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cache_size(viewbox: Viewbox) -> skia::ISize {
|
pub fn get_cache_size(viewbox: Viewbox, dpr: f32) -> skia::ISize {
|
||||||
// First we retrieve the extended area of the viewport that we could render.
|
// First we retrieve the extended area of the viewport that we could render.
|
||||||
let (isx, isy, iex, iey) =
|
let (isx, isy, iex, iey) =
|
||||||
tiles::get_tiles_for_viewbox_with_interest(viewbox, VIEWPORT_INTEREST_AREA_THRESHOLD);
|
tiles::get_tiles_for_viewbox_with_interest(viewbox, VIEWPORT_INTEREST_AREA_THRESHOLD, dpr);
|
||||||
|
|
||||||
let dx = if isx.signum() != iex.signum() { 1 } else { 0 };
|
let dx = if isx.signum() != iex.signum() { 1 } else { 0 };
|
||||||
let dy = if isy.signum() != iey.signum() { 1 } else { 0 };
|
let dy = if isy.signum() != iey.signum() { 1 } else { 0 };
|
||||||
|
@ -447,9 +447,9 @@ impl RenderState {
|
||||||
|
|
||||||
pub fn update_render_context(&mut self, tile: tiles::Tile) {
|
pub fn update_render_context(&mut self, tile: tiles::Tile) {
|
||||||
self.current_tile = Some(tile);
|
self.current_tile = Some(tile);
|
||||||
self.render_area = tiles::get_tile_rect(self.viewbox, tile);
|
self.render_area = tiles::get_tile_rect(tile, self.get_scale());
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.update_render_context(self.render_area, self.viewbox);
|
.update_render_context(self.render_area, self.get_scale());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_from_cache(&mut self) {
|
fn render_from_cache(&mut self) {
|
||||||
|
@ -460,11 +460,15 @@ impl RenderState {
|
||||||
// Scale and translate the target according to the cached data
|
// Scale and translate the target according to the cached data
|
||||||
let navigate_zoom = self.viewbox.zoom / self.cached_viewbox.zoom;
|
let navigate_zoom = self.viewbox.zoom / self.cached_viewbox.zoom;
|
||||||
|
|
||||||
canvas.scale((navigate_zoom, navigate_zoom));
|
canvas.scale((
|
||||||
|
navigate_zoom * self.options.dpr(),
|
||||||
|
navigate_zoom * self.options.dpr(),
|
||||||
|
));
|
||||||
|
|
||||||
let (start_tile_x, start_tile_y, _, _) = tiles::get_tiles_for_viewbox_with_interest(
|
let (start_tile_x, start_tile_y, _, _) = tiles::get_tiles_for_viewbox_with_interest(
|
||||||
self.cached_viewbox,
|
self.cached_viewbox,
|
||||||
VIEWPORT_INTEREST_AREA_THRESHOLD,
|
VIEWPORT_INTEREST_AREA_THRESHOLD,
|
||||||
|
self.options.dpr(),
|
||||||
);
|
);
|
||||||
let offset_x = self.viewbox.area.left * self.cached_viewbox.zoom;
|
let offset_x = self.viewbox.area.left * self.cached_viewbox.zoom;
|
||||||
let offset_y = self.viewbox.area.top * self.cached_viewbox.zoom;
|
let offset_y = self.viewbox.area.top * self.cached_viewbox.zoom;
|
||||||
|
@ -475,7 +479,7 @@ impl RenderState {
|
||||||
));
|
));
|
||||||
|
|
||||||
canvas.clear(self.background_color);
|
canvas.clear(self.background_color);
|
||||||
canvas.draw_image(&snapshot.clone(), (0, 0), Some(&skia::Paint::default()));
|
canvas.draw_image(snapshot.clone(), (0, 0), Some(&skia::Paint::default()));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,10 +521,11 @@ impl RenderState {
|
||||||
let (isx, isy, iex, iey) = tiles::get_tiles_for_viewbox_with_interest(
|
let (isx, isy, iex, iey) = tiles::get_tiles_for_viewbox_with_interest(
|
||||||
self.viewbox,
|
self.viewbox,
|
||||||
VIEWPORT_INTEREST_AREA_THRESHOLD,
|
VIEWPORT_INTEREST_AREA_THRESHOLD,
|
||||||
|
self.options.dpr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let viewbox_cache_size = get_cache_size(self.viewbox);
|
let viewbox_cache_size = get_cache_size(self.viewbox, self.options.dpr());
|
||||||
let cached_viewbox_cache_size = get_cache_size(self.cached_viewbox);
|
let cached_viewbox_cache_size = get_cache_size(self.cached_viewbox, self.options.dpr());
|
||||||
if viewbox_cache_size != cached_viewbox_cache_size {
|
if viewbox_cache_size != cached_viewbox_cache_size {
|
||||||
self.surfaces.resize_cache(
|
self.surfaces.resize_cache(
|
||||||
&mut self.gpu_state,
|
&mut self.gpu_state,
|
||||||
|
@ -530,7 +535,7 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we get the real amount of tiles rendered for the current viewbox.
|
// Then we get the real amount of tiles rendered for the current viewbox.
|
||||||
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(self.viewbox);
|
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(self.viewbox, self.options.dpr());
|
||||||
debug::render_debug_tiles_for_viewbox(self, isx, isy, iex, iey);
|
debug::render_debug_tiles_for_viewbox(self, isx, isy, iex, iey);
|
||||||
let tile_center = ((iex - isx) / 2, (iey - isy) / 2);
|
let tile_center = ((iex - isx) / 2, (iey - isy) / 2);
|
||||||
|
|
||||||
|
@ -650,6 +655,7 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_tile_bounds(&mut self) -> Rect {
|
pub fn get_current_tile_bounds(&mut self) -> Rect {
|
||||||
|
// TODO: check if we need to add dpr to something else here
|
||||||
let (tile_x, tile_y) = self.current_tile.unwrap();
|
let (tile_x, tile_y) = self.current_tile.unwrap();
|
||||||
let scale = self.get_scale();
|
let scale = self.get_scale();
|
||||||
let offset_x = self.viewbox.area.left * scale;
|
let offset_x = self.viewbox.area.left * scale;
|
||||||
|
@ -696,7 +702,6 @@ impl RenderState {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale = self.get_scale();
|
|
||||||
let mut should_stop = false;
|
let mut should_stop = false;
|
||||||
|
|
||||||
while !should_stop {
|
while !should_stop {
|
||||||
|
@ -784,7 +789,7 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
if !transformed_element.extrect().intersects(self.render_area)
|
if !transformed_element.extrect().intersects(self.render_area)
|
||||||
|| transformed_element.hidden()
|
|| transformed_element.hidden()
|
||||||
|| transformed_element.visually_insignificant(scale)
|
|| transformed_element.visually_insignificant(self.get_scale())
|
||||||
{
|
{
|
||||||
debug::render_debug_shape(self, &transformed_element, false);
|
debug::render_debug_shape(self, &transformed_element, false);
|
||||||
continue;
|
continue;
|
||||||
|
@ -916,7 +921,7 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tiles_for_shape(&mut self, shape: &Shape) -> (i32, i32, i32, i32) {
|
pub fn get_tiles_for_shape(&mut self, shape: &Shape) -> (i32, i32, i32, i32) {
|
||||||
let tile_size = tiles::get_tile_size(self.viewbox);
|
let tile_size = tiles::get_tile_size(self.get_scale());
|
||||||
tiles::get_tiles_for_rect(shape.extrect(), tile_size)
|
tiles::get_tiles_for_rect(shape.extrect(), tile_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,14 +100,14 @@ pub fn render_debug_tiles_for_viewbox(
|
||||||
|
|
||||||
// Renders the tiles in the viewbox
|
// Renders the tiles in the viewbox
|
||||||
pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
|
pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
|
||||||
|
let scale = render_state.get_scale();
|
||||||
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
|
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
|
||||||
let mut paint = skia::Paint::default();
|
let mut paint = skia::Paint::default();
|
||||||
paint.set_style(skia::PaintStyle::Stroke);
|
paint.set_style(skia::PaintStyle::Stroke);
|
||||||
paint.set_color(skia::Color::from_rgb(255, 0, 127));
|
paint.set_color(skia::Color::from_rgb(255, 0, 127));
|
||||||
paint.set_stroke_width(1.);
|
paint.set_stroke_width(1.);
|
||||||
|
|
||||||
let tile_size = tiles::get_tile_size(render_state.viewbox);
|
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(render_state.viewbox, scale);
|
||||||
let (sx, sy, ex, ey) = tiles::get_tiles_for_rect(render_state.viewbox.area, tile_size);
|
|
||||||
let str_rect = format!("{} {} {} {}", sx, sy, ex, ey);
|
let str_rect = format!("{} {} {} {}", sx, sy, ex, ey);
|
||||||
|
|
||||||
let debug_font = render_state.fonts.debug_font();
|
let debug_font = render_state.fonts.debug_font();
|
||||||
|
@ -118,6 +118,7 @@ pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
|
||||||
&paint,
|
&paint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let tile_size = tiles::get_tile_size(scale);
|
||||||
for y in sy..=ey {
|
for y in sy..=ey {
|
||||||
for x in sx..=ex {
|
for x in sx..=ex {
|
||||||
let rect = Rect::from_xywh(
|
let rect = Rect::from_xywh(
|
||||||
|
@ -137,14 +138,15 @@ pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_debug_tiles(render_state: &mut RenderState) {
|
pub fn render_debug_tiles(render_state: &mut RenderState) {
|
||||||
|
let scale = render_state.get_scale();
|
||||||
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
|
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
|
||||||
let mut paint = skia::Paint::default();
|
let mut paint = skia::Paint::default();
|
||||||
paint.set_style(skia::PaintStyle::Stroke);
|
paint.set_style(skia::PaintStyle::Stroke);
|
||||||
paint.set_color(skia::Color::from_rgb(127, 0, 255));
|
paint.set_color(skia::Color::from_rgb(127, 0, 255));
|
||||||
paint.set_stroke_width(1.);
|
paint.set_stroke_width(1.);
|
||||||
|
|
||||||
let tile_size = tiles::get_tile_size(render_state.viewbox);
|
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(render_state.viewbox, scale);
|
||||||
let (sx, sy, ex, ey) = tiles::get_tiles_for_rect(render_state.viewbox.area, tile_size);
|
let tile_size = tiles::get_tile_size(scale);
|
||||||
for y in sy..=ey {
|
for y in sy..=ey {
|
||||||
for x in sx..=ex {
|
for x in sx..=ex {
|
||||||
let tile = (x, y);
|
let tile = (x, y);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::shapes::Shape;
|
use crate::shapes::Shape;
|
||||||
use crate::view::Viewbox;
|
|
||||||
use skia_safe::{self as skia, IRect, Paint, RRect};
|
use skia_safe::{self as skia, IRect, Paint, RRect};
|
||||||
|
|
||||||
use super::{gpu_state::GpuState, tiles::Tile, tiles::TILE_SIZE};
|
use super::{gpu_state::GpuState, tiles::Tile, tiles::TILE_SIZE};
|
||||||
|
@ -145,10 +144,10 @@ impl Surfaces {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_render_context(&mut self, render_area: skia::Rect, viewbox: Viewbox) {
|
pub fn update_render_context(&mut self, render_area: skia::Rect, scale: f32) {
|
||||||
let translation = (
|
let translation = (
|
||||||
-render_area.left() + self.margins.width as f32 / viewbox.zoom,
|
-render_area.left() + self.margins.width as f32 / scale,
|
||||||
-render_area.top() + self.margins.height as f32 / viewbox.zoom,
|
-render_area.top() + self.margins.height as f32 / scale,
|
||||||
);
|
);
|
||||||
self.apply_mut(
|
self.apply_mut(
|
||||||
&[
|
&[
|
||||||
|
|
|
@ -28,34 +28,34 @@ pub fn get_tiles_for_rect(rect: skia::Rect, tile_size: f32) -> (i32, i32, i32, i
|
||||||
(sx, sy, ex, ey)
|
(sx, sy, ex, ey)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tiles_for_viewbox(viewbox: Viewbox) -> (i32, i32, i32, i32) {
|
pub fn get_tiles_for_viewbox(viewbox: Viewbox, scale: f32) -> (i32, i32, i32, i32) {
|
||||||
let tile_size = get_tile_size(viewbox);
|
let tile_size = get_tile_size(scale);
|
||||||
get_tiles_for_rect(viewbox.area, tile_size)
|
get_tiles_for_rect(viewbox.area, tile_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tiles_for_viewbox_with_interest(
|
pub fn get_tiles_for_viewbox_with_interest(
|
||||||
viewbox: Viewbox,
|
viewbox: Viewbox,
|
||||||
interest: i32,
|
interest: i32,
|
||||||
|
dpr: f32,
|
||||||
) -> (i32, i32, i32, i32) {
|
) -> (i32, i32, i32, i32) {
|
||||||
let (sx, sy, ex, ey) = get_tiles_for_viewbox(viewbox);
|
let (sx, sy, ex, ey) = get_tiles_for_viewbox(viewbox, dpr);
|
||||||
(sx - interest, sy - interest, ex + interest, ey + interest)
|
(sx - interest, sy - interest, ex + interest, ey + interest)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tile_pos(viewbox: Viewbox, (x, y): Tile) -> (f32, f32) {
|
pub fn get_tile_pos((x, y): Tile, scale: f32) -> (f32, f32) {
|
||||||
(
|
(
|
||||||
x as f32 * get_tile_size(viewbox),
|
x as f32 * get_tile_size(scale),
|
||||||
y as f32 * get_tile_size(viewbox),
|
y as f32 * get_tile_size(scale),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tile_size(viewbox: Viewbox) -> f32 {
|
pub fn get_tile_size(scale: f32) -> f32 {
|
||||||
// TODO: * self.options.dpr() too?
|
1. / scale * TILE_SIZE
|
||||||
1. / viewbox.zoom * TILE_SIZE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tile_rect(viewbox: Viewbox, tile: Tile) -> skia::Rect {
|
pub fn get_tile_rect(tile: Tile, scale: f32) -> skia::Rect {
|
||||||
let (tx, ty) = get_tile_pos(viewbox, tile);
|
let (tx, ty) = get_tile_pos(tile, scale);
|
||||||
let ts = get_tile_size(viewbox);
|
let ts = get_tile_size(scale);
|
||||||
skia::Rect::from_xywh(tx, ty, ts, ts)
|
skia::Rect::from_xywh(tx, ty, ts, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue