mirror of
https://github.com/penpot/penpot.git
synced 2025-12-23 22:48:40 -05:00
Compare commits
42 Commits
STAGING
...
renderer-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32fe91398a | ||
|
|
b36c8cd52a | ||
|
|
f5acfd0787 | ||
|
|
4939bc06ac | ||
|
|
cd63fb78d2 | ||
|
|
3298785436 | ||
|
|
eeb0d21013 | ||
|
|
a11c2af542 | ||
|
|
6d5b0204e9 | ||
|
|
dfe5d861f2 | ||
|
|
445691430b | ||
|
|
88722bcf4f | ||
|
|
43903014c6 | ||
|
|
cf8b62f1a8 | ||
|
|
39b627cb1a | ||
|
|
81680cffe9 | ||
|
|
dc014bd4eb | ||
|
|
0027e77861 | ||
|
|
fa9004d12c | ||
|
|
c7f801dd44 | ||
|
|
0f0b23e38b | ||
|
|
1f8fe2dc4c | ||
|
|
e84622061d | ||
|
|
305de33200 | ||
|
|
80bbfe7a6f | ||
|
|
26ab39a45d | ||
|
|
739b8d7c02 | ||
|
|
e0a9f63015 | ||
|
|
928709a0f2 | ||
|
|
579b157ab7 | ||
|
|
0bf442e626 | ||
|
|
2184af6602 | ||
|
|
78fb938d16 | ||
|
|
dd9185e058 | ||
|
|
5f8d56b366 | ||
|
|
bc0fde68c7 | ||
|
|
024a2ae848 | ||
|
|
4d56bf66f4 | ||
|
|
c83ef201a1 | ||
|
|
6d26abb9e3 | ||
|
|
1b1f08388f | ||
|
|
472c769c9a |
@@ -265,6 +265,16 @@ RUN set -eux; \
|
||||
rm rustup-init; \
|
||||
chmod -R a+w $RUSTUP_HOME $CARGO_HOME;
|
||||
|
||||
WORKDIR /usr/local
|
||||
|
||||
# Install emscripten SDK and activate it
|
||||
RUN set -eux; \
|
||||
git clone https://github.com/emscripten-core/emsdk.git; \
|
||||
cd emsdk; \
|
||||
./emsdk install latest; \
|
||||
./emsdk activate latest; \
|
||||
rustup target add wasm32-unknown-emscripten;
|
||||
|
||||
WORKDIR /home
|
||||
|
||||
COPY files/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
@@ -11,6 +11,7 @@ alias lsf='ls -h *(.)'
|
||||
|
||||
# init Cargo / Rust env
|
||||
. "/usr/local/cargo/env"
|
||||
EMSDK_QUIET=1 . "/usr/local/emsdk/emsdk_env.sh"
|
||||
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc.local" ]; then
|
||||
|
||||
1
frontend/render_v2/cpp/.gitignore
vendored
Normal file
1
frontend/render_v2/cpp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
out
|
||||
108
frontend/render_v2/cpp/Dockerfile
Normal file
108
frontend/render_v2/cpp/Dockerfile
Normal file
@@ -0,0 +1,108 @@
|
||||
FROM debian:11
|
||||
RUN apt update && apt dist-upgrade -y && apt install -y \
|
||||
git \
|
||||
clang \
|
||||
python \
|
||||
curl \
|
||||
build-essential \
|
||||
libfontconfig-dev \
|
||||
libgl1-mesa-dev \
|
||||
libglu1-mesa-dev \
|
||||
procps \
|
||||
vim \
|
||||
binaryen \
|
||||
wabt \
|
||||
&& groupadd -g 2000 skia \
|
||||
&& useradd -u 2000 -g 2000 skia
|
||||
|
||||
# TODO(kjlubick): Try a shallow clone of depot_tools
|
||||
RUN cd /tmp \
|
||||
&& git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'
|
||||
|
||||
RUN cd /tmp \
|
||||
&& git clone 'https://gn.googlesource.com/gn'
|
||||
|
||||
RUN cd /tmp \
|
||||
&& git clone 'https://skia.googlesource.com/skia' \
|
||||
&& cd skia \
|
||||
&& git checkout 'chrome/m129'
|
||||
|
||||
ENV PATH=${PATH}:/tmp/depot_tools
|
||||
ENV PATH=${PATH}:/tmp/gn
|
||||
|
||||
ADD --chown=skia:skia https://storage.googleapis.com/skia-swiftshader/libGLESv2.so /usr/local/lib/libGLESv2.so
|
||||
ADD --chown=skia:skia https://storage.googleapis.com/skia-swiftshader/libEGL.so /usr/local/lib/libEGL.so
|
||||
|
||||
# FIXME: I don't like this approach because it implies that
|
||||
# git-sync-deps is going to fail and we need to run it two
|
||||
# times. The weird thing is that git-sync-deps fails consistently
|
||||
# the first time.
|
||||
RUN cd /tmp/skia; \
|
||||
tools/git-sync-deps; \
|
||||
tools/git-sync-deps; \
|
||||
exit 0
|
||||
|
||||
RUN cd /tmp/skia && python3 bin/fetch-ninja
|
||||
|
||||
RUN . "tmp/skia/third_party/externals/emsdk/emsdk_env.sh"
|
||||
|
||||
RUN cd /tmp/skia && ./bin/gn gen out/wasm \
|
||||
--args="is_debug=false \
|
||||
is_official_build=true \
|
||||
is_component_build=false \
|
||||
is_trivial_abi=true \
|
||||
werror=true \
|
||||
target_cpu=\"wasm\" \
|
||||
skia_use_angle=false \
|
||||
skia_use_dng_sdk=false \
|
||||
skia_use_dawn=false \
|
||||
skia_use_webgl=true \
|
||||
skia_use_webgpu=false \
|
||||
skia_use_expat=false \
|
||||
skia_use_fontconfig=false \
|
||||
skia_use_freetype=true \
|
||||
skia_use_libheif=false \
|
||||
skia_use_libjpeg_turbo_decode=true \
|
||||
skia_use_libjpeg_turbo_encode=true \
|
||||
skia_use_no_jpeg_encode=false \
|
||||
skia_use_libpng_decode=true \
|
||||
skia_use_libpng_encode=true \
|
||||
skia_use_no_png_encode=false \
|
||||
skia_use_libwebp_decode=true \
|
||||
skia_use_libwebp_encode=true \
|
||||
skia_use_no_webp_encode=false \
|
||||
skia_use_lua=false \
|
||||
skia_use_piex=false \
|
||||
skia_use_system_freetype2=false \
|
||||
skia_use_system_libjpeg_turbo=false \
|
||||
skia_use_system_libpng=false \
|
||||
skia_use_system_libwebp=false \
|
||||
skia_use_system_zlib=false \
|
||||
skia_use_vulkan=false \
|
||||
skia_use_wuffs=true \
|
||||
skia_use_zlib=true \
|
||||
skia_enable_ganesh=true \
|
||||
skia_enable_sksl=true \
|
||||
skia_build_for_debugger=false \
|
||||
skia_enable_sksl_tracing=true \
|
||||
skia_use_icu=true \
|
||||
skia_use_client_icu=false \
|
||||
skia_use_libgrapheme=false \
|
||||
skia_use_system_icu=false \
|
||||
skia_use_harfbuzz=true \
|
||||
skia_use_system_harfbuzz=false \
|
||||
skia_enable_fontmgr_custom_directory=false \
|
||||
skia_enable_fontmgr_custom_embedded=true \
|
||||
skia_enable_fontmgr_custom_empty=false \
|
||||
skia_fontmgr_factory=\":fontmgr_custom_embedded_factory\" \
|
||||
skia_use_freetype_woff2=true \
|
||||
skia_enable_skshaper=true \
|
||||
skia_enable_skparagraph=true \
|
||||
skia_enable_pdf=false"
|
||||
|
||||
RUN cd /tmp/skia; ninja -C out/wasm
|
||||
RUN echo "source '/tmp/skia/third_party/externals/emsdk/emsdk_env.sh'" >> /root/.bashrc
|
||||
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
65
frontend/render_v2/cpp/Makefile
Normal file
65
frontend/render_v2/cpp/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
all:
|
||||
# -fno-rtti: Removes C++ Run-Time Type Info support.
|
||||
# --no-entry: Disables the necessity of an entry point.
|
||||
# -sALLOW_MEMORY_GROWTH: Creates a resizable memory ArrayBuffer.
|
||||
# -sMODULARIZE: Exports emscripten as a CommonJS/AMD module.
|
||||
# -sENVIRONMENT: Removes unnecessary environments (node,worker,etc).
|
||||
# -sUSE_PTHREADS: Disables pthreads.
|
||||
# -sMAX_WEBGL_VERSION: Max WebGL set to 2
|
||||
# -sUSE_WEBGL2: Uses WebGL2 by default.
|
||||
em++ \
|
||||
-std=c++20 \
|
||||
-lembind \
|
||||
-fno-rtti \
|
||||
--no-entry \
|
||||
-sALLOW_MEMORY_GROWTH \
|
||||
-sUSE_PTHREADS=0 \
|
||||
-sMODULARIZE=1 \
|
||||
-sDISABLE_EXCEPTION_CATCHING \
|
||||
-sNODEJS_CATCH_EXIT=0 \
|
||||
-sMAX_WEBGL_VERSION=2 \
|
||||
-sUSE_WEBGL2=1 \
|
||||
-sFORCE_FILESYSTEM=0 \
|
||||
-sDYNAMIC_EXECUTION=0 \
|
||||
-sFILESYSTEM=0 \
|
||||
-sENVIRONMENT='web' \
|
||||
-sINITIAL_MEMORY=128MB \
|
||||
-DCK_ENABLE_WEBGL \
|
||||
-DCK_NO_FONTS \
|
||||
-DSK_RELEASE \
|
||||
-DSK_DISABLE_TRACING \
|
||||
-DSK_FORCE_AAA \
|
||||
-DSK_FORCE_8_BYTE_ALIGNMENT \
|
||||
-DSK_SHAPER_HARFBUZZ_AVAILABLE \
|
||||
-DCK_SERIALIZE_SKP \
|
||||
-DSK_GANESH \
|
||||
-DSK_DISABLE_LEGACY_SHADERCONTEXT \
|
||||
-DCK_INCLUDE_PATHOPS \
|
||||
-DCK_INCLUDE_RUNTIME_EFFECT \
|
||||
-DSKSL_ENABLE_TRACING \
|
||||
-DNDEBUG \
|
||||
-DSK_TRIVIAL_ABI="[[clang::trivial_abi]]" \
|
||||
-DSK_TYPEFACE_FACTORY_FREETYPE \
|
||||
-DSK_GL \
|
||||
-DSK_CODEC_DECODES_JPEG \
|
||||
-DSK_CODEC_DECODES_PNG \
|
||||
-DSK_CODEC_DECODES_WEBP \
|
||||
-DSK_HAS_WUFFS_LIBRARY \
|
||||
-DSK_ENABLE_SKSL \
|
||||
-DSK_ENABLE_PRECOMPILE \
|
||||
-DSKNX_NO_SIMD \
|
||||
-DSK_ASSUME_WEBGL=1 \
|
||||
-DSK_USE_WEBGL \
|
||||
-DSK_ENABLE_PARAGRAPH \
|
||||
-DSK_UNICODE_AVAILABLE \
|
||||
-DSK_UNICODE_ICU_IMPLEMENTATION \
|
||||
-DSK_ENABLE_SKOTTIE \
|
||||
-DSK_ENABLE_SKOTTIE_SKSLEFFECT \
|
||||
-DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 \
|
||||
--pre-js js/preamble.js \
|
||||
--pre-js js/postamble.js \
|
||||
-I/tmp/skia \
|
||||
-o out/renderer.js \
|
||||
/tmp/skia/out/wasm/modules/canvaskit/fonts/NotoMono-Regular.ttf.ninja.cpp \
|
||||
/tmp/skia/out/wasm/libskia.a \
|
||||
src/main.cpp
|
||||
49
frontend/render_v2/cpp/README.md
Normal file
49
frontend/render_v2/cpp/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Renderer
|
||||
|
||||
## How this works?
|
||||
|
||||
First of all we need a proper environment to build Skia, this
|
||||
environment is heavily based on the [Skia docker image](https://github.com/google/skia/blob/main/docker/skia-release/Dockerfile) but with some tweaks to support building
|
||||
a C++ WebAssembly module using [Emscripten](https://emscripten.org/index.html).
|
||||
|
||||
## Building everything
|
||||
|
||||
From the root directory of `frontend/renderer` just run:
|
||||
|
||||
```sh
|
||||
./build
|
||||
```
|
||||
|
||||
This is going to build the docker image and run the container to build
|
||||
the artifacts and then copy them to the necessary directories.
|
||||
|
||||
> :smile_cat: Be patient, the first time the docker image is built usually takes
|
||||
> a few minutes.
|
||||
|
||||
## Building the Skia build tools Docker image
|
||||
|
||||
To build just the Skia build tools image:
|
||||
|
||||
```sh
|
||||
cd frontend/renderer
|
||||
docker build . -t skia-build-tools
|
||||
```
|
||||
|
||||
## Building the renderer WebAssembly module
|
||||
|
||||
Just run the container and it will generate all the necessary
|
||||
artifacts in the `out` directory.
|
||||
|
||||
```sh
|
||||
cd frontend/renderer
|
||||
docker run -t -v ${PWD}:/tmp/renderer skia-build-tools
|
||||
```
|
||||
|
||||
Once the `renderer.js` and `renderer.wasm` are created in the `out` directory
|
||||
we need to move them where Penpot can have access to them, so we need to execute
|
||||
`./scripts/copy-artifacts`.
|
||||
|
||||
## C++ <-> JS
|
||||
|
||||
To add some extra functionality to the exported `Module` by the Emscripten
|
||||
compiler, we use a series of javascript scripts that exist on the `js` directory.
|
||||
11
frontend/render_v2/cpp/TODO.md
Normal file
11
frontend/render_v2/cpp/TODO.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# TO DO
|
||||
|
||||
- [x] Compile Skia.
|
||||
- [x] Compile simple `renderer.wasm` with a exported function.
|
||||
- [ ] Compile a `renderer.wasm` that uses a WebGL context.
|
||||
|
||||
## Notes
|
||||
|
||||
- I've used the Skia `main` branch and it looks that there's something missing from the last release (`chrome/m117`) so I tried to switch to that branch but now I have different issues.
|
||||
|
||||
- It is necessary to use the GL emscripten module to deal with WebGL contexts. See `js/preamble.js` and
|
||||
4
frontend/render_v2/cpp/build
Executable file
4
frontend/render_v2/cpp/build
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
docker build . -t skia-build-tools
|
||||
docker run -t -v $PWD:/tmp/renderer skia-build-tools
|
||||
./scripts/copy-artifacts
|
||||
4
frontend/render_v2/cpp/docker/entrypoint.sh
Executable file
4
frontend/render_v2/cpp/docker/entrypoint.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
source /root/.bashrc
|
||||
cd /tmp/renderer
|
||||
emmake make
|
||||
2
frontend/render_v2/cpp/js/postamble.js
Normal file
2
frontend/render_v2/cpp/js/postamble.js
Normal file
@@ -0,0 +1,2 @@
|
||||
console.log("postamble");
|
||||
}(Module));
|
||||
69
frontend/render_v2/cpp/js/preamble.js
Normal file
69
frontend/render_v2/cpp/js/preamble.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// Adds compile-time JS functions to augment Renderer interface.
|
||||
(function (Renderer) {
|
||||
console.log("preamble", Renderer);
|
||||
|
||||
const LCG_MULTIPLIER = 1103515245;
|
||||
const LCG_INCREMENT = 12345;
|
||||
const LCG_MODULUS = Math.pow(2, 31);
|
||||
const LCG_MASK = (LCG_MODULUS - 1);
|
||||
|
||||
function lcg(x, a, c, m) {
|
||||
return (x * a + c) % m;
|
||||
}
|
||||
|
||||
class Random {
|
||||
constructor(seed) {
|
||||
this._seed = seed;
|
||||
}
|
||||
|
||||
value() {
|
||||
this._seed = lcg(this._seed, LCG_MULTIPLIER, LCG_INCREMENT, LCG_MODULUS);
|
||||
return (this._seed & LCG_MASK) / LCG_MODULUS;
|
||||
}
|
||||
}
|
||||
|
||||
const random = new Random(0)
|
||||
|
||||
// Sets canvas.
|
||||
Renderer.setCanvas = function setCanvas(canvas, attrs) {
|
||||
const context = GL.createContext(canvas, attrs);
|
||||
if (!context) {
|
||||
throw new Error('Could not create a new WebGL context')
|
||||
}
|
||||
GL.makeContextCurrent(context);
|
||||
|
||||
// Emscripten does not enable this by default and Skia needs this
|
||||
// to handle certain GPU corner cases.
|
||||
GL.currentContext.GLctx.getExtension('WEBGL_debug_renderer_info');
|
||||
|
||||
// Initializes everything needed.
|
||||
this._InitCanvas(canvas.width, canvas.height);
|
||||
};
|
||||
|
||||
Renderer.setObjects = function setObjects(vbox, zoom, objects) {
|
||||
// this._SetObjects(objects.cnt);
|
||||
const numObjects = 20_000;
|
||||
this._SetObjects(numObjects);
|
||||
for (let index = 0; index < numObjects; index++) {
|
||||
// const object = objects.arr[index * 2 + 1];
|
||||
this._SetObjectRect(
|
||||
index,
|
||||
// object.selrect.x,
|
||||
random.value() * 2000,
|
||||
// object.selrect.y,
|
||||
random.value() * 2000,
|
||||
// object.selrect.width,
|
||||
random.value() * 200,
|
||||
// object.selrect.height,
|
||||
random.value() * 200
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Renderer.drawCanvas = function drawCanvas(vbox, zoom, objects) {
|
||||
performance.mark('draw-canvas:start');
|
||||
this._DrawCanvas(vbox.x, vbox.y, zoom);
|
||||
performance.mark('draw-canvas:end');
|
||||
const { duration } = performance.measure('draw-canvas', 'draw-canvas:start', 'draw-canvas:end');
|
||||
console.log('draw-canvas', `${duration}ms`);
|
||||
};
|
||||
11
frontend/render_v2/cpp/scripts/copy-artifacts
Executable file
11
frontend/render_v2/cpp/scripts/copy-artifacts
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
mkdir -p ../../resources/public/js/render_v2/cpp
|
||||
mkdir -p ../../src/app/render_v2/
|
||||
|
||||
# FIXME: This is a VERY HACKY way to set the correct `scriptDirectory` but
|
||||
# I didn't find a better way yet.
|
||||
PREAMBLE_LINES=`wc -l js/preamble.js | egrep -o [0-9]+`
|
||||
POSTAMBLE_LINES=`wc -l js/postamble.js | egrep -o [0-9]+`
|
||||
LINE_NUMBER=`echo "200 + ${PREAMBLE_LINES} + ${POSTAMBLE_LINES}" | bc | egrep -o [0-9]+`
|
||||
sed "${LINE_NUMBER} i \ \ scriptDirectory += 'js/render_v2/cpp/';" out/renderer.js > ../../src/app/render_v2/cpp.js
|
||||
cp out/renderer.wasm ../../resources/public/js/render_v2/cpp
|
||||
275
frontend/render_v2/cpp/src/main.cpp
Normal file
275
frontend/render_v2/cpp/src/main.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "include/android/SkAnimatedImage.h"
|
||||
#include "include/codec/SkAndroidCodec.h"
|
||||
#include "include/codec/SkEncodedImageFormat.h"
|
||||
#include "include/core/SkBBHFactory.h"
|
||||
#include "include/core/SkBlendMode.h"
|
||||
#include "include/core/SkBlender.h"
|
||||
#include "include/core/SkBlurTypes.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkColorFilter.h"
|
||||
#include "include/core/SkColorSpace.h"
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkImage.h"
|
||||
#include "include/core/SkImageFilter.h"
|
||||
#include "include/core/SkImageGenerator.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkM44.h"
|
||||
#include "include/core/SkMaskFilter.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkPath.h"
|
||||
#include "include/core/SkPathEffect.h"
|
||||
#include "include/core/SkPathMeasure.h"
|
||||
#include "include/core/SkPathUtils.h"
|
||||
#include "include/core/SkPicture.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "include/core/SkPoint3.h"
|
||||
#include "include/core/SkRRect.h"
|
||||
#include "include/core/SkSamplingOptions.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkSerialProcs.h"
|
||||
#include "include/core/SkShader.h"
|
||||
#include "include/core/SkStream.h"
|
||||
#include "include/core/SkString.h"
|
||||
#include "include/core/SkStrokeRec.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/core/SkTextBlob.h"
|
||||
#include "include/core/SkTypeface.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/core/SkVertices.h"
|
||||
#include "include/effects/Sk1DPathEffect.h"
|
||||
#include "include/effects/Sk2DPathEffect.h"
|
||||
#include "include/effects/SkCornerPathEffect.h"
|
||||
#include "include/effects/SkDashPathEffect.h"
|
||||
#include "include/effects/SkDiscretePathEffect.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "include/effects/SkImageFilters.h"
|
||||
#include "include/effects/SkLumaColorFilter.h"
|
||||
#include "include/effects/SkPerlinNoiseShader.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#include "include/effects/SkTrimPathEffect.h"
|
||||
#include "include/encode/SkJpegEncoder.h"
|
||||
#include "include/encode/SkPngEncoder.h"
|
||||
#include "include/encode/SkWebpEncoder.h"
|
||||
#include "include/private/SkShadowFlags.h"
|
||||
#include "include/utils/SkParsePath.h"
|
||||
#include "include/utils/SkShadowUtils.h"
|
||||
#include "src/core/SkPathPriv.h"
|
||||
#include "src/core/SkResourceCache.h"
|
||||
#include "src/image/SkImage_Base.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
|
||||
#include "modules/canvaskit/WasmCommon.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#if defined(CK_ENABLE_WEBGL) || defined(CK_ENABLE_WEBGPU)
|
||||
#define ENABLE_GPU
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_GPU
|
||||
#include "include/gpu/GpuTypes.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "include/gpu/ganesh/GrExternalTextureGenerator.h"
|
||||
#include "include/gpu/ganesh/SkImageGanesh.h"
|
||||
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
|
||||
#include "src/gpu/ganesh/GrCaps.h"
|
||||
#endif // ENABLE_GPU
|
||||
|
||||
#ifdef CK_ENABLE_WEBGL
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrTypes.h"
|
||||
#include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
|
||||
#include "include/gpu/gl/GrGLInterface.h"
|
||||
#include "include/gpu/gl/GrGLTypes.h"
|
||||
#include "src/gpu/RefCntedCallback.h"
|
||||
#include "src/gpu/ganesh/GrProxyProvider.h"
|
||||
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/ganesh/gl/GrGLDefines.h"
|
||||
|
||||
#include <webgl/webgl1.h>
|
||||
#endif // CK_ENABLE_WEBGL
|
||||
|
||||
#ifdef CK_ENABLE_WEBGPU
|
||||
#include <emscripten/html5_webgpu.h>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
#endif // CK_ENABLE_WEBGPU
|
||||
|
||||
#ifndef CK_NO_FONTS
|
||||
#include "include/core/SkFont.h"
|
||||
#include "include/core/SkFontMetrics.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkFontTypes.h"
|
||||
#ifdef CK_INCLUDE_PARAGRAPH
|
||||
#include "modules/skparagraph/include/Paragraph.h"
|
||||
#endif // CK_INCLUDE_PARAGRAPH
|
||||
#endif // CK_NO_FONTS
|
||||
|
||||
#ifdef CK_INCLUDE_PATHOPS
|
||||
#include "include/pathops/SkPathOps.h"
|
||||
#endif
|
||||
|
||||
#if defined(CK_INCLUDE_RUNTIME_EFFECT) && defined(SKSL_ENABLE_TRACING)
|
||||
#include "include/sksl/SkSLDebugTrace.h"
|
||||
#endif
|
||||
|
||||
#ifndef CK_NO_FONTS
|
||||
#include "include/ports/SkFontMgr_data.h"
|
||||
#endif
|
||||
|
||||
// Global data needed to keep everything in place.
|
||||
sk_sp<GrDirectContext> context = nullptr;
|
||||
sk_sp<SkSurface> surface = nullptr;
|
||||
SkCanvas *canvas = nullptr;
|
||||
|
||||
struct PenpotRect {
|
||||
float x, y, width, height;
|
||||
};
|
||||
|
||||
struct PenpotColor {
|
||||
float r, g, b, a;
|
||||
};
|
||||
|
||||
struct PenpotObject {
|
||||
PenpotRect selRect;
|
||||
};
|
||||
|
||||
std::vector<PenpotObject> objects(0);
|
||||
|
||||
constexpr uint32_t LCG_MULTIPLIER = 1103515245;
|
||||
constexpr uint32_t LCG_INCREMENT = 12345;
|
||||
constexpr uint32_t LCG_MODULUS = 0x80000000;
|
||||
constexpr uint32_t LCG_MASK = 0x7FFFFFFF;
|
||||
|
||||
uint32_t lcg(uint32_t x, uint32_t a, uint32_t c, uint32_t m)
|
||||
{
|
||||
return (x * a + c) % m;
|
||||
}
|
||||
|
||||
class Random {
|
||||
private:
|
||||
uint32_t _seed;
|
||||
|
||||
public:
|
||||
Random(uint32_t seed) : _seed(seed) {};
|
||||
|
||||
void reset(uint32_t new_seed) {
|
||||
_seed = new_seed;
|
||||
}
|
||||
|
||||
float value() {
|
||||
_seed = lcg(_seed, LCG_MULTIPLIER, LCG_INCREMENT, LCG_MODULUS);
|
||||
return (float)(_seed & LCG_MASK) / (float)LCG_MODULUS;
|
||||
}
|
||||
|
||||
uint8_t byte() {
|
||||
_seed = lcg(_seed, LCG_MULTIPLIER, LCG_INCREMENT, LCG_MODULUS);
|
||||
return (_seed & LCG_MASK) % 0xFF;
|
||||
}
|
||||
};
|
||||
|
||||
Random lcg_random(0);
|
||||
|
||||
// Initializes all the structures and elements needed to start rendering things.
|
||||
void InitCanvas(int width, int height)
|
||||
{
|
||||
emscripten_log(EM_LOG_CONSOLE, "Initializing canvas %d %d", width, height);
|
||||
|
||||
// We assume that any calls we make to GL for the remainder of this function will go to the
|
||||
// desired WebGL Context.
|
||||
// setup interface.
|
||||
auto interface = GrGLMakeNativeInterface();
|
||||
// setup context.
|
||||
context = GrDirectContext::MakeGL(interface);
|
||||
|
||||
emscripten_log(EM_LOG_CONSOLE, "GL context initialized");
|
||||
|
||||
GrGLint sampleCnt = 0;
|
||||
GrGLint stencil = 16;
|
||||
|
||||
// WebGL should already be clearing the color and stencil buffers, but do it again here to
|
||||
// ensure Skia receives them in the expected state.
|
||||
emscripten_glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
emscripten_glClearColor(0, 0, 0, 0);
|
||||
emscripten_glClearStencil(0);
|
||||
emscripten_glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
context->resetContext(kRenderTarget_GrGLBackendState | kMisc_GrGLBackendState);
|
||||
|
||||
// The on-screen canvas is FBO 0. Wrap it in a Skia render target so Skia can render to it.
|
||||
GrGLFramebufferInfo info;
|
||||
info.fFBOID = 0;
|
||||
|
||||
// Create the colorspace needed to represent graphics.
|
||||
sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
|
||||
|
||||
info.fFormat = GR_GL_RGBA8; // kRGBA_8888_SkColorType;
|
||||
auto target = GrBackendRenderTargets::MakeGL(
|
||||
width,
|
||||
height,
|
||||
sampleCnt,
|
||||
stencil,
|
||||
info
|
||||
);
|
||||
|
||||
emscripten_log(EM_LOG_CONSOLE, "Creating new surface");
|
||||
sk_sp<SkSurface> new_surface(
|
||||
SkSurfaces::WrapBackendRenderTarget(
|
||||
context.get(),
|
||||
target,
|
||||
kBottomLeft_GrSurfaceOrigin,
|
||||
kRGBA_8888_SkColorType,
|
||||
colorSpace,
|
||||
nullptr));
|
||||
|
||||
surface = new_surface;
|
||||
canvas = surface->getCanvas();
|
||||
emscripten_log(EM_LOG_CONSOLE, "Everything's ready!");
|
||||
}
|
||||
|
||||
void DrawCanvas(float x, float y, float zoom)
|
||||
{
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
canvas->save();
|
||||
canvas->scale(zoom, zoom);
|
||||
canvas->translate(-x, -y);
|
||||
lcg_random.reset(0);
|
||||
emscripten_log(EM_LOG_CONSOLE, "Clearing canvas");
|
||||
for (auto object : objects) {
|
||||
// emscripten_log(EM_LOG_CONSOLE, "Drawing object");
|
||||
|
||||
SkPaint paint;
|
||||
paint.setARGB(255, lcg_random.byte(), lcg_random.byte(), lcg_random.byte());
|
||||
paint.setStyle(SkPaint::Style::kFill_Style);
|
||||
|
||||
SkRect rect = SkRect::MakeXYWH(object.selRect.x, object.selRect.y, object.selRect.width, object.selRect.height);
|
||||
canvas->drawRect(rect, paint);
|
||||
}
|
||||
canvas->restore();
|
||||
|
||||
emscripten_log(EM_LOG_CONSOLE, "Flushing and submitting");
|
||||
skgpu::ganesh::FlushAndSubmit(surface);
|
||||
}
|
||||
|
||||
void SetObjects(int num_objects) {
|
||||
// emscripten_log(EM_LOG_CONSOLE, "Resizing objects vector capacity %d", num_objects);
|
||||
objects.resize(num_objects);
|
||||
}
|
||||
|
||||
void SetObjectRect(int index, float x, float y, float width, float height) {
|
||||
// emscripten_log(EM_LOG_CONSOLE, "Setting object at %d %f %f %f %f", index, x, y, width, height);
|
||||
objects[index].selRect.x = x;
|
||||
objects[index].selRect.y = y;
|
||||
objects[index].selRect.width = width;
|
||||
objects[index].selRect.height = height;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(Renderer)
|
||||
{
|
||||
function("_InitCanvas", InitCanvas);
|
||||
function("_DrawCanvas", DrawCanvas);
|
||||
function("_SetObjects", SetObjects);
|
||||
function("_SetObjectRect", SetObjectRect);
|
||||
}
|
||||
11
frontend/render_v2/rs/.gitignore
vendored
Normal file
11
frontend/render_v2/rs/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
664
frontend/render_v2/rs/Cargo.lock
generated
Normal file
664
frontend/render_v2/rs/Cargo.lock
generated
Normal file
@@ -0,0 +1,664 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"libredox",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gl"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gl_generator"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
|
||||
dependencies = [
|
||||
"khronos_api",
|
||||
"log",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "khronos_api"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.159"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "render"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"gl",
|
||||
"skia-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "skia-bindings"
|
||||
version = "0.78.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29880a81b088de322e9c5306236c70761a61b5fa4df3c15c93bad3ce890ce34c"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
"flate2",
|
||||
"heck",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"tar",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skia-safe"
|
||||
version = "0.78.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f15700ac678c06649077495acbba07e7ae01e5ca46b7dc18213f2c3477ada71"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static",
|
||||
"skia-bindings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
|
||||
dependencies = [
|
||||
"either",
|
||||
"home",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26"
|
||||
22
frontend/render_v2/rs/Cargo.toml
Normal file
22
frontend/render_v2/rs/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "render"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/penpot/penpot"
|
||||
license-file = "../../../../LICENSE"
|
||||
description = "Wasm-based canvas render for Penpot"
|
||||
|
||||
[features]
|
||||
default = ["skia-safe/gl", "skia-safe/textlayout"]
|
||||
|
||||
[[bin]]
|
||||
name = "render_v2"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
gl = "0.14.0"
|
||||
skia-safe = "0.78.2"
|
||||
base64 = "0.13"
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
6
frontend/render_v2/rs/build.sh
Executable file
6
frontend/render_v2/rs/build.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
EMSDK_QUIET=1 . "/usr/local/emsdk/emsdk_env.sh"
|
||||
|
||||
EMCC_CFLAGS="--no-entry -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s MAX_WEBGL_VERSION=2 -s MODULARIZE=1 -s EXPORT_NAME=createRustSkiaModule -s EXPORTED_RUNTIME_METHODS=GL -s ENVIRONMENT=web" cargo build --target=wasm32-unknown-emscripten
|
||||
|
||||
BIN
frontend/render_v2/rs/src/RobotoMono-Regular.ttf
Normal file
BIN
frontend/render_v2/rs/src/RobotoMono-Regular.ttf
Normal file
Binary file not shown.
362
frontend/render_v2/rs/src/main.rs
Normal file
362
frontend/render_v2/rs/src/main.rs
Normal file
@@ -0,0 +1,362 @@
|
||||
// use skia_safe::{
|
||||
// gpu::{self, gl::FramebufferInfo, DirectContext},
|
||||
// textlayout::{
|
||||
// FontCollection, ParagraphBuilder, ParagraphStyle, TextStyle, TypefaceFontProvider,
|
||||
// },
|
||||
// Canvas, Data, EncodedImageFormat, FontMgr, Paint, PaintStyle, Path, SurfaceProps,
|
||||
// };
|
||||
use skia_safe::{
|
||||
gpu::{self, gl::FramebufferInfo, DirectContext},
|
||||
textlayout::TypefaceFontProvider,
|
||||
PaintStyle,
|
||||
};
|
||||
use std::boxed::Box;
|
||||
|
||||
use skia_safe as skia;
|
||||
|
||||
static ROBOTO_REGULAR: &[u8] = include_bytes!("RobotoMono-Regular.ttf");
|
||||
static TYPEFACE_ALIAS: &str = "roboto-regular";
|
||||
|
||||
extern "C" {
|
||||
pub fn emscripten_GetProcAddress(
|
||||
name: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
|
||||
struct GpuState {
|
||||
context: DirectContext,
|
||||
framebuffer_info: FramebufferInfo,
|
||||
}
|
||||
|
||||
/// This struct holds the state of the Rust application between JS calls.
|
||||
///
|
||||
/// It is created by [init] and passed to the other exported functions. Note that rust-skia data
|
||||
/// structures are not thread safe, so a state must not be shared between different Web Workers.
|
||||
pub struct State {
|
||||
gpu_state: GpuState,
|
||||
surface: skia::Surface,
|
||||
typeface_font_provider: TypefaceFontProvider,
|
||||
default_font: skia_safe::Font,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new(
|
||||
gpu_state: GpuState,
|
||||
surface: skia::Surface,
|
||||
typeface_font_provider: TypefaceFontProvider,
|
||||
default_font: skia_safe::Font,
|
||||
) -> Self {
|
||||
State {
|
||||
gpu_state,
|
||||
surface,
|
||||
typeface_font_provider,
|
||||
default_font,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_surface(&mut self, surface: skia::Surface) {
|
||||
self.surface = surface;
|
||||
}
|
||||
}
|
||||
|
||||
fn init_gl() {
|
||||
unsafe {
|
||||
gl::load_with(|addr| {
|
||||
let addr = std::ffi::CString::new(addr).unwrap();
|
||||
emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// This needs to be done once per WebGL context.
|
||||
fn create_gpu_state() -> GpuState {
|
||||
let interface = skia_safe::gpu::gl::Interface::new_native().unwrap();
|
||||
let context = skia_safe::gpu::direct_contexts::make_gl(interface, None).unwrap();
|
||||
let framebuffer_info = {
|
||||
let mut fboid: gl::types::GLint = 0;
|
||||
unsafe { gl::GetIntegerv(gl::FRAMEBUFFER_BINDING, &mut fboid) };
|
||||
|
||||
FramebufferInfo {
|
||||
fboid: fboid.try_into().unwrap(),
|
||||
format: skia_safe::gpu::gl::Format::RGBA8.into(),
|
||||
protected: skia_safe::gpu::Protected::No,
|
||||
}
|
||||
};
|
||||
|
||||
GpuState {
|
||||
context,
|
||||
framebuffer_info,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the Skia surface that will be used for rendering.
|
||||
fn create_surface(gpu_state: &mut GpuState, width: i32, height: i32) -> skia::Surface {
|
||||
let backend_render_target =
|
||||
gpu::backend_render_targets::make_gl((width, height), 1, 8, gpu_state.framebuffer_info);
|
||||
|
||||
gpu::surfaces::wrap_backend_render_target(
|
||||
&mut gpu_state.context,
|
||||
&backend_render_target,
|
||||
skia_safe::gpu::SurfaceOrigin::BottomLeft,
|
||||
skia_safe::ColorType::RGBA8888,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn render_rect(surface: &mut skia::Surface, rect: skia::Rect, color: skia::Color) {
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_style(skia::PaintStyle::Fill);
|
||||
paint.set_color(color);
|
||||
// paint.set_anti_alias(true);
|
||||
surface.canvas().draw_rect(rect, &paint);
|
||||
}
|
||||
|
||||
fn render_rect_ref(surface: &mut skia::Surface, rect: &skia::Rect, paint: &skia::Paint) {
|
||||
surface.canvas().draw_rect(rect, paint);
|
||||
}
|
||||
|
||||
/// This is called from JS after the WebGL context has been created.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn init(width: i32, height: i32) -> Box<State> {
|
||||
let mut gpu_state = create_gpu_state();
|
||||
let surface = create_surface(&mut gpu_state, width, height);
|
||||
|
||||
// skia_safe::Font::default() is empty, let's use something better
|
||||
let font_mgr = skia_safe::FontMgr::new();
|
||||
let typeface = font_mgr
|
||||
.new_from_data(ROBOTO_REGULAR, None)
|
||||
.expect("Failed to load ROBOTO font");
|
||||
let default_font = skia_safe::Font::new(typeface.clone(), 10.0);
|
||||
|
||||
let typeface_font_provider = {
|
||||
let mut typeface_font_provider = TypefaceFontProvider::new();
|
||||
// We need a system font manager to be able to load typefaces.
|
||||
typeface_font_provider.register_typeface(typeface, TYPEFACE_ALIAS);
|
||||
typeface_font_provider
|
||||
};
|
||||
|
||||
let state = State::new(gpu_state, surface, typeface_font_provider, default_font);
|
||||
|
||||
Box::new(state)
|
||||
}
|
||||
|
||||
/// This is called from JS when the window is resized.
|
||||
/// # Safety
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn resize_surface(state: *mut State, width: i32, height: i32) {
|
||||
let state = unsafe { state.as_mut() }.expect("got an invalid state pointer");
|
||||
let surface = create_surface(&mut state.gpu_state, width, height);
|
||||
state.set_surface(surface);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Color {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
a: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Rect {
|
||||
left: f32,
|
||||
top: f32,
|
||||
right: f32,
|
||||
bottom: f32,
|
||||
r: f32,
|
||||
g: f32,
|
||||
b: f32,
|
||||
a: f32,
|
||||
}
|
||||
|
||||
#[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;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn free_rects(ptr: *mut Rect, len: usize) {
|
||||
let buf = Vec::<Rect>::from_raw_parts(ptr, len, len);
|
||||
std::mem::forget(buf);
|
||||
}
|
||||
|
||||
/// Draws a rect at the specified coordinates with the give ncolor
|
||||
/// # Safety
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn draw_rect(state: *mut State, rect: &Rect, color: &Color) {
|
||||
let state = unsafe { state.as_mut() }.expect("got an invalid state pointer");
|
||||
let r = skia::Rect::new(rect.left, rect.top, rect.right, rect.bottom);
|
||||
let color = skia::Color::from_argb((color.a * 255.0) as u8, color.r, color.g, color.b);
|
||||
render_rect(&mut state.surface, r, color);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn flush(state: *mut State) {
|
||||
let state = unsafe { state.as_mut() }.expect("got an invalid state pointer");
|
||||
state
|
||||
.gpu_state
|
||||
.context
|
||||
.flush_and_submit_surface(&mut state.surface, None);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn translate(state: *mut State, dx: f32, dy: f32) {
|
||||
(*state).surface.canvas().translate((dx, dy));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn scale(state: *mut State, sx: f32, sy: f32) {
|
||||
(*state).surface.canvas().scale((sx, sy));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn reset_canvas(state: *mut State) {
|
||||
let state = unsafe { state.as_mut() }.expect("got an invalid state pointer");
|
||||
state.surface.canvas().clear(skia_safe::Color::TRANSPARENT);
|
||||
state.surface.canvas().reset_matrix();
|
||||
flush(state);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" 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);
|
||||
|
||||
// let mut text_paint = skia::Paint::default();
|
||||
// text_paint.set_anti_alias(true);
|
||||
// text_paint.set_style(skia_safe::paint::Style::StrokeAndFill);
|
||||
// text_paint.set_stroke_width(1.0);
|
||||
|
||||
// let mut path_paint = skia::Paint::default();
|
||||
// path_paint.set_color(skia_safe::Color::BLACK);
|
||||
// path_paint.set_anti_alias(true);
|
||||
// path_paint.set_stroke_width(1.0);
|
||||
// path_paint.set_style(PaintStyle::Stroke);
|
||||
|
||||
// let svg_canvas = skia_safe::svg::Canvas::new(skia_safe::Rect::from_size((10000, 10000)), None);
|
||||
|
||||
// let mut memory = Vec::new();
|
||||
// let mut document =
|
||||
// skia_safe::pdf::new_document(&mut memory, None).begin_page((10000, 10000), None);
|
||||
// // let pdf_canvas = document.canvas();
|
||||
|
||||
for rect in buf.iter() {
|
||||
let r = skia::Rect::new(rect.left, rect.top, rect.right, rect.bottom);
|
||||
|
||||
let color = skia::Color::from_argb(
|
||||
(rect.a * 255.0) as u8,
|
||||
rect.r as u8,
|
||||
rect.g as u8,
|
||||
rect.b as u8,
|
||||
);
|
||||
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_style(skia::PaintStyle::Fill);
|
||||
paint.set_color(color);
|
||||
|
||||
// render_rect_ref(&mut state.surface, &r, &paint);
|
||||
state.surface.canvas().draw_rect(&r, &paint);
|
||||
// render_rect(&mut state.surface, r, color);
|
||||
|
||||
// paint.set_anti_alias(true);
|
||||
// state.surface.canvas().draw_rect(r, &paint);
|
||||
// state.surface.canvas().draw_text_align(
|
||||
// String::from("Lorem ipsum"),
|
||||
// (rect.left, rect.top),
|
||||
// &state.default_font,
|
||||
// &paint,
|
||||
// skia::utils::text_utils::Align::Left,
|
||||
// );
|
||||
|
||||
// let mut paint = skia::Paint::default();
|
||||
// paint.set_style(skia::PaintStyle::Fill);
|
||||
// paint.set_color(color);
|
||||
// paint.set_anti_alias(true);
|
||||
|
||||
// svg_canvas.draw_rect(r, &paint);
|
||||
// pdf_canvas.draw_rect(r, &paint);
|
||||
|
||||
// text_paint.set_color(color);
|
||||
// state.surface.canvas().draw_str(
|
||||
// "SKIA TEXT",
|
||||
// (rect.left, rect.top),
|
||||
// &state.default_font,
|
||||
// &text_paint,
|
||||
// );
|
||||
|
||||
// svg_canvas.draw_str("SKIA TEXT", (rect.left, rect.top), &state.default_font, &text_paint);
|
||||
// pdf_canvas.draw_str("SKIA TEXT", (rect.left, rect.top), &state.default_font, &text_paint);
|
||||
|
||||
// let mut path = Path::new();
|
||||
// path.move_to((rect.left, rect.top));
|
||||
// path.line_to((rect.right, rect.bottom));
|
||||
// state.surface.canvas().draw_path(&path, &path_paint);
|
||||
// svg_canvas.draw_path(&path, &path_paint);
|
||||
// pdf_canvas.draw_path(&path, &path_paint);
|
||||
|
||||
// https://github.com/rust-skia/rust-skia/blob/02c89a87649af8d2870fb631aae4a5e171887367/skia-org/src/skparagraph_example.rs#L18
|
||||
// let mut font_collection = FontCollection::new();
|
||||
// font_collection
|
||||
// .set_default_font_manager(Some(state.typeface_font_provider.clone().into()), None);
|
||||
// let paragraph_style = ParagraphStyle::new();
|
||||
// let mut paragraph_builder = ParagraphBuilder::new(¶graph_style, font_collection);
|
||||
// let mut ts = TextStyle::new();
|
||||
// ts.set_foreground_paint(&Paint::default())
|
||||
// .set_font_families(&[TYPEFACE_ALIAS]);
|
||||
// paragraph_builder.push_style(&ts);
|
||||
// paragraph_builder.add_text("Other skia text");
|
||||
// let mut paragraph = paragraph_builder.build();
|
||||
// paragraph.layout(256.0);
|
||||
// paragraph.paint(state.surface.canvas(), (rect.left, rect.top));
|
||||
// paragraph.paint(&svg_canvas, (rect.left, rect.top));
|
||||
}
|
||||
|
||||
/*
|
||||
// base64 image of the canvas
|
||||
let image = state.surface.image_snapshot();
|
||||
let mut context = state.surface.direct_context();
|
||||
let encoded_image = image.encode(context.as_mut(), EncodedImageFormat::PNG, None).unwrap();
|
||||
let base64_image = base64::encode(&encoded_image.as_bytes());
|
||||
println!("data:image/png;base64,{}", base64_image);
|
||||
|
||||
// SVG representation
|
||||
let svg_data = svg_canvas.end();
|
||||
let svg = String::from_utf8_lossy(svg_data.as_bytes());
|
||||
println!("svg: {}", svg.replace('\n', ""));
|
||||
|
||||
// PDF
|
||||
document.end_page().close();
|
||||
println!("PDF: ");
|
||||
print!("echo ");
|
||||
for byte in &memory {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
println!("| xxd -r -p > output.pdf");
|
||||
*/
|
||||
|
||||
flush(state);
|
||||
std::mem::forget(buf);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
init_gl();
|
||||
}
|
||||
5
frontend/renderer/.gitignore
vendored
5
frontend/renderer/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
target/
|
||||
debug/
|
||||
|
||||
**/*.rs.bk
|
||||
|
||||
324
frontend/renderer/Cargo.lock
generated
324
frontend/renderer/Cargo.lock
generated
@@ -1,324 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "renderer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"minicov",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
@@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "renderer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/penpot/penpot"
|
||||
license-file = "../../../../LICENSE"
|
||||
description = "Wasm-based canvas renderer for Penpot"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.93"
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.43"
|
||||
@@ -1,36 +0,0 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn print(msg: &str) {
|
||||
log(msg);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn it_works_in_wasm() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@
|
||||
[app.main.repo :as rp]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]
|
||||
[app.renderer-v2 :as renderer]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.http :as http]
|
||||
@@ -354,9 +353,6 @@
|
||||
(dcm/retrieve-comment-threads file-id)
|
||||
(fetch-bundle project-id file-id))
|
||||
|
||||
(when (contains? cf/flags :renderer-v2)
|
||||
(rx/of (renderer/init)))
|
||||
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport]]
|
||||
[app.renderer-v2 :as renderer]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
@@ -200,10 +199,6 @@
|
||||
(ntf/hide)
|
||||
(dw/finalize-file project-id file-id))))
|
||||
|
||||
(mf/with-effect [file-ready?]
|
||||
(when (and file-ready? (contains? cf/flags :renderer-v2))
|
||||
(renderer/print-msg "hello from wasm fn!")))
|
||||
|
||||
[:& (mf/provider ctx/current-file-id) {:value file-id}
|
||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.config :as cf]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.context :as ctx]
|
||||
@@ -47,8 +48,10 @@
|
||||
[app.main.ui.workspace.viewport.utils :as utils]
|
||||
[app.main.ui.workspace.viewport.viewport-ref :refer [create-viewport-ref]]
|
||||
[app.main.ui.workspace.viewport.widgets :as widgets]
|
||||
[app.render-v2 :as render-v2]
|
||||
[app.util.debug :as dbg]
|
||||
[beicon.v2.core :as rx]
|
||||
[promesa.core :as p]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; --- Viewport
|
||||
@@ -130,6 +133,9 @@
|
||||
[viewport-ref
|
||||
on-viewport-ref] (create-viewport-ref)
|
||||
|
||||
canvas-ref (mf/use-ref nil)
|
||||
canvas-init? (mf/use-ref false)
|
||||
|
||||
;; VARS
|
||||
disable-paste (mf/use-var false)
|
||||
in-viewport? (mf/use-var false)
|
||||
@@ -263,6 +269,29 @@
|
||||
|
||||
rule-area-size (/ rulers/ruler-area-size zoom)]
|
||||
|
||||
(when (render-v2/is-enabled?)
|
||||
;; set up canvas and first render
|
||||
(mf/with-effect
|
||||
[canvas-ref]
|
||||
(let [canvas (mf/ref-val canvas-ref)]
|
||||
(when (some? canvas)
|
||||
(-> (p/then (render-v2/init)
|
||||
(fn []
|
||||
(mf/set-ref-val! canvas-init? true)
|
||||
(render-v2/set-canvas canvas vbox' zoom base-objects)))
|
||||
(p/catch (fn [error] (js/console.error error)))))))
|
||||
|
||||
;; redraw when vbox or shapes change
|
||||
(mf/with-effect
|
||||
[vbox canvas-init? base-objects zoom]
|
||||
(when (mf/ref-val canvas-init?)
|
||||
(render-v2/draw-canvas vbox zoom base-objects)))
|
||||
|
||||
(mf/with-effect
|
||||
[base-objects]
|
||||
(when (mf/ref-val canvas-init?)
|
||||
(render-v2/set-objects vbox zoom base-objects))))
|
||||
|
||||
(hooks/setup-dom-events zoom disable-paste in-viewport? workspace-read-only? drawing-tool drawing-path?)
|
||||
(hooks/setup-viewport-size vport viewport-ref)
|
||||
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing? z? workspace-read-only?)
|
||||
@@ -304,50 +333,60 @@
|
||||
:layout layout
|
||||
:viewport-ref viewport-ref}])]
|
||||
|
||||
[:svg
|
||||
{:id "render"
|
||||
:class (stl/css :render-shapes)
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot "https://penpot.app/xmlns"
|
||||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "render" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:style {:background-color background
|
||||
:pointer-events "none"}
|
||||
:fill "none"}
|
||||
(if (or (contains? cf/flags :render-v2-cpp)
|
||||
(contains? cf/flags :render-v2-rs))
|
||||
[:canvas {:id "render"
|
||||
:ref canvas-ref
|
||||
:class (stl/css :render-shapes)
|
||||
:key (str "render" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:style {:background-color background
|
||||
:pointer-events "none"}}]
|
||||
[:svg
|
||||
{:id "render"
|
||||
:class (stl/css :render-shapes)
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot "https://penpot.app/xmlns"
|
||||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "render" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:style {:background-color background
|
||||
:pointer-events "none"}
|
||||
:fill "none"}
|
||||
|
||||
[:defs
|
||||
[:linearGradient {:id "frame-placeholder-gradient"}
|
||||
[:animateTransform
|
||||
{:attributeName "gradientTransform"
|
||||
:type "translate"
|
||||
:from "-1 0"
|
||||
:to "1 0"
|
||||
:dur "2s"
|
||||
:repeatCount "indefinite"}]
|
||||
[:stop {:offset "0%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "50%" :stop-color (str "color-mix(in srgb-linear, " background " 80%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
||||
[:defs
|
||||
[:linearGradient {:id "frame-placeholder-gradient"}
|
||||
[:animateTransform
|
||||
{:attributeName "gradientTransform"
|
||||
:type "translate"
|
||||
:from "-1 0"
|
||||
:to "1 0"
|
||||
:dur "2s"
|
||||
:repeatCount "indefinite"}]
|
||||
[:stop {:offset "0%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "50%" :stop-color (str "color-mix(in srgb-linear, " background " 80%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
||||
|
||||
(when (dbg/enabled? :show-export-metadata)
|
||||
[:& use/export-page {:page page}])
|
||||
(when (dbg/enabled? :show-export-metadata)
|
||||
[:& use/export-page {:page page}])
|
||||
|
||||
;; We need a "real" background shape so layer transforms work properly in firefox
|
||||
[:rect {:width (:width vbox 0)
|
||||
:height (:height vbox 0)
|
||||
:x (:x vbox 0)
|
||||
:y (:y vbox 0)
|
||||
:fill background}]
|
||||
;; We need a "real" background shape so layer transforms work properly in firefox
|
||||
[:rect {:width (:width vbox 0)
|
||||
:height (:height vbox 0)
|
||||
:x (:x vbox 0)
|
||||
:y (:y vbox 0)
|
||||
:fill background}]
|
||||
|
||||
[:& (mf/provider ctx/current-vbox) {:value vbox'}
|
||||
[:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)}
|
||||
;; Render root shape
|
||||
[:& shapes/root-shape {:key page-id
|
||||
:objects base-objects
|
||||
:active-frames @active-frames}]]]]
|
||||
[:& (mf/provider ctx/current-vbox) {:value vbox'}
|
||||
[:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)}
|
||||
;; Render root shape
|
||||
[:& shapes/root-shape {:key page-id
|
||||
:objects base-objects
|
||||
:active-frames @active-frames}]]]])
|
||||
|
||||
[:svg.viewport-controls
|
||||
{:xmlns "http://www.w3.org/2000/svg"
|
||||
|
||||
68
frontend/src/app/render_v2.cljs
Normal file
68
frontend/src/app/render_v2.cljs
Normal file
@@ -0,0 +1,68 @@
|
||||
;; 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-v2
|
||||
(:require
|
||||
[app.config :as cf]
|
||||
[app.render-v2.cpp :as render-v2-cpp]
|
||||
[app.render-v2.rs :as render-v2-rs]))
|
||||
|
||||
(defn is-enabled?
|
||||
[]
|
||||
(or (contains? cf/flags :render-v2-cpp)
|
||||
(contains? cf/flags :render-v2-rs)))
|
||||
|
||||
(defn init
|
||||
[]
|
||||
(cond
|
||||
;; CPP
|
||||
(contains? cf/flags :render-v2-cpp)
|
||||
(render-v2-cpp/init)
|
||||
|
||||
;; Rust
|
||||
(contains? cf/flags :render-v2-rs)
|
||||
(render-v2-rs/init)))
|
||||
|
||||
(defn set-canvas
|
||||
[canvas vbox zoom base-objects]
|
||||
(cond
|
||||
;; CPP
|
||||
(contains? cf/flags :render-v2-cpp)
|
||||
(render-v2-cpp/set-canvas canvas vbox zoom base-objects)
|
||||
|
||||
;; Rust
|
||||
(contains? cf/flags :render-v2-rs)
|
||||
(do
|
||||
(js/performance.mark "rs-set-canvas-start")
|
||||
(render-v2-rs/set-canvas canvas vbox zoom base-objects)
|
||||
(js/performance.mark "rs-set-canvas-end")
|
||||
(let [duration (.-duration (js/performance.measure "rs-set-canvas" "rs-set-canvas-start" "rs-set-canvas-end"))]
|
||||
(js/console.log "Rust set-canvas" duration)))))
|
||||
|
||||
(defn draw-canvas
|
||||
[vbox zoom base-objects]
|
||||
(cond
|
||||
;; CPP
|
||||
(contains? cf/flags :render-v2-cpp)
|
||||
(render-v2-cpp/draw-canvas vbox zoom base-objects)
|
||||
|
||||
;; Rust
|
||||
(contains? cf/flags :render-v2-rs)
|
||||
(do
|
||||
(js/performance.mark "rs-draw-canvas-start")
|
||||
(render-v2-rs/draw-canvas vbox zoom base-objects)
|
||||
(js/performance.mark "rs-draw-canvas-end")
|
||||
(let [duration (.-duration (js/performance.measure "rs-draw-canvas" "rs-draw-canvas-start" "rs-draw-canvas-end"))]
|
||||
(js/console.log "Rust draw-canvas" duration)))))
|
||||
|
||||
(defn set-objects [vbox zoom base-objects]
|
||||
(cond
|
||||
;; Rust
|
||||
(contains? cf/flags :render-v2-rs)
|
||||
(render-v2-rs/set-objects vbox zoom base-objects)
|
||||
|
||||
(contains? cf/flags :render-v2-cpp)
|
||||
(render-v2-cpp/set-objects vbox zoom base-objects)))
|
||||
37
frontend/src/app/render_v2/cpp.cljs
Normal file
37
frontend/src/app/render_v2/cpp.cljs
Normal file
@@ -0,0 +1,37 @@
|
||||
;; 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-v2.cpp
|
||||
(:require
|
||||
["./cpp.js" :as render-v2]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defonce ^:dynamic internal-module nil)
|
||||
|
||||
(defn set-canvas
|
||||
[canvas vbox zoom base-objects]
|
||||
(.setCanvas ^js internal-module canvas #js {:antialias false})
|
||||
(.setObjects ^js internal-module vbox zoom base-objects)
|
||||
(.drawCanvas ^js internal-module vbox zoom base-objects))
|
||||
|
||||
(defn draw-canvas
|
||||
[vbox zoom base-objects]
|
||||
(.drawCanvas ^js internal-module vbox zoom base-objects))
|
||||
|
||||
(defn set-objects
|
||||
[vbox zoom base-objects]
|
||||
(.setObjects ^js internal-module vbox zoom base-objects))
|
||||
|
||||
(defn on-init
|
||||
[module']
|
||||
(set! internal-module module')
|
||||
(js/console.log "internal-module" internal-module module'))
|
||||
|
||||
(defn init
|
||||
[]
|
||||
(p/then (render-v2) #(on-init %)))
|
||||
6713
frontend/src/app/render_v2/cpp.js
Normal file
6713
frontend/src/app/render_v2/cpp.js
Normal file
File diff suppressed because it is too large
Load Diff
118
frontend/src/app/render_v2/rs.cljs
Normal file
118
frontend/src/app/render_v2/rs.cljs
Normal file
@@ -0,0 +1,118 @@
|
||||
;; 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-v2.rs
|
||||
(:require
|
||||
["./rs.js" :as render-v2]
|
||||
[app.common.colors :as cc]
|
||||
[app.config :as cf]
|
||||
[beicon.v2.core :as rx]
|
||||
[goog.object :as gobj]
|
||||
[potok.v2.core :as ptk]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(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")
|
||||
translate (gobj/get ^js internal-module "_translate")
|
||||
reset-canvas (gobj/get ^js internal-module "_reset_canvas")
|
||||
scale (gobj/get ^js internal-module "_scale")
|
||||
flush (gobj/get ^js internal-module "_flush")
|
||||
draw-shapes (gobj/get ^js internal-module "_draw_shapes")]
|
||||
(js/requestAnimationFrame (fn []
|
||||
(draw-shapes gpu-state shapes-ptr shapes-size zoom (- (:x vbox)) (- (:y vbox)))))))
|
||||
|
||||
(defn set-objects
|
||||
[vbox zoom objects]
|
||||
(let [alloc-rects (gobj/get ^js internal-module "_alloc_rects")
|
||||
free_rects (gobj/get ^js internal-module "_free_rects")
|
||||
supported-shapes (filter (fn [shape] (not= (:type shape) :frame)) (vals objects))
|
||||
heap (gobj/get ^js internal-module "HEAPF32")
|
||||
;; Each F32 are 4 bytes
|
||||
;; Each rect has:
|
||||
;; - 4 F32 for points coordinates
|
||||
;; - 4 F32 for color
|
||||
;; rect-size (* 8 4)
|
||||
rect-size (* 8 4)
|
||||
;; kk (data gpu-state)
|
||||
]
|
||||
(when shapes-ptr
|
||||
(free_rects shapes-ptr shapes-size))
|
||||
|
||||
(let [ptr (alloc-rects (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)
|
||||
mem (js/Float32Array. (.-buffer heap) (+ ptr (* rect-size index)) rect-size)]
|
||||
(set! shapes-ptr ptr)
|
||||
(set! shapes-size (count supported-shapes))
|
||||
(.set mem (js/Float32Array. (clj->js [(:x1 sr) (:y1 sr) (:x2 sr) (:y2 sr) r g b (or alpha 1)]))))))
|
||||
(draw-canvas vbox zoom objects)))
|
||||
|
||||
(defn set-objects-benchmark
|
||||
[vbox zoom]
|
||||
(let [alloc-rects (gobj/get ^js internal-module "_alloc_rects")
|
||||
free_rects (gobj/get ^js internal-module "_free_rects")
|
||||
shape-count 10000
|
||||
heap (gobj/get ^js internal-module "HEAPF32")
|
||||
;; Each F32 are 4 bytes
|
||||
;; Each rect has:
|
||||
;; - 4 F32 for points coordinates
|
||||
;; - 4 F32 for color
|
||||
;; rect-size (* 8 4)
|
||||
rect-bytes (* 8 4)
|
||||
]
|
||||
(when shapes-ptr
|
||||
(free_rects shapes-ptr shape-count))
|
||||
|
||||
(let
|
||||
[ptr (alloc-rects shape-count)]
|
||||
(doseq [index (take shape-count (iterate inc 0))]
|
||||
(let [mem (js/Float32Array. (.-buffer heap) (+ ptr (* rect-bytes index)) rect-bytes)
|
||||
x1 (rand-int 4096)
|
||||
x2 (+ x1 (rand-int 256))
|
||||
y1 (rand-int 4096)
|
||||
y2 (+ y1 (rand-int 256))]
|
||||
(set! shapes-ptr ptr)
|
||||
(set! shapes-size shape-count)
|
||||
;; (.set mem (js/Float32Array. (clj->js [0 0 64 64 255 0 0 1])))
|
||||
;; (.set mem (js/Float32Array. (clj->js [(* index 72) 0 (+ (* index 72) 64) 64 255 0 0 1])))
|
||||
(.set mem (js/Float32Array. (clj->js [x1 y1 x2 y2 (rand-int 255) (rand-int 255) (rand-int 255) 1])))
|
||||
)))
|
||||
(draw-canvas vbox zoom nil)))
|
||||
|
||||
(defn set-canvas
|
||||
[canvas vbox zoom objects]
|
||||
(let [gl (gobj/get ^js internal-module "GL")
|
||||
context (.getContext canvas "webgl2" {;; "antialias" true
|
||||
;; "depth" true
|
||||
;; "stencil" false
|
||||
"alpha" true})
|
||||
;; Register the context with emscripten
|
||||
handle (.registerContext gl context {"majorVersion" 2})
|
||||
_ (.makeContextCurrent gl handle)
|
||||
;; Initialize Skia
|
||||
state (._init ^js internal-module (.-width canvas) (.-height canvas))]
|
||||
|
||||
(set! (.-width canvas) (.-clientWidth canvas))
|
||||
(set! (.-height canvas) (.-clientHeight canvas))
|
||||
(set! gpu-state state)
|
||||
(set-objects-benchmark vbox zoom)))
|
||||
;; (set-objects vbox zoom objects)))
|
||||
|
||||
(defn on-init
|
||||
[module']
|
||||
(set! internal-module module')
|
||||
)
|
||||
|
||||
(defn init
|
||||
[]
|
||||
(p/then (render-v2) #(on-init %)))
|
||||
9794
frontend/src/app/render_v2/rs.js
Normal file
9794
frontend/src/app/render_v2/rs.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
;; 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.renderer-v2
|
||||
(:require
|
||||
[app.config :as cf]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(defonce internal-module #js {})
|
||||
|
||||
(defn on-module-loaded
|
||||
[module']
|
||||
(let [init-fn (.-default ^js module')]
|
||||
(->> (rx/from (init-fn))
|
||||
(rx/map (constantly module')))))
|
||||
|
||||
(defn- on-module-initialized
|
||||
[module]
|
||||
(set! internal-module module))
|
||||
|
||||
(defn print-msg [msg]
|
||||
(let [print-fn (.-print internal-module)]
|
||||
(print-fn msg)))
|
||||
|
||||
(defn init
|
||||
[]
|
||||
(ptk/reify ::init
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [module-uri (assoc cf/public-uri :path "/js/renderer/renderer.js")]
|
||||
(->> (rx/from (js/dynamicImport (str module-uri)))
|
||||
(rx/mapcat on-module-loaded)
|
||||
(rx/tap on-module-initialized)
|
||||
(rx/ignore))))))
|
||||
Reference in New Issue
Block a user