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:
parent
1a81631886
commit
8c68e29bf3
8 changed files with 100 additions and 49 deletions
|
@ -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})))))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue