Compare commits

...

17 Commits

Author SHA1 Message Date
Alejandro Alonso
00ce454ba6 WIP 2023-12-22 12:18:59 +01:00
Alejandro Alonso
fa84b1e67d WIP 2023-12-22 07:38:57 +01:00
Alejandro Alonso
4cf1406cae WIP 2023-12-21 21:06:41 +01:00
Alejandro Alonso
5b8c8e93b2 WIP 2023-12-21 19:50:47 +01:00
Aitor
b3871c8bfc wip 2023-12-21 17:05:40 +01:00
Alejandro Alonso
1579be27cc WIP 2023-12-21 16:55:22 +01:00
Alejandro Alonso
218b5e52e5 WIP 2023-12-21 16:49:22 +01:00
Aitor
495a42db0c wip: drop shadow && blur 2023-12-21 16:35:35 +01:00
Aitor
fed74fccc5 wip: easter egg 2023-12-21 15:33:34 +01:00
Aitor
279e0d8bea wip: render shapes 2023-12-21 14:46:20 +01:00
Alejandro Alonso
b5d3de9fab WIP 2023-12-21 11:19:11 +01:00
Alejandro Alonso
cd04a41d98 WIP 2023-12-20 15:09:28 +01:00
Alejandro Alonso
66aa5fd01f WIP 2023-12-20 15:01:58 +01:00
Alejandro Alonso
721d9ee399 WIP 2023-12-20 14:08:15 +01:00
Alejandro Alonso
69582add4b WIP 2023-12-20 13:54:44 +01:00
Alejandro Alonso
a1da3065f7 WIP 2023-12-19 16:57:18 +01:00
Alejandro Alonso
71de1a28fc WIP 2023-12-19 16:56:56 +01:00
6 changed files with 752 additions and 38 deletions

View File

@@ -76,6 +76,7 @@
"vite": "^5.0.2"
},
"dependencies": {
"canvaskit-wasm": "^0.39.1",
"date-fns": "^2.30.0",
"draft-js": "^0.11.7",
"eventsource-parser": "^1.1.1",

View File

@@ -39,6 +39,7 @@
[app.main.ui.workspace.viewport.rules :as rules]
[app.main.ui.workspace.viewport.scroll-bars :as scroll-bars]
[app.main.ui.workspace.viewport.selection :as selection]
[app.main.ui.workspace.viewport.sk :as sk]
[app.main.ui.workspace.viewport.snap-distances :as snap-distances]
[app.main.ui.workspace.viewport.snap-points :as snap-points]
[app.main.ui.workspace.viewport.top-bar :as top-bar]
@@ -92,6 +93,7 @@
;; CONTEXT
page-id (mf/use-ctx ctx/current-page-id)
page (mf/deref refs/workspace-page)
;; DEREFS
drawing (mf/deref refs/workspace-drawing)
@@ -302,49 +304,54 @@
[:& top-bar/top-bar]]
[:svg.render-shapes
{:id "render"
: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"}
#_[:svg.render-shapes
{:id "render"
: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 {:options options}])
(when (dbg/enabled? :show-export-metadata)
[:& use/export-page {:options options}])
;; 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}]
[: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)}
[:& (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}]]]]
[:& shapes/root-shape {:key page-id
:objects base-objects
:active-frames @active-frames}]]]]
;; IT's MAGIC!
[sk/canvas {:objects base-objects
:active-frames @active-frames
:vbox vbox}]
[:svg.viewport-controls
{:xmlns "http://www.w3.org/2000/svg"
@@ -629,4 +636,10 @@
:objects base-objects
:modifiers modifiers
:shape frame
:view-only true}]))]]]]))
:view-only true}]))]]]
(when (= (:name page) "DOOM")
[:iframe {:src "/wasm/doom/index.html"
:width 1280
:height 720
:style {:position "absolute" :top 0 :left 0 :z-index 10000 :pointer-events "all"}}])]))

View File

@@ -0,0 +1,49 @@
(ns app.main.ui.workspace.viewport.sk
(:require-macros [app.main.style :as stl])
(:require
;; TODO el cp de node_modules/canvaskit-wasm/bin/canvaskit.wasm
["./sk_impl.js" :as impl]
[rumext.v2 :as mf]))
(defn get-objects-as-iterable
[objects]
(.values js/Object (clj->js objects)))
(mf/defc canvas
{::mf/wrap-props false}
[props]
(let [objects (unchecked-get props "objects")
vbox (unchecked-get props "vbox")
canvas-ref (mf/use-ref nil)
canvas-kit (mf/use-state nil)]
(mf/with-effect [vbox]
(let [k @canvas-kit
objects (get-objects-as-iterable objects)]
(when (some? k)
(.setVbox ^js k vbox)
(.draw k objects))))
(mf/with-effect [objects]
(js/console.log "whatever")
(let [k @canvas-kit
objects (get-objects-as-iterable objects)]
(when (some? k)
(.draw k objects))))
(mf/with-effect [canvas-ref vbox]
(let [canvas (mf/ref-val canvas-ref)
objects (get-objects-as-iterable objects)]
(when (and (some? canvas) (some? vbox))
(set! (.-width canvas) (.-clientWidth canvas))
(set! (.-height canvas) (.-clientHeight canvas))
(println "init vbox" vbox)
(-> (.initialize impl/CanvasKit "skia-canvas" vbox)
(.then (fn [k]
(reset! canvas-kit k)
(println "init complete")
(.draw k objects)))))))
[:canvas {:id "skia-canvas"
:class (stl/css :canvas)
:ref canvas-ref}]))

View File

@@ -0,0 +1,13 @@
// 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
@import "refactor/common-refactor.scss";
.canvas {
position: absolute;
width: 100%;
height: 100%;
}

View File

@@ -0,0 +1,621 @@
import CanvasKitInit from 'canvaskit-wasm/bin/canvaskit.js';
class CanvasKit {
constructor(canvasId, CanvasKit, fontManager, vbox) {
this.canvasId = canvasId;
this.CanvasKit = CanvasKit;
this.vbox = vbox;
this.fontManager = fontManager;
this.onDraw = this.onDraw.bind(this)
}
static async loadFont(url) {
const response = await fetch(url)
return response.arrayBuffer()
}
static async initialize(canvasId, vbox) {
const kit = await CanvasKitInit();
const fontData = await this.loadFont("/fonts/WorkSans-Regular.woff2");
const fontManager = kit.FontMgr.FromData([fontData]);
return new CanvasKit(canvasId, kit, fontManager, vbox);
}
setVbox(vbox) {
this.vbox = vbox;
}
getTextDirectionFromString(textDirection) {
switch (textDirection) {
case 'ltr': return this.CanvasKit.TextDirection.LTR;
case 'rtl': return this.CanvasKit.TextDirection.RTL;
default: return this.CanvasKit.TextDirection.LTR;
}
}
getTextDecorationFromString(textDecoration) {
switch(textDecoration) {
case 'underline': return this.CanvasKit.UnderlineDecoration;
case 'overline': return this.CanvasKit.OverlineDecoration;
case 'line-through': return this.CanvasKit.LineThroughDecoration;
case 'none': return this.CanvasKit.NoDecoration;
default: return this.CanvasKit.NoDecoration;
}
}
getTextAlignFromString(textAlign) {
console.log('text-align-from-string', textAlign)
switch (textAlign) {
case 'left': return this.CanvasKit.TextAlign.Left;
case 'center': return this.CanvasKit.TextAlign.Center;
case 'right': return this.CanvasKit.TextAlign.Right;
case 'justify': return this.CanvasKit.TextAlign.Justify;
case 'start': return this.CanvasKit.TextAlign.Start;
case 'end': return this.CanvasKit.TextAlign.End;
default: return this.CanvasKit.TextAlign.Left;
}
}
getBlendModeFromObject(object) {
switch (object['blend-mode']) {
case 'normal': return this.CanvasKit.BlendMode.SrcOver;
case 'multiply': return this.CanvasKit.BlendMode.Multiply;
case 'screen': return this.CanvasKit.BlendMode.Screen;
case 'overlay': return this.CanvasKit.BlendMode.Overlay;
case 'darken': return this.CanvasKit.BlendMode.Darken;
case 'lighten': return this.CanvasKit.BlendMode.Lighten;
case 'color-dodge': return this.CanvasKit.BlendMode.ColorDodge;
case 'color-burn': return this.CanvasKit.BlendMode.ColorBurn;
case 'hard-light': return this.CanvasKit.BlendMode.HardLight;
case 'soft-light': return this.CanvasKit.BlendMode.SoftLight;
case 'difference': return this.CanvasKit.BlendMode.Difference;
case 'exclusion': return this.CanvasKit.BlendMode.Exclusion;
case 'hue': return this.CanvasKit.BlendMode.Hue;
case 'saturation': return this.CanvasKit.BlendMode.Saturation;
case 'color': return this.CanvasKit.BlendMode.Color;
case 'luminosity': return this.CanvasKit.BlendMode.Luminosity;
default: return this.CanvasKit.BlendMode.SrcOver;
}
}
drawFrame(canvas, object) {
this.drawRect(canvas, object)
}
drawRect(canvas, shape) {
let blur = null
const paint = new this.CanvasKit.Paint();
paint.setAntiAlias(true);
paint.setBlendMode(this.getBlendModeFromObject(shape));
const rx = shape['rx'] || shape['r1'] || 0;
const ry = shape['ry'] || shape['r1'] || 0;
if (shape.blur) {
blur = this.CanvasKit.ImageFilter.MakeBlur(shape.blur.value, shape.blur.value, this.CanvasKit.TileMode.Decal, null);
}
if (shape.shadow) {
for (const shadow of shape.shadow.reverse()) {
const paintShadow = new this.CanvasKit.Paint();
const color = this.CanvasKit.parseColorString(shadow.color.color)
color[3] = shadow.color.opacity
const shadowFilter = this.CanvasKit.ImageFilter.MakeDropShadowOnly(shadow['offset-x'], shadow['offset-y'], shadow.blur, shadow.blur, color, blur);
const shadowRect = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry)
paintShadow.setImageFilter(shadowFilter)
canvas.drawRRect(shadowRect, paintShadow)
paintShadow.delete()
}
}
// Drawing fills
if (shape.fills) {
for (const fill of shape.fills.reverse()) {
if (fill["fill-color"]) {
paint.setStyle(this.CanvasKit.PaintStyle.Fill);
const color = this.CanvasKit.parseColorString(fill["fill-color"]);
const opacity = fill["fill-opacity"];
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry,
);
canvas.drawRRect(rr, paint);
}
else if (fill["fill-image"]) {
let realPromise = fetch("/assets/by-file-media-id/" + fill["fill-image"].id)
.then((response) => response.blob())
.then((blob) => createImageBitmap(blob))
.then((bitmap) => this.CanvasKit.MakeImageFromCanvasImageSource(bitmap))
.then((img) => {
const self = this;
const s = this.CanvasKit.MakeCanvasSurface(self.canvasId);
s.drawOnce((c) => {
c.drawImage(img, shape.x, shape.y, null)
});
});
}
}
}
// Drawing strokes
if (shape.strokes) {
for (const stroke of shape.strokes.reverse()) {
paint.setStyle(this.CanvasKit.PaintStyle.Stroke);
const color = this.CanvasKit.parseColorString(stroke["stroke-color"]);
const opacity = stroke["stroke-opacity"];
const strokeWidth = stroke["stroke-width"];
paint.setStrokeWidth(strokeWidth);
console.log("stroke", stroke, stroke["stroke-color"], stroke["stroke-opacity"], strokeWidth);
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry,
);
canvas.drawRRect(rr, paint);
}
}
if (shape.blur) {
const paintBlur = new this.CanvasKit.Paint();
if (!shape.shadow) {
const blurRect = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry)
paintBlur.setImageFilter(blur)
canvas.drawRRect(blurRect, paintBlur)
paintBlur.delete()
}
}
paint.delete();
}
drawCircle(canvas, shape) {
let blur = null
const paint = new this.CanvasKit.Paint();
paint.setAntiAlias(true);
paint.setBlendMode(this.getBlendModeFromObject(shape));
if (shape.blur) {
blur = this.CanvasKit.ImageFilter.MakeBlur(shape.blur.value, shape.blur.value, this.CanvasKit.TileMode.Decal, null);
}
if (shape.shadow) {
for (const shadow of shape.shadow.reverse()) {
const paintShadow = new this.CanvasKit.Paint();
const color = this.CanvasKit.parseColorString(shadow.color.color)
color[3] = shadow.color.opacity
const shadowFilter = this.CanvasKit.ImageFilter.MakeDropShadowOnly(shadow['offset-x'], shadow['offset-y'], shadow.blur, shadow.blur, color, blur);
const shadowRect = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0)
paintShadow.setImageFilter(shadowFilter)
canvas.drawOval(shadowRect, paintShadow)
paintShadow.delete()
}
}
// Drawing fills
if (shape.fills) {
for (const fill of shape.fills.reverse()) {
paint.setStyle(this.CanvasKit.PaintStyle.Fill);
const color = this.CanvasKit.parseColorString(fill["fill-color"]);
const opacity = fill["fill-opacity"];
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0,
);
canvas.drawOval(rr, paint);
}
}
// Drawing strokes
if (shape.strokes) {
for (const stroke of shape.strokes.reverse()) {
paint.setStyle(this.CanvasKit.PaintStyle.Stroke);
const color = this.CanvasKit.parseColorString(stroke["stroke-color"]);
const opacity = stroke["stroke-opacity"];
const strokeWidth = stroke["stroke-width"];
paint.setStrokeWidth(strokeWidth);
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0,
);
canvas.drawOval(rr, paint);
}
}
if (shape.blur) {
const paintBlur = new this.CanvasKit.Paint();
if (!shape.shadow) {
const blurRect = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0)
paintBlur.setImageFilter(blur)
canvas.drawOval(blurRect, paintBlur)
paintBlur.delete()
}
}
paint.delete();
}
drawPath(canvas, shape) {
const path = new this.CanvasKit.Path();
for (const { command, params } of shape.content) {
switch (command) {
// :move-to "M"
// :close-path "Z"
// :line-to "L"
// :line-to-horizontal "H"
// :line-to-vertical "V"
// :curve-to "C"
// :smooth-curve-to "S"
// :quadratic-bezier-curve-to "Q"
// :smooth-quadratic-bezier-curve-to "T"
// :elliptical-arc "A"
case 'move-to': path.moveTo(params.x, params.y); break;
case 'line-to': path.lineTo(params.x, params.y); break;
case 'line-to-horizontal': /* path.lineTo(...params); */ break;
case 'line-to-vertical': /* path.lineTo(...params); */ break;
case 'curve-to': path.cubicTo(params.c1x, params.c1y, params.c2x, params.c2y, params.x, params.y); break;
case 'smooth-curve-to': path.cubicTo(...params); break;
case 'quadratic-bezier-to': path.quadTo(...params); break;
case 'smooth-quadratic-bezier-curve-to': path.quadTo(...params); break;
case 'elliptical-arc': path.arcTo(...params); break;
case 'close-path': path.close(); break;
}
}
const paint = new this.CanvasKit.Paint();
paint.setAntiAlias(true);
paint.setBlendMode(this.getBlendModeFromObject(shape));
// Drawing fills
if (shape.fills) {
for (const fill of shape.fills.reverse()) {
paint.setStyle(this.CanvasKit.PaintStyle.Fill);
const color = this.CanvasKit.parseColorString(fill["fill-color"]);
const opacity = fill["fill-opacity"];
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0,
);
canvas.drawPath(path, paint);
}
}
// Drawing strokes
if (shape.strokes) {
for (const stroke of shape.strokes.reverse()) {
paint.setStyle(this.CanvasKit.PaintStyle.Stroke);
const color = this.CanvasKit.parseColorString(stroke["stroke-color"]);
const opacity = stroke["stroke-opacity"];
const strokeWidth = stroke["stroke-width"];
paint.setStrokeWidth(strokeWidth);
color[3] = opacity;
paint.setColor(color);
const rr = this.CanvasKit.RRectXY(
this.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
0,
0,
);
canvas.drawPath(path, paint);
}
}
paint.delete();
}
drawTextRun(canvas, shape, textRun) {
if (!textRun.children) {
console.warn('textRun.children is undefined', textRun)
return;
}
for (const child of textRun.children) {
if (child.type === 'paragraph') {
const textDirection = this.getTextDirectionFromString(child["text-direction"]);
const textAlign = this.getTextAlignFromString(child["text-align"]);
console.log("text-align", textAlign);
if (!child.children) {
console.warn('child.children is undefined', child)
continue
}
for (const paragraphText of child.children) {
if (paragraphText.text === '') continue;
for (const fill of paragraphText.fills) {
const color = this.CanvasKit.parseColorString(fill["fill-color"]);
color[3] = fill["fill-opacity"];
const decoration = this.getTextDecorationFromString(paragraphText["text-decoration"]);
const paragraphStyle = new this.CanvasKit.ParagraphStyle({
textDirection,
textStyle: {
color,
decoration,
fontFamilies: [paragraphText["font-family"]],
fontSize: parseInt(paragraphText["font-size"], 10),
/*
// TODO: Hacer una función que devuelva el weight o un valor de los del enum
fontStyle: {
weight: parseInt(textRun['font-weight'], 10),
},
*/
letterSpacing: parseFloat(paragraphText["letter-spacing"]) || -1,
},
textAlign,
});
const text = paragraphText.text;
const builder = this.CanvasKit.ParagraphBuilder.Make(paragraphStyle, this.fontManager);
builder.addText(text);
const paragraph = builder.build();
const layoutWidth = shape["grow-type"] === "fixed" ? shape.width : Infinity;
console.log(layoutWidth)
paragraph.layout(layoutWidth); // width in pixels to use when wrapping text
canvas.drawParagraph(paragraph, shape.x, shape.y);
}
}
} else {
this.drawTextRun(canvas, shape, child)
}
}
}
drawText(canvas, shape) {
console.log('drawText', shape)
if (!shape.content) {
console.warn('drawText: shape.content is undefined', shape);
return;
}
this.drawTextRun(canvas, shape, shape.content);
}
drawGroup(canvas, object) {
console.warn("To be implemented");
}
drawObject(canvas, object) {
canvas.save();
canvas.rotate(object.rotation, object.x + object.width / 2, object.y + object.height / 2);
switch (object.type) {
case "frame":
this.drawFrame(canvas, object);
break;
case "rect":
this.drawRect(canvas, object);
break;
case "circle":
this.drawCircle(canvas, object);
break;
case "path":
this.drawPath(canvas, object);
break;
case "text":
this.drawText(canvas, object);
break;
case "group":
this.drawGroup(canvas, object);
break;
default:
console.warn("Unknown object type", object.type);
break;
}
canvas.restore();
}
onDraw(canvas) {
// Es posible que no haga falta.
// canvas.clear(CanvasKit.TRANSPARENT);
console.log(this.vbox);
canvas.save()
canvas.scale(this.surface.width() / this.vbox.width, this.surface.height() / this.vbox.height);
canvas.translate(-this.vbox.x, -this.vbox.y);
for (const object of this.objects) {
this.drawObject(canvas, object);
}
canvas.restore()
}
draw(objects) {
this.objects = objects;
this.surface = this.CanvasKit.MakeCanvasSurface(this.canvasId);
this.surface.drawOnce(this.onDraw);
}
paintRect(shape) {
const surface = this.CanvasKit.MakeCanvasSurface(this.canvasId);
const self = this;
function draw(canvas) {
if (self.vbox) {
canvas.translate(-self.vbox.x, -self.vbox.y);
}
const paint = new self.CanvasKit.Paint();
// Drawing fills
if (shape.fills) {
for (const fill of shape.fills.reverse()) {
paint.setStyle(self.CanvasKit.PaintStyle.Fill);
const color = self.CanvasKit.parseColorString(fill["fill-color"]);
const opacity = fill["fill-opacity"];
color[3] = opacity;
paint.setColor(color);
const rr = self.CanvasKit.RRectXY(
self.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry,
);
canvas.drawRRect(rr, paint);
}
}
// Drawing strokes
if (shape.strokes) {
for (const stroke of shape.strokes.reverse()) {
paint.setStyle(self.CanvasKit.PaintStyle.Stroke);
const color = self.CanvasKit.parseColorString(stroke["stroke-color"]);
const opacity = stroke["stroke-opacity"];
const strokeWidth = stroke["stroke-width"];
paint.setStrokeWidth(strokeWidth);
color[3] = opacity;
paint.setColor(color);
const rr = self.CanvasKit.RRectXY(
self.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height),
rx,
ry,
);
canvas.drawRRect(rr, paint);
// Inner stroke?
// const rr2 = self.CanvasKit.RRectXY(self.CanvasKit.LTRBRect(shape.x, shape.y, shape.x + shape.width, shape.y + shape.height), 0, 0);
// canvas.clipRRect(rr2, self.CanvasKit.ClipOp.Intersect, true);
}
}
paint.delete();
}
surface.drawOnce(draw);
// // Drawing another border
// const paint2 = new this.CanvasKit.Paint();
// paint2.setColor(this.CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
// paint2.setStyle(this.CanvasKit.PaintStyle.Stroke);
// paint2.setStrokeWidth(25.0);
// paint2.setAntiAlias(true);
// const rr2 = this.CanvasKit.RRectXY(this.CanvasKit.LTRBRect(x, y, width, height), 0, 0);
// // Drawing a shadow
// const paint3 = new this.CanvasKit.Paint();
// paint3.setColor(this.CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
// paint3.setStyle(this.CanvasKit.PaintStyle.Fill);
// const rr3 = this.CanvasKit.RRectXY(this.CanvasKit.LTRBRect(x, y, width, height), 0, 0);
// const drop = this.CanvasKit.ImageFilter.MakeDropShadow(4, 4, 4, 4,this.CanvasKit.MAGENTA, null);
// paint3.setImageFilter(drop)
// // Drawing a blur
// const paint4 = new this.CanvasKit.Paint();
// paint4.setColor(this.CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
// paint4.setStyle(this.CanvasKit.PaintStyle.Fill);
// const rr4 = this.CanvasKit.RRectXY(this.CanvasKit.LTRBRect(x, y, width, height), 0, 0);
// const blur = this.CanvasKit.ImageFilter.MakeBlur(4, 4, this.CanvasKit.TileMode.Decal, null);
// paint4.setImageFilter(blur)
// const self = this;
// function draw(canvas) {
// canvas.translate(- self.vbox.x, - self.vbox.y);
// // canvas.scale(kk3, kk3);
// for (const d of toDraw) {
// canvas.drawRRect(d, paint);
// }
// // canvas.drawRRect(rr2, paint2);
// // canvas.drawRRect(rr3, paint3);
// // canvas.drawRRect(rr4, paint4);
// paint.delete();
// // paint2.delete();
// // paint3.delete();
// // paint4.delete();
// }
// surface.drawOnce(draw);
}
}
export { CanvasKit };
export function init() {
return CanvasKitInit();
}
export function rect(CanvasKit, canvasId, x, y, width, height, kk1, kk2, kk3) {
surface = CanvasKit.MakeCanvasSurface(canvasId)
// Drawing a border
console.log("rect:", x, y, width, height)
const paint = new CanvasKit.Paint();
paint.setColor(CanvasKit.Color4f(0.9, 0, 0, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Stroke);
paint.setStrokeWidth(50.0);
// paint.setStrokeCap(CanvasKit.StrokeCap.Round);
paint.setAntiAlias(true);
const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, width, height), 0, 0);
// Drawing another border
const paint2 = new CanvasKit.Paint();
paint2.setColor(CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
paint2.setStyle(CanvasKit.PaintStyle.Stroke);
paint2.setStrokeWidth(25.0);
paint2.setAntiAlias(true);
const rr2 = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, width, height), 0, 0);
// Drawing a shadow
const paint3 = new CanvasKit.Paint();
paint3.setColor(CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
paint3.setStyle(CanvasKit.PaintStyle.Fill);
const rr3 = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, width, height), 0, 0);
const drop = CanvasKit.ImageFilter.MakeDropShadow(4, 4, 4, 4, CanvasKit.MAGENTA, null);
paint3.setImageFilter(drop)
// Drawing a blur
const paint4 = new CanvasKit.Paint();
paint4.setColor(CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
paint4.setStyle(CanvasKit.PaintStyle.Fill);
const rr4 = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, width, height), 0, 0);
const blur = CanvasKit.ImageFilter.MakeBlur(4, 4, CanvasKit.TileMode.Decal, null);
paint4.setImageFilter(blur)
function draw(canvas) {
canvas.translate(- kk1, - kk2);
// canvas.scale(kk3, kk3);
// canvas.drawRRect(rr, paint);
// canvas.drawRRect(rr2, paint2);
// canvas.drawRRect(rr3, paint3);
canvas.drawRRect(rr4, paint4);
paint.delete();
paint2.delete();
paint3.delete();
}
surface.drawOnce(draw);
}
export function path(CanvasKit, canvasId, x, y, content, kk1, kk2, kk3) {
// surface = CanvasKit.MakeCanvasSurface(canvasId)
console.log("path:", x, y, content)
surface = CanvasKit.MakeCanvasSurface(canvasId)
const paint = new CanvasKit.Paint();
paint.setStrokeWidth(1.0);
paint.setAntiAlias(true);
paint.setColor(CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Stroke);
const path = CanvasKit.Path.MakeFromSVGString(content);
function draw(canvas) {
canvas.translate(- kk1, - kk2);
// canvas.scale(kk3, kk3);
canvas.drawPath(path, paint);
paint.delete();
}
surface.drawOnce(draw);
}
// export function shadow(CanvasKit, canvasId, kk1, kk2, kk3) {
// console.log("CanvasKit", CanvasKit)
// console.log("CanvasKit.ImageFilter", CanvasKit.ImageFilter.MakeDropShadow())
// const paint = new CanvasKit.Paint();
// paint.setColor(CanvasKit.Color4f(0.9, 0, 1.0, 1.0));
// paint.setStyle(CanvasKit.PaintStyle.Fill);
// // var paint = SKPaint
// // {
// // Color = SKColors.Red,
// // Style = SKPaintStyle.Fill
// // };
// const drop = CanvasKit.ImageFilter.MakeDropShadow(0, 0, 4.0, 2.0, CanvasKit.MAGENTA, null);
// const paint = new CanvasKit.Paint();
// paint.setImageFilter(drop)
// }

View File

@@ -4167,6 +4167,13 @@ __metadata:
languageName: node
linkType: hard
"@webgpu/types@npm:0.1.21":
version: 0.1.21
resolution: "@webgpu/types@npm:0.1.21"
checksum: 74de9683b70064aeadcdd31381747650b323e7e2183fb38f90a35f1a79f80ad267c0a2ee5010c264befb3d31ad213dbdffa04897e2808f6b04feff8d66bc53e0
languageName: node
linkType: hard
"@xmldom/xmldom@npm:^0.8.3":
version: 0.8.10
resolution: "@xmldom/xmldom@npm:0.8.10"
@@ -5278,6 +5285,15 @@ __metadata:
languageName: node
linkType: hard
"canvaskit-wasm@npm:^0.39.1":
version: 0.39.1
resolution: "canvaskit-wasm@npm:0.39.1"
dependencies:
"@webgpu/types": "npm:0.1.21"
checksum: 0ae60ae5c430aaa88152f3a20f40fc9a6debb15714a2ce1bdebef93005ec6d5e72e0316b91ab637f50aab220dd8694101abac497209bcf16788d00db78f5a898
languageName: node
linkType: hard
"chalk@npm:^2.4.1, chalk@npm:^2.4.2":
version: 2.4.2
resolution: "chalk@npm:2.4.2"
@@ -7582,6 +7598,7 @@ __metadata:
"@storybook/testing-library": "npm:^0.2.2"
animate.css: "npm:^4.1.1"
autoprefixer: "npm:^10.4.15"
canvaskit-wasm: "npm:^0.39.1"
concurrently: "npm:^8.2.2"
date-fns: "npm:^2.30.0"
draft-js: "npm:^0.11.7"