@lvl99dotcom/paintcanvas 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/lib/classes/PaintCanvas/index.d.ts +13 -5
- package/dist/lib/classes/PaintCanvas/index.js +10 -6
- package/dist/lib/classes/UiSettings/index.d.ts +24 -2
- package/dist/lib/classes/UiSettings/index.js +32 -7
- package/dist/lib/settings/schema.d.ts +4 -1
- package/dist/lib/settings/schema.js +3 -2
- package/dist/lib/storage/index.d.ts +26 -0
- package/dist/lib/storage/index.js +38 -1
- package/dist/lib/validation/validators.generated.js +20 -2
- package/dist/lib/version/index.d.ts +25 -0
- package/dist/lib/version/index.js +35 -0
- package/dist/locales/en-GB.js +5 -0
- package/dist/locales/en-US.js +5 -0
- package/dist/locales/fr.js +5 -0
- package/dist/locales/ja.js +5 -0
- package/dist/locales/ko.js +5 -0
- package/dist/locales/zh-Hans.js +5 -0
- package/dist/locales/zh-Hant.js +5 -0
- package/dist/package.js +1 -1
- package/dist/ui/elements/PaintCanvas/index.d.ts +13 -3
- package/dist/ui/elements/PaintCanvas/index.js +22 -5
- package/dist/ui/elements/PcAppSettings/index.d.ts +10 -2
- package/dist/ui/elements/PcAppSettings/index.js +42 -7
- package/dist/ui/elements/PcBrushConfig/index.d.ts +1 -0
- package/dist/ui/elements/PcBrushConfig/index.js +8 -9
- package/dist/ui/elements/PcBrushTest/index.d.ts +1 -0
- package/dist/ui/elements/PcBrushTest/index.js +8 -7
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcButtonMenu/index.d.ts +88 -0
- package/dist/ui/elements/PcButtonMenu/index.js +125 -0
- package/dist/ui/elements/PcCanvas/index.d.ts +9 -0
- package/dist/ui/elements/PcCanvas/index.js +33 -17
- package/dist/ui/elements/PcClipboardTools/index.d.ts +7 -4
- package/dist/ui/elements/PcClipboardTools/index.js +20 -26
- package/dist/ui/elements/PcInputSettings/index.d.ts +2 -1
- package/dist/ui/elements/PcInputSettings/index.js +9 -15
- package/dist/ui/elements/PcLayerItem/index.d.ts +21 -6
- package/dist/ui/elements/PcLayerItem/index.js +53 -26
- package/dist/ui/elements/PcLayerItem/style.js +1 -1
- package/dist/ui/elements/PcSliderRange/index.js +3 -2
- package/dist/ui/elements/PcToggleCheckbox/index.d.ts +13 -2
- package/dist/ui/elements/PcToggleCheckbox/index.js +27 -8
- package/dist/ui/elements/PcToolSettings/index.d.ts +1 -0
- package/dist/ui/elements/PcToolSettings/index.js +8 -8
- package/dist/ui/elements/PcVersion/index.d.ts +12 -0
- package/dist/ui/elements/PcVersion/index.js +43 -0
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.js +4 -2
- package/dist/ui/layout/index.d.ts +2 -2
- package/dist/ui/layout/index.js +2 -2
- package/locales/en-GB.json +5 -0
- package/locales/en-US.json +5 -0
- package/locales/fr.json +5 -0
- package/locales/ja.json +5 -0
- package/locales/ko.json +5 -0
- package/locales/zh-Hans.json +5 -0
- package/locales/zh-Hant.json +5 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -89,9 +89,9 @@ The demo is published at https://lvl99.github.io/paintcanvas/app/. To run it loc
|
|
|
89
89
|
pnpm dev
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Starts a development server and opens the demo in your browser. It uses the source directly, so saving a change to `src/`, `demo/` or `locales/` reloads the page with the change straight away. (The whole page reloads because custom elements can't be redefined in a running page, so the drawing starts again.)
|
|
92
|
+
Starts a development server and opens the demo in your browser. It uses the source directly, so saving a change to `src/`, `demo/` or `locales/` reloads the page with the change straight away. (The whole page reloads because custom elements can't be redefined in a running page, so the drawing starts again.) It uses vite.demo.config.ts, which also gives the demo the commit it was built from (see scripts/build-info.ts).
|
|
93
93
|
|
|
94
|
-
- http://localhost:5190/: a full-page PaintCanvas with a layers panel, the colour palette (from the colours at the top of the toolbar), a menu with input settings, keyboard shortcuts, settings import and export, a theme picker (light, dark or system) and a "New drawing" button. The drawing and the settings, including the theme and
|
|
94
|
+
- http://localhost:5190/: a full-page PaintCanvas with a layers panel, the colour palette (from the colours at the top of the toolbar), a menu with PaintCanvas's version, input settings, a "Draw with the GPU" switch, keyboard shortcuts, settings import and export, a theme picker (light, dark or system) and a "New drawing" button. The drawing and the settings, including the theme, language and rendering (CPU or GPU), are kept in the browser, so they survive reloads. Below 600px wide, the toolbar and the layers rail sit over the canvas.
|
|
95
95
|
- http://localhost:5190/elements.html: the base elements.
|
|
96
96
|
|
|
97
97
|
To try it with a pen or touch on another device (e.g. a tablet) on the same network, run `pnpm dev --host` and open the network address it prints. This makes the server reachable by anyone on that network.
|
|
@@ -18,7 +18,7 @@ import type { LayerStoreLike } from "../../storage";
|
|
|
18
18
|
import type { AssetAuthor, BrushConfig } from "../../brushes/types";
|
|
19
19
|
import CustomPresets, { type PresetStoreLike } from "../CustomPresets";
|
|
20
20
|
import InputSettings from "../InputSettings";
|
|
21
|
-
import UiSettings from "../UiSettings";
|
|
21
|
+
import UiSettings, { type Rendering } from "../UiSettings";
|
|
22
22
|
import Palette from "../Palette";
|
|
23
23
|
import ProfileGraphs from "../ProfileGraphs";
|
|
24
24
|
import ShortcutSettings from "../ShortcutSettings";
|
|
@@ -116,9 +116,15 @@ export interface PaintCanvasOptions {
|
|
|
116
116
|
/** Most layers the user can have (default `DEFAULT_MAX_LAYERS`) */
|
|
117
117
|
maxLayers?: number;
|
|
118
118
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
119
|
+
* Where the canvases draw (`cpu` by default): `cpu` keeps their pixels in regular memory (`createMemoryCanvas`) so
|
|
120
|
+
* saving and copying don't stall phones; `gpu` asks the browser to keep them on the GPU (`createOffscreenCanvas`).
|
|
121
|
+
* Browsers fix this when a canvas is made, so it can't change while the canvas runs: to follow the user's choice
|
|
122
|
+
* (`ui.data.rendering`), pass the one they made last time (`<paint-canvas>` does this with its `settings-store`).
|
|
123
|
+
*/
|
|
124
|
+
rendering?: Rendering;
|
|
125
|
+
/**
|
|
126
|
+
* Creates the canvases the engine draws in: layers, stroke buffers, masks and copies. Chosen by `rendering` unless
|
|
127
|
+
* given (replaceable for tests).
|
|
122
128
|
*/
|
|
123
129
|
createCanvas?: CanvasFactory;
|
|
124
130
|
/** Where custom brush presets are kept (defaults to keeping them in memory only) */
|
|
@@ -172,7 +178,7 @@ export default class PaintCanvas extends EventTarget {
|
|
|
172
178
|
readonly background: BackgroundWork;
|
|
173
179
|
/** How the user's input devices control the canvas (scrolling, pinching, touch gestures, focus pen mode) */
|
|
174
180
|
readonly input: InputSettings;
|
|
175
|
-
/** The user's interface choices (theme and
|
|
181
|
+
/** The user's interface choices (theme, language and where canvases draw), kept with the other app settings */
|
|
176
182
|
readonly ui: UiSettings;
|
|
177
183
|
/** The user's saved colours, shown as swatches */
|
|
178
184
|
readonly palette: Palette;
|
|
@@ -233,6 +239,8 @@ export default class PaintCanvas extends EventTarget {
|
|
|
233
239
|
/** The layer stack whose changes are being sent */
|
|
234
240
|
private sendingLayers?;
|
|
235
241
|
private readonly onLayersChangeToSend;
|
|
242
|
+
/** Where the canvases draw, chosen when the canvas started (the user's choice for next time is `ui.data.rendering`) */
|
|
243
|
+
readonly rendering: Rendering;
|
|
236
244
|
/** Creates the canvases the app draws on (fake ones in tests) */
|
|
237
245
|
readonly createCanvas: CanvasFactory;
|
|
238
246
|
/** Who the custom presets belong to (passed to the preset store) */
|
|
@@ -11,15 +11,15 @@ import Selection from "../../selection/Selection/index.js";
|
|
|
11
11
|
import Lasso from "../../selection/Lasso/index.js";
|
|
12
12
|
import Transformer, { applyMask, contentBounds, copyArea, drawTransformed } from "../../transform/Transformer/index.js";
|
|
13
13
|
import { boxBounds } from "../../transform/geometry/index.js";
|
|
14
|
-
import Layer, { createMemoryCanvas } from "../Layer/index.js";
|
|
14
|
+
import Layer, { createMemoryCanvas, createOffscreenCanvas } from "../Layer/index.js";
|
|
15
15
|
import LayerAutosave from "../LayerAutosave/index.js";
|
|
16
16
|
import { brushPresets, eraserPresets } from "../../brushes/index.js";
|
|
17
17
|
import { BUILT_IN_AUTHOR, UNKNOWN_AUTHOR, authorHandle } from "../../brushes/authors/index.js";
|
|
18
18
|
import "../../presets/index.js";
|
|
19
|
-
import { BRUSH_PRESET_FILE_FORMAT } from "../../presets/schema.js";
|
|
20
19
|
import CustomPresets from "../CustomPresets/index.js";
|
|
20
|
+
import { BRUSH_PRESET_FILE_FORMAT } from "../../presets/schema.js";
|
|
21
21
|
import InputSettings from "../InputSettings/index.js";
|
|
22
|
-
import UiSettings from "../UiSettings/index.js";
|
|
22
|
+
import UiSettings, { DEFAULT_UI_SETTINGS } from "../UiSettings/index.js";
|
|
23
23
|
import Palette from "../Palette/index.js";
|
|
24
24
|
import { PALETTE_FILE_FORMAT } from "../../palette/schema.js";
|
|
25
25
|
import ProfileGraphs from "../ProfileGraphs/index.js";
|
|
@@ -127,8 +127,8 @@ var PaintCanvas = class extends EventTarget {
|
|
|
127
127
|
background = new BackgroundWork(this.strokeLog);
|
|
128
128
|
/** How the user's input devices control the canvas (scrolling, pinching, touch gestures, focus pen mode) */
|
|
129
129
|
input = new InputSettings();
|
|
130
|
-
/** The user's interface choices (theme and
|
|
131
|
-
ui
|
|
130
|
+
/** The user's interface choices (theme, language and where canvases draw), kept with the other app settings */
|
|
131
|
+
ui;
|
|
132
132
|
/** The user's saved colours, shown as swatches */
|
|
133
133
|
palette = new Palette();
|
|
134
134
|
/** The user's own profile graphs (and the presets), for shaping how brush settings vary */
|
|
@@ -212,6 +212,8 @@ var PaintCanvas = class extends EventTarget {
|
|
|
212
212
|
/** The layer stack whose changes are being sent */
|
|
213
213
|
sendingLayers;
|
|
214
214
|
onLayersChangeToSend = () => this.sender?.schedule();
|
|
215
|
+
/** Where the canvases draw, chosen when the canvas started (the user's choice for next time is `ui.data.rendering`) */
|
|
216
|
+
rendering;
|
|
215
217
|
/** Creates the canvases the app draws on (fake ones in tests) */
|
|
216
218
|
createCanvas;
|
|
217
219
|
/** Who the custom presets belong to (passed to the preset store) */
|
|
@@ -242,7 +244,9 @@ var PaintCanvas = class extends EventTarget {
|
|
|
242
244
|
this.customPresets = new CustomPresets(this.ownerId, options.presetStore);
|
|
243
245
|
this.customPresets.addEventListener("change", () => this.listCustomPresets());
|
|
244
246
|
this.customPresets.load().catch(() => void 0);
|
|
245
|
-
this.
|
|
247
|
+
this.rendering = options.rendering ?? DEFAULT_UI_SETTINGS.rendering;
|
|
248
|
+
this.ui = new UiSettings({ rendering: this.rendering });
|
|
249
|
+
this.createCanvas = options.createCanvas ?? (this.rendering === "gpu" ? createOffscreenCanvas : createMemoryCanvas);
|
|
246
250
|
this.systemClipboard = options.systemClipboard === null ? void 0 : options.systemClipboard ?? globalThis.navigator?.clipboard;
|
|
247
251
|
this.canvasWidth = DEFAULT_CANVAS_SIZE;
|
|
248
252
|
this.canvasHeight = DEFAULT_CANVAS_SIZE;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/** The themes: light, dark, or following the device's (system) */
|
|
2
2
|
export declare const THEMES: readonly ["light", "dark", "system"];
|
|
3
3
|
export type Theme = (typeof THEMES)[number];
|
|
4
|
+
/**
|
|
5
|
+
* Where canvases draw: `cpu` keeps their pixels in regular memory (reading and saving them never waits for the GPU),
|
|
6
|
+
* `gpu` asks the browser to keep them on the GPU (drawing may be quicker; the browser can still use the CPU)
|
|
7
|
+
*/
|
|
8
|
+
export declare const RENDERINGS: readonly ["cpu", "gpu"];
|
|
9
|
+
export type Rendering = (typeof RENDERINGS)[number];
|
|
4
10
|
/** Longest locale tag kept in UI settings (characters) */
|
|
5
11
|
export declare const MAX_LOCALE_LENGTH = 35;
|
|
6
12
|
/** A locale tag's characters: letters, digits and hyphens (e.g. `zh-Hant`) */
|
|
@@ -13,6 +19,14 @@ export declare const LOCALE_PATTERN = "^[A-Za-z0-9-]+$";
|
|
|
13
19
|
* isTheme(undefined); // false
|
|
14
20
|
*/
|
|
15
21
|
export declare const isTheme: (value: unknown) => value is Theme;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a value is one of the renderings.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* isRendering("gpu"); // true
|
|
27
|
+
* isRendering("webgl"); // false
|
|
28
|
+
*/
|
|
29
|
+
export declare const isRendering: (value: unknown) => value is Rendering;
|
|
16
30
|
/**
|
|
17
31
|
* Whether a value can be a locale tag (letters, digits and hyphens, at most `MAX_LOCALE_LENGTH` characters).
|
|
18
32
|
*
|
|
@@ -27,7 +41,14 @@ export interface UiSettingsData {
|
|
|
27
41
|
theme: Theme;
|
|
28
42
|
/** The language's locale tag, e.g. `fr`, or undefined to follow the device's languages */
|
|
29
43
|
locale?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Where canvases draw (`cpu` by default). Browsers fix this when a canvas is made, so a change applies the next time
|
|
46
|
+
* the canvas starts (e.g. after reloading the page; see `PaintCanvasOptions.rendering`).
|
|
47
|
+
*/
|
|
48
|
+
rendering: Rendering;
|
|
30
49
|
}
|
|
50
|
+
/** UI settings used for anything not given */
|
|
51
|
+
export declare const DEFAULT_UI_SETTINGS: Readonly<UiSettingsData>;
|
|
31
52
|
/** UI settings the UI can show and change: PaintCanvas's `UiSettings`, or anything with the same data and `update` */
|
|
32
53
|
export interface UiSettingsLike extends EventTarget {
|
|
33
54
|
readonly data: Readonly<UiSettingsData>;
|
|
@@ -38,11 +59,12 @@ export interface UiSettingsLike extends EventTarget {
|
|
|
38
59
|
* or invalid. Other properties are left out.
|
|
39
60
|
*
|
|
40
61
|
* @example
|
|
41
|
-
* sanitiseUiSettings({ theme: "dark", locale: 42 }, { theme: "system"
|
|
62
|
+
* sanitiseUiSettings({ theme: "dark", locale: 42 }, { theme: "system", rendering: "cpu" });
|
|
63
|
+
* // { theme: "dark", rendering: "cpu" }
|
|
42
64
|
*/
|
|
43
65
|
export declare const sanitiseUiSettings: (input: unknown, defaults: UiSettingsData) => UiSettingsData;
|
|
44
66
|
/**
|
|
45
|
-
* The user's interface choices: the theme and
|
|
67
|
+
* The user's interface choices: the theme, the language and where canvases draw. Kept in memory; the implementer saves and restores them
|
|
46
68
|
* with the other app settings (see `SettingsAutosave`), and the UI shows and applies them (e.g. `<pc-theme-picker>` and
|
|
47
69
|
* `<pc-input-settings>`).
|
|
48
70
|
*
|
|
@@ -5,6 +5,11 @@ var THEMES = [
|
|
|
5
5
|
"dark",
|
|
6
6
|
"system"
|
|
7
7
|
];
|
|
8
|
+
/**
|
|
9
|
+
* Where canvases draw: `cpu` keeps their pixels in regular memory (reading and saving them never waits for the GPU),
|
|
10
|
+
* `gpu` asks the browser to keep them on the GPU (drawing may be quicker; the browser can still use the CPU)
|
|
11
|
+
*/
|
|
12
|
+
var RENDERINGS = ["cpu", "gpu"];
|
|
8
13
|
/** Longest locale tag kept in UI settings (characters) */
|
|
9
14
|
var MAX_LOCALE_LENGTH = 35;
|
|
10
15
|
/** A locale tag's characters: letters, digits and hyphens (e.g. `zh-Hant`) */
|
|
@@ -18,6 +23,14 @@ var LOCALE_PATTERN = "^[A-Za-z0-9-]+$";
|
|
|
18
23
|
*/
|
|
19
24
|
var isTheme = (value) => THEMES.includes(value);
|
|
20
25
|
/**
|
|
26
|
+
* Whether a value is one of the renderings.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* isRendering("gpu"); // true
|
|
30
|
+
* isRendering("webgl"); // false
|
|
31
|
+
*/
|
|
32
|
+
var isRendering = (value) => RENDERINGS.includes(value);
|
|
33
|
+
/**
|
|
21
34
|
* Whether a value can be a locale tag (letters, digits and hyphens, at most `MAX_LOCALE_LENGTH` characters).
|
|
22
35
|
*
|
|
23
36
|
* @example
|
|
@@ -25,24 +38,35 @@ var isTheme = (value) => THEMES.includes(value);
|
|
|
25
38
|
* isLocaleTag("<script>"); // false
|
|
26
39
|
*/
|
|
27
40
|
var isLocaleTag = (value) => typeof value === "string" && value.length <= 35 && (/* @__PURE__ */ new RegExp("^[A-Za-z0-9-]+$")).test(value);
|
|
41
|
+
/** UI settings used for anything not given */
|
|
42
|
+
var DEFAULT_UI_SETTINGS = {
|
|
43
|
+
theme: "system",
|
|
44
|
+
rendering: "cpu"
|
|
45
|
+
};
|
|
28
46
|
/**
|
|
29
47
|
* Keep only valid UI settings from an untrusted value (e.g. stored or imported), using `defaults` for anything missing
|
|
30
48
|
* or invalid. Other properties are left out.
|
|
31
49
|
*
|
|
32
50
|
* @example
|
|
33
|
-
* sanitiseUiSettings({ theme: "dark", locale: 42 }, { theme: "system"
|
|
51
|
+
* sanitiseUiSettings({ theme: "dark", locale: 42 }, { theme: "system", rendering: "cpu" });
|
|
52
|
+
* // { theme: "dark", rendering: "cpu" }
|
|
34
53
|
*/
|
|
35
54
|
var sanitiseUiSettings = (input, defaults) => {
|
|
36
55
|
const value = typeof input === "object" && input !== null ? input : {};
|
|
37
56
|
const theme = isTheme(value.theme) ? value.theme : defaults.theme;
|
|
38
57
|
const locale = isLocaleTag(value.locale) ? value.locale : defaults.locale;
|
|
39
|
-
|
|
58
|
+
const rendering = isRendering(value.rendering) ? value.rendering : defaults.rendering;
|
|
59
|
+
return locale === void 0 ? {
|
|
60
|
+
theme,
|
|
61
|
+
rendering
|
|
62
|
+
} : {
|
|
40
63
|
theme,
|
|
41
|
-
locale
|
|
64
|
+
locale,
|
|
65
|
+
rendering
|
|
42
66
|
};
|
|
43
67
|
};
|
|
44
68
|
/**
|
|
45
|
-
* The user's interface choices: the theme and
|
|
69
|
+
* The user's interface choices: the theme, the language and where canvases draw. Kept in memory; the implementer saves and restores them
|
|
46
70
|
* with the other app settings (see `SettingsAutosave`), and the UI shows and applies them (e.g. `<pc-theme-picker>` and
|
|
47
71
|
* `<pc-input-settings>`).
|
|
48
72
|
*
|
|
@@ -57,7 +81,7 @@ var UiSettings = class extends EventTarget {
|
|
|
57
81
|
values;
|
|
58
82
|
constructor(initial) {
|
|
59
83
|
super();
|
|
60
|
-
this.values = sanitiseUiSettings(initial,
|
|
84
|
+
this.values = sanitiseUiSettings(initial, DEFAULT_UI_SETTINGS);
|
|
61
85
|
}
|
|
62
86
|
/** Current settings (read-only copy) */
|
|
63
87
|
get data() {
|
|
@@ -74,9 +98,10 @@ var UiSettings = class extends EventTarget {
|
|
|
74
98
|
...this.values,
|
|
75
99
|
...changes
|
|
76
100
|
}, this.values);
|
|
77
|
-
|
|
101
|
+
const keys = Object.keys(next);
|
|
102
|
+
if (keys.length === Object.keys(this.values).length && keys.every((key) => next[key] === this.values[key])) return;
|
|
78
103
|
this.values = next;
|
|
79
104
|
this.dispatchEvent(new Event("change"));
|
|
80
105
|
}
|
|
81
106
|
};
|
|
82
|
-
export { LOCALE_PATTERN, MAX_LOCALE_LENGTH, THEMES, UiSettings as default, isLocaleTag, isTheme, sanitiseUiSettings };
|
|
107
|
+
export { DEFAULT_UI_SETTINGS, LOCALE_PATTERN, MAX_LOCALE_LENGTH, RENDERINGS, THEMES, UiSettings as default, isLocaleTag, isRendering, isTheme, sanitiseUiSettings };
|
|
@@ -27,7 +27,7 @@ export interface AppSettings {
|
|
|
27
27
|
};
|
|
28
28
|
/** The user's own profile graphs */
|
|
29
29
|
profiles?: ProfileGraph[];
|
|
30
|
-
/** The theme and
|
|
30
|
+
/** The theme, language and where canvases draw */
|
|
31
31
|
ui?: Partial<UiSettingsData>;
|
|
32
32
|
}
|
|
33
33
|
/** A settings file: what users export and import */
|
|
@@ -191,6 +191,9 @@ export declare const settingsSchema: {
|
|
|
191
191
|
readonly maxLength: 35;
|
|
192
192
|
readonly pattern: "^[A-Za-z0-9-]+$";
|
|
193
193
|
};
|
|
194
|
+
readonly rendering: {
|
|
195
|
+
readonly enum: readonly ["cpu", "gpu"];
|
|
196
|
+
};
|
|
194
197
|
};
|
|
195
198
|
};
|
|
196
199
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LOCALE_PATTERN, THEMES } from "../classes/UiSettings/index.js";
|
|
1
|
+
import { LOCALE_PATTERN, RENDERINGS, THEMES } from "../classes/UiSettings/index.js";
|
|
2
2
|
import { HEX_COLOUR_PATTERN, MAX_PALETTE_COLOURS, paletteFileSchema } from "../palette/schema.js";
|
|
3
3
|
import { profileGraphSchema } from "../profiles/schema.js";
|
|
4
4
|
// src/lib/settings/schema.ts
|
|
@@ -94,7 +94,8 @@ var settingsSchema = {
|
|
|
94
94
|
minLength: 1,
|
|
95
95
|
maxLength: 35,
|
|
96
96
|
pattern: LOCALE_PATTERN
|
|
97
|
-
}
|
|
97
|
+
},
|
|
98
|
+
rendering: { enum: RENDERINGS }
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LayerConfig } from "../classes/Layer";
|
|
2
2
|
import type { AppSettings } from "../settings/schema";
|
|
3
|
+
import { type Rendering } from "../classes/UiSettings";
|
|
3
4
|
/** Version of a saved drawing's shape, so drawings saved by other versions can be recognised */
|
|
4
5
|
export declare const SAVED_DRAWING_VERSION = 1;
|
|
5
6
|
/** Name of the IndexedDB database `IndexedDbLayerStore` keeps drawings in, and `IndexedDbSettingsStore` settings */
|
|
@@ -92,3 +93,28 @@ export declare class IndexedDbSettingsStore implements SettingsStoreLike {
|
|
|
92
93
|
load(): Promise<unknown>;
|
|
93
94
|
save(settings: AppSettings): Promise<void>;
|
|
94
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* The browser storage key that keeps the rendering chosen with the app settings of a name (see
|
|
98
|
+
* `loadRenderingChoice`).
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* renderingChoiceKey("demo"); // "paintcanvas-rendering:demo"
|
|
102
|
+
*/
|
|
103
|
+
export declare const renderingChoiceKey: (name: string) => string;
|
|
104
|
+
/**
|
|
105
|
+
* The rendering (`cpu` or `gpu`) last chosen with the app settings of a name, kept in `localStorage` so it can be read
|
|
106
|
+
* before the canvas is made (the app settings themselves load later, from IndexedDB). Undefined when none was kept, it
|
|
107
|
+
* isn't valid, or the storage can't be read (e.g. blocked by the browser).
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* new PaintCanvas({ rendering: loadRenderingChoice("demo") });
|
|
111
|
+
*/
|
|
112
|
+
export declare const loadRenderingChoice: (name?: string, storage?: Pick<Storage, "getItem"> | undefined) => Rendering | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Keep the rendering chosen with the app settings of a name, to be read with `loadRenderingChoice` when the canvas is
|
|
115
|
+
* next made. Does nothing if the storage can't be written.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* canvas.ui.addEventListener("change", () => saveRenderingChoice("demo", canvas.ui.data.rendering));
|
|
119
|
+
*/
|
|
120
|
+
export declare const saveRenderingChoice: (name: string, rendering: Rendering, storage?: Pick<Storage, "setItem"> | undefined) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRendering } from "../classes/UiSettings/index.js";
|
|
1
2
|
// src/lib/storage/index.ts
|
|
2
3
|
/** Version of a saved drawing's shape, so drawings saved by other versions can be recognised */
|
|
3
4
|
var SAVED_DRAWING_VERSION = 1;
|
|
@@ -169,4 +170,40 @@ var IndexedDbSettingsStore = class {
|
|
|
169
170
|
await done;
|
|
170
171
|
}
|
|
171
172
|
};
|
|
172
|
-
|
|
173
|
+
/**
|
|
174
|
+
* The browser storage key that keeps the rendering chosen with the app settings of a name (see
|
|
175
|
+
* `loadRenderingChoice`).
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* renderingChoiceKey("demo"); // "paintcanvas-rendering:demo"
|
|
179
|
+
*/
|
|
180
|
+
var renderingChoiceKey = (name) => `${DATABASE_NAME}-rendering:${name}`;
|
|
181
|
+
/**
|
|
182
|
+
* The rendering (`cpu` or `gpu`) last chosen with the app settings of a name, kept in `localStorage` so it can be read
|
|
183
|
+
* before the canvas is made (the app settings themselves load later, from IndexedDB). Undefined when none was kept, it
|
|
184
|
+
* isn't valid, or the storage can't be read (e.g. blocked by the browser).
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* new PaintCanvas({ rendering: loadRenderingChoice("demo") });
|
|
188
|
+
*/
|
|
189
|
+
var loadRenderingChoice = (name = DEFAULT_SETTINGS_NAME, storage = globalThis.localStorage) => {
|
|
190
|
+
try {
|
|
191
|
+
const value = storage?.getItem(renderingChoiceKey(name));
|
|
192
|
+
return isRendering(value) ? value : void 0;
|
|
193
|
+
} catch {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Keep the rendering chosen with the app settings of a name, to be read with `loadRenderingChoice` when the canvas is
|
|
199
|
+
* next made. Does nothing if the storage can't be written.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* canvas.ui.addEventListener("change", () => saveRenderingChoice("demo", canvas.ui.data.rendering));
|
|
203
|
+
*/
|
|
204
|
+
var saveRenderingChoice = (name, rendering, storage = globalThis.localStorage) => {
|
|
205
|
+
try {
|
|
206
|
+
storage?.setItem(renderingChoiceKey(name), rendering);
|
|
207
|
+
} catch {}
|
|
208
|
+
};
|
|
209
|
+
export { DATABASE_NAME, DATABASE_VERSION, DEFAULT_SETTINGS_NAME, IndexedDbSettingsStore, SAVED_DRAWING_VERSION, IndexedDbLayerStore as default, loadRenderingChoice, renderingChoiceKey, saveRenderingChoice };
|
|
@@ -29059,7 +29059,8 @@ var schema20 = {
|
|
|
29059
29059
|
"minLength": 1,
|
|
29060
29060
|
"maxLength": 35,
|
|
29061
29061
|
"pattern": "^[A-Za-z0-9-]+$"
|
|
29062
|
-
}
|
|
29062
|
+
},
|
|
29063
|
+
"rendering": { "enum": ["cpu", "gpu"] }
|
|
29063
29064
|
}
|
|
29064
29065
|
}
|
|
29065
29066
|
}
|
|
@@ -30009,7 +30010,7 @@ function validate17(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
30009
30010
|
if (errors === _errs70) {
|
|
30010
30011
|
if (data28 && typeof data28 == "object" && !Array.isArray(data28)) {
|
|
30011
30012
|
const _errs72 = errors;
|
|
30012
|
-
for (const key9 in data28) if (!(key9 === "theme" || key9 === "locale")) {
|
|
30013
|
+
for (const key9 in data28) if (!(key9 === "theme" || key9 === "locale" || key9 === "rendering")) {
|
|
30013
30014
|
validate17.errors = [{
|
|
30014
30015
|
instancePath: instancePath + "/ui",
|
|
30015
30016
|
schemaPath: "#/properties/ui/additionalProperties",
|
|
@@ -30082,6 +30083,23 @@ function validate17(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
30082
30083
|
}
|
|
30083
30084
|
var valid14 = _errs74 === errors;
|
|
30084
30085
|
} else var valid14 = true;
|
|
30086
|
+
if (valid14) {
|
|
30087
|
+
if (data28.rendering !== void 0) {
|
|
30088
|
+
let data31 = data28.rendering;
|
|
30089
|
+
const _errs76 = errors;
|
|
30090
|
+
if (!(data31 === "cpu" || data31 === "gpu")) {
|
|
30091
|
+
validate17.errors = [{
|
|
30092
|
+
instancePath: instancePath + "/ui/rendering",
|
|
30093
|
+
schemaPath: "#/properties/ui/properties/rendering/enum",
|
|
30094
|
+
keyword: "enum",
|
|
30095
|
+
params: { allowedValues: schema20.properties.ui.properties.rendering.enum },
|
|
30096
|
+
message: "must be equal to one of the allowed values"
|
|
30097
|
+
}];
|
|
30098
|
+
return false;
|
|
30099
|
+
}
|
|
30100
|
+
var valid14 = _errs76 === errors;
|
|
30101
|
+
} else var valid14 = true;
|
|
30102
|
+
}
|
|
30085
30103
|
}
|
|
30086
30104
|
}
|
|
30087
30105
|
} else {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** PaintCanvas's version, from its package.json, e.g. `0.6.0` */
|
|
2
|
+
export declare const PAINTCANVAS_VERSION: string;
|
|
3
|
+
/** What the commit is called when it's unknown */
|
|
4
|
+
export declare const UNKNOWN_COMMIT = "unknown";
|
|
5
|
+
/**
|
|
6
|
+
* Read the commit's hash, or `UNKNOWN_COMMIT` when it wasn't put in place (e.g. the source served or bundled without
|
|
7
|
+
* PaintCanvas's Vite config, where `__PAINTCANVAS_COMMIT__` is undefined).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* readCommit(() => "ac12a0d"); // "ac12a0d"
|
|
11
|
+
* readCommit(() => { throw new ReferenceError(); }); // "unknown"
|
|
12
|
+
*/
|
|
13
|
+
export declare const readCommit: (read: () => unknown) => string;
|
|
14
|
+
/** The short hash of the commit PaintCanvas was built from, e.g. `ac12a0d` (`unknown` when it can't be told) */
|
|
15
|
+
export declare const PAINTCANVAS_COMMIT: string;
|
|
16
|
+
/** Where PaintCanvas's source code is */
|
|
17
|
+
export declare const PAINTCANVAS_REPOSITORY_URL = "https://github.com/lvl99/paintcanvas";
|
|
18
|
+
/**
|
|
19
|
+
* PaintCanvas's name, version and commit as one line.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* versionText(); // "PaintCanvas v0.6.0 (ac12a0d)"
|
|
23
|
+
* versionText("1.0.0", "abc1234"); // "PaintCanvas v1.0.0 (abc1234)"
|
|
24
|
+
*/
|
|
25
|
+
export declare const versionText: (version?: string, commit?: string) => string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { version } from "../../package.js";
|
|
2
|
+
// src/lib/version/index.ts
|
|
3
|
+
/** PaintCanvas's version, from its package.json, e.g. `0.6.0` */
|
|
4
|
+
var PAINTCANVAS_VERSION = version;
|
|
5
|
+
/** What the commit is called when it's unknown */
|
|
6
|
+
var UNKNOWN_COMMIT = "unknown";
|
|
7
|
+
/**
|
|
8
|
+
* Read the commit's hash, or `UNKNOWN_COMMIT` when it wasn't put in place (e.g. the source served or bundled without
|
|
9
|
+
* PaintCanvas's Vite config, where `__PAINTCANVAS_COMMIT__` is undefined).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* readCommit(() => "ac12a0d"); // "ac12a0d"
|
|
13
|
+
* readCommit(() => { throw new ReferenceError(); }); // "unknown"
|
|
14
|
+
*/
|
|
15
|
+
var readCommit = (read) => {
|
|
16
|
+
try {
|
|
17
|
+
const commit = read();
|
|
18
|
+
return typeof commit === "string" && commit ? commit : UNKNOWN_COMMIT;
|
|
19
|
+
} catch {
|
|
20
|
+
return UNKNOWN_COMMIT;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/** The short hash of the commit PaintCanvas was built from, e.g. `ac12a0d` (`unknown` when it can't be told) */
|
|
24
|
+
var PAINTCANVAS_COMMIT = readCommit(() => "9f00978");
|
|
25
|
+
/** Where PaintCanvas's source code is */
|
|
26
|
+
var PAINTCANVAS_REPOSITORY_URL = "https://github.com/lvl99/paintcanvas";
|
|
27
|
+
/**
|
|
28
|
+
* PaintCanvas's name, version and commit as one line.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* versionText(); // "PaintCanvas v0.6.0 (ac12a0d)"
|
|
32
|
+
* versionText("1.0.0", "abc1234"); // "PaintCanvas v1.0.0 (abc1234)"
|
|
33
|
+
*/
|
|
34
|
+
var versionText = (version = PAINTCANVAS_VERSION, commit = PAINTCANVAS_COMMIT) => `PaintCanvas v${version} (${commit})`;
|
|
35
|
+
export { PAINTCANVAS_COMMIT, PAINTCANVAS_REPOSITORY_URL, PAINTCANVAS_VERSION, UNKNOWN_COMMIT, readCommit, versionText };
|
package/dist/locales/en-GB.js
CHANGED
|
@@ -164,6 +164,8 @@ var en_GB_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "Alpha lock",
|
|
165
165
|
"paintCanvas.layers.blendMode": "Blending mode",
|
|
166
166
|
"paintCanvas.layers.actions": "Layer actions",
|
|
167
|
+
"paintCanvas.layers.rename": "Rename…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "Rename layer",
|
|
167
169
|
"paintCanvas.layers.reorder": "Reorder {name}: drag, or press for actions",
|
|
168
170
|
"paintCanvas.layers.duplicate": "Duplicate",
|
|
169
171
|
"paintCanvas.layers.createMask": "Create mask",
|
|
@@ -291,6 +293,9 @@ var en_GB_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "Settings JSON file not compatible",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "Failed to read settings JSON file",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "Error exporting settings JSON file",
|
|
296
|
+
"paintCanvas.settings.gpu": "Draw with the GPU",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "Try this if drawing is slow. It applies after reloading the page.",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "Reload the page to apply this change.",
|
|
294
299
|
"paintCanvas.stats.label": "Canvas details",
|
|
295
300
|
"paintCanvas.stats.size": "Canvas: {width} × {height} px",
|
|
296
301
|
"paintCanvas.stats.zoom": "Zoom: {zoom}",
|
package/dist/locales/en-US.js
CHANGED
|
@@ -164,6 +164,8 @@ var en_US_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "Alpha lock",
|
|
165
165
|
"paintCanvas.layers.blendMode": "Blending mode",
|
|
166
166
|
"paintCanvas.layers.actions": "Layer actions",
|
|
167
|
+
"paintCanvas.layers.rename": "Rename…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "Rename layer",
|
|
167
169
|
"paintCanvas.layers.reorder": "Reorder {name}: drag, or press for actions",
|
|
168
170
|
"paintCanvas.layers.duplicate": "Duplicate",
|
|
169
171
|
"paintCanvas.layers.createMask": "Create mask",
|
|
@@ -291,6 +293,9 @@ var en_US_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "Settings JSON file not compatible",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "Failed to read settings JSON file",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "Error exporting settings JSON file",
|
|
296
|
+
"paintCanvas.settings.gpu": "Draw with the GPU",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "Try this if drawing is slow. It applies after reloading the page.",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "Reload the page to apply this change.",
|
|
294
299
|
"paintCanvas.stats.label": "Canvas details",
|
|
295
300
|
"paintCanvas.stats.size": "Canvas: {width} × {height} px",
|
|
296
301
|
"paintCanvas.stats.zoom": "Zoom: {zoom}",
|
package/dist/locales/fr.js
CHANGED
|
@@ -164,6 +164,8 @@ var fr_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "Verrouillage alpha",
|
|
165
165
|
"paintCanvas.layers.blendMode": "Mode de fusion",
|
|
166
166
|
"paintCanvas.layers.actions": "Actions du calque",
|
|
167
|
+
"paintCanvas.layers.rename": "Renommer…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "Renommer le calque",
|
|
167
169
|
"paintCanvas.layers.reorder": "Réorganiser {name}\xA0: faire glisser, ou appuyer pour les actions",
|
|
168
170
|
"paintCanvas.layers.duplicate": "Dupliquer",
|
|
169
171
|
"paintCanvas.layers.createMask": "Créer un masque",
|
|
@@ -291,6 +293,9 @@ var fr_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "Fichier JSON de réglages incompatible",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "Échec de la lecture du fichier JSON de réglages",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "Erreur lors de l'exportation du fichier JSON de réglages",
|
|
296
|
+
"paintCanvas.settings.gpu": "Dessiner avec le GPU",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "Essayez ceci si le dessin est lent. Le changement s’applique après le rechargement de la page.",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "Rechargez la page pour appliquer ce changement.",
|
|
294
299
|
"paintCanvas.stats.label": "Détails de la toile",
|
|
295
300
|
"paintCanvas.stats.size": "Toile\xA0: {width} × {height}\xA0px",
|
|
296
301
|
"paintCanvas.stats.zoom": "Zoom\xA0: {zoom}",
|
package/dist/locales/ja.js
CHANGED
|
@@ -164,6 +164,8 @@ var ja_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "透明部分をロック",
|
|
165
165
|
"paintCanvas.layers.blendMode": "描画モード",
|
|
166
166
|
"paintCanvas.layers.actions": "レイヤーの操作",
|
|
167
|
+
"paintCanvas.layers.rename": "名前を変更…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "レイヤー名を変更",
|
|
167
169
|
"paintCanvas.layers.reorder": "{name}の並べ替え:ドラッグ、または押して操作を表示",
|
|
168
170
|
"paintCanvas.layers.duplicate": "複製",
|
|
169
171
|
"paintCanvas.layers.createMask": "マスクを作成",
|
|
@@ -291,6 +293,9 @@ var ja_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "この設定のJSONファイルには対応していません",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "設定のJSONファイルを読み込めませんでした",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "設定のJSONファイルを書き出せませんでした",
|
|
296
|
+
"paintCanvas.settings.gpu": "GPU で描画する",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "描画が遅い場合にお試しください。ページを再読み込みすると適用されます。",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "この変更を適用するにはページを再読み込みしてください。",
|
|
294
299
|
"paintCanvas.stats.label": "キャンバスの詳細",
|
|
295
300
|
"paintCanvas.stats.size": "キャンバス: {width} × {height} px",
|
|
296
301
|
"paintCanvas.stats.zoom": "ズーム: {zoom}",
|
package/dist/locales/ko.js
CHANGED
|
@@ -164,6 +164,8 @@ var ko_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "투명 픽셀 잠금",
|
|
165
165
|
"paintCanvas.layers.blendMode": "혼합 모드",
|
|
166
166
|
"paintCanvas.layers.actions": "레이어 작업",
|
|
167
|
+
"paintCanvas.layers.rename": "이름 바꾸기…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "레이어 이름 바꾸기",
|
|
167
169
|
"paintCanvas.layers.reorder": "{name} 순서 변경: 드래그하거나 눌러서 작업 보기",
|
|
168
170
|
"paintCanvas.layers.duplicate": "복제",
|
|
169
171
|
"paintCanvas.layers.createMask": "마스크 만들기",
|
|
@@ -291,6 +293,9 @@ var ko_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "호환되지 않는 설정 JSON 파일입니다",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "설정 JSON 파일을 읽지 못했습니다",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "설정 JSON 파일을 내보내지 못했습니다",
|
|
296
|
+
"paintCanvas.settings.gpu": "GPU로 그리기",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "그리기가 느리면 사용해 보세요. 페이지를 새로 고친 후 적용됩니다.",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "이 변경 사항을 적용하려면 페이지를 새로 고치세요.",
|
|
294
299
|
"paintCanvas.stats.label": "캔버스 정보",
|
|
295
300
|
"paintCanvas.stats.size": "캔버스: {width} × {height} px",
|
|
296
301
|
"paintCanvas.stats.zoom": "확대/축소: {zoom}",
|
package/dist/locales/zh-Hans.js
CHANGED
|
@@ -164,6 +164,8 @@ var zh_Hans_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "锁定透明像素",
|
|
165
165
|
"paintCanvas.layers.blendMode": "混合模式",
|
|
166
166
|
"paintCanvas.layers.actions": "图层操作",
|
|
167
|
+
"paintCanvas.layers.rename": "重命名…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "重命名图层",
|
|
167
169
|
"paintCanvas.layers.reorder": "调整{name}的顺序:拖动,或按下以显示操作",
|
|
168
170
|
"paintCanvas.layers.duplicate": "复制",
|
|
169
171
|
"paintCanvas.layers.createMask": "创建蒙版",
|
|
@@ -291,6 +293,9 @@ var zh_Hans_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "不兼容的设置 JSON 文件",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "无法读取设置 JSON 文件",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "导出设置 JSON 文件时出错",
|
|
296
|
+
"paintCanvas.settings.gpu": "使用 GPU 绘制",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "如果绘制缓慢,请尝试此选项。重新加载页面后生效。",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "重新加载页面以应用此更改。",
|
|
294
299
|
"paintCanvas.stats.label": "画布详情",
|
|
295
300
|
"paintCanvas.stats.size": "画布:{width} × {height} 像素",
|
|
296
301
|
"paintCanvas.stats.zoom": "缩放:{zoom}",
|
package/dist/locales/zh-Hant.js
CHANGED
|
@@ -164,6 +164,8 @@ var zh_Hant_default = {
|
|
|
164
164
|
"paintCanvas.layers.alphaLock": "鎖定透明像素",
|
|
165
165
|
"paintCanvas.layers.blendMode": "混合模式",
|
|
166
166
|
"paintCanvas.layers.actions": "圖層動作",
|
|
167
|
+
"paintCanvas.layers.rename": "重新命名…",
|
|
168
|
+
"paintCanvas.layers.renameTitle": "重新命名圖層",
|
|
167
169
|
"paintCanvas.layers.reorder": "調整{name}的順序:拖曳,或按下以顯示動作",
|
|
168
170
|
"paintCanvas.layers.duplicate": "複製",
|
|
169
171
|
"paintCanvas.layers.createMask": "建立遮罩",
|
|
@@ -291,6 +293,9 @@ var zh_Hant_default = {
|
|
|
291
293
|
"paintCanvas.settings.fileIncompatible": "不相容的設定 JSON 檔案",
|
|
292
294
|
"paintCanvas.settings.fileReadFailed": "無法讀取設定 JSON 檔案",
|
|
293
295
|
"paintCanvas.settings.exportFailed": "匯出設定 JSON 檔案時發生錯誤",
|
|
296
|
+
"paintCanvas.settings.gpu": "使用 GPU 繪製",
|
|
297
|
+
"paintCanvas.settings.gpuHint": "如果繪製緩慢,請嘗試此選項。重新載入頁面後生效。",
|
|
298
|
+
"paintCanvas.settings.reloadToApply": "重新載入頁面以套用此變更。",
|
|
294
299
|
"paintCanvas.stats.label": "畫布詳細資料",
|
|
295
300
|
"paintCanvas.stats.size": "畫布:{width} × {height} 像素",
|
|
296
301
|
"paintCanvas.stats.zoom": "縮放:{zoom}",
|
package/dist/package.js
CHANGED