mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 19:41:27 -05:00
✨ Serialization of grid layout data (#6148)
* ✨ Add serializators for grid layout properties * ✨ Extract serializers for wasm api module
This commit is contained in:
parent
7284fb539f
commit
83d41dba6f
9 changed files with 892 additions and 282 deletions
|
@ -21,6 +21,7 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.ui.shapes.text.fontfaces :as fonts]
|
||||
[app.render-wasm.helpers :as h]
|
||||
[app.render-wasm.serializers :as sr]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.http :as http]
|
||||
[app.util.webapi :as wapi]
|
||||
|
@ -39,6 +40,7 @@
|
|||
(def dpr
|
||||
(if use-dpr? js/window.devicePixelRatio 1.0))
|
||||
|
||||
|
||||
;; Based on app.main.render/object-svg
|
||||
(mf/defc object-svg
|
||||
{::mf/props :obj}
|
||||
|
@ -121,22 +123,9 @@
|
|||
[clip-content]
|
||||
(h/call internal-module "_set_shape_clip_content" clip-content))
|
||||
|
||||
(defn- translate-shape-type
|
||||
[type]
|
||||
(case type
|
||||
:frame 0
|
||||
:group 1
|
||||
:bool 2
|
||||
:rect 3
|
||||
:path 4
|
||||
:text 5
|
||||
:circle 6
|
||||
:svg-raw 7
|
||||
:image 8))
|
||||
|
||||
(defn set-shape-type
|
||||
[type]
|
||||
(h/call internal-module "_set_shape_type" (translate-shape-type type)))
|
||||
(h/call internal-module "_set_shape_type" (sr/translate-shape-type type)))
|
||||
|
||||
(defn set-masked
|
||||
[masked]
|
||||
|
@ -301,26 +290,6 @@
|
|||
(store-image id))))))
|
||||
fills))
|
||||
|
||||
(defn- translate-stroke-style
|
||||
[stroke-style]
|
||||
(case stroke-style
|
||||
:dotted 1
|
||||
:dashed 2
|
||||
:mixed 3
|
||||
0))
|
||||
|
||||
(defn- translate-stroke-cap
|
||||
[stroke-cap]
|
||||
(case stroke-cap
|
||||
:line-arrow 1
|
||||
:triangle-arrow 2
|
||||
:square-marker 3
|
||||
:circle-marker 4
|
||||
:diamond-marker 5
|
||||
:round 6
|
||||
:square 7
|
||||
0))
|
||||
|
||||
(defn set-shape-strokes
|
||||
[strokes]
|
||||
(h/call internal-module "_clear_shape_strokes")
|
||||
|
@ -331,9 +300,9 @@
|
|||
image (:stroke-image stroke)
|
||||
width (:stroke-width stroke)
|
||||
align (:stroke-alignment stroke)
|
||||
style (-> stroke :stroke-style translate-stroke-style)
|
||||
cap-start (-> stroke :stroke-cap-start translate-stroke-cap)
|
||||
cap-end (-> stroke :stroke-cap-end translate-stroke-cap)]
|
||||
style (-> stroke :stroke-style sr/translate-stroke-style)
|
||||
cap-start (-> stroke :stroke-cap-start sr/translate-stroke-cap)
|
||||
cap-end (-> stroke :stroke-cap-end sr/translate-stroke-cap)]
|
||||
(case align
|
||||
:inner (h/call internal-module "_add_shape_inner_stroke" width style cap-start cap-end)
|
||||
:outer (h/call internal-module "_add_shape_outer_stroke" width style cap-start cap-end)
|
||||
|
@ -388,14 +357,7 @@
|
|||
(h/call internal-module "_add_shape_stroke_solid_fill" rgba)))))
|
||||
strokes))
|
||||
|
||||
(defn serialize-path-attrs
|
||||
[svg-attrs]
|
||||
(reduce
|
||||
(fn [acc [key value]]
|
||||
(str/concat
|
||||
acc
|
||||
(str/kebab key) "\0"
|
||||
value "\0")) "" svg-attrs))
|
||||
|
||||
|
||||
(defn set-shape-path-attrs
|
||||
[attrs]
|
||||
|
@ -403,7 +365,7 @@
|
|||
attrs (-> attrs
|
||||
(dissoc :style)
|
||||
(merge style))
|
||||
str (serialize-path-attrs attrs)
|
||||
str (sr/serialize-path-attrs attrs)
|
||||
size (count str)
|
||||
ptr (h/call internal-module "_alloc_bytes" size)]
|
||||
(h/call internal-module "stringToUTF8" str ptr size)
|
||||
|
@ -426,95 +388,45 @@
|
|||
(h/call internal-module "stringToUTF8" content ptr size)
|
||||
(h/call internal-module "_set_shape_svg_raw_content")))
|
||||
|
||||
(defn- translate-blend-mode
|
||||
[blend-mode]
|
||||
(case blend-mode
|
||||
:normal 3
|
||||
:darken 16
|
||||
:multiply 24
|
||||
:color-burn 19
|
||||
:lighten 17
|
||||
:screen 14
|
||||
:color-dodge 18
|
||||
:overlay 15
|
||||
:soft-light 21
|
||||
:hard-light 20
|
||||
:difference 22
|
||||
:exclusion 23
|
||||
:hue 25
|
||||
:saturation 26
|
||||
:color 27
|
||||
:luminosity 28
|
||||
3))
|
||||
|
||||
|
||||
(defn set-shape-blend-mode
|
||||
[blend-mode]
|
||||
;; These values correspond to skia::BlendMode representation
|
||||
;; https://rust-skia.github.io/doc/skia_safe/enum.BlendMode.html
|
||||
(h/call internal-module "_set_shape_blend_mode" (translate-blend-mode blend-mode)))
|
||||
(h/call internal-module "_set_shape_blend_mode" (sr/translate-blend-mode blend-mode)))
|
||||
|
||||
(defn set-shape-opacity
|
||||
[opacity]
|
||||
(h/call internal-module "_set_shape_opacity" (or opacity 1)))
|
||||
|
||||
(defn- translate-constraint-h
|
||||
[type]
|
||||
(case type
|
||||
:left 0
|
||||
:right 1
|
||||
:leftright 2
|
||||
:center 3
|
||||
:scale 4))
|
||||
|
||||
|
||||
(defn set-constraints-h
|
||||
[constraint]
|
||||
(when constraint
|
||||
(h/call internal-module "_set_shape_constraint_h" (translate-constraint-h constraint))))
|
||||
|
||||
(defn- translate-constraint-v
|
||||
[type]
|
||||
(case type
|
||||
:top 0
|
||||
:bottom 1
|
||||
:topbottom 2
|
||||
:center 3
|
||||
:scale 4))
|
||||
(h/call internal-module "_set_shape_constraint_h" (sr/translate-constraint-h constraint))))
|
||||
|
||||
(defn set-constraints-v
|
||||
[constraint]
|
||||
(when constraint
|
||||
(h/call internal-module "_set_shape_constraint_v" (translate-constraint-v constraint))))
|
||||
(h/call internal-module "_set_shape_constraint_v" (sr/translate-constraint-v constraint))))
|
||||
|
||||
(defn set-shape-hidden
|
||||
[hidden]
|
||||
(h/call internal-module "_set_shape_hidden" hidden))
|
||||
|
||||
(defn- translate-bool-type
|
||||
[bool-type]
|
||||
(case bool-type
|
||||
:union 0
|
||||
:difference 1
|
||||
:intersection 2
|
||||
:exclusion 3
|
||||
0))
|
||||
|
||||
(defn set-shape-bool-type
|
||||
[bool-type]
|
||||
(h/call internal-module "_set_shape_bool_type" (translate-bool-type bool-type)))
|
||||
(h/call internal-module "_set_shape_bool_type" (sr/translate-bool-type bool-type)))
|
||||
|
||||
(defn set-shape-bool-content
|
||||
[content]
|
||||
(set-shape-path-content content))
|
||||
|
||||
(defn- translate-blur-type
|
||||
[blur-type]
|
||||
(case blur-type
|
||||
:layer-blur 1
|
||||
0))
|
||||
|
||||
(defn set-shape-blur
|
||||
[blur]
|
||||
(let [type (-> blur :type translate-blur-type)
|
||||
(let [type (-> blur :type sr/translate-blur-type)
|
||||
hidden (:hidden blur)
|
||||
value (:value blur)]
|
||||
(h/call internal-module "_set_shape_blur" type hidden value)))
|
||||
|
@ -527,71 +439,18 @@
|
|||
r4 (or (get corners 3) 0)]
|
||||
(h/call internal-module "_set_shape_corners" r1 r2 r3 r4)))
|
||||
|
||||
|
||||
(defn translate-layout-flex-dir
|
||||
[flex-dir]
|
||||
(case flex-dir
|
||||
:row 0
|
||||
:row-reverse 1
|
||||
:column 2
|
||||
:column-reverse 3))
|
||||
|
||||
(defn translate-layout-align-items
|
||||
[align-items]
|
||||
(case align-items
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:stretch 3))
|
||||
|
||||
(defn translate-layout-align-content
|
||||
[align-content]
|
||||
(case align-content
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:space-between 3
|
||||
:space-around 4
|
||||
:space-evenly 5
|
||||
:stretch 6))
|
||||
|
||||
(defn translate-layout-justify-items
|
||||
[justify-items]
|
||||
(case justify-items
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:stretch 3))
|
||||
|
||||
(defn translate-layout-justify-content
|
||||
[justify-content]
|
||||
(case justify-content
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:space-between 3
|
||||
:space-around 4
|
||||
:space-evenly 5
|
||||
:stretch 6))
|
||||
|
||||
(defn translate-layout-wrap-type
|
||||
[wrap-type]
|
||||
(case wrap-type
|
||||
:wrap 0
|
||||
:nowrap 1))
|
||||
|
||||
(defn set-flex-layout
|
||||
[shape]
|
||||
(let [dir (-> (or (dm/get-prop shape :layout-flex-dir) :row) translate-layout-flex-dir)
|
||||
(let [dir (-> (or (dm/get-prop shape :layout-flex-dir) :row) sr/translate-layout-flex-dir)
|
||||
gap (dm/get-prop shape :layout-gap)
|
||||
row-gap (or (dm/get-prop gap :row-gap) 0)
|
||||
column-gap (or (dm/get-prop gap :column-gap) 0)
|
||||
|
||||
align-items (-> (or (dm/get-prop shape :layout-align-items) :start) translate-layout-align-items)
|
||||
align-content (-> (or (dm/get-prop shape :layout-align-content) :stretch) translate-layout-align-content)
|
||||
justify-items (-> (or (dm/get-prop shape :layout-justify-items) :start) translate-layout-justify-items)
|
||||
justify-content (-> (or (dm/get-prop shape :layout-justify-content) :stretch) translate-layout-justify-content)
|
||||
wrap-type (-> (or (dm/get-prop shape :layout-wrap-type) :nowrap) translate-layout-wrap-type)
|
||||
align-items (-> (or (dm/get-prop shape :layout-align-items) :start) sr/translate-layout-align-items)
|
||||
align-content (-> (or (dm/get-prop shape :layout-align-content) :stretch) sr/translate-layout-align-content)
|
||||
justify-items (-> (or (dm/get-prop shape :layout-justify-items) :start) sr/translate-layout-justify-items)
|
||||
justify-content (-> (or (dm/get-prop shape :layout-justify-content) :stretch) sr/translate-layout-justify-content)
|
||||
wrap-type (-> (or (dm/get-prop shape :layout-wrap-type) :nowrap) sr/translate-layout-wrap-type)
|
||||
|
||||
padding (dm/get-prop shape :layout-padding)
|
||||
padding-top (or (dm/get-prop padding :p1) 0)
|
||||
|
@ -614,23 +473,128 @@
|
|||
padding-left)))
|
||||
|
||||
(defn set-grid-layout
|
||||
[_shape])
|
||||
[shape]
|
||||
|
||||
(defn translate-layout-sizing
|
||||
[value]
|
||||
(case value
|
||||
:fill 0
|
||||
:fix 1
|
||||
:auto 2))
|
||||
(let [dir (-> (or (dm/get-prop shape :layout-grid-dir) :row) sr/translate-layout-grid-dir)
|
||||
gap (dm/get-prop shape :layout-gap)
|
||||
row-gap (or (dm/get-prop gap :row-gap) 0)
|
||||
column-gap (or (dm/get-prop gap :column-gap) 0)
|
||||
|
||||
(defn translate-align-self
|
||||
[value]
|
||||
(when value
|
||||
(case value
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:stretch 3)))
|
||||
align-items (-> (or (dm/get-prop shape :layout-align-items) :start) sr/translate-layout-align-items)
|
||||
align-content (-> (or (dm/get-prop shape :layout-align-content) :stretch) sr/translate-layout-align-content)
|
||||
justify-items (-> (or (dm/get-prop shape :layout-justify-items) :start) sr/translate-layout-justify-items)
|
||||
justify-content (-> (or (dm/get-prop shape :layout-justify-content) :stretch) sr/translate-layout-justify-content)
|
||||
|
||||
padding (dm/get-prop shape :layout-padding)
|
||||
padding-top (or (dm/get-prop padding :p1) 0)
|
||||
padding-right (or (dm/get-prop padding :p2) 0)
|
||||
padding-bottom (or (dm/get-prop padding :p3) 0)
|
||||
padding-left (or (dm/get-prop padding :p4) 0)]
|
||||
|
||||
(h/call internal-module
|
||||
"_set_grid_layout_data"
|
||||
dir
|
||||
row-gap
|
||||
column-gap
|
||||
align-items
|
||||
align-content
|
||||
justify-items
|
||||
justify-content
|
||||
padding-top
|
||||
padding-right
|
||||
padding-bottom
|
||||
padding-left))
|
||||
|
||||
;; Send Rows
|
||||
(let [entry-size 5
|
||||
entries (:layout-grid-rows shape)
|
||||
ptr (h/call internal-module "_alloc_bytes" (* entry-size (count entries)))
|
||||
|
||||
heap
|
||||
(js/Uint8Array.
|
||||
(.-buffer (gobj/get ^js internal-module "HEAPU8"))
|
||||
ptr
|
||||
(* entry-size (count entries)))]
|
||||
(loop [entries (seq entries)
|
||||
offset 0]
|
||||
(when-not (empty? entries)
|
||||
(let [{:keys [type value]} (first entries)]
|
||||
(.set heap (sr/u8 (sr/translate-grid-track-type type)) (+ offset 0))
|
||||
(.set heap (sr/f32->u8 value) (+ offset 1))
|
||||
(recur (rest entries) (+ offset entry-size)))))
|
||||
(h/call internal-module "_set_grid_rows"))
|
||||
|
||||
;; Send Columns
|
||||
(let [entry-size 5
|
||||
entries (:layout-grid-columns shape)
|
||||
ptr (h/call internal-module "_alloc_bytes" (* entry-size (count entries)))
|
||||
|
||||
heap
|
||||
(js/Uint8Array.
|
||||
(.-buffer (gobj/get ^js internal-module "HEAPU8"))
|
||||
ptr
|
||||
(* entry-size (count entries)))]
|
||||
(loop [entries (seq entries)
|
||||
offset 0]
|
||||
(when-not (empty? entries)
|
||||
(let [{:keys [type value]} (first entries)]
|
||||
(.set heap (sr/u8 (sr/translate-grid-track-type type)) (+ offset 0))
|
||||
(.set heap (sr/f32->u8 value) (+ offset 1))
|
||||
(recur (rest entries) (+ offset entry-size)))))
|
||||
(h/call internal-module "_set_grid_columns"))
|
||||
|
||||
;; Send cells
|
||||
(let [entry-size 37
|
||||
entries (-> shape :layout-grid-cells vals)
|
||||
ptr (h/call internal-module "_alloc_bytes" (* entry-size (count entries)))
|
||||
|
||||
heap
|
||||
(js/Uint8Array.
|
||||
(.-buffer (gobj/get ^js internal-module "HEAPU8"))
|
||||
ptr
|
||||
(* entry-size (count entries)))]
|
||||
|
||||
(loop [entries (seq entries)
|
||||
offset 0]
|
||||
(when-not (empty? entries)
|
||||
(let [cell (first entries)]
|
||||
|
||||
;; row: [u8; 4],
|
||||
(.set heap (sr/i32->u8 (:row cell)) (+ offset 0))
|
||||
|
||||
;; row_span: [u8; 4],
|
||||
(.set heap (sr/i32->u8 (:row-span cell)) (+ offset 4))
|
||||
|
||||
;; column: [u8; 4],
|
||||
(.set heap (sr/i32->u8 (:column cell)) (+ offset 8))
|
||||
|
||||
;; column_span: [u8; 4],
|
||||
(.set heap (sr/i32->u8 (:column-span cell)) (+ offset 12))
|
||||
|
||||
;; has_align_self: u8,
|
||||
(.set heap (sr/bool->u8 (some? (:align-self cell))) (+ offset 16))
|
||||
|
||||
;; align_self: u8,
|
||||
(.set heap (sr/u8 (sr/translate-align-self (:align-self cell))) (+ offset 17))
|
||||
|
||||
;; has_justify_self: u8,
|
||||
(.set heap (sr/bool->u8 (some? (:justify-self cell))) (+ offset 18))
|
||||
|
||||
;; justify_self: u8,
|
||||
(.set heap (sr/u8 (sr/translate-justify-self (:justify-self cell))) (+ offset 19))
|
||||
|
||||
;; has_shape_id: u8,
|
||||
(.set heap (sr/bool->u8 (d/not-empty? (:shapes cell))) (+ offset 20))
|
||||
|
||||
;; shape_id_a: [u8; 4],
|
||||
;; shape_id_b: [u8; 4],
|
||||
;; shape_id_c: [u8; 4],
|
||||
;; shape_id_d: [u8; 4],
|
||||
(.set heap (sr/uuid->u8 (or (-> cell :shapes first) uuid/zero)) (+ offset 21))
|
||||
|
||||
(recur (rest entries) (+ offset entry-size)))))
|
||||
|
||||
(h/call internal-module "_set_grid_cells")))
|
||||
|
||||
(defn set-layout-child
|
||||
[shape]
|
||||
|
@ -640,9 +604,9 @@
|
|||
margin-bottom (or (dm/get-prop margins :m3) 0)
|
||||
margin-left (or (dm/get-prop margins :m4) 0)
|
||||
|
||||
h-sizing (-> (dm/get-prop shape :layout-item-h-sizing) (or :fix) translate-layout-sizing)
|
||||
v-sizing (-> (dm/get-prop shape :layout-item-v-sizing) (or :fix) translate-layout-sizing)
|
||||
align-self (-> (dm/get-prop shape :layout-item-align-self) translate-align-self)
|
||||
h-sizing (-> (dm/get-prop shape :layout-item-h-sizing) (or :fix) sr/translate-layout-sizing)
|
||||
v-sizing (-> (dm/get-prop shape :layout-item-v-sizing) (or :fix) sr/translate-layout-sizing)
|
||||
align-self (-> (dm/get-prop shape :layout-item-align-self) sr/translate-align-self)
|
||||
|
||||
max-h (dm/get-prop shape :layout-item-max-h)
|
||||
has-max-h (some? max-h)
|
||||
|
@ -675,13 +639,6 @@
|
|||
is-absolute
|
||||
z-index)))
|
||||
|
||||
(defn- translate-shadow-style
|
||||
[style]
|
||||
(case style
|
||||
:drop-shadow 0
|
||||
:inner-shadow 1
|
||||
0))
|
||||
|
||||
(defn set-shape-shadows
|
||||
[shadows]
|
||||
(h/call internal-module "_clear_shape_shadows")
|
||||
|
@ -697,7 +654,7 @@
|
|||
y (dm/get-prop shadow :offset-y)
|
||||
spread (dm/get-prop shadow :spread)
|
||||
style (dm/get-prop shadow :style)]
|
||||
(h/call internal-module "_add_shape_shadow" rgba blur spread x y (translate-shadow-style style) hidden)
|
||||
(h/call internal-module "_add_shape_shadow" rgba blur spread x y (sr/translate-shadow-style style) hidden)
|
||||
(recur (inc index)))))))
|
||||
|
||||
(defn utf8->buffer [text]
|
||||
|
@ -898,24 +855,6 @@
|
|||
(clear-drawing-cache)
|
||||
(request-render "set-objects")))))))
|
||||
|
||||
(defn uuid->u8
|
||||
[id]
|
||||
(let [buffer (uuid/get-u32 id)
|
||||
u32-arr (js/Uint32Array. 4)]
|
||||
(doseq [i (range 0 4)]
|
||||
(aset u32-arr i (aget buffer i)))
|
||||
(js/Uint8Array. (.-buffer u32-arr))))
|
||||
|
||||
(defn matrix->u8
|
||||
[{:keys [a b c d e f]}]
|
||||
(let [f32-arr (js/Float32Array. 6)]
|
||||
(aset f32-arr 0 a)
|
||||
(aset f32-arr 1 b)
|
||||
(aset f32-arr 2 c)
|
||||
(aset f32-arr 3 d)
|
||||
(aset f32-arr 4 e)
|
||||
(aset f32-arr 5 f)
|
||||
(js/Uint8Array. (.-buffer f32-arr))))
|
||||
|
||||
(defn data->entry
|
||||
[data offset]
|
||||
|
@ -951,8 +890,8 @@
|
|||
offset 0]
|
||||
(when-not (empty? entries)
|
||||
(let [{:keys [id transform]} (first entries)]
|
||||
(.set heap (uuid->u8 id) offset)
|
||||
(.set heap (matrix->u8 transform) (+ offset 16))
|
||||
(.set heap (sr/uuid->u8 id) offset)
|
||||
(.set heap (sr/matrix->u8 transform) (+ offset 16))
|
||||
(recur (rest entries) (+ offset entry-size)))))
|
||||
|
||||
(let [result-ptr (h/call internal-module "_propagate_modifiers")
|
||||
|
@ -991,8 +930,8 @@
|
|||
offset 0]
|
||||
(when-not (empty? entries)
|
||||
(let [{:keys [id transform]} (first entries)]
|
||||
(.set heap (uuid->u8 id) offset)
|
||||
(.set heap (matrix->u8 transform) (+ offset 16))
|
||||
(.set heap (sr/uuid->u8 id) offset)
|
||||
(.set heap (sr/matrix->u8 transform) (+ offset 16))
|
||||
(recur (rest entries) (+ offset ENTRY_SIZE)))))
|
||||
|
||||
(h/call internal-module "_set_modifiers")
|
||||
|
|
253
frontend/src/app/render_wasm/serializers.cljs
Normal file
253
frontend/src/app/render_wasm/serializers.cljs
Normal file
|
@ -0,0 +1,253 @@
|
|||
;; 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.render-wasm.serializers
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn u8
|
||||
[value]
|
||||
(let [u8-arr (js/Uint8Array. 1)]
|
||||
(aset u8-arr 0 value)
|
||||
u8-arr))
|
||||
|
||||
(defn f32->u8
|
||||
[value]
|
||||
(let [f32-arr (js/Float32Array. 1)]
|
||||
(aset f32-arr 0 value)
|
||||
(js/Uint8Array. (.-buffer f32-arr))))
|
||||
|
||||
(defn i32->u8
|
||||
[value]
|
||||
(let [i32-arr (js/Int32Array. 1)]
|
||||
(aset i32-arr 0 value)
|
||||
(js/Uint8Array. (.-buffer i32-arr))))
|
||||
|
||||
(defn bool->u8
|
||||
[value]
|
||||
(let [result (js/Uint8Array. 1)]
|
||||
(aset result 0 (if value 1 0))
|
||||
result))
|
||||
|
||||
(defn uuid->u8
|
||||
[id]
|
||||
(let [buffer (uuid/get-u32 id)
|
||||
u32-arr (js/Uint32Array. 4)]
|
||||
(aset u32-arr 0 (aget buffer 0))
|
||||
(aset u32-arr 1 (aget buffer 1))
|
||||
(aset u32-arr 2 (aget buffer 2))
|
||||
(aset u32-arr 3 (aget buffer 3))
|
||||
(js/Uint8Array. (.-buffer u32-arr))))
|
||||
|
||||
(defn matrix->u8
|
||||
[{:keys [a b c d e f]}]
|
||||
(let [f32-arr (js/Float32Array. 6)]
|
||||
(aset f32-arr 0 a)
|
||||
(aset f32-arr 1 b)
|
||||
(aset f32-arr 2 c)
|
||||
(aset f32-arr 3 d)
|
||||
(aset f32-arr 4 e)
|
||||
(aset f32-arr 5 f)
|
||||
(js/Uint8Array. (.-buffer f32-arr))))
|
||||
|
||||
(defn translate-shape-type
|
||||
[type]
|
||||
(case type
|
||||
:frame 0
|
||||
:group 1
|
||||
:bool 2
|
||||
:rect 3
|
||||
:path 4
|
||||
:text 5
|
||||
:circle 6
|
||||
:svg-raw 7
|
||||
:image 8))
|
||||
|
||||
(defn translate-stroke-style
|
||||
[stroke-style]
|
||||
(case stroke-style
|
||||
:dotted 1
|
||||
:dashed 2
|
||||
:mixed 3
|
||||
0))
|
||||
|
||||
(defn translate-stroke-cap
|
||||
[stroke-cap]
|
||||
(case stroke-cap
|
||||
:line-arrow 1
|
||||
:triangle-arrow 2
|
||||
:square-marker 3
|
||||
:circle-marker 4
|
||||
:diamond-marker 5
|
||||
:round 6
|
||||
:square 7
|
||||
0))
|
||||
|
||||
|
||||
(defn serialize-path-attrs
|
||||
[svg-attrs]
|
||||
(reduce
|
||||
(fn [acc [key value]]
|
||||
(str/concat
|
||||
acc
|
||||
(str/kebab key) "\0"
|
||||
value "\0")) "" svg-attrs))
|
||||
|
||||
(defn translate-blend-mode
|
||||
[blend-mode]
|
||||
(case blend-mode
|
||||
:normal 3
|
||||
:darken 16
|
||||
:multiply 24
|
||||
:color-burn 19
|
||||
:lighten 17
|
||||
:screen 14
|
||||
:color-dodge 18
|
||||
:overlay 15
|
||||
:soft-light 21
|
||||
:hard-light 20
|
||||
:difference 22
|
||||
:exclusion 23
|
||||
:hue 25
|
||||
:saturation 26
|
||||
:color 27
|
||||
:luminosity 28
|
||||
3))
|
||||
|
||||
(defn translate-constraint-h
|
||||
[type]
|
||||
(case type
|
||||
:left 0
|
||||
:right 1
|
||||
:leftright 2
|
||||
:center 3
|
||||
:scale 4))
|
||||
|
||||
(defn translate-constraint-v
|
||||
[type]
|
||||
(case type
|
||||
:top 0
|
||||
:bottom 1
|
||||
:topbottom 2
|
||||
:center 3
|
||||
:scale 4))
|
||||
|
||||
(defn translate-bool-type
|
||||
[bool-type]
|
||||
(case bool-type
|
||||
:union 0
|
||||
:difference 1
|
||||
:intersection 2
|
||||
:exclusion 3
|
||||
0))
|
||||
|
||||
(defn translate-blur-type
|
||||
[blur-type]
|
||||
(case blur-type
|
||||
:layer-blur 1
|
||||
0))
|
||||
|
||||
(defn translate-layout-flex-dir
|
||||
[flex-dir]
|
||||
(case flex-dir
|
||||
:row 0
|
||||
:row-reverse 1
|
||||
:column 2
|
||||
:column-reverse 3))
|
||||
|
||||
(defn translate-layout-grid-dir
|
||||
[flex-dir]
|
||||
(case flex-dir
|
||||
:row 0
|
||||
:column 1))
|
||||
|
||||
(defn translate-layout-align-items
|
||||
[align-items]
|
||||
(case align-items
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:stretch 3))
|
||||
|
||||
(defn translate-layout-align-content
|
||||
[align-content]
|
||||
(case align-content
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:space-between 3
|
||||
:space-around 4
|
||||
:space-evenly 5
|
||||
:stretch 6))
|
||||
|
||||
(defn translate-layout-justify-items
|
||||
[justify-items]
|
||||
(case justify-items
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:stretch 3))
|
||||
|
||||
(defn translate-layout-justify-content
|
||||
[justify-content]
|
||||
(case justify-content
|
||||
:start 0
|
||||
:end 1
|
||||
:center 2
|
||||
:space-between 3
|
||||
:space-around 4
|
||||
:space-evenly 5
|
||||
:stretch 6))
|
||||
|
||||
(defn translate-layout-wrap-type
|
||||
[wrap-type]
|
||||
(case wrap-type
|
||||
:wrap 0
|
||||
:nowrap 1))
|
||||
|
||||
(defn translate-grid-track-type
|
||||
[type]
|
||||
(case type
|
||||
:percent 0
|
||||
:flex 1
|
||||
:auto 2
|
||||
:fixed 3))
|
||||
|
||||
(defn translate-layout-sizing
|
||||
[value]
|
||||
(case value
|
||||
:fill 0
|
||||
:fix 1
|
||||
:auto 2))
|
||||
|
||||
(defn translate-align-self
|
||||
[value]
|
||||
(when value
|
||||
(case value
|
||||
:auto 0
|
||||
:start 1
|
||||
:end 2
|
||||
:center 3
|
||||
:stretch 4)))
|
||||
|
||||
(defn translate-justify-self
|
||||
[value]
|
||||
(when value
|
||||
(case value
|
||||
:auto 0
|
||||
:start 1
|
||||
:end 2
|
||||
:center 3
|
||||
:stretch 4)))
|
||||
|
||||
(defn translate-shadow-style
|
||||
[style]
|
||||
(case style
|
||||
:drop-shadow 0
|
||||
:inner-shadow 1
|
||||
0))
|
||||
|
|
@ -142,7 +142,7 @@ Shadow styles are serialized as `u8`:
|
|||
|
||||
## Layout
|
||||
|
||||
### Direction
|
||||
### Flex Direction
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------------- |
|
||||
|
@ -152,6 +152,14 @@ Shadow styles are serialized as `u8`:
|
|||
| 3 | ColumnReverse |
|
||||
| \_ | error |
|
||||
|
||||
### Grid Direction
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------------- |
|
||||
| 0 | Row |
|
||||
| 1 | Column |
|
||||
| \_ | error |
|
||||
|
||||
### Align Items
|
||||
|
||||
| Value | Field |
|
||||
|
@ -208,6 +216,28 @@ Shadow styles are serialized as `u8`:
|
|||
| 6 | Stretch |
|
||||
| \_ | error |
|
||||
|
||||
### Align Self
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------- |
|
||||
| 0 | Auto |
|
||||
| 1 | Start |
|
||||
| 2 | End |
|
||||
| 3 | Center |
|
||||
| 4 | Stretch |
|
||||
| \_ | error |
|
||||
|
||||
### Justify Self
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------- |
|
||||
| 0 | Auto |
|
||||
| 1 | Start |
|
||||
| 2 | End |
|
||||
| 3 | Center |
|
||||
| 4 | Stretch |
|
||||
| \_ | error |
|
||||
|
||||
### Wrap type
|
||||
|
||||
| Value | Field |
|
||||
|
@ -225,6 +255,18 @@ Shadow styles are serialized as `u8`:
|
|||
| 2 | Auto |
|
||||
| \_ | error |
|
||||
|
||||
### Grid Track Type
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------- |
|
||||
| 0 | Percent |
|
||||
| 1 | Flex |
|
||||
| 2 | Auto |
|
||||
| 3 | Fixed |
|
||||
| \_ | error |
|
||||
|
||||
|
||||
|
||||
## Font
|
||||
|
||||
### Style
|
||||
|
|
|
@ -636,7 +636,7 @@ pub extern "C" fn set_flex_layout_data(
|
|||
padding_bottom: f32,
|
||||
padding_left: f32,
|
||||
) {
|
||||
let dir = shapes::Direction::from_u8(dir);
|
||||
let dir = shapes::FlexDirection::from_u8(dir);
|
||||
let align_items = shapes::AlignItems::from_u8(align_items);
|
||||
let align_content = shapes::AlignContent::from_u8(align_content);
|
||||
let justify_items = shapes::JustifyItems::from_u8(justify_items);
|
||||
|
@ -714,13 +714,89 @@ pub extern "C" fn set_layout_child_data(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_grid_layout_data() {}
|
||||
pub extern "C" fn set_grid_layout_data(
|
||||
dir: u8,
|
||||
row_gap: f32,
|
||||
column_gap: f32,
|
||||
align_items: u8,
|
||||
align_content: u8,
|
||||
justify_items: u8,
|
||||
justify_content: u8,
|
||||
padding_top: f32,
|
||||
padding_right: f32,
|
||||
padding_bottom: f32,
|
||||
padding_left: f32,
|
||||
) {
|
||||
let dir = shapes::GridDirection::from_u8(dir);
|
||||
let align_items = shapes::AlignItems::from_u8(align_items);
|
||||
let align_content = shapes::AlignContent::from_u8(align_content);
|
||||
let justify_items = shapes::JustifyItems::from_u8(justify_items);
|
||||
let justify_content = shapes::JustifyContent::from_u8(justify_content);
|
||||
|
||||
with_current_shape!(state, |shape: &mut Shape| {
|
||||
shape.set_grid_layout_data(
|
||||
dir,
|
||||
row_gap,
|
||||
column_gap,
|
||||
align_items,
|
||||
align_content,
|
||||
justify_items,
|
||||
justify_content,
|
||||
padding_top,
|
||||
padding_right,
|
||||
padding_bottom,
|
||||
padding_left,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn add_grid_track() {}
|
||||
pub extern "C" fn set_grid_columns() {
|
||||
let bytes = mem::bytes();
|
||||
|
||||
let entries: Vec<_> = bytes
|
||||
.chunks(size_of::<shapes::RawGridTrack>())
|
||||
.map(|data| shapes::RawGridTrack::from_bytes(data.try_into().unwrap()))
|
||||
.collect();
|
||||
|
||||
with_current_shape!(state, |shape: &mut Shape| {
|
||||
shape.set_grid_columns(entries);
|
||||
});
|
||||
|
||||
mem::free_bytes();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_grid_cell() {}
|
||||
pub extern "C" fn set_grid_rows() {
|
||||
let bytes = mem::bytes();
|
||||
|
||||
let entries: Vec<_> = bytes
|
||||
.chunks(size_of::<shapes::RawGridTrack>())
|
||||
.map(|data| shapes::RawGridTrack::from_bytes(data.try_into().unwrap()))
|
||||
.collect();
|
||||
|
||||
with_current_shape!(state, |shape: &mut Shape| {
|
||||
shape.set_grid_rows(entries);
|
||||
});
|
||||
|
||||
mem::free_bytes();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_grid_cells() {
|
||||
let bytes = mem::bytes();
|
||||
|
||||
let entries: Vec<_> = bytes
|
||||
.chunks(size_of::<shapes::RawGridCell>())
|
||||
.map(|data| shapes::RawGridCell::from_bytes(data.try_into().unwrap()))
|
||||
.collect();
|
||||
|
||||
with_current_shape!(state, |shape: &mut Shape| {
|
||||
shape.set_grid_cells(entries);
|
||||
});
|
||||
|
||||
mem::free_bytes();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
init_gl!();
|
||||
|
|
|
@ -318,7 +318,7 @@ impl Shape {
|
|||
|
||||
pub fn set_flex_layout_data(
|
||||
&mut self,
|
||||
direction: Direction,
|
||||
direction: FlexDirection,
|
||||
row_gap: f32,
|
||||
column_gap: f32,
|
||||
align_items: AlignItems,
|
||||
|
@ -334,7 +334,6 @@ impl Shape {
|
|||
match &mut self.shape_type {
|
||||
Type::Frame(data) => {
|
||||
let layout_data = LayoutData {
|
||||
direction,
|
||||
align_items,
|
||||
align_content,
|
||||
justify_items,
|
||||
|
@ -343,11 +342,12 @@ impl Shape {
|
|||
padding_right,
|
||||
padding_bottom,
|
||||
padding_left,
|
||||
row_gap,
|
||||
column_gap,
|
||||
};
|
||||
|
||||
let flex_data = FlexData {
|
||||
row_gap,
|
||||
column_gap,
|
||||
direction,
|
||||
wrap_type,
|
||||
};
|
||||
|
||||
|
@ -357,6 +357,73 @@ impl Shape {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_grid_layout_data(
|
||||
&mut self,
|
||||
direction: GridDirection,
|
||||
row_gap: f32,
|
||||
column_gap: f32,
|
||||
align_items: AlignItems,
|
||||
align_content: AlignContent,
|
||||
justify_items: JustifyItems,
|
||||
justify_content: JustifyContent,
|
||||
padding_top: f32,
|
||||
padding_right: f32,
|
||||
padding_bottom: f32,
|
||||
padding_left: f32,
|
||||
) {
|
||||
match &mut self.shape_type {
|
||||
Type::Frame(data) => {
|
||||
let layout_data = LayoutData {
|
||||
align_items,
|
||||
align_content,
|
||||
justify_items,
|
||||
justify_content,
|
||||
padding_top,
|
||||
padding_right,
|
||||
padding_bottom,
|
||||
padding_left,
|
||||
row_gap,
|
||||
column_gap,
|
||||
};
|
||||
|
||||
let mut grid_data = GridData::default();
|
||||
grid_data.direction = direction;
|
||||
data.layout = Some(Layout::GridLayout(layout_data, grid_data));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_grid_columns(&mut self, tracks: Vec<RawGridTrack>) {
|
||||
let Type::Frame(frame_data) = &mut self.shape_type else {
|
||||
return;
|
||||
};
|
||||
let Some(Layout::GridLayout(_, grid_data)) = &mut frame_data.layout else {
|
||||
return;
|
||||
};
|
||||
grid_data.columns = tracks.iter().map(GridTrack::from_raw).collect();
|
||||
}
|
||||
|
||||
pub fn set_grid_rows(&mut self, tracks: Vec<RawGridTrack>) {
|
||||
let Type::Frame(frame_data) = &mut self.shape_type else {
|
||||
return;
|
||||
};
|
||||
let Some(Layout::GridLayout(_, grid_data)) = &mut frame_data.layout else {
|
||||
return;
|
||||
};
|
||||
grid_data.rows = tracks.iter().map(GridTrack::from_raw).collect();
|
||||
}
|
||||
|
||||
pub fn set_grid_cells(&mut self, cells: Vec<RawGridCell>) {
|
||||
let Type::Frame(frame_data) = &mut self.shape_type else {
|
||||
return;
|
||||
};
|
||||
let Some(Layout::GridLayout(_, grid_data)) = &mut frame_data.layout else {
|
||||
return;
|
||||
};
|
||||
grid_data.cells = cells.iter().map(GridCell::from_raw).collect();
|
||||
}
|
||||
|
||||
pub fn set_blur(&mut self, blur_type: u8, hidden: bool, value: f32) {
|
||||
self.blur = Blur::new(blur_type, hidden, value);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use crate::utils::uuid_from_u32_quartet;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Layout {
|
||||
|
@ -6,14 +9,14 @@ pub enum Layout {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Direction {
|
||||
pub enum FlexDirection {
|
||||
Row,
|
||||
RowReverse,
|
||||
Column,
|
||||
ColumnReverse,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
impl FlexDirection {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Self::Row,
|
||||
|
@ -25,6 +28,22 @@ impl Direction {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum GridDirection {
|
||||
Row,
|
||||
Column,
|
||||
}
|
||||
|
||||
impl GridDirection {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Self::Row,
|
||||
1 => Self::Column,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum AlignItems {
|
||||
Start,
|
||||
|
@ -132,9 +151,82 @@ impl WrapType {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum GridTrackType {
|
||||
Percent,
|
||||
Flex,
|
||||
Auto,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
impl GridTrackType {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Self::Percent,
|
||||
1 => Self::Flex,
|
||||
2 => Self::Auto,
|
||||
3 => Self::Fixed,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct GridTrack {}
|
||||
pub struct GridTrack {
|
||||
track_type: GridTrackType,
|
||||
value: f32,
|
||||
}
|
||||
|
||||
impl GridTrack {
|
||||
pub fn from_raw(raw: &RawGridTrack) -> Self {
|
||||
Self {
|
||||
track_type: GridTrackType::from_u8(raw.track_type),
|
||||
value: f32::from_le_bytes(raw.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct GridCell {
|
||||
row: i32,
|
||||
row_span: i32,
|
||||
column: i32,
|
||||
column_span: i32,
|
||||
align_self: Option<AlignSelf>,
|
||||
justify_self: Option<JustifySelf>,
|
||||
shape: Option<Uuid>,
|
||||
}
|
||||
|
||||
impl GridCell {
|
||||
pub fn from_raw(raw: &RawGridCell) -> Self {
|
||||
Self {
|
||||
row: i32::from_le_bytes(raw.row),
|
||||
row_span: i32::from_le_bytes(raw.row_span),
|
||||
column: i32::from_le_bytes(raw.column),
|
||||
column_span: i32::from_le_bytes(raw.column_span),
|
||||
align_self: if raw.has_align_self == 1 {
|
||||
AlignSelf::from_u8(raw.align_self)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
justify_self: if raw.has_justify_self == 1 {
|
||||
JustifySelf::from_u8(raw.justify_self)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
shape: if raw.has_shape_id == 1 {
|
||||
Some(uuid_from_u32_quartet(
|
||||
u32::from_le_bytes(raw.shape_id_a),
|
||||
u32::from_le_bytes(raw.shape_id_b),
|
||||
u32::from_le_bytes(raw.shape_id_c),
|
||||
u32::from_le_bytes(raw.shape_id_d),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
pub enum Sizing {
|
||||
|
@ -156,7 +248,6 @@ impl Sizing {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct LayoutData {
|
||||
pub direction: Direction,
|
||||
pub align_items: AlignItems,
|
||||
pub align_content: AlignContent,
|
||||
pub justify_items: JustifyItems,
|
||||
|
@ -165,33 +256,13 @@ pub struct LayoutData {
|
|||
pub padding_right: f32,
|
||||
pub padding_bottom: f32,
|
||||
pub padding_left: f32,
|
||||
}
|
||||
|
||||
impl LayoutData {
|
||||
pub fn is_reverse(&self) -> bool {
|
||||
match &self.direction {
|
||||
Direction::RowReverse | Direction::ColumnReverse => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_row(&self) -> bool {
|
||||
match &self.direction {
|
||||
Direction::RowReverse | Direction::Row => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_column(&self) -> bool {
|
||||
match &self.direction {
|
||||
Direction::ColumnReverse | Direction::Column => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub row_gap: f32,
|
||||
pub column_gap: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum AlignSelf {
|
||||
Auto,
|
||||
Start,
|
||||
End,
|
||||
Center,
|
||||
|
@ -201,10 +272,33 @@ pub enum AlignSelf {
|
|||
impl AlignSelf {
|
||||
pub fn from_u8(value: u8) -> Option<AlignSelf> {
|
||||
match value {
|
||||
0 => Some(Self::Start),
|
||||
1 => Some(Self::End),
|
||||
2 => Some(Self::Center),
|
||||
3 => Some(Self::Stretch),
|
||||
0 => Some(Self::Auto),
|
||||
1 => Some(Self::Start),
|
||||
2 => Some(Self::End),
|
||||
3 => Some(Self::Center),
|
||||
4 => Some(Self::Stretch),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum JustifySelf {
|
||||
Auto,
|
||||
Start,
|
||||
End,
|
||||
Center,
|
||||
Stretch,
|
||||
}
|
||||
|
||||
impl JustifySelf {
|
||||
pub fn from_u8(value: u8) -> Option<JustifySelf> {
|
||||
match value {
|
||||
0 => Some(Self::Auto),
|
||||
1 => Some(Self::Start),
|
||||
2 => Some(Self::End),
|
||||
3 => Some(Self::Center),
|
||||
4 => Some(Self::Stretch),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -212,11 +306,26 @@ impl AlignSelf {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct FlexData {
|
||||
pub row_gap: f32,
|
||||
pub column_gap: f32,
|
||||
pub direction: FlexDirection,
|
||||
pub wrap_type: WrapType,
|
||||
}
|
||||
|
||||
impl FlexData {
|
||||
pub fn is_reverse(&self) -> bool {
|
||||
match &self.direction {
|
||||
FlexDirection::RowReverse | FlexDirection::ColumnReverse => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_row(&self) -> bool {
|
||||
match &self.direction {
|
||||
FlexDirection::RowReverse | FlexDirection::Row => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FlexData {
|
||||
pub fn is_wrap(&self) -> bool {
|
||||
match self.wrap_type {
|
||||
|
@ -228,9 +337,78 @@ impl FlexData {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct GridData {
|
||||
pub direction: GridDirection,
|
||||
pub rows: Vec<GridTrack>,
|
||||
pub columns: Vec<GridTrack>,
|
||||
// layout-grid-cells ;; map of id->grid-cell
|
||||
pub cells: Vec<GridCell>,
|
||||
}
|
||||
|
||||
impl GridData {
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
direction: GridDirection::Row,
|
||||
rows: vec![],
|
||||
columns: vec![],
|
||||
cells: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct RawGridTrack {
|
||||
track_type: u8,
|
||||
value: [u8; 4],
|
||||
}
|
||||
|
||||
impl RawGridTrack {
|
||||
pub fn from_bytes(bytes: [u8; 5]) -> Self {
|
||||
Self {
|
||||
track_type: bytes[0],
|
||||
value: [bytes[1], bytes[2], bytes[3], bytes[4]],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct RawGridCell {
|
||||
row: [u8; 4],
|
||||
row_span: [u8; 4],
|
||||
column: [u8; 4],
|
||||
column_span: [u8; 4],
|
||||
has_align_self: u8,
|
||||
align_self: u8,
|
||||
has_justify_self: u8,
|
||||
justify_self: u8,
|
||||
has_shape_id: u8,
|
||||
shape_id_a: [u8; 4],
|
||||
shape_id_b: [u8; 4],
|
||||
shape_id_c: [u8; 4],
|
||||
shape_id_d: [u8; 4],
|
||||
}
|
||||
|
||||
impl RawGridCell {
|
||||
pub fn from_bytes(bytes: [u8; 37]) -> Self {
|
||||
Self {
|
||||
row: [bytes[0], bytes[1], bytes[2], bytes[3]],
|
||||
row_span: [bytes[4], bytes[5], bytes[6], bytes[7]],
|
||||
column: [bytes[8], bytes[9], bytes[10], bytes[11]],
|
||||
column_span: [bytes[12], bytes[13], bytes[14], bytes[15]],
|
||||
|
||||
has_align_self: bytes[16],
|
||||
align_self: bytes[17],
|
||||
|
||||
has_justify_self: bytes[18],
|
||||
justify_self: bytes[19],
|
||||
|
||||
has_shape_id: bytes[20],
|
||||
shape_id_a: [bytes[21], bytes[22], bytes[23], bytes[24]],
|
||||
shape_id_b: [bytes[25], bytes[26], bytes[27], bytes[28]],
|
||||
shape_id_c: [bytes[29], bytes[30], bytes[31], bytes[32]],
|
||||
shape_id_d: [bytes[33], bytes[34], bytes[35], bytes[36]],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
|
|
|
@ -159,6 +159,8 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
continue;
|
||||
};
|
||||
|
||||
let mut reflow_parent = false;
|
||||
|
||||
match &shape.shape_type {
|
||||
Type::Frame(Frame {
|
||||
layout: Some(_), ..
|
||||
|
@ -173,10 +175,17 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
// 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;
|
||||
reflow_parent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if shape.is_layout_vertical_auto()
|
||||
|| shape.is_layout_horizontal_auto()
|
||||
{
|
||||
reflow_parent = true;
|
||||
}
|
||||
|
||||
if !skip_reflow {
|
||||
layout_reflows.push(id);
|
||||
}
|
||||
|
@ -186,6 +195,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
if let Some(child) = shapes.get(&shape.children[0]) {
|
||||
let child_bounds = bounds.find(&child);
|
||||
bounds.insert(shape.id, child_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
}
|
||||
Type::Group(_) => {
|
||||
|
@ -193,6 +203,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
calculate_group_bounds(shape, shapes, &bounds)
|
||||
{
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
}
|
||||
Type::Bool(_) => {
|
||||
|
@ -203,6 +214,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
calculate_group_bounds(shape, shapes, &bounds)
|
||||
{
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -211,7 +223,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
}
|
||||
|
||||
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {
|
||||
if parent.has_layout() || parent.is_group_like() {
|
||||
if reflow_parent && (parent.has_layout() || parent.is_group_like()) {
|
||||
entries.push_back(Modifier::reflow(parent.id));
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +243,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
let Type::Frame(frame_data) = &shape.shape_type else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(Layout::FlexLayout(layout_data, flex_data)) = &frame_data.layout {
|
||||
let mut children = flex_layout::reflow_flex_layout(
|
||||
shape,
|
||||
|
@ -242,11 +255,11 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
|
|||
entries.append(&mut children);
|
||||
}
|
||||
|
||||
if let Some(Layout::GridLayout(layout_data, grid_data)) = &frame_data.layout {
|
||||
let mut children =
|
||||
grid_layout::reflow_grid_layout(shape, layout_data, grid_data, shapes, &bounds);
|
||||
entries.append(&mut children);
|
||||
}
|
||||
// if let Some(Layout::GridLayout(layout_data, grid_data)) = &frame_data.layout {
|
||||
// let mut children =
|
||||
// grid_layout::reflow_grid_layout(shape, layout_data, grid_data, shapes, &bounds);
|
||||
// entries.append(&mut children);
|
||||
// }
|
||||
reflown.insert(*id);
|
||||
}
|
||||
layout_reflows = Vec::new();
|
||||
|
|
|
@ -67,7 +67,7 @@ impl LayoutAxis {
|
|||
layout_data: &LayoutData,
|
||||
flex_data: &FlexData,
|
||||
) -> Self {
|
||||
if layout_data.is_row() {
|
||||
if flex_data.is_row() {
|
||||
Self {
|
||||
main_size: layout_bounds.width(),
|
||||
across_size: layout_bounds.height(),
|
||||
|
@ -77,8 +77,8 @@ impl LayoutAxis {
|
|||
padding_main_end: layout_data.padding_right,
|
||||
padding_across_start: layout_data.padding_top,
|
||||
padding_across_end: layout_data.padding_bottom,
|
||||
gap_main: flex_data.column_gap,
|
||||
gap_across: flex_data.row_gap,
|
||||
gap_main: layout_data.column_gap,
|
||||
gap_across: layout_data.row_gap,
|
||||
is_auto_main: shape.is_layout_horizontal_auto(),
|
||||
is_auto_across: shape.is_layout_vertical_auto(),
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ impl LayoutAxis {
|
|||
padding_main_end: layout_data.padding_bottom,
|
||||
padding_across_start: layout_data.padding_left,
|
||||
padding_across_end: layout_data.padding_right,
|
||||
gap_main: flex_data.row_gap,
|
||||
gap_across: flex_data.column_gap,
|
||||
gap_main: layout_data.row_gap,
|
||||
gap_across: layout_data.column_gap,
|
||||
is_auto_main: shape.is_layout_vertical_auto(),
|
||||
is_auto_across: shape.is_layout_horizontal_auto(),
|
||||
}
|
||||
|
@ -121,10 +121,10 @@ struct ChildAxis {
|
|||
}
|
||||
|
||||
impl ChildAxis {
|
||||
fn new(child: &Shape, child_bounds: &Bounds, layout_data: &LayoutData) -> Self {
|
||||
fn new(child: &Shape, child_bounds: &Bounds, flex_data: &FlexData) -> Self {
|
||||
let id = child.id;
|
||||
let layout_item = child.layout_item;
|
||||
let mut result = if layout_data.is_row() {
|
||||
let mut result = if flex_data.is_row() {
|
||||
Self {
|
||||
id,
|
||||
main_size: child_bounds.width(),
|
||||
|
@ -176,7 +176,6 @@ fn initialize_tracks(
|
|||
shape: &Shape,
|
||||
layout_bounds: &Bounds,
|
||||
layout_axis: &LayoutAxis,
|
||||
layout_data: &LayoutData,
|
||||
flex_data: &FlexData,
|
||||
shapes: &HashMap<Uuid, Shape>,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
|
@ -186,7 +185,7 @@ fn initialize_tracks(
|
|||
let mut children = shape.children.clone();
|
||||
let mut first = true;
|
||||
|
||||
if !layout_data.is_reverse() {
|
||||
if !flex_data.is_reverse() {
|
||||
children.reverse();
|
||||
}
|
||||
|
||||
|
@ -204,7 +203,7 @@ fn initialize_tracks(
|
|||
.box_bounds(&default_bounds)
|
||||
.unwrap_or(default_bounds);
|
||||
|
||||
let child_axis = ChildAxis::new(child, &child_bounds, layout_data);
|
||||
let child_axis = ChildAxis::new(child, &child_bounds, flex_data);
|
||||
|
||||
let child_main_size = child_axis.margin_main_start
|
||||
+ child_axis.margin_main_end
|
||||
|
@ -466,7 +465,6 @@ fn calculate_track_data(
|
|||
shape,
|
||||
layout_bounds,
|
||||
&layout_axis,
|
||||
layout_data,
|
||||
flex_data,
|
||||
shapes,
|
||||
bounds,
|
||||
|
@ -617,7 +615,7 @@ pub fn reflow_flex_layout(
|
|||
let child_bounds = &child_axis.bounds;
|
||||
let delta_v = Vector::new_points(&child_bounds.nw, &position);
|
||||
|
||||
let (new_width, new_height) = if layout_data.is_row() {
|
||||
let (new_width, new_height) = if flex_data.is_row() {
|
||||
(child_axis.main_size, child_axis.across_size)
|
||||
} else {
|
||||
(child_axis.across_size, child_axis.main_size)
|
||||
|
@ -681,7 +679,7 @@ pub fn reflow_flex_layout(
|
|||
0.0
|
||||
};
|
||||
|
||||
let (scale_width, scale_height) = if layout_data.is_row() {
|
||||
let (scale_width, scale_height) = if flex_data.is_row() {
|
||||
(
|
||||
if layout_axis.is_auto_main {
|
||||
auto_main_size / width
|
||||
|
|
|
@ -1,15 +1,59 @@
|
|||
use crate::math::Bounds;
|
||||
#![allow(dead_code, unused_variables)]
|
||||
use crate::math::{Bounds, Matrix, Point, Vector, VectorExt};
|
||||
use crate::shapes::{GridData, LayoutData, Modifier, Shape};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub fn reflow_grid_layout(
|
||||
_shape: &Shape,
|
||||
_layout_data: &LayoutData,
|
||||
_grid_data: &GridData,
|
||||
_shapes: &HashMap<Uuid, Shape>,
|
||||
_bounds: &HashMap<Uuid, Bounds>,
|
||||
) -> VecDeque<Modifier> {
|
||||
// TODO
|
||||
VecDeque::new()
|
||||
use super::common::GetBounds;
|
||||
|
||||
const MIN_SIZE: f32 = 0.01;
|
||||
const MAX_SIZE: f32 = f32::INFINITY;
|
||||
|
||||
struct CellData<'a> {
|
||||
shape: &'a Shape,
|
||||
main_size: f32,
|
||||
across_size: f32,
|
||||
}
|
||||
|
||||
fn calculate_cell_data<'a>(
|
||||
shape: &Shape,
|
||||
layout_data: &LayoutData,
|
||||
grid_data: &GridData,
|
||||
shapes: &'a HashMap<Uuid, Shape>,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
) -> Vec<CellData<'a>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn child_position(child_bounds: &Bounds, cell: &CellData) -> Point {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn reflow_grid_layout<'a>(
|
||||
shape: &Shape,
|
||||
layout_data: &LayoutData,
|
||||
grid_data: &GridData,
|
||||
shapes: &'a HashMap<Uuid, Shape>,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
) -> VecDeque<Modifier> {
|
||||
let mut result = VecDeque::new();
|
||||
|
||||
let cells = calculate_cell_data(shape, layout_data, grid_data, shapes, bounds);
|
||||
|
||||
for cell in cells.iter() {
|
||||
let child = cell.shape;
|
||||
let child_bounds = bounds.find(child);
|
||||
let position = child_position(&child_bounds, cell);
|
||||
|
||||
let mut transform = Matrix::default();
|
||||
let delta_v = Vector::new_points(&child_bounds.nw, &position);
|
||||
|
||||
if delta_v.x.abs() > MIN_SIZE || delta_v.y.abs() > MIN_SIZE {
|
||||
transform.post_concat(&Matrix::translate(delta_v));
|
||||
}
|
||||
|
||||
result.push_back(Modifier::transform(child.id, transform));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue