From a72e50f67435774c5bd293f8c83329da2d1ac459 Mon Sep 17 00:00:00 2001 From: Aitor Date: Mon, 10 Jul 2023 17:35:19 +0200 Subject: [PATCH] :bug: Fix SVG text rendering on thumbnails --- .../app/main/data/workspace/thumbnails.cljs | 2 +- .../shapes/frame/thumbnail_render.cljs | 13 +++------ frontend/src/app/util/thumbnails.cljs | 29 +++++++++++++++++++ frontend/src/app/util/webapi.cljs | 29 +++++++++++++++++++ 4 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 frontend/src/app/util/thumbnails.cljs diff --git a/frontend/src/app/main/data/workspace/thumbnails.cljs b/frontend/src/app/main/data/workspace/thumbnails.cljs index 64f1b4c03..2019b340b 100644 --- a/frontend/src/app/main/data/workspace/thumbnails.cljs +++ b/frontend/src/app/main/data/workspace/thumbnails.cljs @@ -40,7 +40,7 @@ (rx/take 1))] ;; renders #svg image (if (some? node) - (->> (rx/from (js/createImageBitmap node)) + (->> (rx/from (wapi/create-image-bitmap-with-workaround node)) (rx/switch-map #(uw/ask! {:cmd :thumbnails/render-offscreen-canvas} %)) (rx/map :result)) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs index 2b14872f4..f2ee9f0d2 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs @@ -9,7 +9,6 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.shapes :as gsh] - [app.common.math :as mth] [app.config :as cf] [app.main.data.workspace.thumbnails :as dwt] [app.main.refs :as refs] @@ -17,6 +16,7 @@ [app.main.ui.hooks :as hooks] [app.main.ui.shapes.frame :as frame] [app.util.dom :as dom] + [app.util.thumbnails :as th] [app.util.timers :as ts] [app.util.webapi :as wapi] [beicon.core :as rx] @@ -41,16 +41,11 @@ [rect node style-node] (let [{:keys [x y width height]} rect viewbox (dm/str x " " y " " width " " height) - + ;; Calculate the fixed width and height - ;; We don't want to generate thumbnails + ;; We don't want to generate thumbnails ;; bigger than 2000px - [fixed-width fixed-height] - (if (> width height) - [(mth/clamp width 250 2000) - (/ (* height (mth/clamp width 250 2000)) width)] - [(/ (* width (mth/clamp height 250 2000)) height) - (mth/clamp height 250 2000)]) + [fixed-width fixed-height] (th/get-proportional-size width height) ;; This is way faster than creating a node ;; through the DOM API diff --git a/frontend/src/app/util/thumbnails.cljs b/frontend/src/app/util/thumbnails.cljs new file mode 100644 index 000000000..e44a7be3e --- /dev/null +++ b/frontend/src/app/util/thumbnails.cljs @@ -0,0 +1,29 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.util.thumbnails + (:require + [app.common.math :as mth])) + +(def ^:const min-size 250) +(def ^:const max-size 2000) + +(defn get-proportional-size + "Returns a proportional size given a width and height and some size constraints." + ([width height] + (get-proportional-size width height min-size max-size min-size max-size)) + ([width height min-size max-size] + (get-proportional-size width height min-size max-size min-size max-size)) + ([width height min-width max-width min-height max-height] + (let [[fixed-width fixed-height] + (if (> width height) + [(mth/clamp width min-width max-width) + (/ (* height (mth/clamp width min-width max-width)) width)] + [(/ (* width (mth/clamp height min-height max-height)) height) + (mth/clamp height min-height max-height)])] + [fixed-width fixed-height]))) + + diff --git a/frontend/src/app/util/webapi.cljs b/frontend/src/app/util/webapi.cljs index 183573c13..db5fd1146 100644 --- a/frontend/src/app/util/webapi.cljs +++ b/frontend/src/app/util/webapi.cljs @@ -11,6 +11,7 @@ [app.common.exceptions :as ex] [app.common.logging :as log] [app.util.object :as obj] + [app.util.thumbnails :as th] [beicon.core :as rx] [cuerdas.core :as str] [promesa.core :as p])) @@ -130,12 +131,40 @@ (map #(.item ^js file-list %)) (filter #(str/starts-with? (.-type %) "image/")))))) +(defn create-canvas-element + [width height] + (let [canvas (.createElement js/document "canvas")] + (obj/set! canvas "width" width) + (obj/set! canvas "height" height) + canvas)) + +(defn create-offscreen-canvas + [width height] + (if (obj/in? js/window "OffscreenCanvas") + (js/OffscreenCanvas. width height) + (create-canvas-element width height))) + (defn create-image-bitmap ([image] (js/createImageBitmap image)) ([image options] (js/createImageBitmap image options))) +;; Why this? Because as described in https://bugs.chromium.org/p/chromium/issues/detail?id=1463435 +;; the createImageBitmap seems to apply premultiplied alpha multiples times on the same image +;; which results in harsh borders around text being rendered. This is a workaround to avoid this issue. +(defn create-image-bitmap-with-workaround + ([image] + (create-image-bitmap-with-workaround image nil)) + ([image options] + (let [width (.-value (.-baseVal (.-width image))) + height (.-value (.-baseVal (.-height image))) + [width height] (th/get-proportional-size width height) + offscreen-canvas (create-offscreen-canvas width height) + offscreen-context (.getContext offscreen-canvas "2d")] + (.drawImage offscreen-context image 0 0) + (create-image-bitmap offscreen-canvas options)))) + (defn request-fullscreen [el] (cond