Skip to content

Commit 07a19da

Browse files
committed
progress
1 parent 01b5581 commit 07a19da

File tree

7 files changed

+71
-12
lines changed

7 files changed

+71
-12
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@
3232
"cross-env": "^7.0.3",
3333
"npm-run-all": "^4.1.5",
3434
"raw-loader": "^4.0.2",
35-
"typescript": "^5.3.2"
35+
"typescript": "^5.7.3"
3636
}
3737
}

src/pg/inputPixelEditor/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ See usage for each method below.
4444
| `getLayers()` | - | Get layer array. |
4545
| `addLayer(option)` | - | Add layer. |
4646
| `removeLayer(index)` | - | Remove layer. |
47+
| `flattenLayers(layerIndexes)` | - | Flatten layers. |
4748
| `moveLayer(startIndex, endIndex)` | - | Move layer. |
4849
| `getColors()` | - | Get colors. |
4950
| `addColor(r, g, b, a)` | - | Add color. |

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ <h3>Layer Tools</h3>
5252
<button part="addLayer">Add Layer</button>
5353
<pre part="layers"></pre>
5454
</div>
55+
<div>
56+
<h3>Example Tools</h3>
57+
<input part="file" type="file" />
58+
<button part="saveSvg">Save SVG</button>
59+
<button part="savePng">Save Image</button>
60+
</div>
5561
<div part="debug"></div>
5662
<pre part="output" contenteditable></pre>
5763
</div>

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, Part } from '@pictogrammers/element';
22
import PgInputPixelEditor from '../../inputPixelEditor';
3+
import { maskToBitmap } from '../../utils/maskToBitmap';
34

45
import template from './basic.html';
56
import style from './basic.css';
@@ -33,6 +34,9 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
3334
@Part() $save: HTMLButtonElement;
3435
@Part() $open: HTMLButtonElement;
3536
@Part() $output: HTMLPreElement;
37+
@Part() $file: HTMLInputElement;
38+
@Part() $saveSvg: HTMLInputElement;
39+
@Part() $savePng: HTMLInputElement;
3640

3741
@Part() $colors: HTMLPreElement;
3842
@Part() $layers: HTMLPreElement;
@@ -83,6 +87,53 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
8387
const json = JSON.parse(this.$output.textContent || '');
8488
this.$input.open(json as any);
8589
});
90+
this.$file.addEventListener('change', this.handleFile.bind(this));
91+
this.$saveSvg.addEventListener('click', async () => {
92+
// @ts-ignore
93+
const handle = await window.showSaveFilePicker({
94+
suggestedName: 'CanvasName',
95+
types: [{
96+
description: 'SVG Document',
97+
accept: {'image/svg+xml': ['.svg']},
98+
}],
99+
});
100+
const writable = await handle.createWritable();
101+
await writable.write('something');
102+
await writable.close();
103+
});
104+
this.$savePng.addEventListener('click', () => {
105+
106+
});
107+
}
108+
109+
handleFile(e) {
110+
const { files } = e.currentTarget;
111+
if (files.length !== 1) {
112+
throw new Error('select only 1 file');
113+
}
114+
switch(files[0].type) {
115+
case 'image/svg+xml':
116+
// Read the file
117+
const reader = new FileReader();
118+
reader.onload = () => {
119+
const content = reader.result as string;
120+
const size = content.match(/viewBox="\d+ \d+ (\d+) (\d+)"/) as string[];
121+
const width = parseInt(size[1], 10);
122+
const height = parseInt(size[2], 10);
123+
const path = (content.match(/d="([^"]+)"/) as string[])[1];
124+
// Render path
125+
console.log(path, size[1], size[2]);
126+
this.$input.applyTemplate(maskToBitmap(path, width, height));
127+
;
128+
};
129+
reader.onerror = () => {
130+
throw new Error("Error reading the file. Please try again.");
131+
};
132+
reader.readAsText(files[0]);
133+
break;
134+
default:
135+
throw new Error('Unsupported format.');
136+
}
86137
}
87138

88139
handleChange(e: CustomEvent) {

src/pg/inputPixelEditor/inputPixelEditor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ export default class PgInputPixelEditor extends HTMLElement {
630630

631631
applyTemplate(template: number[][]) {
632632
this.#data = [template];
633+
this.#setPixelAll();
633634
}
634635

635636
flipHorizontal() {

src/pg/inputPixelEditor/utils/maskToBitmap.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
export function rasterizePath(pathData: string, width: number, height: number) {
2-
const grid: Number[][] = Array(height).fill(0).map(() => Array(width).fill(0));
1+
export function maskToBitmap(pathData: string, width: number, height: number) {
2+
const grid: number[][] = Array(height).fill(0).map(() => Array(width).fill(0));
33

44
// Store only the vertical edges
55
const verticalEdges: { x: number, y: number[] }[] = [];
@@ -11,7 +11,7 @@ export function rasterizePath(pathData: string, width: number, height: number) {
1111
let x;
1212
let y;
1313
// Split the path data into commands
14-
const commands = path.match(/[MHVZ][\d,]*/g) || [];
14+
const commands = path.match(/[MHVZ][\d, ]*/g) || [];
1515

1616
for (const cmd of commands) {
1717
const type = cmd[0];
@@ -20,7 +20,7 @@ export function rasterizePath(pathData: string, width: number, height: number) {
2020

2121
switch (type) {
2222
case 'M': {
23-
const [vX, vY] = value.split(',').map(v => parseInt(v, 10));
23+
const [vX, vY] = value.split(/,| /).map(v => parseInt(v, 10));
2424
x = vX;
2525
y = vY;
2626
x0 = vX;

0 commit comments

Comments
 (0)