Skip to content

Commit

Permalink
fix: opacity render wrong (fix #204)
Browse files Browse the repository at this point in the history
  • Loading branch information
F-star committed Nov 15, 2024
1 parent 7a7d971 commit 04da2ca
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 178 deletions.
2 changes: 2 additions & 0 deletions packages/core/src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ export class SuikaEditor {
width: 0,
height: 0,
});
this.doc.setEditor(this);

this.sceneGraph = new SceneGraph(this);

this.cursorManager = new CursorManger(this);
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/graphics/document.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EventEmitter, throttle } from '@suika/common';

import { type SuikaEditor } from '../editor';
import { GraphicsStoreManager } from '../graphics_manger';
import { GraphicsType, type Optional } from '../type';
import {
Expand Down Expand Up @@ -34,10 +35,16 @@ export class SuikaDocument extends SuikaGraphics<SuikaCanvasAttrs> {
updatedIds: new Set<string>(),
};

private editor!: SuikaEditor;

constructor(attrs: Optional<SuikaCanvasAttrs, 'id' | 'transform'>) {
super({ ...attrs, type: GraphicsType.Document }, {} as IGraphicsOpts);
}

setEditor(editor: SuikaEditor) {
this.editor = editor;
}

clear() {
// TODO: update doc.updateInfo
this.graphicsStoreManager.clear();
Expand Down Expand Up @@ -131,6 +138,14 @@ export class SuikaDocument extends SuikaGraphics<SuikaCanvasAttrs> {
// { leading: false },
);

getDeviceViewSize() {
const canvasEl = this.editor.canvasElement;
return {
width: canvasEl.width,
height: canvasEl.height,
};
}

on<T extends keyof Events>(eventName: T, listener: Events[T]) {
this.emitter.on(eventName, listener);
}
Expand Down
67 changes: 45 additions & 22 deletions packages/core/src/graphics/ellipse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
SuikaGraphics,
} from './graphics';
import { type IDrawInfo } from './type';
import { drawLayer } from './utils';

export type EllipseAttrs = GraphicsAttrs;

Expand Down Expand Up @@ -55,35 +56,57 @@ export class SuikaEllipse extends SuikaGraphics<EllipseAttrs> {
if (opacity < 1) {
ctx.globalAlpha = opacity;
}
ctx.beginPath();
ctx.ellipse(cx, cy, attrs.width / 2, attrs.height / 2, 0, 0, DOUBLE_PI);
for (const paint of attrs.fill ?? []) {
if (paint.type === PaintType.Solid) {
ctx.fillStyle = parseRGBAStr(paint.attrs);
ctx.fill();
} else if (paint.type === PaintType.Image) {
if (imgManager) {
ctx.clip();
this.fillImage(ctx, paint, imgManager, smooth);
} else {
console.warn('ImgManager is not provided');
}
}
}

if (attrs.strokeWidth) {
ctx.lineWidth = attrs.strokeWidth;
for (const paint of attrs.stroke ?? []) {
const draw = (layerCtx: CanvasRenderingContext2D) => {
layerCtx.beginPath();
layerCtx.ellipse(
cx,
cy,
attrs.width / 2,
attrs.height / 2,
0,
0,
DOUBLE_PI,
);
for (const paint of attrs.fill ?? []) {
if (paint.type === PaintType.Solid) {
ctx.strokeStyle = parseRGBAStr(paint.attrs);
ctx.stroke();
layerCtx.fillStyle = parseRGBAStr(paint.attrs);
layerCtx.fill();
} else if (paint.type === PaintType.Image) {
// TODO:
if (imgManager) {
layerCtx.clip();
this.fillImage(layerCtx, paint, imgManager, smooth);
} else {
console.warn('ImgManager is not provided');
}
}
}

if (attrs.strokeWidth) {
layerCtx.lineWidth = attrs.strokeWidth;
for (const paint of attrs.stroke ?? []) {
if (paint.type === PaintType.Solid) {
layerCtx.strokeStyle = parseRGBAStr(paint.attrs);
layerCtx.stroke();
} else if (paint.type === PaintType.Image) {
// TODO:
}
}
}

layerCtx.closePath();
};

if (opacity !== 1) {
drawLayer({
originCtx: ctx,
viewSize: this.doc.getDeviceViewSize(),
draw,
});
} else {
draw(ctx);
}

ctx.closePath();
ctx.restore();
}

Expand Down
122 changes: 68 additions & 54 deletions packages/core/src/graphics/path/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
SuikaGraphics,
} from '../graphics';
import { type IDrawInfo } from '../type';
import { drawLayer } from '../utils';

export interface PathAttrs extends GraphicsAttrs {
pathData: IPathItem[];
Expand Down Expand Up @@ -224,74 +225,87 @@ export class SuikaPath extends SuikaGraphics<PathAttrs> {
if (opacity < 1) {
ctx.globalAlpha = opacity;
}
ctx.beginPath();
for (const pathItem of pathData) {
const first = pathItem.segs[0];
if (!first) continue;
ctx.moveTo(first.point.x, first.point.y);

const segs = pathItem.segs;
for (let i = 1; i <= segs.length; i++) {
if (i === segs.length && !pathItem.closed) {
continue;
}
const currSeg = segs[i % segs.length];
const prevSeg = segs[i - 1];
const pointX = currSeg.point.x;
const pointY = currSeg.point.y;
const handle1 = SuikaPath.getHandleOut(prevSeg);
const handle2 = SuikaPath.getHandleIn(currSeg);
if (!handle1 && !handle2) {
ctx.lineTo(pointX, pointY);
} else {
ctx.bezierCurveTo(
handle1.x,
handle1.y,
handle2.x,
handle2.y,
pointX,
pointY,
);
}
}
if (pathItem.closed) {
ctx.closePath();
}
}

for (const paint of fill ?? []) {
switch (paint.type) {
case PaintType.Solid: {
ctx.fillStyle = parseRGBAStr(paint.attrs);
ctx.fill();
break;
}
case PaintType.Image: {
if (imgManager) {
ctx.clip();
this.fillImage(ctx, paint, imgManager, smooth);
const draw = (layerCtx: CanvasRenderingContext2D) => {
layerCtx.beginPath();
for (const pathItem of pathData) {
const first = pathItem.segs[0];
if (!first) continue;
layerCtx.moveTo(first.point.x, first.point.y);

const segs = pathItem.segs;
for (let i = 1; i <= segs.length; i++) {
if (i === segs.length && !pathItem.closed) {
continue;
}
const currSeg = segs[i % segs.length];
const prevSeg = segs[i - 1];
const pointX = currSeg.point.x;
const pointY = currSeg.point.y;
const handle1 = SuikaPath.getHandleOut(prevSeg);
const handle2 = SuikaPath.getHandleIn(currSeg);
if (!handle1 && !handle2) {
layerCtx.lineTo(pointX, pointY);
} else {
console.warn('ImgManager is not provided');
layerCtx.bezierCurveTo(
handle1.x,
handle1.y,
handle2.x,
handle2.y,
pointX,
pointY,
);
}
}
if (pathItem.closed) {
layerCtx.closePath();
}
}
}
if (strokeWidth) {
ctx.lineWidth = strokeWidth;
for (const paint of stroke ?? []) {

for (const paint of fill ?? []) {
switch (paint.type) {
case PaintType.Solid: {
ctx.strokeStyle = parseRGBAStr(paint.attrs);
ctx.stroke();
layerCtx.fillStyle = parseRGBAStr(paint.attrs);
layerCtx.fill();
break;
}
case PaintType.Image: {
// TODO: stroke image
if (imgManager) {
layerCtx.clip();
this.fillImage(layerCtx, paint, imgManager, smooth);
} else {
console.warn('ImgManager is not provided');
}
}
}
}
if (strokeWidth) {
layerCtx.lineWidth = strokeWidth;
for (const paint of stroke ?? []) {
switch (paint.type) {
case PaintType.Solid: {
layerCtx.strokeStyle = parseRGBAStr(paint.attrs);
layerCtx.stroke();
break;
}
case PaintType.Image: {
// TODO: stroke image
}
}
}
}
layerCtx.closePath();
};

if (opacity !== 1) {
drawLayer({
originCtx: ctx,
viewSize: this.doc.getDeviceViewSize(),
draw,
});
} else {
draw(ctx);
}
ctx.closePath();
ctx.restore();
}

Expand Down
Loading

0 comments on commit 04da2ca

Please sign in to comment.