mirror of
https://github.com/penpot/penpot.git
synced 2025-03-28 15:41:25 -05:00
Draw shapes from memory
This commit is contained in:
parent
fa9004d12c
commit
0027e77861
4 changed files with 126 additions and 94 deletions
|
@ -145,6 +145,17 @@ pub extern "C" fn make_rect(left: f32, top: f32, right: f32, bottom: f32) -> Box
|
|||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn alloc_rects(len: usize) -> *mut Rect {
|
||||
// create a new mutable buffer with capacity `len`
|
||||
let mut buf : Vec<Rect> = Vec::with_capacity(len);
|
||||
let ptr = buf.as_mut_ptr();
|
||||
// take ownership of the memory block and ensure the its destructor is not
|
||||
// called when the object goes out of scope at the end of the function
|
||||
std::mem::forget(buf);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// Draws a rect at the specified coordinates with the give ncolor
|
||||
/// # Safety
|
||||
#[no_mangle]
|
||||
|
@ -180,6 +191,23 @@ pub unsafe extern "C" fn reset_canvas(state: *mut State) {
|
|||
(*state).surface.canvas().reset_matrix();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn draw_shapes(state: *mut State, ptr: *mut Rect, len: usize, zoom: f32, dx: f32, dy: f32) {
|
||||
let state = unsafe { state.as_mut() }.expect("got an invalid state pointer");
|
||||
reset_canvas(state);
|
||||
scale(state, zoom, zoom);
|
||||
translate(state, dx, dy);
|
||||
// create a `Vec<Rect>` from the pointer to the linear memory and length
|
||||
let buf = Vec::<Rect>::from_raw_parts(ptr, len, len);
|
||||
for rect in buf.iter() {
|
||||
let r = skia::Rect::new(rect.left, rect.top, rect.right, rect.bottom);
|
||||
let color = skia::Color::from_argb(255, 0, 0, 0);
|
||||
render_rect(&mut state.surface, r, color);
|
||||
}
|
||||
flush(state);
|
||||
std::mem::forget(buf);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
init_gl();
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
hover-top-frame-id (mf/use-state nil)
|
||||
frame-hover (mf/use-state nil)
|
||||
active-frames (mf/use-state #{})
|
||||
canvas-set? (mf/use-state false)
|
||||
canvas-init? (mf/use-ref false)
|
||||
|
||||
;; REFS
|
||||
[viewport-ref
|
||||
|
@ -273,16 +273,20 @@
|
|||
(when (render-v2/is-enabled?)
|
||||
;; set up canvas and first render
|
||||
(mf/with-effect
|
||||
[canvas-ref vbox' @canvas-set? base-objects zoom]
|
||||
[canvas-ref]
|
||||
(let [canvas (mf/ref-val canvas-ref)]
|
||||
(when (and (some? vbox') (not @canvas-set?))
|
||||
(p/then (render-v2/init) (fn []
|
||||
(render-v2/set-canvas canvas vbox' zoom base-objects)
|
||||
(swap! canvas-set? true))))))
|
||||
(when (some? canvas)
|
||||
(p/then (render-v2/init)
|
||||
(fn []
|
||||
(render-v2/set-canvas canvas vbox' zoom base-objects)
|
||||
(mf/set-ref-val! canvas-init? true))))))
|
||||
|
||||
;; redraw when vbox or shapes change
|
||||
(mf/with-effect
|
||||
[vbox base-objects canvas-set? zoom]
|
||||
(when @canvas-set?
|
||||
[vbox base-objects canvas-init? zoom]
|
||||
(js/console.log "jibiri")
|
||||
(when (mf/ref-val canvas-init?)
|
||||
(js/console.log "jibiri ho")
|
||||
(render-v2/draw-canvas vbox zoom base-objects))))
|
||||
|
||||
(hooks/setup-dom-events zoom disable-paste in-viewport? workspace-read-only? drawing-tool drawing-path?)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
(defonce ^:dynamic internal-module #js {})
|
||||
(defonce ^:dynamic gpu-state #js {})
|
||||
(defonce ^:dynamic shapes-ptr nil)
|
||||
(defonce ^:dynamic shapes-size nil)
|
||||
|
||||
(defn draw-canvas [vbox zoom objects]
|
||||
(let [draw-rect (gobj/get ^js internal-module "_draw_rect")
|
||||
|
@ -23,22 +25,9 @@
|
|||
reset-canvas (gobj/get ^js internal-module "_reset_canvas")
|
||||
scale (gobj/get ^js internal-module "_scale")
|
||||
flush (gobj/get ^js internal-module "_flush")
|
||||
make-color (gobj/get ^js internal-module "_make_color")
|
||||
make-rect (gobj/get ^js internal-module "_make_rect")
|
||||
supported-shapes (filter (fn [shape] (not= (:type shape) :frame)) (vals objects))]
|
||||
|
||||
draw-shapes (gobj/get ^js internal-module "_draw_shapes")]
|
||||
(js/requestAnimationFrame (fn []
|
||||
(reset-canvas gpu-state)
|
||||
(scale gpu-state zoom zoom)
|
||||
(translate gpu-state (- (:x vbox)) (- (:y vbox)))
|
||||
(doseq [shape supported-shapes]
|
||||
(let [sr (:selrect shape)
|
||||
[r g b] (cc/hex->rgb (-> shape :fills first :fill-color))
|
||||
alpha (-> shape :fills first :fill-opacity)
|
||||
color (make-color r g b alpha)
|
||||
rect (make-rect (:x1 sr) (:y1 sr) (:x2 sr) (:y2 sr))]
|
||||
(draw-rect gpu-state rect color)))
|
||||
(flush gpu-state)))))
|
||||
(draw-shapes gpu-state shapes-ptr shapes-size zoom (- (:x vbox)) (- (:y vbox)))))))
|
||||
|
||||
(defn set-canvas
|
||||
[canvas vbox zoom objects]
|
||||
|
@ -52,18 +41,31 @@
|
|||
_ (.makeContextCurrent gl handle)
|
||||
;; Initialize Skia
|
||||
state (._init ^js internal-module (.-width canvas) (.-height canvas))
|
||||
draw_rect (gobj/get ^js internal-module "_draw_rect")
|
||||
translate (gobj/get ^js internal-module "_translate")
|
||||
scale (gobj/get ^js internal-module "_scale")
|
||||
resize_surface (gobj/get ^js internal-module "_resize_surface")]
|
||||
alloc-rects (gobj/get ^js internal-module "_alloc_rects")
|
||||
heap (gobj/get ^js internal-module "HEAPF32")
|
||||
supported-shapes (filter (fn [shape] (not= (:type shape) :frame)) (vals objects))
|
||||
ptr (alloc-rects (count supported-shapes))]
|
||||
|
||||
(set! (.-width canvas) (.-clientWidth canvas))
|
||||
(set! (.-height canvas) (.-clientHeight canvas))
|
||||
(set! gpu-state state)
|
||||
(set! shapes-ptr ptr)
|
||||
(set! shapes-size (count supported-shapes))
|
||||
|
||||
(doseq [[shape index] (zipmap supported-shapes (range))]
|
||||
(let [sr (:selrect shape)
|
||||
[r g b] (cc/hex->rgb (-> shape :fills first :fill-color))
|
||||
alpha (-> shape :fills first :fill-opacity)
|
||||
;; color (make-color r g b alpha)
|
||||
;; rect (make-rect (:x1 sr) (:y1 sr) (:x2 sr) (:y2 sr))
|
||||
;; Each F32 are 4 bytes and each rect has 4 F32
|
||||
mem (js/Float32Array. (.-buffer heap) (+ ptr (* (* 4 4) index)) (* 4 4))]
|
||||
;; (js-debugger)
|
||||
(.set mem (js/Float32Array. (clj->js [(:x1 sr) (:y1 sr) (:x2 sr) (:y2 sr)])))))
|
||||
|
||||
(draw-canvas vbox zoom objects)
|
||||
|
||||
#_(draw_rect state 100 100 500 500)
|
||||
(println "set-canvas ok" (.-width canvas) (.-height canvas))))
|
||||
|
||||
(defn on-init
|
||||
|
|
|
@ -28,7 +28,7 @@ var readyPromise = new Promise((resolve, reject) => {
|
|||
readyPromiseResolve = resolve;
|
||||
readyPromiseReject = reject;
|
||||
});
|
||||
["_draw_rect","_flush","_init","_main","_make_color","_make_rect","_reset_canvas","_resize_surface","_scale","_translate","getExceptionMessage","incrementExceptionRefcount","decrementExceptionRefcount","_memory","___indirect_function_table","onRuntimeInitialized"].forEach((prop) => {
|
||||
["_alloc_rects","_draw_rect","_draw_shapes","_flush","_init","_main","_make_color","_make_rect","_reset_canvas","_resize_surface","_scale","_translate","getExceptionMessage","incrementExceptionRefcount","decrementExceptionRefcount","_memory","___indirect_function_table","onRuntimeInitialized"].forEach((prop) => {
|
||||
if (!Object.getOwnPropertyDescriptor(readyPromise, prop)) {
|
||||
Object.defineProperty(readyPromise, prop, {
|
||||
get: () => abort('You are getting ' + prop + ' on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js'),
|
||||
|
@ -700,7 +700,7 @@ function createWasm() {
|
|||
}
|
||||
}
|
||||
|
||||
wasmBinaryFile ??= findWasmBinary();
|
||||
if (!wasmBinaryFile) wasmBinaryFile = findWasmBinary();
|
||||
|
||||
// If instantiation fails, reject the module ready promise.
|
||||
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
|
||||
|
@ -752,51 +752,45 @@ function isExportedByForceFilesystem(name) {
|
|||
name === 'removeRunDependency';
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept access to a global symbol. This enables us to give informative
|
||||
* warnings/errors when folks attempt to use symbols they did not include in
|
||||
* their build, or no symbols that no longer exist.
|
||||
*/
|
||||
function hookGlobalSymbolAccess(sym, func) {
|
||||
if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {
|
||||
function missingGlobal(sym, msg) {
|
||||
if (typeof globalThis != 'undefined') {
|
||||
Object.defineProperty(globalThis, sym, {
|
||||
configurable: true,
|
||||
get() {
|
||||
func();
|
||||
warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`);
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function missingGlobal(sym, msg) {
|
||||
hookGlobalSymbolAccess(sym, () => {
|
||||
warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`);
|
||||
});
|
||||
}
|
||||
|
||||
missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer');
|
||||
missingGlobal('asm', 'Please use wasmExports instead');
|
||||
|
||||
function missingLibrarySymbol(sym) {
|
||||
hookGlobalSymbolAccess(sym, () => {
|
||||
// Can't `abort()` here because it would break code that does runtime
|
||||
// checks. e.g. `if (typeof SDL === 'undefined')`.
|
||||
var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;
|
||||
// DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
|
||||
// library.js, which means $name for a JS name with no prefix, or name
|
||||
// for a JS name like _name.
|
||||
var librarySymbol = sym;
|
||||
if (!librarySymbol.startsWith('_')) {
|
||||
librarySymbol = '$' + sym;
|
||||
}
|
||||
msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;
|
||||
if (isExportedByForceFilesystem(sym)) {
|
||||
msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
|
||||
}
|
||||
warnOnce(msg);
|
||||
});
|
||||
|
||||
if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {
|
||||
Object.defineProperty(globalThis, sym, {
|
||||
configurable: true,
|
||||
get() {
|
||||
// Can't `abort()` here because it would break code that does runtime
|
||||
// checks. e.g. `if (typeof SDL === 'undefined')`.
|
||||
var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;
|
||||
// DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
|
||||
// library.js, which means $name for a JS name with no prefix, or name
|
||||
// for a JS name like _name.
|
||||
var librarySymbol = sym;
|
||||
if (!librarySymbol.startsWith('_')) {
|
||||
librarySymbol = '$' + sym;
|
||||
}
|
||||
msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;
|
||||
if (isExportedByForceFilesystem(sym)) {
|
||||
msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
|
||||
}
|
||||
warnOnce(msg);
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Any symbol that is not included from the JS library is also (by definition)
|
||||
// not exported on the Module object.
|
||||
unexportedRuntimeSymbol(sym);
|
||||
|
@ -1311,7 +1305,12 @@ function dbg(...args) {
|
|||
|
||||
var _emscripten_date_now = () => Date.now();
|
||||
|
||||
var _emscripten_get_now = () => performance.now();
|
||||
var _emscripten_get_now;
|
||||
// Modern environment where performance.now() is supported:
|
||||
// N.B. a shorter form "_emscripten_get_now = performance.now;" is
|
||||
// unfortunately not allowed even in current browsers (e.g. FF Nightly 75).
|
||||
_emscripten_get_now = () => performance.now();
|
||||
;
|
||||
|
||||
var GLctx;
|
||||
|
||||
|
@ -5642,8 +5641,6 @@ function dbg(...args) {
|
|||
},
|
||||
filesystems:null,
|
||||
syncFSRequests:0,
|
||||
readFiles:{
|
||||
},
|
||||
FSStream:class {
|
||||
constructor() {
|
||||
// TODO(https://github.com/emscripten-core/emscripten/issues/21414):
|
||||
|
@ -6543,6 +6540,7 @@ function dbg(...args) {
|
|||
stream.stream_ops.open(stream);
|
||||
}
|
||||
if (Module['logReadFiles'] && !(flags & 1)) {
|
||||
if (!FS.readFiles) FS.readFiles = {};
|
||||
if (!(path in FS.readFiles)) {
|
||||
FS.readFiles[path] = 1;
|
||||
}
|
||||
|
@ -6963,7 +6961,7 @@ function dbg(...args) {
|
|||
createDevice(parent, name, input, output) {
|
||||
var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name);
|
||||
var mode = FS_getMode(!!input, !!output);
|
||||
FS.createDevice.major ??= 64;
|
||||
if (!FS.createDevice.major) FS.createDevice.major = 64;
|
||||
var dev = FS.makedev(FS.createDevice.major++, 0);
|
||||
// Create a fake device that a set of stream ops to emulate
|
||||
// the old behavior.
|
||||
|
@ -8567,11 +8565,13 @@ var _init = Module['_init'] = createExportWrapper('init', 2);
|
|||
var _resize_surface = Module['_resize_surface'] = createExportWrapper('resize_surface', 3);
|
||||
var _make_color = Module['_make_color'] = createExportWrapper('make_color', 4);
|
||||
var _make_rect = Module['_make_rect'] = createExportWrapper('make_rect', 4);
|
||||
var _alloc_rects = Module['_alloc_rects'] = createExportWrapper('alloc_rects', 1);
|
||||
var _draw_rect = Module['_draw_rect'] = createExportWrapper('draw_rect', 3);
|
||||
var _flush = Module['_flush'] = createExportWrapper('flush', 1);
|
||||
var _translate = Module['_translate'] = createExportWrapper('translate', 3);
|
||||
var _scale = Module['_scale'] = createExportWrapper('scale', 3);
|
||||
var _reset_canvas = Module['_reset_canvas'] = createExportWrapper('reset_canvas', 1);
|
||||
var _draw_shapes = Module['_draw_shapes'] = createExportWrapper('draw_shapes', 6);
|
||||
var _main = Module['_main'] = createExportWrapper('main', 2);
|
||||
var _fflush = createExportWrapper('fflush', 1);
|
||||
var _free = createExportWrapper('free', 1);
|
||||
|
@ -8617,10 +8617,10 @@ var dynCall_iiiiij = Module['dynCall_iiiiij'] = createExportWrapper('dynCall_iii
|
|||
var dynCall_iiiiijj = Module['dynCall_iiiiijj'] = createExportWrapper('dynCall_iiiiijj', 9);
|
||||
var dynCall_iiiiiijj = Module['dynCall_iiiiiijj'] = createExportWrapper('dynCall_iiiiiijj', 10);
|
||||
|
||||
function invoke_iii(index,a1,a2) {
|
||||
function invoke_vii(index,a1,a2) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
return getWasmTableEntry(index)(a1,a2);
|
||||
getWasmTableEntry(index)(a1,a2);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
|
@ -8639,17 +8639,6 @@ function invoke_ii(index,a1) {
|
|||
}
|
||||
}
|
||||
|
||||
function invoke_vii(index,a1,a2) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
getWasmTableEntry(index)(a1,a2);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
_setThrew(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function invoke_viii(index,a1,a2,a3) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
|
@ -8672,10 +8661,21 @@ function invoke_vi(index,a1) {
|
|||
}
|
||||
}
|
||||
|
||||
function invoke_iiii(index,a1,a2,a3) {
|
||||
function invoke_iii(index,a1,a2) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
return getWasmTableEntry(index)(a1,a2,a3);
|
||||
return getWasmTableEntry(index)(a1,a2);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
_setThrew(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function invoke_viiii(index,a1,a2,a3,a4) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
getWasmTableEntry(index)(a1,a2,a3,a4);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
|
@ -8705,6 +8705,17 @@ function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) {
|
|||
}
|
||||
}
|
||||
|
||||
function invoke_iiii(index,a1,a2,a3) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
return getWasmTableEntry(index)(a1,a2,a3);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
_setThrew(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function invoke_iiiii(index,a1,a2,a3,a4) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
|
@ -8738,17 +8749,6 @@ function invoke_iiff(index,a1,a2,a3) {
|
|||
}
|
||||
}
|
||||
|
||||
function invoke_viiii(index,a1,a2,a3,a4) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
getWasmTableEntry(index)(a1,a2,a3,a4);
|
||||
} catch(e) {
|
||||
stackRestore(sp);
|
||||
if (!(e instanceof EmscriptenEH)) throw e;
|
||||
_setThrew(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
|
||||
var sp = stackSave();
|
||||
try {
|
||||
|
@ -9052,14 +9052,12 @@ var missingLibrarySymbols = [
|
|||
'setImmediateWrapped',
|
||||
'clearImmediateWrapped',
|
||||
'polyfillSetImmediate',
|
||||
'registerPostMainLoop',
|
||||
'registerPreMainLoop',
|
||||
'getPromise',
|
||||
'makePromise',
|
||||
'idsToPromises',
|
||||
'makePromiseCallback',
|
||||
'Browser_asyncPrepareDataCounter',
|
||||
'safeRequestAnimationFrame',
|
||||
'setMainLoop',
|
||||
'isLeapYear',
|
||||
'ydayFromDate',
|
||||
'arraySum',
|
||||
|
|
Loading…
Add table
Reference in a new issue