diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 695e9fb44e..e6cc837b52 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -60,10 +60,10 @@ (defn render-thumbnail [file-id revn] (if (features/active-feature? @st/state "render-wasm/v1") - (->> (mw/ask! {:cmd :thumbnails/generate-for-file-wasm - :revn revn - :file-id file-id - :width thumbnail-width})) + (mw/ask! {:cmd :thumbnails/generate-for-file-wasm + :revn revn + :file-id file-id + :width thumbnail-width}) (->> (mw/ask! {:cmd :thumbnails/generate-for-file :revn revn :file-id file-id diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index cfcd403870..ba5525791e 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -128,11 +128,12 @@ (defn update-text-rect! [id] - (mw/emit! - {:cmd :index/update-text-rect - :page-id (:current-page-id @st/state) - :shape-id id - :dimensions (get-text-dimensions id)})) + (when wasm/context-initialized? + (mw/emit! + {:cmd :index/update-text-rect + :page-id (:current-page-id @st/state) + :shape-id id + :dimensions (get-text-dimensions id)}))) (defn- ensure-text-content @@ -198,70 +199,71 @@ (defn set-shape-children [children] (perf/begin-measure "set-shape-children") - (case (count children) - 0 - (h/call wasm/internal-module "_set_children_0") + (let [children (into [] (filter uuid?) children)] + (case (count 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))) + 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))) + 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))) + 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))) + 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))) + 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) - size (mem/get-alloc-size children UUID-U8-SIZE) - offset (mem/alloc->offset-32 size)] - (reduce - (fn [offset id] - (mem.h32/write-uuid offset heap id)) - offset - children) - (h/call wasm/internal-module "_set_children"))) + ;; Dynamic call for children > 5 + (let [heap (mem/get-heap-u32) + size (mem/get-alloc-size children UUID-U8-SIZE) + offset (mem/alloc->offset-32 size)] + (reduce + (fn [offset id] + (mem.h32/write-uuid offset heap id)) + offset + children) + (h/call wasm/internal-module "_set_children")))) (perf/end-measure "set-shape-children") nil) @@ -1031,8 +1033,9 @@ (into full-acc full))) {:thumbnails thumbnails-acc :full full-acc}))] (perf/end-measure "set-objects") - (process-pending shapes thumbnails full render-callback + (process-pending shapes thumbnails full noop-fn (fn [] + (when render-callback (render-callback)) (ug/dispatch! (ug/event "penpot:wasm:set-objects"))))))) (defn clear-focus-mode diff --git a/frontend/src/app/render_wasm/api/fonts.cljs b/frontend/src/app/render_wasm/api/fonts.cljs index 1962ed224f..1e3bcc6ca5 100644 --- a/frontend/src/app/render_wasm/api/fonts.cljs +++ b/frontend/src/app/render_wasm/api/fonts.cljs @@ -83,12 +83,13 @@ (defn update-text-layout [id] - (let [shape-id-buffer (uuid/get-u32 id)] - (h/call wasm/internal-module "_update_shape_text_layout_for" - (aget shape-id-buffer 0) - (aget shape-id-buffer 1) - (aget shape-id-buffer 2) - (aget shape-id-buffer 3)))) + (when wasm/context-initialized? + (let [shape-id-buffer (uuid/get-u32 id)] + (h/call wasm/internal-module "_update_shape_text_layout_for" + (aget shape-id-buffer 0) + (aget shape-id-buffer 1) + (aget shape-id-buffer 2) + (aget shape-id-buffer 3))))) ;; IMPORTANT: Only TTF fonts can be stored. (defn- store-font-buffer diff --git a/frontend/src/app/worker/thumbnails.cljs b/frontend/src/app/worker/thumbnails.cljs index 5871c8c58e..517d7895a4 100644 --- a/frontend/src/app/worker/thumbnails.cljs +++ b/frontend/src/app/worker/thumbnails.cljs @@ -13,6 +13,7 @@ [app.common.logging :as log] [app.common.types.color :as cc] [app.common.uri :as u] + [app.common.uuid :as uuid] [app.config :as cf] [app.main.fonts :as fonts] [app.main.render :as render] @@ -125,58 +126,75 @@ (def thumbnail-aspect-ratio (/ 2 3)) -(defmethod impl/handler :thumbnails/generate-for-file-wasm - [{:keys [file-id revn width] :as message} _] +(defn render-canvas-blob + [canvas width height background-color] + (-> (.convertToBlob canvas) + (p/then + (fn [blob] + (rds/renderToStaticMarkup + (mf/element + svg-wrapper + #js {:data-uri (blob->uri blob) + :width width + :height height + :background background-color})))))) +(defn process-wasm-thumbnail + [{:keys [id file-id revn width] :as message}] (->> (rx/from @init-wasm) (rx/mapcat #(request-data-for-thumbnail file-id revn false)) (rx/mapcat (fn [{:keys [page] :as file}] (rx/create (fn [subs] - (try - (let [background-color (or (:background page) cc/canvas) - height (* width thumbnail-aspect-ratio) - canvas (js/OffscreenCanvas. width height) - init? (wasm.api/init-canvas-context canvas)] - (if init? - (let [objects (:objects page) - frame (some->> page :thumbnail-frame-id (get objects)) - vbox (if frame - (-> (gsb/get-object-bounds objects frame) - (grc/fix-aspect-ratio thumbnail-aspect-ratio)) - (render/calculate-dimensions objects thumbnail-aspect-ratio)) - zoom (/ width (:width vbox))] + (let [background-color (or (:background page) cc/canvas) + height (* width thumbnail-aspect-ratio) + canvas (js/OffscreenCanvas. width height) + init? (wasm.api/init-canvas-context canvas)] + (if init? + (let [objects (:objects page) + frame (some->> page :thumbnail-frame-id (get objects)) + vbox (if frame + (-> (gsb/get-object-bounds objects frame) + (grc/fix-aspect-ratio thumbnail-aspect-ratio)) + (render/calculate-dimensions objects thumbnail-aspect-ratio)) + zoom (/ width (:width vbox))] - (wasm.api/initialize-viewport - objects zoom vbox background-color - (fn [] - (if frame - (wasm.api/render-sync-shape (:id frame)) - (wasm.api/render-sync)) + (wasm.api/initialize-viewport + objects zoom vbox background-color + (fn [] + (if frame + (wasm.api/render-sync-shape (:id frame)) + (wasm.api/render-sync)) - (-> (.convertToBlob canvas) - (p/then - (fn [blob] - (let [data - (rds/renderToStaticMarkup - (mf/element - svg-wrapper - #js {:data-uri (blob->uri blob) - :width width - :height height - :background background-color}))] - (rx/push! subs {:data data :file-id file-id :revn revn})))) - (p/catch #(do (.error js/console %) - (rx/error! subs %))) - (p/finally #(rx/end! subs)))))) + (-> (render-canvas-blob canvas width height background-color) + (p/then #(rx/push! subs {:id id :data % :file-id file-id :revn revn})) + (p/catch #(rx/error! subs %)) + (p/finally #(rx/end! subs)))))) - (do (rx/error! subs "Error loading webgl context") - (rx/end! subs))) + (rx/end! subs)) - nil) + nil))))))) - (catch :default err - (.error js/console err) - (rx/error! subs err) - (rx/end! subs))))))))) +(defonce thumbs-subject (rx/subject)) + +(defonce thumbs-stream + (->> thumbs-subject + (rx/mapcat process-wasm-thumbnail) + (rx/share))) + +(defmethod impl/handler :thumbnails/generate-for-file-wasm + [message _] + (rx/create + (fn [subs] + (let [id (uuid/next) + sid + (->> thumbs-stream + (rx/filter #(= id (:id %))) + (rx/subs! + #(do + (rx/push! subs %) + (rx/end! subs))))] + (rx/push! thumbs-subject (assoc message :id id)) + + #(rx/dispose! sid))))) diff --git a/render-wasm/src/wasm/text.rs b/render-wasm/src/wasm/text.rs index a45b03c9de..f4dcc12086 100644 --- a/render-wasm/src/wasm/text.rs +++ b/render-wasm/src/wasm/text.rs @@ -291,9 +291,10 @@ pub extern "C" fn set_shape_text_content() { let bytes = mem::bytes(); with_current_shape_mut!(state, |shape: &mut Shape| { let raw_text_data = RawParagraph::try_from(&bytes).unwrap(); - shape - .add_paragraph(raw_text_data.into()) - .expect("Failed to add paragraph"); + + if let Err(_) = shape.add_paragraph(raw_text_data.into()) { + println!("Error with set_shape_text_content on {:?}", shape.id); + } }); mem::free_bytes(); }