mirror of
https://github.com/penpot/penpot.git
synced 2026-09-07 04:29:31 +00:00
♻️ Clean unnecessary methods (#11472)
* ♻️ Remove duplicated/unused set-children code * ♻️ Remove unused methods
This commit is contained in:
parent
b9ddfc1596
commit
03e6f119e5
@ -17,7 +17,6 @@
|
|||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.render-wasm.helpers :as h]
|
[app.common.render-wasm.helpers :as h]
|
||||||
[app.common.render-wasm.mem :as mem]
|
[app.common.render-wasm.mem :as mem]
|
||||||
[app.common.render-wasm.mem.heap32 :as mem.h32]
|
|
||||||
[app.common.render-wasm.serializers :as sr]
|
[app.common.render-wasm.serializers :as sr]
|
||||||
[app.common.render-wasm.serializers.color :as sr-clr]
|
[app.common.render-wasm.serializers.color :as sr-clr]
|
||||||
[app.common.render-wasm.wasm :as wasm]
|
[app.common.render-wasm.wasm :as wasm]
|
||||||
@ -27,22 +26,6 @@
|
|||||||
|
|
||||||
(def ^:const MAX_BUFFER_CHUNK_SIZE (* 256 1024))
|
(def ^:const MAX_BUFFER_CHUNK_SIZE (* 256 1024))
|
||||||
|
|
||||||
(def ^:const UUID-U8-SIZE 16)
|
|
||||||
|
|
||||||
(defn set-shape-children
|
|
||||||
"Uploads the child id list via the dynamic `_set_children` path (handles any
|
|
||||||
count). The browser also has fixed-arity fast paths for the incremental edit
|
|
||||||
path; this dynamic one is the shared/batch version."
|
|
||||||
[children]
|
|
||||||
(let [children (into [] (filter uuid?) children)]
|
|
||||||
(if (empty? children)
|
|
||||||
(h/call wasm/internal-module "_set_children_0")
|
|
||||||
(let [heap (mem/get-heap-u32)
|
|
||||||
size (mem/get-alloc-size children UUID-U8-SIZE)
|
|
||||||
offset (mem/alloc->offset-32 size)]
|
|
||||||
(reduce (fn [o id] (mem.h32/write-uuid o heap id)) offset children)
|
|
||||||
(h/call wasm/internal-module "_set_children")))))
|
|
||||||
|
|
||||||
(defn set-shape-bool-type
|
(defn set-shape-bool-type
|
||||||
[bool-type]
|
[bool-type]
|
||||||
(h/call wasm/internal-module "_set_shape_bool_type" (sr/translate-bool-type bool-type)))
|
(h/call wasm/internal-module "_set_shape_bool_type" (sr/translate-bool-type bool-type)))
|
||||||
|
|||||||
@ -844,61 +844,8 @@
|
|||||||
[children]
|
[children]
|
||||||
(perf/begin-measure "set-shape-children")
|
(perf/begin-measure "set-shape-children")
|
||||||
(let [children (into [] (filter uuid?) children)]
|
(let [children (into [] (filter uuid?) children)]
|
||||||
(case (count children)
|
(if (empty? children)
|
||||||
0
|
|
||||||
(h/call wasm/internal-module "_set_children_0")
|
(h/call wasm/internal-module "_set_children_0")
|
||||||
|
|
||||||
1
|
|
||||||
(let [[c1] children
|
|
||||||
c1 (uuid/get-u32 c1)]
|
|
||||||
(h/call wasm/internal-module "_set_children_1"
|
|
||||||
(aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3)))
|
|
||||||
|
|
||||||
2
|
|
||||||
(let [[c1 c2] children
|
|
||||||
c1 (uuid/get-u32 c1)
|
|
||||||
c2 (uuid/get-u32 c2)]
|
|
||||||
(h/call wasm/internal-module "_set_children_2"
|
|
||||||
(aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3)
|
|
||||||
(aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3)))
|
|
||||||
|
|
||||||
3
|
|
||||||
(let [[c1 c2 c3] children
|
|
||||||
c1 (uuid/get-u32 c1)
|
|
||||||
c2 (uuid/get-u32 c2)
|
|
||||||
c3 (uuid/get-u32 c3)]
|
|
||||||
(h/call wasm/internal-module "_set_children_3"
|
|
||||||
(aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3)
|
|
||||||
(aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3)
|
|
||||||
(aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3)))
|
|
||||||
|
|
||||||
4
|
|
||||||
(let [[c1 c2 c3 c4] children
|
|
||||||
c1 (uuid/get-u32 c1)
|
|
||||||
c2 (uuid/get-u32 c2)
|
|
||||||
c3 (uuid/get-u32 c3)
|
|
||||||
c4 (uuid/get-u32 c4)]
|
|
||||||
(h/call wasm/internal-module "_set_children_4"
|
|
||||||
(aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3)
|
|
||||||
(aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3)
|
|
||||||
(aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3)
|
|
||||||
(aget c4 0) (aget c4 1) (aget c4 2) (aget c4 3)))
|
|
||||||
|
|
||||||
5
|
|
||||||
(let [[c1 c2 c3 c4 c5] children
|
|
||||||
c1 (uuid/get-u32 c1)
|
|
||||||
c2 (uuid/get-u32 c2)
|
|
||||||
c3 (uuid/get-u32 c3)
|
|
||||||
c4 (uuid/get-u32 c4)
|
|
||||||
c5 (uuid/get-u32 c5)]
|
|
||||||
(h/call wasm/internal-module "_set_children_5"
|
|
||||||
(aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3)
|
|
||||||
(aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3)
|
|
||||||
(aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3)
|
|
||||||
(aget c4 0) (aget c4 1) (aget c4 2) (aget c4 3)
|
|
||||||
(aget c5 0) (aget c5 1) (aget c5 2) (aget c5 3)))
|
|
||||||
|
|
||||||
;; Dynamic call for children > 5
|
|
||||||
(let [heap (mem/get-heap-u32)
|
(let [heap (mem/get-heap-u32)
|
||||||
size (mem/get-alloc-size children UUID-U8-SIZE)
|
size (mem/get-alloc-size children UUID-U8-SIZE)
|
||||||
offset (mem/alloc->offset-32 size)]
|
offset (mem/alloc->offset-32 size)]
|
||||||
|
|||||||
@ -51,47 +51,6 @@ pub extern "C" fn set_render_options(debug: u32, dpr: f32) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_viewport_interest_area_threshold(
|
|
||||||
viewport_interest_area_threshold: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let render_state = get_render_state();
|
|
||||||
render_state.set_viewport_interest_area_threshold(viewport_interest_area_threshold)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_max_blocking_time_ms(max_blocking_time_ms: i32) -> Result<()> {
|
|
||||||
let render_state = get_render_state();
|
|
||||||
render_state.set_max_blocking_time_ms(max_blocking_time_ms);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_node_batch_threshold(node_batch_threshold: i32) -> Result<()> {
|
|
||||||
let render_state = get_render_state();
|
|
||||||
render_state.set_node_batch_threshold(node_batch_threshold);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_blur_downscale_threshold(blur_downscale_threshold: f32) -> Result<()> {
|
|
||||||
let render_state = get_render_state();
|
|
||||||
render_state.set_blur_downscale_threshold(blur_downscale_threshold);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_antialias_threshold(threshold: f32) -> Result<()> {
|
|
||||||
get_render_state().set_antialias_threshold(threshold);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[wasm_error]
|
#[wasm_error]
|
||||||
pub extern "C" fn set_canvas_background(raw_color: u32) -> Result<()> {
|
pub extern "C" fn set_canvas_background(raw_color: u32) -> Result<()> {
|
||||||
@ -469,16 +428,6 @@ pub extern "C" fn has_shape(a: u32, b: u32, c: u32, d: u32) -> Result<bool> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn touch_shape(a: u32, b: u32, c: u32, d: u32) -> Result<()> {
|
|
||||||
with_state!(state, {
|
|
||||||
let shape_id = uuid_from_u32_quartet(a, b, c, d);
|
|
||||||
state.touch_shape(shape_id);
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[wasm_error]
|
#[wasm_error]
|
||||||
pub extern "C" fn set_parent(a: u32, b: u32, c: u32, d: u32) -> Result<()> {
|
pub extern "C" fn set_parent(a: u32, b: u32, c: u32, d: u32) -> Result<()> {
|
||||||
@ -541,16 +490,6 @@ pub extern "C" fn set_shape_transform(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn add_shape_child(a: u32, b: u32, c: u32, d: u32) -> Result<()> {
|
|
||||||
with_current_shape_mut!(state, |shape: &mut Shape| {
|
|
||||||
let id = uuid_from_u32_quartet(a, b, c, d);
|
|
||||||
shape.add_child(id);
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_children_set(entries: Vec<Uuid>) -> Result<()> {
|
fn set_children_set(entries: Vec<Uuid>) -> Result<()> {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
state.set_current_shape_children(entries)?;
|
state.set_current_shape_children(entries)?;
|
||||||
@ -566,124 +505,6 @@ pub extern "C" fn set_children_0() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_children_1(a1: u32, b1: u32, c1: u32, d1: u32) -> Result<()> {
|
|
||||||
let entries = vec![uuid_from_u32_quartet(a1, b1, c1, d1)];
|
|
||||||
set_children_set(entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_children_2(
|
|
||||||
a1: u32,
|
|
||||||
b1: u32,
|
|
||||||
c1: u32,
|
|
||||||
d1: u32,
|
|
||||||
a2: u32,
|
|
||||||
b2: u32,
|
|
||||||
c2: u32,
|
|
||||||
d2: u32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entries = vec![
|
|
||||||
uuid_from_u32_quartet(a1, b1, c1, d1),
|
|
||||||
uuid_from_u32_quartet(a2, b2, c2, d2),
|
|
||||||
];
|
|
||||||
set_children_set(entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_children_3(
|
|
||||||
a1: u32,
|
|
||||||
b1: u32,
|
|
||||||
c1: u32,
|
|
||||||
d1: u32,
|
|
||||||
a2: u32,
|
|
||||||
b2: u32,
|
|
||||||
c2: u32,
|
|
||||||
d2: u32,
|
|
||||||
a3: u32,
|
|
||||||
b3: u32,
|
|
||||||
c3: u32,
|
|
||||||
d3: u32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entries = vec![
|
|
||||||
uuid_from_u32_quartet(a1, b1, c1, d1),
|
|
||||||
uuid_from_u32_quartet(a2, b2, c2, d2),
|
|
||||||
uuid_from_u32_quartet(a3, b3, c3, d3),
|
|
||||||
];
|
|
||||||
set_children_set(entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_children_4(
|
|
||||||
a1: u32,
|
|
||||||
b1: u32,
|
|
||||||
c1: u32,
|
|
||||||
d1: u32,
|
|
||||||
a2: u32,
|
|
||||||
b2: u32,
|
|
||||||
c2: u32,
|
|
||||||
d2: u32,
|
|
||||||
a3: u32,
|
|
||||||
b3: u32,
|
|
||||||
c3: u32,
|
|
||||||
d3: u32,
|
|
||||||
a4: u32,
|
|
||||||
b4: u32,
|
|
||||||
c4: u32,
|
|
||||||
d4: u32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entries = vec![
|
|
||||||
uuid_from_u32_quartet(a1, b1, c1, d1),
|
|
||||||
uuid_from_u32_quartet(a2, b2, c2, d2),
|
|
||||||
uuid_from_u32_quartet(a3, b3, c3, d3),
|
|
||||||
uuid_from_u32_quartet(a4, b4, c4, d4),
|
|
||||||
];
|
|
||||||
set_children_set(entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[wasm_error]
|
|
||||||
pub extern "C" fn set_children_5(
|
|
||||||
a1: u32,
|
|
||||||
b1: u32,
|
|
||||||
c1: u32,
|
|
||||||
d1: u32,
|
|
||||||
a2: u32,
|
|
||||||
b2: u32,
|
|
||||||
c2: u32,
|
|
||||||
d2: u32,
|
|
||||||
a3: u32,
|
|
||||||
b3: u32,
|
|
||||||
c3: u32,
|
|
||||||
d3: u32,
|
|
||||||
a4: u32,
|
|
||||||
b4: u32,
|
|
||||||
c4: u32,
|
|
||||||
d4: u32,
|
|
||||||
a5: u32,
|
|
||||||
b5: u32,
|
|
||||||
c5: u32,
|
|
||||||
d5: u32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entries = vec![
|
|
||||||
uuid_from_u32_quartet(a1, b1, c1, d1),
|
|
||||||
uuid_from_u32_quartet(a2, b2, c2, d2),
|
|
||||||
uuid_from_u32_quartet(a3, b3, c3, d3),
|
|
||||||
uuid_from_u32_quartet(a4, b4, c4, d4),
|
|
||||||
uuid_from_u32_quartet(a5, b5, c5, d5),
|
|
||||||
];
|
|
||||||
set_children_set(entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[wasm_error]
|
#[wasm_error]
|
||||||
pub extern "C" fn set_children() -> Result<()> {
|
pub extern "C" fn set_children() -> Result<()> {
|
||||||
|
|||||||
@ -911,37 +911,6 @@ impl RenderState {
|
|||||||
.ensure_tile_atlas_layout(self.tile_viewbox.interest_rect.len().max(1) as usize);
|
.ensure_tile_atlas_layout(self.tile_viewbox.interest_rect.len().max(1) as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_antialias_threshold(&mut self, value: f32) {
|
|
||||||
self.options.set_antialias_threshold(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_viewport_interest_area_threshold(&mut self, value: i32) -> Result<()> {
|
|
||||||
// Only when this function returns true (it means the value
|
|
||||||
// was changed properly) the tile_viewbox.set_interest is called.
|
|
||||||
if self.options.set_viewport_interest_area_threshold(value) {
|
|
||||||
// The TileViewbox stores its own copy of `interest` (set at
|
|
||||||
// construction). Without propagating, options change wouldn't
|
|
||||||
// affect pending_tiles generation.
|
|
||||||
self.tile_viewbox
|
|
||||||
.set_interest(self.options.dpr_viewport_interest_area_threshold);
|
|
||||||
self.tile_viewbox.update(&self.viewbox);
|
|
||||||
self.ensure_tile_atlas_layout();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_node_batch_threshold(&mut self, value: i32) {
|
|
||||||
self.options.set_node_batch_threshold(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_max_blocking_time_ms(&mut self, value: i32) {
|
|
||||||
self.options.set_max_blocking_time_ms(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_blur_downscale_threshold(&mut self, value: f32) {
|
|
||||||
self.options.set_blur_downscale_threshold(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_background_color(&mut self, color: skia::Color) {
|
pub fn set_background_color(&mut self, color: skia::Color) {
|
||||||
self.background_color = color;
|
self.background_color = color;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,45 +121,4 @@ impl RenderOptions {
|
|||||||
pub fn show_wasm_info(&self) -> bool {
|
pub fn show_wasm_info(&self) -> bool {
|
||||||
self.flags & SHOW_WASM_INFO == SHOW_WASM_INFO
|
self.flags & SHOW_WASM_INFO == SHOW_WASM_INFO
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_antialias_threshold(&mut self, value: f32) -> bool {
|
|
||||||
if value.is_finite() && value > 0.0 {
|
|
||||||
self.antialias_threshold = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_blur_downscale_threshold(&mut self, value: f32) -> bool {
|
|
||||||
if value.is_finite() && value > 0.0 {
|
|
||||||
self.blur_downscale_threshold = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_viewport_interest_area_threshold(&mut self, value: i32) -> bool {
|
|
||||||
if value >= 0 && self.viewport_interest_area_threshold != value {
|
|
||||||
self.viewport_interest_area_threshold = value;
|
|
||||||
self.update_dpr_viewport_interest_area_threshold();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_node_batch_threshold(&mut self, value: i32) -> bool {
|
|
||||||
if value > 0 {
|
|
||||||
self.node_batch_threshold = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_max_blocking_time_ms(&mut self, value: i32) -> bool {
|
|
||||||
if value > 0 {
|
|
||||||
self.max_blocking_time_ms = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -652,6 +652,7 @@ impl Shape {
|
|||||||
self.background_blur.filter(|blur| !blur.hidden)
|
self.background_blur.filter(|blur| !blur.hidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn add_child(&mut self, id: Uuid) {
|
pub fn add_child(&mut self, id: Uuid) {
|
||||||
self.children.push(id);
|
self.children.push(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
use macros::{wasm_error, ToJs};
|
use macros::{wasm_error, ToJs};
|
||||||
|
|
||||||
use crate::globals::{get_render_state, get_text_editor_state};
|
use crate::globals::{get_render_state, get_text_editor_state};
|
||||||
use crate::math::{Matrix, Point, Rect};
|
use crate::math::{Matrix, Point};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::render::text_editor as text_editor_render;
|
use crate::render::text_editor as text_editor_render;
|
||||||
use crate::render::SurfaceId;
|
use crate::render::SurfaceId;
|
||||||
use crate::shapes::{Shape, TextAlign, TextContent, TextPositionWithAffinity, Type, VerticalAlign};
|
use crate::shapes::{TextAlign, TextPositionWithAffinity, Type, VerticalAlign};
|
||||||
use crate::state::{State, TextEditorEvent, TextSelection};
|
use crate::state::{State, TextEditorEvent};
|
||||||
use crate::utils::uuid_from_u32_quartet;
|
use crate::utils::uuid_from_u32_quartet;
|
||||||
use crate::utils::uuid_to_u32_quartet;
|
use crate::utils::uuid_to_u32_quartet;
|
||||||
use crate::uuid::Uuid;
|
use crate::uuid::Uuid;
|
||||||
@ -643,40 +643,6 @@ pub extern "C" fn text_editor_move_cursor(
|
|||||||
// RENDERING & EXPORT
|
// RENDERING & EXPORT
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn text_editor_get_cursor_rect() -> *mut u8 {
|
|
||||||
with_state!(state, {
|
|
||||||
if !get_text_editor_state().has_focus || !get_text_editor_state().cursor_visible {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(shape_id) = get_text_editor_state().active_shape_id else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(shape) = state.shapes.get(&shape_id) else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let Type::Text(text_content) = &shape.shape_type else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let cursor = &get_text_editor_state().selection.focus;
|
|
||||||
|
|
||||||
if let Some(rect) = get_cursor_rect(text_content, cursor, shape) {
|
|
||||||
let mut bytes = vec![0u8; 16];
|
|
||||||
bytes[0..4].copy_from_slice(&rect.left().to_le_bytes());
|
|
||||||
bytes[4..8].copy_from_slice(&rect.top().to_le_bytes());
|
|
||||||
bytes[8..12].copy_from_slice(&rect.width().to_le_bytes());
|
|
||||||
bytes[12..16].copy_from_slice(&rect.height().to_le_bytes());
|
|
||||||
return mem::write_bytes(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ptr::null_mut()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_get_current_styles() -> *mut u8 {
|
pub extern "C" fn text_editor_get_current_styles() -> *mut u8 {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
@ -838,47 +804,6 @@ pub extern "C" fn text_editor_get_current_styles() -> *mut u8 {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn text_editor_get_selection_rects() -> *mut u8 {
|
|
||||||
with_state!(state, {
|
|
||||||
if !get_text_editor_state().has_focus {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
if get_text_editor_state().selection.is_collapsed() {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(shape_id) = get_text_editor_state().active_shape_id else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(shape) = state.shapes.get(&shape_id) else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let Type::Text(text_content) = &shape.shape_type else {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
};
|
|
||||||
|
|
||||||
let selection = &get_text_editor_state().selection;
|
|
||||||
let rects = get_selection_rects(text_content, selection, shape);
|
|
||||||
if rects.is_empty() {
|
|
||||||
return std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(4 + rects.len() * 16);
|
|
||||||
bytes.extend_from_slice(&(rects.len() as u32).to_le_bytes());
|
|
||||||
for rect in rects {
|
|
||||||
bytes.extend_from_slice(&rect.left().to_le_bytes());
|
|
||||||
bytes.extend_from_slice(&rect.top().to_le_bytes());
|
|
||||||
bytes.extend_from_slice(&rect.width().to_le_bytes());
|
|
||||||
bytes.extend_from_slice(&rect.height().to_le_bytes());
|
|
||||||
}
|
|
||||||
mem::write_bytes(bytes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_update_blink(timestamp_ms: f32) {
|
pub extern "C" fn text_editor_update_blink(timestamp_ms: f32) {
|
||||||
get_text_editor_state().update_blink(timestamp_ms);
|
get_text_editor_state().update_blink(timestamp_ms);
|
||||||
@ -1124,139 +1049,3 @@ pub extern "C" fn text_editor_get_selection(buffer_ptr: *mut u32) -> bool {
|
|||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// HELPERS: Cursor & Selection
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
fn get_cursor_rect(
|
|
||||||
text_content: &TextContent,
|
|
||||||
cursor: &TextPositionWithAffinity,
|
|
||||||
shape: &Shape,
|
|
||||||
) -> Option<Rect> {
|
|
||||||
let paragraphs = text_content.paragraphs();
|
|
||||||
if cursor.paragraph >= paragraphs.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let layout_paragraphs: Vec<_> = text_content.layout.paragraphs.iter().flatten().collect();
|
|
||||||
|
|
||||||
let total_height: f32 = layout_paragraphs.iter().map(|p| p.height()).sum();
|
|
||||||
let valign_offset = match shape.vertical_align() {
|
|
||||||
VerticalAlign::Center => (shape.selrect().height() - total_height) / 2.0,
|
|
||||||
VerticalAlign::Bottom => shape.selrect().height() - total_height,
|
|
||||||
_ => 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut y_offset = valign_offset;
|
|
||||||
for (idx, laid_out_para) in layout_paragraphs.iter().enumerate() {
|
|
||||||
if idx == cursor.paragraph {
|
|
||||||
let utf16_pos = paragraphs[cursor.paragraph].char_offset_to_utf16(cursor.offset);
|
|
||||||
|
|
||||||
use skia_safe::textlayout::{RectHeightStyle, RectWidthStyle};
|
|
||||||
let rects = laid_out_para.get_rects_for_range(
|
|
||||||
utf16_pos..utf16_pos,
|
|
||||||
RectHeightStyle::Tight,
|
|
||||||
RectWidthStyle::Tight,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (x, height) = if !rects.is_empty() {
|
|
||||||
(rects[0].rect.left(), rects[0].rect.height())
|
|
||||||
} else {
|
|
||||||
let pos = laid_out_para.get_glyph_position_at_coordinate((0.0, 0.0));
|
|
||||||
let height = laid_out_para.height();
|
|
||||||
(pos.position as f32, height)
|
|
||||||
};
|
|
||||||
|
|
||||||
let selrect = shape.selrect();
|
|
||||||
let base_x = selrect.x();
|
|
||||||
let base_y = selrect.y() + y_offset;
|
|
||||||
|
|
||||||
return Some(Rect::from_xywh(base_x + x, base_y, 1.0, height));
|
|
||||||
}
|
|
||||||
y_offset += laid_out_para.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get selection rectangles for a given selection.
|
|
||||||
fn get_selection_rects(
|
|
||||||
text_content: &TextContent,
|
|
||||||
selection: &TextSelection,
|
|
||||||
shape: &Shape,
|
|
||||||
) -> Vec<Rect> {
|
|
||||||
let mut rects = Vec::new();
|
|
||||||
|
|
||||||
let start = selection.start();
|
|
||||||
let end = selection.end();
|
|
||||||
|
|
||||||
let paragraphs = text_content.paragraphs();
|
|
||||||
let layout_paragraphs: Vec<_> = text_content.layout.paragraphs.iter().flatten().collect();
|
|
||||||
|
|
||||||
let selrect = shape.selrect();
|
|
||||||
|
|
||||||
let total_height: f32 = layout_paragraphs.iter().map(|p| p.height()).sum();
|
|
||||||
let valign_offset = match shape.vertical_align() {
|
|
||||||
VerticalAlign::Center => (selrect.height() - total_height) / 2.0,
|
|
||||||
VerticalAlign::Bottom => selrect.height() - total_height,
|
|
||||||
_ => 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut y_offset = valign_offset;
|
|
||||||
|
|
||||||
for (para_idx, laid_out_para) in layout_paragraphs.iter().enumerate() {
|
|
||||||
let para_height = laid_out_para.height();
|
|
||||||
|
|
||||||
if para_idx < start.paragraph || para_idx > end.paragraph {
|
|
||||||
y_offset += para_height;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if para_idx >= paragraphs.len() {
|
|
||||||
y_offset += para_height;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let para = ¶graphs[para_idx];
|
|
||||||
let para_char_count: usize = para
|
|
||||||
.children()
|
|
||||||
.iter()
|
|
||||||
.map(|span| span.text.chars().count())
|
|
||||||
.sum();
|
|
||||||
let range_start = if para_idx == start.paragraph {
|
|
||||||
start.offset
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
let range_end = if para_idx == end.paragraph {
|
|
||||||
end.offset
|
|
||||||
} else {
|
|
||||||
para_char_count
|
|
||||||
};
|
|
||||||
|
|
||||||
if range_start < range_end {
|
|
||||||
use skia_safe::textlayout::{RectHeightStyle, RectWidthStyle};
|
|
||||||
let text_boxes = laid_out_para.get_rects_for_range(
|
|
||||||
para.char_offset_to_utf16(range_start)..para.char_offset_to_utf16(range_end),
|
|
||||||
RectHeightStyle::Tight,
|
|
||||||
RectWidthStyle::Tight,
|
|
||||||
);
|
|
||||||
|
|
||||||
for text_box in text_boxes {
|
|
||||||
let r = text_box.rect;
|
|
||||||
rects.push(Rect::from_xywh(
|
|
||||||
selrect.x() + r.left(),
|
|
||||||
selrect.y() + y_offset + r.top(),
|
|
||||||
r.width(),
|
|
||||||
r.height(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y_offset += para_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
rects
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user