mirror of
https://github.com/penpot/penpot.git
synced 2025-06-28 00:36:59 +02:00
Merge pull request #6491 from penpot/alotor-perf-pixel-precision
✨ Pixel precision for new renderer
This commit is contained in:
commit
58b1cf6b0c
8 changed files with 76 additions and 22 deletions
|
@ -529,17 +529,15 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(wasm.api/clean-modifiers)
|
(wasm.api/clean-modifiers)
|
||||||
|
|
||||||
(let [prev-wasm-props (:prev-wasm-props state)
|
(let [prev-wasm-props (:prev-wasm-props state)
|
||||||
wasm-props (:wasm-props state)
|
wasm-props (:wasm-props state)
|
||||||
objects (dsh/lookup-page-objects state)]
|
objects (dsh/lookup-page-objects state)
|
||||||
|
pixel-precision false]
|
||||||
(set-wasm-props! objects prev-wasm-props wasm-props)
|
(set-wasm-props! objects prev-wasm-props wasm-props)
|
||||||
|
|
||||||
(let [structure-entries (parse-structure-modifiers modif-tree)]
|
(let [structure-entries (parse-structure-modifiers modif-tree)]
|
||||||
(wasm.api/set-structure-modifiers structure-entries)
|
(wasm.api/set-structure-modifiers structure-entries)
|
||||||
(let [geometry-entries (parse-geometry-modifiers modif-tree)
|
(let [geometry-entries (parse-geometry-modifiers modif-tree)
|
||||||
selrect (wasm.api/propagate-apply geometry-entries)]
|
selrect (wasm.api/propagate-apply geometry-entries pixel-precision)]
|
||||||
(rx/of (set-temporary-selrect selrect))))))))
|
(rx/of (set-temporary-selrect selrect))))))))
|
||||||
|
|
||||||
#_:clj-kondo/ignore
|
#_:clj-kondo/ignore
|
||||||
|
@ -549,15 +547,18 @@
|
||||||
:as params}]
|
:as params}]
|
||||||
(ptk/reify ::apply-wasm-modifiesr
|
(ptk/reify ::apply-wasm-modifiesr
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
(let [geometry-entries
|
(let [geometry-entries
|
||||||
(parse-geometry-modifiers modif-tree)
|
(parse-geometry-modifiers modif-tree)
|
||||||
|
|
||||||
|
snap-pixel?
|
||||||
|
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||||
|
|
||||||
transforms
|
transforms
|
||||||
(into
|
(into
|
||||||
{}
|
{}
|
||||||
(map (fn [{:keys [id transform]}] [id transform]))
|
(map (fn [{:keys [id transform]}] [id transform]))
|
||||||
(wasm.api/propagate-modifiers geometry-entries))
|
(wasm.api/propagate-modifiers geometry-entries snap-pixel?))
|
||||||
|
|
||||||
ids
|
ids
|
||||||
(into (set (keys modif-tree)) (keys transforms))
|
(into (set (keys modif-tree)) (keys transforms))
|
||||||
|
|
|
@ -262,10 +262,10 @@
|
||||||
|
|
||||||
[x y width height]
|
[x y width height]
|
||||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||||
(let [{:keys [width height]} (wasm.api/text-dimensions shape-id)
|
(let [{:keys [max-width height]} (wasm.api/text-dimensions shape-id)
|
||||||
{:keys [x y]} (:selrect shape)]
|
{:keys [x y]} (:selrect shape)]
|
||||||
|
|
||||||
[x y width height])
|
[x y max-width height])
|
||||||
|
|
||||||
(let [bounds (gst/shape->rect shape)
|
(let [bounds (gst/shape->rect shape)
|
||||||
x (mth/min (dm/get-prop bounds :x)
|
x (mth/min (dm/get-prop bounds :x)
|
||||||
|
|
|
@ -654,9 +654,10 @@
|
||||||
(let [offset (h/call wasm/internal-module "_get_text_dimensions")
|
(let [offset (h/call wasm/internal-module "_get_text_dimensions")
|
||||||
heapf32 (mem/get-heap-f32)
|
heapf32 (mem/get-heap-f32)
|
||||||
width (aget heapf32 (mem/ptr8->ptr32 offset))
|
width (aget heapf32 (mem/ptr8->ptr32 offset))
|
||||||
height (aget heapf32 (mem/ptr8->ptr32 (+ offset 4)))]
|
height (aget heapf32 (mem/ptr8->ptr32 (+ offset 4)))
|
||||||
|
max-width (aget heapf32 (mem/ptr8->ptr32 (+ offset 8)))]
|
||||||
(h/call wasm/internal-module "_free_bytes")
|
(h/call wasm/internal-module "_free_bytes")
|
||||||
{:width width :height height})))
|
{:width width :height height :max-width max-width})))
|
||||||
|
|
||||||
(defn set-view-box
|
(defn set-view-box
|
||||||
[zoom vbox]
|
[zoom vbox]
|
||||||
|
@ -803,7 +804,7 @@
|
||||||
(h/call wasm/internal-module "_set_structure_modifiers"))))
|
(h/call wasm/internal-module "_set_structure_modifiers"))))
|
||||||
|
|
||||||
(defn propagate-modifiers
|
(defn propagate-modifiers
|
||||||
[entries]
|
[entries pixel-precision]
|
||||||
(when (d/not-empty? entries)
|
(when (d/not-empty? entries)
|
||||||
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
|
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
|
||||||
heapf32 (mem/get-heap-f32)
|
heapf32 (mem/get-heap-f32)
|
||||||
|
@ -817,7 +818,7 @@
|
||||||
(sr/heapf32-set-matrix transform heapf32 (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-TRANSFORM-OFFSET)))
|
(sr/heapf32-set-matrix transform heapf32 (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-TRANSFORM-OFFSET)))
|
||||||
(recur (rest entries) (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-SIZE))))))
|
(recur (rest entries) (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-SIZE))))))
|
||||||
|
|
||||||
(let [result-offset (h/call wasm/internal-module "_propagate_modifiers")
|
(let [result-offset (h/call wasm/internal-module "_propagate_modifiers" pixel-precision)
|
||||||
heapf32 (mem/get-heap-f32)
|
heapf32 (mem/get-heap-f32)
|
||||||
heapu32 (mem/get-heap-u32)
|
heapu32 (mem/get-heap-u32)
|
||||||
len (aget heapu32 (mem/ptr8->ptr32 result-offset))
|
len (aget heapu32 (mem/ptr8->ptr32 result-offset))
|
||||||
|
@ -829,7 +830,7 @@
|
||||||
result))))
|
result))))
|
||||||
|
|
||||||
(defn propagate-apply
|
(defn propagate-apply
|
||||||
[entries]
|
[entries pixel-precision]
|
||||||
(when (d/not-empty? entries)
|
(when (d/not-empty? entries)
|
||||||
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
|
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
|
||||||
heapf32 (mem/get-heap-f32)
|
heapf32 (mem/get-heap-f32)
|
||||||
|
@ -843,7 +844,7 @@
|
||||||
(sr/heapf32-set-matrix transform heapf32 (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-TRANSFORM-OFFSET)))
|
(sr/heapf32-set-matrix transform heapf32 (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-TRANSFORM-OFFSET)))
|
||||||
(recur (rest entries) (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-SIZE))))))
|
(recur (rest entries) (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-SIZE))))))
|
||||||
|
|
||||||
(let [offset (h/call wasm/internal-module "_propagate_apply")
|
(let [offset (h/call wasm/internal-module "_propagate_apply" pixel-precision)
|
||||||
heapf32 (mem/get-heap-f32)
|
heapf32 (mem/get-heap-f32)
|
||||||
width (aget heapf32 (mem/ptr8->ptr32 (+ offset 0)))
|
width (aget heapf32 (mem/ptr8->ptr32 (+ offset 0)))
|
||||||
height (aget heapf32 (mem/ptr8->ptr32 (+ offset 4)))
|
height (aget heapf32 (mem/ptr8->ptr32 (+ offset 4)))
|
||||||
|
|
|
@ -389,7 +389,7 @@ pub extern "C" fn set_shape_path_attrs(num_attrs: u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn propagate_modifiers() -> *mut u8 {
|
pub extern "C" fn propagate_modifiers(pixel_precision: bool) -> *mut u8 {
|
||||||
let bytes = mem::bytes();
|
let bytes = mem::bytes();
|
||||||
|
|
||||||
let entries: Vec<_> = bytes
|
let entries: Vec<_> = bytes
|
||||||
|
@ -398,13 +398,13 @@ pub extern "C" fn propagate_modifiers() -> *mut u8 {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
let (result, _) = shapes::propagate_modifiers(state, &entries);
|
let (result, _) = shapes::propagate_modifiers(state, &entries, pixel_precision);
|
||||||
mem::write_vec(result)
|
mem::write_vec(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn propagate_apply() -> *mut u8 {
|
pub extern "C" fn propagate_apply(pixel_precision: bool) -> *mut u8 {
|
||||||
let bytes = mem::bytes();
|
let bytes = mem::bytes();
|
||||||
|
|
||||||
let entries: Vec<_> = bytes
|
let entries: Vec<_> = bytes
|
||||||
|
@ -413,7 +413,7 @@ pub extern "C" fn propagate_apply() -> *mut u8 {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
let (result, bounds) = shapes::propagate_modifiers(state, &entries);
|
let (result, bounds) = shapes::propagate_modifiers(state, &entries, pixel_precision);
|
||||||
|
|
||||||
for entry in result {
|
for entry in result {
|
||||||
state.modifiers.insert(entry.id, entry.transform);
|
state.modifiers.insert(entry.id, entry.transform);
|
||||||
|
|
|
@ -103,9 +103,35 @@ fn calculate_group_bounds(
|
||||||
shape_bounds.with_points(result)
|
shape_bounds.with_points(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_pixel_precision(transform: &mut Matrix, bounds: &mut Bounds) {
|
||||||
|
let tr = bounds.transform_matrix().unwrap_or_default();
|
||||||
|
let tr_inv = tr.invert().unwrap_or_default();
|
||||||
|
|
||||||
|
let x = bounds.min_x().round();
|
||||||
|
let y = bounds.min_y().round();
|
||||||
|
|
||||||
|
let mut round_transform = Matrix::scale((
|
||||||
|
bounds.width().round() / bounds.width(),
|
||||||
|
bounds.height().round() / bounds.height(),
|
||||||
|
));
|
||||||
|
round_transform.post_concat(&tr);
|
||||||
|
round_transform.pre_concat(&tr_inv);
|
||||||
|
|
||||||
|
transform.post_concat(&round_transform);
|
||||||
|
bounds.transform_mut(&round_transform);
|
||||||
|
|
||||||
|
let dx = x - bounds.min_x();
|
||||||
|
let dy = y - bounds.min_y();
|
||||||
|
|
||||||
|
let round_transform = Matrix::translate((dx, dy));
|
||||||
|
transform.post_concat(&round_transform);
|
||||||
|
bounds.transform_mut(&round_transform);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn propagate_modifiers(
|
pub fn propagate_modifiers(
|
||||||
state: &State,
|
state: &State,
|
||||||
modifiers: &[TransformEntry],
|
modifiers: &[TransformEntry],
|
||||||
|
pixel_precision: bool,
|
||||||
) -> (Vec<TransformEntry>, HashMap<Uuid, Bounds>) {
|
) -> (Vec<TransformEntry>, HashMap<Uuid, Bounds>) {
|
||||||
let shapes = &state.shapes;
|
let shapes = &state.shapes;
|
||||||
|
|
||||||
|
@ -161,6 +187,10 @@ pub fn propagate_modifiers(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pixel_precision {
|
||||||
|
set_pixel_precision(&mut transform, &mut shape_bounds_after);
|
||||||
|
}
|
||||||
|
|
||||||
if entry.propagate {
|
if entry.propagate {
|
||||||
let mut children = propagate_children(
|
let mut children = propagate_children(
|
||||||
shape,
|
shape,
|
||||||
|
@ -180,6 +210,10 @@ pub fn propagate_modifiers(
|
||||||
shape_modif.post_concat(&transform);
|
shape_modif.post_concat(&transform);
|
||||||
modifiers.insert(shape.id, shape_modif);
|
modifiers.insert(shape.id, shape_modif);
|
||||||
|
|
||||||
|
if shape.has_layout() {
|
||||||
|
entries.push_back(Modifier::reflow(shape.id));
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {
|
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {
|
||||||
if parent.has_layout() || parent.is_group_like() {
|
if parent.has_layout() || parent.is_group_like() {
|
||||||
entries.push_back(Modifier::reflow(parent.id));
|
entries.push_back(Modifier::reflow(parent.id));
|
||||||
|
|
|
@ -187,7 +187,7 @@ fn initialize_tracks(
|
||||||
let mut children = modified_children_ids(shape, structure.get(&shape.id));
|
let mut children = modified_children_ids(shape, structure.get(&shape.id));
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
if !flex_data.is_reverse() {
|
if flex_data.is_reverse() {
|
||||||
children.reverse();
|
children.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +497,14 @@ fn next_anchor(
|
||||||
prev_anchor: Point,
|
prev_anchor: Point,
|
||||||
total_shapes_size: f32,
|
total_shapes_size: f32,
|
||||||
) -> Point {
|
) -> Point {
|
||||||
|
if layout_axis.is_auto_main {
|
||||||
|
let delta = child_axis.margin_main_start
|
||||||
|
+ child_axis.margin_main_end
|
||||||
|
+ child_axis.main_size
|
||||||
|
+ layout_axis.gap_main;
|
||||||
|
return prev_anchor + layout_axis.main_v * delta;
|
||||||
|
}
|
||||||
|
|
||||||
let delta = child_axis.margin_main_start
|
let delta = child_axis.margin_main_start
|
||||||
+ child_axis.margin_main_end
|
+ child_axis.margin_main_end
|
||||||
+ match layout_data.justify_content {
|
+ match layout_data.justify_content {
|
||||||
|
|
|
@ -594,6 +594,13 @@ pub fn auto_width(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn max_width(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 {
|
||||||
|
paragraphs
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.fold(0.0, |max_width, p| f32::max(p.max_width(), max_width))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn auto_height(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 {
|
pub fn auto_height(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 {
|
||||||
paragraphs
|
paragraphs
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::shapes::{auto_height, auto_width, GrowType, RawTextData, Type};
|
use crate::shapes::{auto_height, auto_width, max_width, GrowType, RawTextData, Type};
|
||||||
|
|
||||||
use crate::STATE;
|
use crate::STATE;
|
||||||
use crate::{with_current_shape, with_state};
|
use crate::{with_current_shape, with_state};
|
||||||
|
@ -42,6 +42,7 @@ pub extern "C" fn get_text_dimensions() -> *mut u8 {
|
||||||
|
|
||||||
let mut width = 0.01;
|
let mut width = 0.01;
|
||||||
let mut height = 0.01;
|
let mut height = 0.01;
|
||||||
|
let mut m_width = 0.01;
|
||||||
with_current_shape!(state, |shape: &mut Shape| {
|
with_current_shape!(state, |shape: &mut Shape| {
|
||||||
width = shape.selrect.width();
|
width = shape.selrect.width();
|
||||||
height = shape.selrect.height();
|
height = shape.selrect.height();
|
||||||
|
@ -49,14 +50,16 @@ pub extern "C" fn get_text_dimensions() -> *mut u8 {
|
||||||
if let Type::Text(content) = &shape.shape_type {
|
if let Type::Text(content) = &shape.shape_type {
|
||||||
let paragraphs = content.get_skia_paragraphs(font_col);
|
let paragraphs = content.get_skia_paragraphs(font_col);
|
||||||
height = auto_height(¶graphs).ceil();
|
height = auto_height(¶graphs).ceil();
|
||||||
|
m_width = max_width(¶graphs);
|
||||||
if content.grow_type() == GrowType::AutoWidth {
|
if content.grow_type() == GrowType::AutoWidth {
|
||||||
width = auto_width(¶graphs).ceil();
|
width = auto_width(¶graphs).ceil();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut bytes = vec![0; 8];
|
let mut bytes = vec![0; 12];
|
||||||
bytes[0..4].clone_from_slice(&width.to_le_bytes());
|
bytes[0..4].clone_from_slice(&width.to_le_bytes());
|
||||||
bytes[4..8].clone_from_slice(&height.to_le_bytes());
|
bytes[4..8].clone_from_slice(&height.to_le_bytes());
|
||||||
|
bytes[8..12].clone_from_slice(&m_width.to_le_bytes());
|
||||||
mem::write_bytes(bytes)
|
mem::write_bytes(bytes)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue