0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 18:48:37 -05:00

🐛 Fix custom font rendering on exporting shapes.

This commit is contained in:
Andrey Antukh 2021-06-04 13:17:35 +02:00 committed by Alonso Torres
parent 1a81631886
commit 8c68e29bf3
8 changed files with 100 additions and 49 deletions

View file

@ -8,12 +8,16 @@
(:require (:require
[app.common.spec :as us] [app.common.spec :as us]
[app.db :as db] [app.db :as db]
[app.rpc.queries.files :as files]
[app.rpc.queries.projects :as projects]
[app.rpc.queries.teams :as teams] [app.rpc.queries.teams :as teams]
[app.util.services :as sv] [app.util.services :as sv]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
;; --- Query: Team Font Variants ;; --- Query: Team Font Variants
;; TODO: deprecated, should be removed on 1.7.x
(s/def ::team-id ::us/uuid) (s/def ::team-id ::us/uuid)
(s/def ::profile-id ::us/uuid) (s/def ::profile-id ::us/uuid)
(s/def ::team-font-variants (s/def ::team-font-variants
@ -27,3 +31,43 @@
{:team-id team-id {:team-id team-id
:deleted-at nil}))) :deleted-at nil})))
;; --- Query: Font Variants
(s/def ::file-id ::us/uuid)
(s/def ::project-id ::us/uuid)
(s/def ::font-variants
(s/and
(s/keys :req-un [::profile-id]
:opt-un [::team-id
::file-id
::project-id])
(fn [o]
(or (contains? o :team-id)
(contains? o :file-id)
(contains? o :project-id)))))
(sv/defmethod ::font-variants
[{:keys [pool] :as cfg} {:keys [profile-id team-id file-id project-id] :as params}]
(with-open [conn (db/open pool)]
(cond
(uuid? team-id)
(do
(teams/check-read-permissions! conn profile-id team-id)
(db/query conn :team-font-variant
{:team-id team-id
:deleted-at nil}))
(uuid? project-id)
(let [project (db/get-by-id conn :project project-id {:columns [:id :team-id]})]
(projects/check-read-permissions! conn profile-id project-id)
(db/query conn :team-font-variant
{:team-id (:team-id project)
:deleted-at nil}))
(uuid? file-id)
(let [file (db/get-by-id conn :file file-id {:columns [:id :project-id]})
project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]})]
(files/check-read-permissions! conn profile-id file-id)
(db/query conn :team-font-variant
{:team-id (:team-id project)
:deleted-at nil})))))

View file

@ -356,8 +356,8 @@
([shape {:keys [round-coords?] ([shape {:keys [round-coords?]
:or {round-coords? true}}] :or {round-coords? true}}]
(let [shape (apply-displacement shape) (let [shape (apply-displacement shape)
center (gco/center-shape shape) center (gco/center-shape shape)
modifiers (:modifiers shape)] modifiers (:modifiers shape)]
(if (and modifiers center) (if (and modifiers center)
(let [transform (modifiers->transform center modifiers)] (let [transform (modifiers->transform center modifiers)]
@ -376,7 +376,7 @@
:y (- (:y new-selrect 0) (:y selrect 0)) :y (- (:y new-selrect 0) (:y selrect 0))
:width (- (:width new-selrect 1) (:width selrect 1)) :width (- (:width new-selrect 1) (:width selrect 1))
:height (- (:height new-selrect 1) (:height selrect 1))}] :height (- (:height new-selrect 1) (:height selrect 1))}]
(cond-> group (cond-> group
(and (some? svg-viewbox) (some? selrect) (some? new-selrect)) (and (some? svg-viewbox) (some? selrect) (some? new-selrect))
(update :svg-viewbox (update :svg-viewbox

View file

@ -25,7 +25,7 @@
;; General purpose events & IMPL ;; General purpose events & IMPL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn team-fonts-loaded (defn fonts-fetched
[fonts] [fonts]
(letfn [;; Prepare font to the internal font database format. (letfn [;; Prepare font to the internal font database format.
(prepare-font [[id [item :as items]]] (prepare-font [[id [item :as items]]]
@ -74,8 +74,8 @@
(ptk/reify ::load-team-fonts (ptk/reify ::load-team-fonts
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(->> (rp/query :team-font-variants {:team-id team-id}) (->> (rp/query :font-variants {:team-id team-id})
(rx/map team-fonts-loaded))))) (rx/map fonts-fetched)))))
(defn process-upload (defn process-upload
"Given a seq of blobs and the team id, creates a ready-to-use fonts "Given a seq of blobs and the team id, creates a ready-to-use fonts

View file

@ -7,26 +7,26 @@
(ns app.main.exports (ns app.main.exports
"The main logic for SVG export functionality." "The main logic for SVG export functionality."
(:require (:require
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.common.uuid :as uuid]
[app.common.pages :as cp]
[app.common.math :as mth]
[app.common.geom.shapes :as gsh]
[app.common.geom.align :as gal] [app.common.geom.align :as gal]
[app.common.geom.point :as gpt]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.util.timers :as ts] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.common.pages :as cp]
[app.common.uuid :as uuid]
[app.main.ui.shapes.circle :as circle]
[app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.frame :as frame] [app.main.ui.shapes.frame :as frame]
[app.main.ui.shapes.circle :as circle] [app.main.ui.shapes.group :as group]
[app.main.ui.shapes.image :as image] [app.main.ui.shapes.image :as image]
[app.main.ui.shapes.path :as path] [app.main.ui.shapes.path :as path]
[app.main.ui.shapes.rect :as rect] [app.main.ui.shapes.rect :as rect]
[app.main.ui.shapes.text :as text] [app.main.ui.shapes.shape :refer [shape-container]]
[app.main.ui.shapes.group :as group]
[app.main.ui.shapes.svg-raw :as svg-raw] [app.main.ui.shapes.svg-raw :as svg-raw]
[app.main.ui.shapes.shape :refer [shape-container]])) [app.main.ui.shapes.text :as text]
[app.util.timers :as ts]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
(def ^:private default-color "#E8E9EA") ;; $color-canvas (def ^:private default-color "#E8E9EA") ;; $color-canvas

View file

@ -20,7 +20,7 @@
(cond (cond
(= 204 status) (= 204 status)
;; We need to send "something" so the streams listening downstream can act ;; We need to send "something" so the streams listening downstream can act
(rx/of :empty) (rx/of nil)
(= 502 status) (= 502 status)
(rx/throw {:type :bad-gateway}) (rx/throw {:type :bad-gateway})

View file

@ -12,11 +12,14 @@
[app.common.math :as mth] [app.common.math :as mth]
[app.common.pages :as cp] [app.common.pages :as cp]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.store :as st]
[app.main.data.fonts :as df]
[app.main.exports :as exports] [app.main.exports :as exports]
[app.main.repo :as repo] [app.main.repo :as repo]
[app.main.ui.context :as muc] [app.main.ui.context :as muc]
[app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.shape :refer [shape-container]]
[app.main.ui.shapes.text.embed :refer [embed-fontfaces-style]]
[beicon.core :as rx] [beicon.core :as rx]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -42,6 +45,9 @@
objects (reduce updt-fn objects mod-ids) objects (reduce updt-fn objects mod-ids)
object (get objects object-id) object (get objects object-id)
txt-xfm (comp (map #(get objects %))
(filter #(= :text (:type %))))
txt-objs (into [] txt-xfm mod-ids)
{:keys [width height]} (gsh/points->selrect (:points object)) {:keys [width height]} (gsh/points->selrect (:points object))
@ -72,6 +78,9 @@
] ]
[:& (mf/provider muc/embed-ctx) {:value true} [:& (mf/provider muc/embed-ctx) {:value true}
(when (seq txt-objs)
[:& embed-fontfaces-style {:shapes txt-objs}])
[:svg {:id "screenshot" [:svg {:id "screenshot"
:view-box vbox :view-box vbox
:width width :width width
@ -79,6 +88,7 @@
:version "1.1" :version "1.1"
:xmlnsXlink "http://www.w3.org/1999/xlink" :xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns "http://www.w3.org/2000/svg"} :xmlns "http://www.w3.org/2000/svg"}
(case (:type object) (case (:type object)
:frame [:& frame-wrapper {:shape object :view-box vbox}] :frame [:& frame-wrapper {:shape object :view-box vbox}]
:group [:> shape-container {:shape object} :group [:> shape-container {:shape object}
@ -97,7 +107,6 @@
(assoc objects (:id object) object)) (assoc objects (:id object) object))
objects)) objects))
;; NOTE: for now, it is ok download the entire file for render only ;; NOTE: for now, it is ok download the entire file for render only
;; single page but in a future we need consider to add a specific ;; single page but in a future we need consider to add a specific
;; backend entry point for download only the data of single page. ;; backend entry point for download only the data of single page.
@ -106,12 +115,19 @@
[{:keys [file-id page-id object-id] :as props}] [{:keys [file-id page-id object-id] :as props}]
(let [objects (mf/use-state nil)] (let [objects (mf/use-state nil)]
(mf/use-effect (mf/use-effect
#(let [subs (->> (repo/query! :file {:id file-id}) (mf/deps file-id page-id object-id)
(rx/subs (fn [{:keys [data]}] (fn []
(let [objs (get-in data [:pages-index page-id :objects]) (->> (rx/zip
objs (adapt-root-frame objs object-id)] (repo/query! :font-variants {:file-id file-id})
(reset! objects objs)))))] (repo/query! :file {:id file-id}))
(fn [] (rx/dispose! subs)))) (rx/subs
(fn [[fonts {:keys [data]} :as kaka]]
(when (seq fonts)
(st/emit! (df/fonts-fetched fonts)))
(let [objs (get-in data [:pages-index page-id :objects])
objs (adapt-root-frame objs object-id)]
(reset! objects objs)))))
(constantly nil)))
(when @objects (when @objects
[:& object-svg {:objects @objects [:& object-svg {:objects @objects

View file

@ -86,12 +86,6 @@
:weight weight})] :weight weight})]
(p/resolved result)))) (p/resolved result))))
(defn- to-promise
[observable]
(p/create (fn [resolve reject]
(->> (rx/take 1 observable)
(rx/subs resolve reject)))))
(defn fetch-font-data (defn fetch-font-data
"Parses the CSS and retrieves the font data as DataURI." "Parses the CSS and retrieves the font data as DataURI."
[^string css] [^string css]
@ -137,10 +131,10 @@
{::mf/wrap-props false {::mf/wrap-props false
::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]} ::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
[props] [props]
(let [shapes (obj/get props "shapes") (let [shapes (obj/get props "shapes")
node {:children (->> shapes (map :content))} node {:children (->> shapes (map :content))}
fonts (-> node get-node-fonts memoize) fonts (-> node get-node-fonts memoize)
style (mf/use-state nil)] style (mf/use-state nil)]
(mf/use-effect (mf/use-effect
(mf/deps fonts) (mf/deps fonts)

View file

@ -102,23 +102,20 @@
{::mf/wrap [#(mf/memo' % check-frame-props) custom-deferred] {::mf/wrap [#(mf/memo' % check-frame-props) custom-deferred]
::mf/wrap-props false} ::mf/wrap-props false}
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects") objects (unchecked-get props "objects")
thumbnail? (unchecked-get props "thumbnail?") thumbnail? (unchecked-get props "thumbnail?")
edition (mf/deref refs/selected-edition) edition (mf/deref refs/selected-edition)
embed-fonts? (mf/use-ctx muc/embed-ctx) embed-fonts? (mf/use-ctx muc/embed-ctx)
shape (gsh/transform-shape shape) shape (gsh/transform-shape shape)
children (mapv #(get objects %) (:shapes shape)) children (mapv #(get objects %) (:shapes shape))
text-childs (->> objects text-childs (->> (vals objects)
vals (filterv #(and (= :text (:type %))
(filterv #(and (= :text (:type %)) (= (:id shape) (:frame-id %)))))
(= (:id shape) (:frame-id %)))))
ds-modifier (get-in shape [:modifiers :displacement]) rendered? (mf/use-state false)
rendered? (mf/use-state false)
show-thumbnail? (and thumbnail? (some? (:thumbnail shape))) show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))