Compare commits

..

5 Commits

Author SHA1 Message Date
Alejandro Alonso
86cb6b6f51 WIP 2026-02-04 14:16:26 +01:00
Alejandro Alonso
f3e0c2409e WIP 2026-02-04 14:11:12 +01:00
Alejandro Alonso
8584e070f9 WIP 2026-02-04 14:06:03 +01:00
Alejandro Alonso
49ea9a30a9 🐛 Fix pdf export 2026-02-04 13:58:03 +01:00
Alejandro Alonso
24c8fc484f 🐛 Fix Internal Error when adding a new text layer and trying to go back to Dashboard without saving 2026-02-04 10:01:10 +01:00
19 changed files with 157 additions and 283 deletions

View File

@@ -407,19 +407,17 @@
(defn change-text
"Changes the content of the text shape to use the text as argument. Will use the styles of the
first paragraph and text that is present in the shape (and override the rest)"
[content text & {:as styles}]
[content text]
(let [root-styles (select-keys content root-attrs)
paragraph-style
(merge
default-text-attrs
styles
(select-keys (->> content (node-seq is-paragraph-node?) first) text-all-attrs))
text-style
(merge
default-text-attrs
styles
(select-keys (->> content (node-seq is-text-node?) first) text-all-attrs))
paragraph-texts

View File

@@ -38,6 +38,26 @@
(assoc :path "/render.html")
(assoc :query (u/map->query-string params)))))
(sync-page-size! [dom]
(bw/eval! dom
(fn [elem]
(let [rect (.getBoundingClientRect ^js elem)
width (js/Math.max (or (some-> (.getAttribute ^js elem "width") js/parseFloat) 0)
(.-width rect))
height (js/Math.max (or (some-> (.getAttribute ^js elem "height") js/parseFloat) 0)
(.-height rect))
width-px (str width "px")
height-px (str height "px")
style-node (or (.getElementById js/document "penpot-pdf-page-size")
(let [node (.createElement js/document "style")]
(set! (.-id node) "penpot-pdf-page-size")
(.appendChild (.-head js/document) node)
node))]
(set! (.-textContent style-node)
(str "@page { size: " width-px " " height-px "; margin: 0; }\n"
"html, body, #app { margin: 0; padding: 0;"
"width: " width-px "; height: " height-px "; }"))))))
(render-object [page base-uri {:keys [id] :as object}]
(p/let [uri (prepare-uri base-uri id)
path (sh/tempfile :prefix "penpot.tmp.pdf." :suffix (mime/get-extension type))]
@@ -45,6 +65,7 @@
(bw/nav! page uri)
(p/let [dom (bw/select page (dm/str "#screenshot-" id))]
(bw/wait-for dom)
(sync-page-size! dom)
(bw/screenshot dom {:full-page? true})
(bw/sleep page 2000) ; the good old fix with sleep
(bw/pdf page {:path path})

View File

@@ -104,7 +104,7 @@
(watch [_ state _]
(let [page-id (or page-id (:current-page-id state))
objects (dsh/lookup-page-objects state page-id)
ids (->> ids (remove uuid/zero?) (filter #(contains? objects %)))]
ids (->> ids (filter #(contains? objects %)))]
(if (d/not-empty? ids)
(let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))]
(if (features/active-feature? state "render-wasm/v1")

View File

@@ -776,7 +776,11 @@
(rx/of (v2-update-text-editor-styles id attrs)))
(when (features/active-feature? state "render-wasm/v1")
(rx/of (dwwt/resize-wasm-text-debounce id)))))))
;; This delay is to give time for the font to be correctly rendered
;; in wasm.
(cond->> (rx/of (dwwt/resize-wasm-text id))
(contains? attrs :font-id)
(rx/delay 200)))))))
ptk/EffectEvent
(effect [_ state _]

View File

@@ -10,7 +10,6 @@
This exists to avoid circular deps:
workspace.texts -> workspace.libraries -> workspace.texts"
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
@@ -18,7 +17,6 @@
[app.main.data.helpers :as dsh]
[app.main.data.workspace.modifiers :as dwm]
[app.render-wasm.api :as wasm.api]
[app.render-wasm.api.fonts :as wasm.fonts]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@@ -64,81 +62,6 @@
(rx/of (dwm/apply-wasm-modifiers (resize-wasm-text-modifiers shape)))
(rx/empty))))))
(defn resize-wasm-text-debounce-commit
[]
(ptk/reify ::resize-wasm-text
ptk/WatchEvent
(watch [_ state _]
(let [ids (get state ::resize-wasm-text-debounce-ids)
objects (dsh/lookup-page-objects state)
modifiers
(reduce
(fn [modifiers id]
(let [shape (get objects id)]
(cond-> modifiers
(and (some? shape)
(cfh/text-shape? shape)
(not= :fixed (:grow-type shape)))
(merge (resize-wasm-text-modifiers shape)))))
{}
ids)]
(if (not (empty? modifiers))
(rx/of (dwm/apply-wasm-modifiers modifiers))
(rx/empty))))))
;; This event will debounce the resize events so, if there are many, they
;; are processed at the same time and not one-by-one. This will improve
;; performance because it's better to make only one layout calculation instead
;; of (potentialy) hundreds.
(defn resize-wasm-text-debounce
[id]
(let [cur-event (js/Symbol)]
(ptk/reify ::resize-wasm-text-debounce
ptk/UpdateEvent
(update [_ state]
(-> state
(update ::resize-wasm-text-debounce-ids (fnil conj []) id)
(cond-> (nil? (::resize-wasm-text-debounce-event state))
(assoc ::resize-wasm-text-debounce-event cur-event))))
ptk/WatchEvent
(watch [_ state stream]
(let [page-id (:current-page-id state)
objects (dsh/lookup-page-objects state page-id)
content (dm/get-in objects [id :content])
fonts (wasm.fonts/get-content-fonts content)
fonts-loaded?
(->> fonts
(every?
(fn [font]
(let [font-data (wasm.fonts/make-font-data font)]
(wasm.fonts/font-stored? font-data (:emoji? font-data))))))]
(cond
(not fonts-loaded?)
(->> (rx/of (resize-wasm-text-debounce id))
(rx/delay 20))
(= (::resize-wasm-text-debounce-event state) cur-event)
(let [stopper (->> stream (rx/filter (ptk/type? :app.main.data.workspace/finalize)))]
(rx/concat
(rx/merge
(->> stream
(rx/filter (ptk/type? ::resize-wasm-text-debounce))
(rx/debounce 20)
(rx/take 1)
;; (rx/delay 200)
(rx/map #(resize-wasm-text-debounce-commit))
(rx/take-until stopper))
(rx/of (resize-wasm-text-debounce id)))
(rx/of #(dissoc %
::resize-wasm-text-debounce-ids
::resize-wasm-text-debounce-event))))
:else
(rx/empty)))))))
(defn resize-wasm-text-all
"Resize all text shapes (auto-width/auto-height) from a collection of ids."
[ids]

View File

@@ -78,13 +78,15 @@
(fn []
(close-modals)
;; FIXME: move set-mode to uri?
(st/emit! (dw/set-options-mode :design)
(st/emit! :interrupt
(dw/set-options-mode :design)
(dcm/go-to-dashboard-recent))))
nav-to-project
(mf/use-fn
(mf/deps project-id)
#(st/emit! (dcm/go-to-dashboard-files ::rt/new-window true :project-id project-id)))]
#(st/emit! :interrupt
(dcm/go-to-dashboard-files ::rt/new-window true :project-id project-id)))]
(mf/with-effect [editing?]
(when ^boolean editing?

View File

@@ -75,31 +75,32 @@
[{:keys [points] :as shape} zoom grid-edition?]
(let [leftmost (->> points (reduce left?))
topmost (->> points (remove #{leftmost}) (reduce top?))
rightmost (->> points (remove #{leftmost topmost}) (reduce right?))]
(when (and (some? leftmost) (some? topmost) (some? rightmost))
(let [left-top (gpt/to-vec leftmost topmost)
left-top-angle (gpt/angle left-top)
rightmost (->> points (remove #{leftmost topmost}) (reduce right?))
top-right (gpt/to-vec topmost rightmost)
top-right-angle (gpt/angle top-right)
left-top (gpt/to-vec leftmost topmost)
left-top-angle (gpt/angle left-top)
;; Choose the position that creates the less angle between left-side and top-side
[label-pos angle h-pos v-pos]
(if (< (mth/abs left-top-angle) (mth/abs top-right-angle))
[leftmost left-top-angle left-top (gpt/perpendicular left-top)]
[topmost top-right-angle top-right (gpt/perpendicular top-right)])
top-right (gpt/to-vec topmost rightmost)
top-right-angle (gpt/angle top-right)
delta-x (if grid-edition? 40 0)
delta-y (if grid-edition? 50 10)
;; Choose the position that creates the less angle between left-side and top-side
[label-pos angle h-pos v-pos]
(if (< (mth/abs left-top-angle) (mth/abs top-right-angle))
[leftmost left-top-angle left-top (gpt/perpendicular left-top)]
[topmost top-right-angle top-right (gpt/perpendicular top-right)])
label-pos
(-> label-pos
(gpt/subtract (gpt/scale (gpt/unit v-pos) (/ delta-y zoom)))
(gpt/subtract (gpt/scale (gpt/unit h-pos) (/ delta-x zoom))))]
(dm/fmt "rotate(% %,%) scale(%, %) translate(%, %)"
;; rotate
angle (:x label-pos) (:y label-pos)
;; scale
(/ 1 zoom) (/ 1 zoom)
;; translate
(* zoom (:x label-pos)) (* zoom (:y label-pos)))))))
delta-x (if grid-edition? 40 0)
delta-y (if grid-edition? 50 10)
label-pos
(-> label-pos
(gpt/subtract (gpt/scale (gpt/unit v-pos) (/ delta-y zoom)))
(gpt/subtract (gpt/scale (gpt/unit h-pos) (/ delta-x zoom))))]
(dm/fmt "rotate(% %,%) scale(%, %) translate(%, %)"
;; rotate
angle (:x label-pos) (:y label-pos)
;; scale
(/ 1 zoom) (/ 1 zoom)
;; translate
(* zoom (:x label-pos)) (* zoom (:y label-pos)))))

View File

@@ -26,7 +26,6 @@
[app.main.data.workspace.groups :as dwg]
[app.main.data.workspace.media :as dwm]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.wasm-text :as dwwt]
[app.main.fonts :refer [fetch-font-css]]
[app.main.router :as rt]
[app.main.store :as st]
@@ -339,14 +338,9 @@
:else
(let [page (dsh/lookup-page @st/state)
shape (-> (cts/setup-shape {:type :text
:x 0 :y 0
:width 1 :height 1
:grow-type :auto-width})
(update :content txt/change-text text
;; Text should be given a color by default
{:fills [{:fill-color "#000000" :fill-opacity 1}]})
(dissoc :position-data))
shape (-> (cts/setup-shape {:type :text :x 0 :y 0 :grow-type :auto-width})
(update :content txt/change-text text)
(assoc :position-data nil))
changes
(-> (cb/empty-changes)
@@ -354,9 +348,7 @@
(cb/with-objects (:objects page))
(cb/add-object shape))]
(st/emit!
(ch/commit-changes changes)
(dwwt/resize-wasm-text-debounce (:id shape)))
(st/emit! (ch/commit-changes changes))
(shape/shape-proxy plugin-id (:id shape)))))
:createShapeFromSvg

View File

@@ -190,13 +190,11 @@
(defn update-text-rect!
[id]
(when wasm/context-initialized?
(let [dimensions (get-text-dimensions id)
page-id (:current-page-id @st/state)]
(mw/emit!
{:cmd :index/update-text-rect
:page-id page-id
:shape-id id
:dimensions dimensions}))))
(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
@@ -867,10 +865,10 @@
(set-shape-vertical-align (get content :vertical-align))
(let [fonts (f/get-content-fonts content)
(let [fonts (f/get-content-fonts content)
fallback-fonts (fonts-from-text-content content true)
all-fonts (concat fonts fallback-fonts)
result (f/store-fonts shape-id all-fonts)]
all-fonts (concat fonts fallback-fonts)
result (f/store-fonts shape-id all-fonts)]
(f/load-fallback-fonts-for-editor! fallback-fonts)
(h/call wasm/internal-module "_update_shape_text_layout")
result))
@@ -1566,7 +1564,7 @@
:text-decoration (get element :text-decoration)
:letter-spacing (get element :letter-spacing)
:font-style (get element :font-style)
:fills (d/nilv (get element :fills) [{:fill-color "#000000"}])
:fills (get element :fills)
:text text}))))))]
(mem/free)

View File

@@ -20,7 +20,6 @@
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[goog.object :as gobj]
[potok.v2.core :as ptk]
[lambdaisland.uri :as u]
[okulary.core :as l]))
@@ -98,8 +97,9 @@
;; IMPORTANT: Only TTF fonts can be stored.
(defn- store-font-buffer
[font-data font-array-buffer emoji? fallback?]
[shape-id font-data font-array-buffer emoji? fallback?]
(let [font-id-buffer (:family-id-buffer font-data)
shape-id-buffer (uuid/get-u32 shape-id)
size (.-byteLength font-array-buffer)
ptr (h/call wasm/internal-module "_alloc_bytes" size)
heap (gobj/get ^js wasm/internal-module "HEAPU8")
@@ -107,6 +107,10 @@
(.set mem (js/Uint8Array. font-array-buffer))
(h/call wasm/internal-module "_store_font"
(aget shape-id-buffer 0)
(aget shape-id-buffer 1)
(aget shape-id-buffer 2)
(aget shape-id-buffer 3)
(aget font-id-buffer 0)
(aget font-id-buffer 1)
(aget font-id-buffer 2)
@@ -115,35 +119,24 @@
(:style font-data)
emoji?
fallback?)
true))
;; This variable will store the fonts that are currently being fetched
;; so we don't fetch more than once the same font
(def fetching (atom #{}))
(update-text-layout shape-id)
true))
(defn- fetch-font
[shape-id font-data font-url emoji? fallback?]
(when-not (contains? @fetching font-url)
(swap! fetching conj font-url)
{:key font-url
:callback
(fn []
(->> (http/send! {:method :get
:uri font-url
:response-type :buffer})
(rx/map (fn [{:keys [body]}]
(swap! fetching disj font-url)
(store-font-buffer font-data body emoji? fallback?)
(update-text-layout shape-id)
;; TODO: Emit font fetched event
(prn ">>Fetched" font-data)
(ptk/data-event :wasm-text/font-fetched {:font font-data})))
(rx/catch (fn [cause]
(swap! fetching disj font-url)
(log/error :hint "Could not fetch font"
:font-url font-url
:cause cause)
(rx/empty)))))}))
{:key font-url
:callback #(->> (http/send! {:method :get
:uri font-url
:response-type :buffer})
(rx/map (fn [{:keys [body]}]
(store-font-buffer shape-id font-data body emoji? fallback?)))
(rx/catch (fn [cause]
(log/error :hint "Could not fetch font"
:font-url font-url
:cause cause)
(rx/empty))))})
(defn- google-font-ttf-url
[font-id font-variant-id font-weight font-style]
@@ -162,29 +155,20 @@
:builtin
(dm/str (u/join cf/public-uri "fonts/" asset-id))))
(defn font-stored?
[font-data emoji?]
(let [id-buffer (uuid/get-u32 (:wasm-id font-data))]
(not= 0 (h/call wasm/internal-module "_is_font_uploaded"
(aget id-buffer 0)
(aget id-buffer 1)
(aget id-buffer 2)
(aget id-buffer 3)
(:weight font-data)
(:style font-data)
emoji?))))
(defn- store-font-id
[shape-id font-data asset-id emoji? fallback?]
(when asset-id
(let [uri (font-id->ttf-url
(:font-id font-data) asset-id
(:font-variant-id font-data)
(:weight font-data)
(:style-name font-data))
(let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data) (:weight font-data) (:style-name font-data))
id-buffer (uuid/get-u32 (:wasm-id font-data))
font-data (assoc font-data :family-id-buffer id-buffer)
font-stored? (font-stored? font-data emoji?)]
font-stored? (not= 0 (h/call wasm/internal-module "_is_font_uploaded"
(aget id-buffer 0)
(aget id-buffer 1)
(aget id-buffer 2)
(aget id-buffer 3)
(:weight font-data)
(:style font-data)
emoji?))]
(when-not font-stored?
(fetch-font shape-id font-data uri emoji? fallback?)))))
@@ -296,8 +280,8 @@
"regular"
font-variant-id))
(defn make-font-data
[font]
(defn store-font
[shape-id font]
(let [font-id (get font :font-id)
font-variant-id (get font :font-variant-id)
normalized-variant-id (when font-variant-id
@@ -323,14 +307,7 @@
:font-variant-id variant-id
:style (serialize-font-style style)
:style-name style
:weight weight
:emoji? emoji?
:fallbck? fallback?
:asset-id asset-id}]))
(defn store-font
[shape-id font]
(let [{:keys [asset-id emoji? fallback?] :as font-data} (make-font-data font)]
:weight weight}]
(store-font-id shape-id font-data asset-id emoji? fallback?)))
;; FIXME: This is a temporary function to load the fallback fonts for the editor.

View File

@@ -346,14 +346,6 @@ pub extern "C" fn use_shape(a: u32, b: u32, c: u32, d: u32) {
});
}
#[no_mangle]
pub extern "C" fn touch_shape(a: u32, b: u32, c: u32, d: u32) {
with_state_mut!(state, {
let shape_id = uuid_from_u32_quartet(a, b, c, d);
state.touch_shape(shape_id);
});
}
#[no_mangle]
pub extern "C" fn set_parent(a: u32, b: u32, c: u32, d: u32) {
with_state_mut!(state, {

View File

@@ -1074,10 +1074,6 @@ impl Shape {
self.children.first()
}
pub fn children_count(&self) -> usize {
self.children_ids_iter(false).count()
}
pub fn children_ids(&self, include_hidden: bool) -> Vec<Uuid> {
if include_hidden {
return self.children.iter().rev().copied().collect();

View File

@@ -264,7 +264,7 @@ fn propagate_transform(
// If this is a layout and we're only moving don't need to reflow
if shape.has_layout() && is_resize {
entries.push_back(Modifier::reflow(shape.id, false));
entries.push_back(Modifier::reflow(shape.id));
}
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {
@@ -272,7 +272,7 @@ fn propagate_transform(
// if the current transformation is not a move propagation.
// If it's a move propagation we don't need to reflow, the parent is already changed.
if (parent.has_layout() || parent.is_group_like()) && (is_resize || !is_propagate) {
entries.push_back(Modifier::reflow(parent.id, false));
entries.push_back(Modifier::reflow(parent.id));
}
}
}
@@ -282,7 +282,7 @@ fn propagate_reflow(
state: &State,
entries: &mut VecDeque<Modifier>,
bounds: &mut HashMap<Uuid, Bounds>,
layout_reflows: &mut HashSet<Uuid>,
layout_reflows: &mut Vec<Uuid>,
reflown: &mut HashSet<Uuid>,
modifiers: &HashMap<Uuid, Matrix>,
) {
@@ -300,7 +300,20 @@ fn propagate_reflow(
Type::Frame(Frame {
layout: Some(_), ..
}) => {
layout_reflows.insert(*id);
let mut skip_reflow = false;
if shape.is_layout_horizontal_fill() || shape.is_layout_vertical_fill() {
if let Some(parent_id) = shape.parent_id {
if parent_id != Uuid::nil() && !reflown.contains(&parent_id) {
// If this is a fill layout but the parent has not been reflown yet
// we wait for the next iteration for reflow
skip_reflow = true;
}
}
}
if !skip_reflow {
layout_reflows.push(*id);
}
}
Type::Group(Group { masked: true }) => {
let children_ids = shape.children_ids(true);
@@ -327,7 +340,7 @@ fn propagate_reflow(
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {
if parent.has_layout() || parent.is_group_like() {
entries.push_back(Modifier::reflow(parent.id, false));
entries.push_back(Modifier::reflow(parent.id));
}
}
}
@@ -369,20 +382,19 @@ pub fn propagate_modifiers(
let mut entries: VecDeque<_> = modifiers
.iter()
.map(|entry| {
// If we receive a identity matrix we force a reflow
// If we receibe a identity matrix we force a reflow
if math::identitish(&entry.transform) {
Modifier::Reflow(entry.id, false)
Modifier::Reflow(entry.id)
} else {
Modifier::Transform(*entry)
}
})
.collect();
let shapes = &state.shapes;
let mut modifiers = HashMap::<Uuid, Matrix>::new();
let mut bounds = HashMap::<Uuid, Bounds>::new();
let mut reflown = HashSet::<Uuid>::new();
let mut layout_reflows = HashSet::<Uuid>::new();
let mut layout_reflows = Vec::<Uuid>::new();
// We first propagate the transforms to the children and then after
// recalculate the layouts. The layout can create further transforms that
@@ -400,43 +412,25 @@ pub fn propagate_modifiers(
&mut bounds,
&mut modifiers,
),
Modifier::Reflow(id, force_reflow) => {
if force_reflow {
reflown.remove(&id);
}
propagate_reflow(
&id,
state,
&mut entries,
&mut bounds,
&mut layout_reflows,
&mut reflown,
&modifiers,
)
},
Modifier::Reflow(id) => propagate_reflow(
&id,
state,
&mut entries,
&mut bounds,
&mut layout_reflows,
&mut reflown,
&modifiers,
),
}
}
let mut layout_reflows_vec: Vec<Uuid> = layout_reflows.into_iter().collect();
// We sort the reflows so they are process first the ones that are more
// deep in the tree structure. This way we can be sure that the children layouts
// are already reflowed.
layout_reflows_vec.sort_unstable_by(|id_a, id_b| {
let da = shapes.get_depth(id_a);
let db = shapes.get_depth(id_b);
db.cmp(&da)
});
let mut bounds_temp = bounds.clone();
for id in layout_reflows_vec.iter() {
for id in layout_reflows.iter() {
if reflown.contains(id) {
continue;
}
reflow_shape(id, state, &mut reflown, &mut entries, &mut bounds_temp);
reflow_shape(id, state, &mut reflown, &mut entries, &mut bounds);
}
layout_reflows = HashSet::new();
layout_reflows = Vec::new();
}
modifiers

View File

@@ -61,7 +61,6 @@ impl LayoutAxis {
layout_data: &LayoutData,
flex_data: &FlexData,
) -> Self {
let num_child = shape.children_count();
if flex_data.is_row() {
Self {
main_size: layout_bounds.width(),
@@ -74,8 +73,8 @@ impl LayoutAxis {
padding_across_end: layout_data.padding_bottom,
gap_main: layout_data.column_gap,
gap_across: layout_data.row_gap,
is_auto_main: num_child > 0 && shape.is_layout_horizontal_auto(),
is_auto_across: num_child > 0 && shape.is_layout_vertical_auto(),
is_auto_main: shape.is_layout_horizontal_auto(),
is_auto_across: shape.is_layout_vertical_auto(),
}
} else {
Self {
@@ -89,8 +88,8 @@ impl LayoutAxis {
padding_across_end: layout_data.padding_right,
gap_main: layout_data.row_gap,
gap_across: layout_data.column_gap,
is_auto_main: num_child > 0 && shape.is_layout_vertical_auto(),
is_auto_across: num_child > 0 && shape.is_layout_horizontal_auto(),
is_auto_main: shape.is_layout_vertical_auto(),
is_auto_across: shape.is_layout_horizontal_auto(),
}
}
}
@@ -346,10 +345,7 @@ fn distribute_fill_across_space(layout_axis: &LayoutAxis, tracks: &mut [TrackDat
let mut size =
track.across_size - child.margin_across_start - child.margin_across_end;
size = size.clamp(child.min_across_size, child.max_across_size);
if !layout_axis.is_auto_across {
size = f32::min(size, layout_axis.across_space());
}
size = f32::min(size, layout_axis.across_space());
child.across_size = size;
}
}
@@ -624,12 +620,9 @@ pub fn reflow_flex_layout(
let mut transform = Matrix::default();
let mut force_reflow = false;
if (new_width - child_bounds.width()).abs() > MIN_SIZE
|| (new_height - child_bounds.height()).abs() > MIN_SIZE
{
// When the child is fill we need to force a reflow
force_reflow = true;
transform.post_concat(&math::resize_matrix(
layout_bounds,
child_bounds,
@@ -644,7 +637,7 @@ pub fn reflow_flex_layout(
result.push_back(Modifier::transform_propagate(child.id, transform));
if child.has_layout() {
result.push_back(Modifier::reflow(child.id, force_reflow));
result.push_back(Modifier::reflow(child.id));
}
shape_anchor = next_anchor(

View File

@@ -765,12 +765,9 @@ pub fn reflow_grid_layout(
let mut transform = Matrix::default();
let mut force_reflow = false;
if (new_width - child_bounds.width()).abs() > MIN_SIZE
|| (new_height - child_bounds.height()).abs() > MIN_SIZE
{
// When the child is a fill it needs to be reflown
force_reflow = true;
transform.post_concat(&math::resize_matrix(
&layout_bounds,
&child_bounds,
@@ -796,7 +793,7 @@ pub fn reflow_grid_layout(
result.push_back(Modifier::transform_propagate(child.id, transform));
if child.has_layout() {
result.push_back(Modifier::reflow(child.id, force_reflow));
result.push_back(Modifier::reflow(child.id));
}
}

View File

@@ -8,7 +8,7 @@ use skia::Matrix;
#[derive(PartialEq, Debug, Clone)]
pub enum Modifier {
Transform(TransformEntry),
Reflow(Uuid, bool),
Reflow(Uuid),
}
impl Modifier {
@@ -18,8 +18,8 @@ impl Modifier {
pub fn parent(id: Uuid, transform: Matrix) -> Self {
Modifier::Transform(TransformEntry::parent(id, transform))
}
pub fn reflow(id: Uuid, force_reflow: bool) -> Self {
Modifier::Reflow(id, force_reflow)
pub fn reflow(id: Uuid) -> Self {
Modifier::Reflow(id)
}
}

View File

@@ -177,26 +177,6 @@ impl ShapesPoolImpl {
}
}
// Given an id, returns the depth in the tree-shaped structure
// of shapes.
pub fn get_depth(&self, id: &Uuid) -> usize {
if id == &Uuid::nil() {
return 0;
}
let Some(idx) = self.uuid_to_idx.get(id) else {
return 0;
};
let shape = &self.shapes[*idx];
let Some(parent_id) = shape.parent_id else {
return 0;
};
self.get_depth(&parent_id) + 1
}
#[allow(dead_code)]
pub fn iter(&self) -> std::slice::Iter<'_, Shape> {
self.shapes.iter()

View File

@@ -31,17 +31,21 @@ impl From<RawFontStyle> for FontStyle {
#[no_mangle]
pub extern "C" fn store_font(
a: u32,
b: u32,
c: u32,
d: u32,
a1: u32,
b1: u32,
c1: u32,
d1: u32,
a2: u32,
b2: u32,
c2: u32,
d2: u32,
weight: u32,
style: u8,
is_emoji: bool,
is_fallback: bool,
) {
with_state_mut!(state, {
let id = uuid_from_u32_quartet(a, b, c, d);
let id = uuid_from_u32_quartet(a2, b2, c2, d2);
let font_bytes = mem::bytes();
let font_style = RawFontStyle::from(style);
@@ -53,6 +57,9 @@ pub extern "C" fn store_font(
.add(family, &font_bytes, is_emoji, is_fallback);
mem::free_bytes();
let shape_id = uuid_from_u32_quartet(a1, b1, c1, d1);
state.touch_shape(shape_id);
});
}

View File

@@ -384,7 +384,6 @@ pub extern "C" fn update_shape_text_layout_for(a: u32, b: u32, c: u32, d: u32) {
if let Some(shape) = state.shapes.get_mut(&shape_id) {
update_text_layout(shape);
}
state.touch_shape(shape_id);
});
}