From 6cfaeb8a447d6f229ce6e2e296dd9ddda9c1800f Mon Sep 17 00:00:00 2001 From: Melvin Laplanche Date: Sat, 31 Jan 2026 17:55:30 -0800 Subject: [PATCH] :tada: Add woff2 support on user uploaded fonts Signed-off-by: Melvin Laplanche --- backend/src/app/media.clj | 41 ++++++- backend/test/backend_tests/rpc_font_test.clj | 35 ++++++ .../backend_tests/test_files/font-1.woff2 | Bin 0 -> 75876 bytes common/src/app/common/media.cljc | 26 +++-- common/test/common_tests/media_test.cljc | 33 ++++++ frontend/src/app/main/data/fonts.cljs | 105 +++++++++++------- frontend/src/app/main/ui/dashboard/fonts.cljs | 7 +- 7 files changed, 190 insertions(+), 57 deletions(-) create mode 100644 backend/test/backend_tests/test_files/font-1.woff2 diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index 7d6bb2a894..a1d22c0832 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -381,6 +381,22 @@ (when (zero? (:exit res)) (:out res)))) + (woff2->sfnt [data] + ;; woff2_decompress outputs to same directory with .ttf extension + (let [finput (tmp/tempfile :prefix "penpot.font." :suffix ".woff2") + foutput (fs/path (str/replace (str finput) #"\.woff2$" ".ttf"))] + (try + (io/write* finput data) + (let [res (sh/sh "woff2_decompress" (str finput))] + (if (zero? (:exit res)) + foutput + (do + (when (fs/exists? foutput) + (fs/delete foutput)) + nil))) + (finally + (fs/delete finput))))) + ;; Documented here: ;; https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory (get-sfnt-type [data] @@ -430,4 +446,27 @@ (= stype :ttf) (-> (assoc "font/otf" (ttf->otf sfnt)) - (assoc "font/ttf" sfnt))))))))) + (assoc "font/ttf" sfnt))))) + + (contains? current "font/woff2") + (let [data (get input "font/woff2") + foutput (woff2->sfnt data)] + (when-not foutput + (ex/raise :type :validation + :code :invalid-woff2-file + :hint "invalid woff2 file")) + (try + (let [sfnt (io/read* foutput) + type (get-sfnt-type sfnt)] + (cond-> input + (= type :otf) + (-> (assoc "font/otf" sfnt) + (assoc "font/ttf" (otf->ttf sfnt)) + (update "font/woff" gen-if-nil #(ttf-or-otf->woff sfnt))) + + (= type :ttf) + (-> (assoc "font/ttf" sfnt) + (assoc "font/otf" (ttf->otf sfnt)) + (update "font/woff" gen-if-nil #(ttf-or-otf->woff sfnt))))) + (finally + (fs/delete foutput)))))))) diff --git a/backend/test/backend_tests/rpc_font_test.clj b/backend/test/backend_tests/rpc_font_test.clj index 1316b237c9..be5410ffd0 100644 --- a/backend/test/backend_tests/rpc_font_test.clj +++ b/backend/test/backend_tests/rpc_font_test.clj @@ -93,6 +93,41 @@ :font-weight :font-style)))) +(t/deftest woff2-font-upload-1 + (let [prof (th/create-profile* 1 {:is-active true}) + team-id (:default-team-id prof) + proj-id (:default-project-id prof) + font-id (uuid/custom 10 1) + + data (-> (io/resource "backend_tests/test_files/font-1.woff2") + (io/read*)) + + params {::th/type :create-font-variant + ::rpc/profile-id (:id prof) + :team-id team-id + :font-id font-id + :font-family "somefont" + :font-weight 400 + :font-style "normal" + :data {"font/woff2" data}} + out (th/command! params)] + + ;; (th/print-result! out) + (t/is (nil? (:error out))) + (let [result (:result out)] + (t/is (uuid? (:id result))) + (t/is (uuid? (:ttf-file-id result))) + (t/is (uuid? (:otf-file-id result))) + (t/is (uuid? (:woff1-file-id result))) + (t/is (uuid? (:woff2-file-id result))) + (t/are [k] (= (get params k) + (get result k)) + :team-id + :font-id + :font-family + :font-weight + :font-style)))) + (t/deftest font-deletion-1 (let [prof (th/create-profile* 1 {:is-active true}) team-id (:default-team-id prof) diff --git a/backend/test/backend_tests/test_files/font-1.woff2 b/backend/test/backend_tests/test_files/font-1.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..492d463d90e29712d342073f84832c91b834f976 GIT binary patch literal 75876 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 literal 0 HcmV?d00001 diff --git a/common/src/app/common/media.cljc b/common/src/app/common/media.cljc index 4cdf8488ce..fc349765a2 100644 --- a/common/src/app/common/media.cljc +++ b/common/src/app/common/media.cljc @@ -12,6 +12,7 @@ (def font-types #{"font/ttf" "font/woff" + "font/woff2" "font/otf" "font/opentype"}) @@ -81,21 +82,22 @@ (defn parse-font-weight [variant] (cond - (re-seq #"(?i)(?:hairline|thin)" variant) 100 - (re-seq #"(?i)(?:extra\s*light|ultra\s*light)" variant) 200 - (re-seq #"(?i)(?:light)" variant) 300 - (re-seq #"(?i)(?:normal|regular)" variant) 400 - (re-seq #"(?i)(?:medium)" variant) 500 - (re-seq #"(?i)(?:semi\s*bold|demi\s*bold)" variant) 600 - (re-seq #"(?i)(?:extra\s*bold|ultra\s*bold)" variant) 800 - (re-seq #"(?i)(?:bold)" variant) 700 - (re-seq #"(?i)(?:extra\s*black|ultra\s*black)" variant) 950 - (re-seq #"(?i)(?:black|heavy|solid)" variant) 900 - :else 400)) + (re-seq #"(?i)(?:^|[-_\s])(hairline|thin)(?=(?:[-_\s]|$|italic\b))" variant) 100 + (re-seq #"(?i)(?:^|[-_\s])(extra\s*light|ultra\s*light)(?=(?:[-_\s]|$|italic\b))" variant) 200 + (re-seq #"(?i)(?:^|[-_\s])(light)(?=(?:[-_\s]|$|italic\b))" variant) 300 + (re-seq #"(?i)(?:^|[-_\s])(normal|regular)(?=(?:[-_\s]|$|italic\b))" variant) 400 + (re-seq #"(?i)(?:^|[-_\s])(medium)(?=(?:[-_\s]|$|italic\b))" variant) 500 + (re-seq #"(?i)(?:^|[-_\s])(semi\s*bold|demi\s*bold)(?=(?:[-_\s]|$|italic\b))" variant) 600 + (re-seq #"(?i)(?:^|[-_\s])(extra\s*bold|ultra\s*bold)(?=(?:[-_\s]|$|italic\b))" variant) 800 + (re-seq #"(?i)(?:^|[-_\s])(bold)(?=(?:[-_\s]|$|italic\b))" variant) 700 + (re-seq #"(?i)(?:^|[-_\s])(extra\s*black|ultra\s*black)(?=(?:[-_\s]|$|italic\b))" variant) 950 + (re-seq #"(?i)(?:^|[-_\s])(black|heavy|solid)(?=(?:[-_\s]|$|italic\b))" variant) 900 + :else 400)) (defn parse-font-style [variant] - (if (re-seq #"(?i)(?:italic)" variant) + (if (or (re-seq #"(?i)(?:^|[-_\s])(italic)(?:[-_\s]|$)" variant) + (re-seq #"(?i)italic$" variant)) "italic" "normal")) diff --git a/common/test/common_tests/media_test.cljc b/common/test/common_tests/media_test.cljc index 5098bf6e82..b6c18aab2d 100644 --- a/common/test/common_tests/media_test.cljc +++ b/common/test/common_tests/media_test.cljc @@ -9,6 +9,39 @@ [app.common.media :as media] [clojure.test :as t])) +(t/deftest test-parse-font-weight + (t/testing "matches weight tokens with proper boundaries" + (t/is (= 700 (media/parse-font-weight "Roboto-Bold"))) + (t/is (= 700 (media/parse-font-weight "Roboto_Bold"))) + (t/is (= 700 (media/parse-font-weight "Roboto Bold"))) + (t/is (= 700 (media/parse-font-weight "Bold"))) + (t/is (= 800 (media/parse-font-weight "Roboto-ExtraBold"))) + (t/is (= 600 (media/parse-font-weight "OpenSans-SemiBold"))) + (t/is (= 300 (media/parse-font-weight "Lato-Light"))) + (t/is (= 100 (media/parse-font-weight "Roboto-Thin"))) + (t/is (= 200 (media/parse-font-weight "Roboto-ExtraLight"))) + (t/is (= 500 (media/parse-font-weight "Roboto-Medium"))) + (t/is (= 900 (media/parse-font-weight "Roboto-Black")))) + + (t/testing "does not match weight tokens embedded in words" + (t/is (= 400 (media/parse-font-weight "Boldini"))) + (t/is (= 400 (media/parse-font-weight "Lighthaus"))) + (t/is (= 400 (media/parse-font-weight "Blackwood"))) + (t/is (= 400 (media/parse-font-weight "Thinker"))) + (t/is (= 400 (media/parse-font-weight "Mediaeval"))))) + +(t/deftest test-parse-font-style + (t/testing "matches italic with proper boundaries" + (t/is (= "italic" (media/parse-font-style "Roboto-Italic"))) + (t/is (= "italic" (media/parse-font-style "Roboto_Italic"))) + (t/is (= "italic" (media/parse-font-style "Roboto Italic"))) + (t/is (= "italic" (media/parse-font-style "Italic"))) + (t/is (= "italic" (media/parse-font-style "Roboto-BoldItalic")))) + + (t/testing "does not match italic embedded in words" + (t/is (= "normal" (media/parse-font-style "Italica"))) + (t/is (= "normal" (media/parse-font-style "Roboto-Regular"))))) + (t/deftest test-strip-image-extension (t/testing "removes extension from supported image files" (t/is (= (media/strip-image-extension "foo.png") "foo")) diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs index 28f702ed8a..d72cde8436 100644 --- a/frontend/src/app/main/data/fonts.cljs +++ b/frontend/src/app/main/data/fonts.cljs @@ -99,46 +99,65 @@ map with temporal ID's associated to each font entry." [blobs team-id] (letfn [(prepare [{:keys [font type name data] :as params}] - (let [family (or (.getEnglishName ^js font "preferredFamily") - (.getEnglishName ^js font "fontFamily")) - variant (or (.getEnglishName ^js font "preferredSubfamily") - (.getEnglishName ^js font "fontSubfamily")) + (if font + ;; Font was parsed with opentype.js (ttf, otf, woff) + (let [family (or (.getEnglishName ^js font "preferredFamily") + (.getEnglishName ^js font "fontFamily")) + variant (or (.getEnglishName ^js font "preferredSubfamily") + (.getEnglishName ^js font "fontSubfamily")) - ;; Vertical metrics determine the baseline in a text and the space between lines of - ;; text. For historical reasons, there are three pairs of ascender/descender - ;; values, known as hhea, OS/2 and uSWin metrics. Depending on the font, operating - ;; system and application a different set will be used to render text on the - ;; screen. On Mac, Safari and Chrome use the hhea values to render text. Firefox - ;; will respect the useTypoMetrics setting and will use the OS/2 if it is set. If - ;; the useTypoMetrics is not set, Firefox will also use metrics from the hhea - ;; table. On Windows, all browsers use the usWin metrics, but respect the - ;; useTypoMetrics setting and if set will use the OS/2 values. + ;; Vertical metrics determine the baseline in a text and the space between lines of + ;; text. For historical reasons, there are three pairs of ascender/descender + ;; values, known as hhea, OS/2 and uSWin metrics. Depending on the font, operating + ;; system and application a different set will be used to render text on the + ;; screen. On Mac, Safari and Chrome use the hhea values to render text. Firefox + ;; will respect the useTypoMetrics setting and will use the OS/2 if it is set. If + ;; the useTypoMetrics is not set, Firefox will also use metrics from the hhea + ;; table. On Windows, all browsers use the usWin metrics, but respect the + ;; useTypoMetrics setting and if set will use the OS/2 values. - hhea-ascender (abs (-> ^js font .-tables .-hhea .-ascender)) - hhea-descender (abs (-> ^js font .-tables .-hhea .-descender)) + hhea-ascender (abs (-> ^js font .-tables .-hhea .-ascender)) + hhea-descender (abs (-> ^js font .-tables .-hhea .-descender)) - win-ascent (abs (-> ^js font .-tables .-os2 .-usWinAscent)) - win-descent (abs (-> ^js font .-tables .-os2 .-usWinDescent)) + win-ascent (abs (-> ^js font .-tables .-os2 .-usWinAscent)) + win-descent (abs (-> ^js font .-tables .-os2 .-usWinDescent)) - os2-ascent (abs (-> ^js font .-tables .-os2 .-sTypoAscender)) - os2-descent (abs (-> ^js font .-tables .-os2 .-sTypoDescender)) + os2-ascent (abs (-> ^js font .-tables .-os2 .-sTypoAscender)) + os2-descent (abs (-> ^js font .-tables .-os2 .-sTypoDescender)) - ;; useTypoMetrics can be read from the 7th bit - f-selection (-> ^js font .-tables .-os2 .-fsSelection (bit-test 7)) + ;; useTypoMetrics can be read from the 7th bit + f-selection (-> ^js font .-tables .-os2 .-fsSelection (bit-test 7)) - height-warning? (or (not= hhea-ascender win-ascent) - (not= hhea-descender win-descent) - (and f-selection (or - (not= hhea-ascender os2-ascent) - (not= hhea-descender os2-descent)))) - data (js/Uint8Array. data)] - {:content {:data (chunk-array data default-chunk-size) - :name name - :type type} - :font-family (or family "") - :font-weight (cm/parse-font-weight variant) - :font-style (cm/parse-font-style variant) - :height-warning? height-warning?})) + height-warning? (or (not= hhea-ascender win-ascent) + (not= hhea-descender win-descent) + (and f-selection (or + (not= hhea-ascender os2-ascent) + (not= hhea-descender os2-descent)))) + data (js/Uint8Array. data)] + {:content {:data (chunk-array data default-chunk-size) + :name name + :type type} + :font-family (or family "") + :font-weight (cm/parse-font-weight variant) + :font-style (cm/parse-font-style variant) + :height-warning? height-warning?}) + ;; Font could not be parsed (woff2), extract metadata from filename + (let [base-name (str/replace name #"\.[^.]+$" "") + ;; Strip known weight/style tokens and separators to derive family name + ;; Use word boundaries to avoid matching substrings (e.g. "Boldini" should not match "bold") + raw-family-name (-> base-name + (str/replace #"(?i)(^|[-_\s])(extra\s*black|ultra\s*black|extra\s*bold|ultra\s*bold|semi\s*bold|demi\s*bold|extra\s*light|ultra\s*light|hairline|thin|light|normal|regular|medium|bold|black|heavy|solid|italic)([-_\s]|$)" "$1$3") + (str/replace #"[-_\s]+" " ") + (str/trim)) + family-name (if (str/blank? raw-family-name) base-name raw-family-name) + data (js/Uint8Array. data)] + {:content {:data (chunk-array data default-chunk-size) + :name name + :type type} + :font-family family-name + :font-weight (cm/parse-font-weight base-name) + :font-style (cm/parse-font-style base-name) + :height-warning? false}))) (join [res {:keys [content] :as font}] (let [key-fn (juxt :font-family :font-weight :font-style) @@ -166,14 +185,18 @@ (case sg "117 124 124 117" "font/otf" "0 1 0 0" "font/ttf" - "167 117 106 106" "font/woff"))) + "167 117 106 106" "font/woff" + "167 117 106 62" "font/woff2"))) - (parse-font [{:keys [data] :as params}] - (try - (assoc params :font (ot/parse data)) - (catch :default _e - (log/warn :msg (str/fmt "skipping file %s, unsupported format" (:name params))) - nil))) + (parse-font [{:keys [data type name] :as params}] + (if (= type "font/woff2") + ;; woff2 cannot be parsed by opentype.js, extract metadata from filename + (assoc params :font nil) + (try + (assoc params :font (ot/parse data)) + (catch :default _e + (log/warn :msg (str/fmt "skipping file %s, unsupported format" name)) + nil)))) (read-blob [blob] (->> (wa/read-file-as-array-buffer blob) diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index 45c7f101b5..fb40826a49 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -9,6 +9,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.exceptions :as ex] [app.common.media :as cm] [app.common.uuid :as uuid] [app.config :as cf] @@ -34,7 +35,7 @@ (def ^:private accept-font-types (str (str/join "," cm/font-types) ;; A workaround to solve a problem with chrome input selector - ",.ttf,application/font-woff,woff,.otf")) + ",.ttf,application/font-woff,.woff,.woff2,.otf")) (defn- use-page-title [team section] @@ -118,10 +119,10 @@ (swap! fonts* dissoc id) (swap! uploading* disj id) (st/emit! (df/add-font font))) - (fn [error] + (fn [cause] (st/emit! (ntf/error (tr "errors.bad-font" (first (:names item))))) (swap! fonts* dissoc id) - (js/console.log "error" error)))))) + (ex/print-throwable cause)))))) on-upload (mf/use-fn