Skip to content

Commit 01b5581

Browse files
committed
bug fixes
1 parent d24fb0c commit 01b5581

File tree

5 files changed

+112
-11
lines changed

5 files changed

+112
-11
lines changed

src/pg/inputPixelEditor/__examples__/basic/basic.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@
1717
label {
1818
display: flex;
1919
flex-direction: column;
20+
}
21+
22+
h3 {
23+
margin: 0.25rem 0;
24+
font-size: 1.125rem;
2025
}

src/pg/inputPixelEditor/__examples__/basic/basic.html

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</label>
1111
<label>
1212
Size
13-
<input part="size" type="range" min="4" max="16">
13+
<input part="size" type="range" step="2" min="4" max="16">
1414
</label>
1515
<label>
1616
<input part="transparent" type="checkbox">
@@ -24,24 +24,34 @@
2424
<div>
2525
<code>oninput: <span part="value2"></span></code>
2626
</div>
27-
2827
<div>
28+
<h3>Canvas Tools</h3>
2929
<button part="reset">Reset</button>
3030
<button part="clear">Clear</button>
3131
<button part="invert">Invert</button>
32+
|
33+
<button part="save">Save</button>
34+
<button part="open">Open</button>
35+
</div>
36+
<div>
37+
<h3>Drawing Tools</h3>
3238
<button part="modePixel">Pixel</button>
3339
<button part="modeLine">Line</button>
3440
<button part="modeRectangle">Rectangle</button>
3541
<button part="modeRectangleOutline">Rectangle Outline</button>
3642
<button part="modeEllipse">Ellipse</button>
3743
<button part="modeEllipseOutline">Ellipse Outline</button>
3844
</div>
39-
<div part="debug"></div>
4045
<div>
41-
<button part="save">Save</button>
42-
<button part="open">Open</button>
46+
<h3>Color Tools</h3>
47+
<button part="addColor">Add Color</button>
48+
<pre part="colors"></pre>
4349
</div>
44-
<pre part="output">
45-
46-
</pre>
50+
<div>
51+
<h3>Layer Tools</h3>
52+
<button part="addLayer">Add Layer</button>
53+
<pre part="layers"></pre>
54+
</div>
55+
<div part="debug"></div>
56+
<pre part="output" contenteditable></pre>
4757
</div>

src/pg/inputPixelEditor/__examples__/basic/basic.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
3434
@Part() $open: HTMLButtonElement;
3535
@Part() $output: HTMLPreElement;
3636

37+
@Part() $colors: HTMLPreElement;
38+
@Part() $layers: HTMLPreElement;
39+
3740
connectedCallback() {
3841
this.$width.value = '10';
3942
this.$height.value = '10';
@@ -77,7 +80,7 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
7780
this.$output.textContent = JSON.stringify(json, null, 4);
7881
});
7982
this.$open.addEventListener('click', () => {
80-
const json = this.$output.textContent;
83+
const json = JSON.parse(this.$output.textContent || '');
8184
this.$input.open(json as any);
8285
});
8386
}

src/pg/inputPixelEditor/inputPixelEditor.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ export default class PgInputPixelEditor extends HTMLElement {
196196
this.#baseLayerContext.fillStyle = WHITE;
197197
this.#baseLayerContext.fillRect(x * totalSize, y * totalSize, this.size + 1, this.size + 1);
198198
this.#baseLayerContext.fillStyle = '#DDD';
199-
this.#baseLayerContext.fillRect(x * totalSize + 5, y * totalSize, 5, 5);
200-
this.#baseLayerContext.fillRect(x * totalSize, y * totalSize + 5, 5, 5);
199+
this.#baseLayerContext.fillRect(x * totalSize + Math.ceil(this.size / 2), y * totalSize, Math.floor(this.size / 2), Math.floor(this.size / 2));
200+
this.#baseLayerContext.fillRect(x * totalSize, y * totalSize + Math.floor(this.size / 2), Math.ceil(this.size / 2), Math.ceil(this.size / 2));
201201
}
202202
}
203203
} else {
@@ -807,6 +807,9 @@ export default class PgInputPixelEditor extends HTMLElement {
807807
}
808808

809809
async open(json: File) {
810+
if (typeof json !== 'object') {
811+
return ['json must be type object'];
812+
}
810813
const errors: string[] = [];
811814
// Validate 6 properties exist
812815
const keys = Object.keys(json);
@@ -816,6 +819,20 @@ export default class PgInputPixelEditor extends HTMLElement {
816819
errors.push(`JSON key '${key}' required.`);
817820
}
818821
});
822+
// Set props
823+
this.width = json.width;
824+
this.height = json.height;
825+
this.transparent = json.transparent;
826+
this.#colors = json.colors;
827+
this.#layers = json.layers;
828+
this.#data = json.data;
829+
if (json.undo) {
830+
this.#undoHistory = json.undo;
831+
}
832+
if (json.redo) {
833+
this.#redoHistory = json.redo;
834+
}
835+
this.#init();
819836
}
820837

821838
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
export function rasterizePath(pathData: string, width: number, height: number) {
2+
const grid: Number[][] = Array(height).fill(0).map(() => Array(width).fill(0));
3+
4+
// Store only the vertical edges
5+
const verticalEdges: { x: number, y: number[] }[] = [];
6+
7+
const paths = pathData.match(/M[^Z]*Z/g) || [];
8+
for (const path of paths) {
9+
let x0;
10+
let y0;
11+
let x;
12+
let y;
13+
// Split the path data into commands
14+
const commands = path.match(/[MHVZ][\d,]*/g) || [];
15+
16+
for (const cmd of commands) {
17+
const type = cmd[0];
18+
const value = cmd.slice(1);
19+
let newY;
20+
21+
switch (type) {
22+
case 'M': {
23+
const [vX, vY] = value.split(',').map(v => parseInt(v, 10));
24+
x = vX;
25+
y = vY;
26+
x0 = vX;
27+
y0 = vY;
28+
break;
29+
}
30+
case 'H':
31+
x = parseInt(value, 10);
32+
break;
33+
case 'V':
34+
newY = parseInt(value, 10);
35+
verticalEdges.push({ x, y: [y, newY].sort((a, b) => a - b) });
36+
y = newY;
37+
break;
38+
case 'Z':
39+
if (x0 === x) {
40+
verticalEdges.push({ x, y: [y, y0].sort((a, b) => a - b) });
41+
}
42+
break;
43+
}
44+
}
45+
}
46+
47+
// Fill the shape using scan-line algorithm
48+
for (let y = 0; y < height; ++y) {
49+
let inside = false;
50+
51+
for (let x = 0; x < width; ++x) {
52+
// Check if we cross a vertical edge
53+
for (const verticalEdge of verticalEdges) {
54+
if (verticalEdge.x === x && y >= verticalEdge.y[0] && y < verticalEdge.y[1]) {
55+
inside = !inside;
56+
break;
57+
}
58+
}
59+
if (inside) {
60+
grid[y][x] = 1;
61+
}
62+
}
63+
}
64+
65+
return grid;
66+
}

0 commit comments

Comments
 (0)