@next2d/renderer 2.0.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/package.json +31 -0
  4. package/src/Command/service/CommandInitializeContextService.d.ts +11 -0
  5. package/src/Command/service/CommandInitializeContextService.js +27 -0
  6. package/src/Command/service/CommandRemoveCacheService.d.ts +10 -0
  7. package/src/Command/service/CommandRemoveCacheService.js +24 -0
  8. package/src/Command/service/CommandResizeService.d.ts +12 -0
  9. package/src/Command/service/CommandResizeService.js +27 -0
  10. package/src/Command/usecase/CommandCaptureUseCase.d.ts +13 -0
  11. package/src/Command/usecase/CommandCaptureUseCase.js +53 -0
  12. package/src/Command/usecase/CommandRenderUseCase.d.ts +11 -0
  13. package/src/Command/usecase/CommandRenderUseCase.js +70 -0
  14. package/src/CommandController.d.ts +38 -0
  15. package/src/CommandController.js +102 -0
  16. package/src/DisplayObject/service/DisplayObjectGetBlendModeService.d.ts +11 -0
  17. package/src/DisplayObject/service/DisplayObjectGetBlendModeService.js +45 -0
  18. package/src/DisplayObjectContainer/usecase/DisplayObjectContainerClipRenderUseCase.d.ts +11 -0
  19. package/src/DisplayObjectContainer/usecase/DisplayObjectContainerClipRenderUseCase.js +29 -0
  20. package/src/DisplayObjectContainer/usecase/DisplayObjectContainerRenderUseCase.d.ts +12 -0
  21. package/src/DisplayObjectContainer/usecase/DisplayObjectContainerRenderUseCase.js +120 -0
  22. package/src/RendererUtil.d.ts +136 -0
  23. package/src/RendererUtil.js +214 -0
  24. package/src/Shape/service/ShapeCommandService.d.ts +11 -0
  25. package/src/Shape/service/ShapeCommandService.js +252 -0
  26. package/src/Shape/usecase/ShapeClipRenderUseCase.d.ts +11 -0
  27. package/src/Shape/usecase/ShapeClipRenderUseCase.js +33 -0
  28. package/src/Shape/usecase/ShapeRenderUseCase.d.ts +11 -0
  29. package/src/Shape/usecase/ShapeRenderUseCase.js +154 -0
  30. package/src/TextField/service/TextFieldGenerateFontStyleService.d.ts +11 -0
  31. package/src/TextField/service/TextFieldGenerateFontStyleService.js +19 -0
  32. package/src/TextField/service/TextFiledGetAlignOffsetService.d.ts +15 -0
  33. package/src/TextField/service/TextFiledGetAlignOffsetService.js +33 -0
  34. package/src/TextField/usecase/TextFieldDrawOffscreenCanvasUseCase.d.ts +15 -0
  35. package/src/TextField/usecase/TextFieldDrawOffscreenCanvasUseCase.js +272 -0
  36. package/src/TextField/usecase/TextFieldRenderUseCase.d.ts +11 -0
  37. package/src/TextField/usecase/TextFieldRenderUseCase.js +150 -0
  38. package/src/Video/usecase/VideoRenderUseCase.d.ts +12 -0
  39. package/src/Video/usecase/VideoRenderUseCase.js +88 -0
  40. package/src/index.d.ts +2 -0
  41. package/src/index.js +26 -0
  42. package/src/interface/IBlendMode.d.ts +1 -0
  43. package/src/interface/IBlendMode.js +1 -0
  44. package/src/interface/IMessage.d.ts +11 -0
  45. package/src/interface/IMessage.js +1 -0
  46. package/src/interface/INode.d.ts +7 -0
  47. package/src/interface/INode.js +1 -0
  48. package/src/interface/IRGBA.d.ts +6 -0
  49. package/src/interface/IRGBA.js +1 -0
  50. package/src/interface/ITextData.d.ts +8 -0
  51. package/src/interface/ITextData.js +1 -0
  52. package/src/interface/ITextFieldAutoSize.d.ts +1 -0
  53. package/src/interface/ITextFieldAutoSize.js +1 -0
  54. package/src/interface/ITextFormat.d.ts +14 -0
  55. package/src/interface/ITextFormat.js +1 -0
  56. package/src/interface/ITextFormatAlign.d.ts +1 -0
  57. package/src/interface/ITextFormatAlign.js +1 -0
  58. package/src/interface/ITextObject.d.ts +12 -0
  59. package/src/interface/ITextObject.js +1 -0
  60. package/src/interface/ITextObjectMode.d.ts +1 -0
  61. package/src/interface/ITextObjectMode.js +1 -0
  62. package/src/interface/ITextSetting.d.ts +25 -0
  63. package/src/interface/ITextSetting.js +1 -0
@@ -0,0 +1,272 @@
1
+ import { execute as textFiledGetAlignOffsetService } from "../service/TextFiledGetAlignOffsetService";
2
+ import { execute as textFieldGenerateFontStyleService } from "../service/TextFieldGenerateFontStyleService";
3
+ import { $intToRGBA } from "../../RendererUtil";
4
+ /**
5
+ * @description TextDataを元にOffscreenCanvasにテキストを描画
6
+ * Draw text in OffscreenCanvas based on TextData
7
+ *
8
+ * @param {ITextData} text_data
9
+ * @param {object} text_setting
10
+ * @param {number} x_scale
11
+ * @param {number} y_scale
12
+ * @return {OffscreenCanvas}
13
+ * @method
14
+ * @protected
15
+ */
16
+ export const execute = (text_data, text_setting, x_scale, y_scale) => {
17
+ const canvas = new OffscreenCanvas(text_setting.width, text_setting.height);
18
+ const context = canvas.getContext("2d");
19
+ if (!context) {
20
+ return canvas;
21
+ }
22
+ const lineWidth = Math.min(1, Math.max(x_scale, y_scale));
23
+ // border and background
24
+ if (text_setting.background || text_setting.border) {
25
+ context.beginPath();
26
+ context.moveTo(0, 0);
27
+ context.lineTo(text_setting.width, 0);
28
+ context.lineTo(text_setting.width, text_setting.height);
29
+ context.lineTo(0, text_setting.height);
30
+ context.lineTo(0, 0);
31
+ if (text_setting.background) {
32
+ const color = $intToRGBA(text_setting.backgroundColor);
33
+ context.fillStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
34
+ context.fill();
35
+ }
36
+ if (text_setting.border) {
37
+ const color = $intToRGBA(text_setting.borderColor);
38
+ context.lineWidth = lineWidth;
39
+ context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
40
+ context.stroke();
41
+ }
42
+ }
43
+ if (!text_data) {
44
+ return canvas;
45
+ }
46
+ context.save();
47
+ context.beginPath();
48
+ context.moveTo(2, 2);
49
+ context.lineTo(text_setting.width - 2, 2);
50
+ context.lineTo(text_setting.width - 2, text_setting.height - 2);
51
+ context.lineTo(2, text_setting.height - 2);
52
+ context.lineTo(2, 2);
53
+ context.clip();
54
+ let tx = 2;
55
+ if (text_setting.scrollX > 0) {
56
+ const scaleX = (text_setting.textWidth + 4 - text_setting.rawWidth) / text_setting.rawWidth;
57
+ tx += -text_setting.scrollX * scaleX;
58
+ }
59
+ let ty = 2;
60
+ if (text_setting.scrollY > 0) {
61
+ const scaleY = (text_setting.textHeight + 2 - text_setting.rawHeight) / text_setting.rawHeight;
62
+ ty += -text_setting.scrollY * scaleY;
63
+ }
64
+ context.setTransform(x_scale, 0, 0, y_scale, tx * x_scale, ty * y_scale);
65
+ context.beginPath();
66
+ if (text_setting.selectIndex > -1
67
+ && text_setting.focusIndex > -1) {
68
+ const range = text_data.textTable.length - 1;
69
+ let minIndex = 0;
70
+ let maxIndex = 0;
71
+ if (text_setting.focusIndex <= text_setting.selectIndex) {
72
+ minIndex = Math.min(text_setting.focusIndex, range);
73
+ maxIndex = Math.min(text_setting.selectIndex, range);
74
+ }
75
+ else {
76
+ minIndex = Math.min(text_setting.selectIndex, range);
77
+ maxIndex = Math.min(text_setting.focusIndex - 1, range);
78
+ }
79
+ const textObject = text_data.textTable[minIndex];
80
+ const lineObject = text_data.lineTable[textObject.line];
81
+ const offsetAlign = textFiledGetAlignOffsetService(text_data, lineObject, text_setting);
82
+ let x = 0;
83
+ if (minIndex && textObject.mode === "text") {
84
+ let idx = minIndex;
85
+ while (idx) {
86
+ const textObject = text_data.textTable[--idx];
87
+ if (textObject.mode !== "text") {
88
+ break;
89
+ }
90
+ x += textObject.w;
91
+ }
92
+ }
93
+ context.fillStyle = "#b4d7ff";
94
+ let w = 0;
95
+ for (let idx = minIndex; idx <= maxIndex; ++idx) {
96
+ const textObject = text_data.textTable[idx];
97
+ if (textObject.mode === "text") {
98
+ w += textObject.w;
99
+ if (idx !== maxIndex) {
100
+ continue;
101
+ }
102
+ }
103
+ let y = 0;
104
+ const line = textObject.mode === "text"
105
+ ? textObject.line
106
+ : textObject.line - 1;
107
+ for (let idx = 0; idx < line; ++idx) {
108
+ y += text_data.heightTable[idx];
109
+ }
110
+ context.beginPath();
111
+ context.rect(x, y, w + offsetAlign, text_data.heightTable[line]);
112
+ context.fill();
113
+ x = 0;
114
+ w = 0;
115
+ }
116
+ }
117
+ const rawWidth = text_setting.rawWidth;
118
+ let scrollX = 0;
119
+ if (text_setting.scrollX > 0) {
120
+ const scaleX = (text_setting.textWidth - rawWidth) / rawWidth;
121
+ scrollX = text_setting.scrollX * scaleX;
122
+ }
123
+ const limitWidth = rawWidth + scrollX;
124
+ const rawHeight = text_setting.rawHeight;
125
+ let scrollY = 0;
126
+ if (text_setting.scrollY > 0) {
127
+ const scaleY = (text_setting.textHeight - rawHeight) / rawHeight;
128
+ scrollY = text_setting.scrollY * scaleY;
129
+ }
130
+ const limitHeight = rawHeight + scrollY;
131
+ // setup
132
+ let offsetWidth = 0;
133
+ let offsetHeight = 0;
134
+ let offsetAlign = 0;
135
+ let verticalAlign = 0;
136
+ let skip = false;
137
+ let currentIndex = -1;
138
+ for (let idx = 0; idx < text_data.textTable.length; ++idx) {
139
+ const textObject = text_data.textTable[idx];
140
+ if (!textObject) {
141
+ continue;
142
+ }
143
+ if (textObject.mode === "text" || textObject.mode === "break") {
144
+ currentIndex++;
145
+ if (text_setting.stopIndex > -1
146
+ && currentIndex > text_setting.stopIndex) {
147
+ break;
148
+ }
149
+ }
150
+ if (skip && textObject.mode === "text") {
151
+ continue;
152
+ }
153
+ const textFormat = textObject.textFormat;
154
+ // check
155
+ if (text_setting.autoSize === "none") {
156
+ if (offsetHeight > limitHeight) {
157
+ break;
158
+ }
159
+ if (textObject.mode === "text") {
160
+ if (scrollX > offsetWidth + textObject.w
161
+ || offsetWidth > limitWidth) {
162
+ offsetWidth += textObject.w;
163
+ continue;
164
+ }
165
+ }
166
+ }
167
+ // color setting
168
+ const color = $intToRGBA(textFormat.color || 0);
169
+ context.fillStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
170
+ // focus line
171
+ if (text_setting.focusVisible
172
+ && text_setting.focusIndex === idx) {
173
+ const x = offsetWidth + offsetAlign + 0.1;
174
+ let line = textObject.line;
175
+ let h = textObject.y;
176
+ let y = text_data.ascentTable[line];
177
+ if (textObject.mode !== "text") {
178
+ h = textObject.mode === "break"
179
+ ? textObject.h
180
+ : text_data.ascentTable[line - 1];
181
+ if (line > 0) {
182
+ line = textObject.line - 1;
183
+ y = text_data.ascentTable[line];
184
+ }
185
+ else {
186
+ y = textObject.h;
187
+ }
188
+ }
189
+ if (line > 0 && text_data.ascentTable[line] === 0) {
190
+ line++;
191
+ }
192
+ for (let idx = 0; idx < line; ++idx) {
193
+ y += text_data.heightTable[idx];
194
+ }
195
+ context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
196
+ context.beginPath();
197
+ context.moveTo(x, y);
198
+ context.lineTo(x, y - h);
199
+ context.stroke();
200
+ }
201
+ if (text_setting.thickness) {
202
+ const color = $intToRGBA(text_setting.thicknessColor);
203
+ context.lineWidth = text_setting.thickness;
204
+ context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
205
+ }
206
+ const line = textObject.line | 0;
207
+ switch (textObject.mode) {
208
+ case "break":
209
+ case "wrap":
210
+ // reset width
211
+ offsetWidth = 0;
212
+ if (line) {
213
+ offsetHeight += text_data.heightTable[line - 1];
214
+ }
215
+ if (scrollY > offsetHeight + text_data.heightTable[line]) {
216
+ skip = true;
217
+ continue;
218
+ }
219
+ verticalAlign = text_data.ascentTable[line];
220
+ offsetAlign = textFiledGetAlignOffsetService(text_data, textObject, text_setting);
221
+ skip = false;
222
+ break;
223
+ case "text":
224
+ {
225
+ context.beginPath();
226
+ context.font = textFieldGenerateFontStyleService(textFormat);
227
+ const x = offsetWidth + offsetAlign;
228
+ const y = offsetHeight + verticalAlign;
229
+ if (textFormat.underline) {
230
+ const color = $intToRGBA(textFormat.color || 0);
231
+ context.lineWidth = lineWidth;
232
+ context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
233
+ context.beginPath();
234
+ context.moveTo(x, y + 2);
235
+ context.lineTo(x + textObject.w, y + 2);
236
+ context.stroke();
237
+ }
238
+ if (text_setting.thickness) {
239
+ context.strokeText(textObject.text, x, y);
240
+ }
241
+ context.fillText(textObject.text, x, y);
242
+ offsetWidth += textObject.w;
243
+ }
244
+ break;
245
+ case "image":
246
+ break;
247
+ default:
248
+ break;
249
+ }
250
+ }
251
+ if (text_setting.focusVisible
252
+ && text_setting.focusIndex >= text_data.textTable.length) {
253
+ const textObject = text_data.textTable[text_setting.focusIndex - 1];
254
+ if (textObject) {
255
+ const color = $intToRGBA(textObject.textFormat.color || 0);
256
+ context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${color.A})`;
257
+ const x = offsetWidth + offsetAlign + 0.1;
258
+ const y = offsetHeight + verticalAlign;
259
+ context.beginPath();
260
+ if (textObject.mode === "text") {
261
+ context.moveTo(x, y - textObject.y);
262
+ }
263
+ else {
264
+ context.moveTo(x, y + textObject.h);
265
+ }
266
+ context.lineTo(x, y);
267
+ context.stroke();
268
+ }
269
+ }
270
+ context.restore();
271
+ return canvas;
272
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @description TextFieldの描画を実行します。
3
+ * Execute the drawing of TextField.
4
+ *
5
+ * @param {Float32Array} render_queue
6
+ * @param {number} index
7
+ * @return {number}
8
+ * @method
9
+ * @protected
10
+ */
11
+ export declare const execute: (render_queue: Float32Array, index: number) => number;
@@ -0,0 +1,150 @@
1
+ import { $cacheStore } from "@next2d/cache";
2
+ import { execute as displayObjectGetBlendModeService } from "../../DisplayObject/service/DisplayObjectGetBlendModeService";
3
+ import { execute as textFieldDrawOffscreenCanvasUseCase } from "./TextFieldDrawOffscreenCanvasUseCase";
4
+ import { $context } from "../../RendererUtil";
5
+ /**
6
+ * @type {TextDecoder}
7
+ * @private
8
+ */
9
+ const $textDecoder = new TextDecoder();
10
+ /**
11
+ * @description TextFieldの描画を実行します。
12
+ * Execute the drawing of TextField.
13
+ *
14
+ * @param {Float32Array} render_queue
15
+ * @param {number} index
16
+ * @return {number}
17
+ * @method
18
+ * @protected
19
+ */
20
+ export const execute = (render_queue, index) => {
21
+ const matrix = render_queue.subarray(index, index + 6);
22
+ index += 6;
23
+ const colorTransform = render_queue.subarray(index, index + 8);
24
+ index += 8;
25
+ const bounds = render_queue.subarray(index, index + 4);
26
+ index += 4;
27
+ // baseBounds
28
+ const xMin = render_queue[index++];
29
+ const yMin = render_queue[index++];
30
+ const xMax = render_queue[index++];
31
+ const yMax = render_queue[index++];
32
+ // cache uniqueKey
33
+ const uniqueKey = `${render_queue[index++]}`;
34
+ const cacheKey = render_queue[index++];
35
+ // text state
36
+ const changed = Boolean(render_queue[index++]);
37
+ const xScale = Math.round(Math.sqrt(matrix[0] * matrix[0]
38
+ + matrix[1] * matrix[1]) * 10000) / 10000;
39
+ const yScale = Math.round(Math.sqrt(matrix[2] * matrix[2]
40
+ + matrix[3] * matrix[3]) * 10000) / 10000;
41
+ let node;
42
+ const hasCache = render_queue[index++];
43
+ if (!hasCache) {
44
+ const width = Math.ceil(Math.abs(xMax - xMin) * xScale);
45
+ const height = Math.ceil(Math.abs(yMax - yMin) * yScale);
46
+ const hasNode = Boolean(render_queue[index++]);
47
+ node = hasNode
48
+ ? $cacheStore.get(uniqueKey, `${cacheKey}`)
49
+ : $context.createNode(width, height);
50
+ if (!hasNode) {
51
+ $cacheStore.set(uniqueKey, `${cacheKey}`, node);
52
+ }
53
+ const length = render_queue[index++];
54
+ const buffer = new Uint8Array(render_queue.subarray(index, index + length));
55
+ index += length;
56
+ let autoSize = "none";
57
+ switch (render_queue[index++]) {
58
+ case 0:
59
+ autoSize = "center";
60
+ break;
61
+ case 1:
62
+ autoSize = "left";
63
+ break;
64
+ case 2:
65
+ autoSize = "none";
66
+ break;
67
+ case 3:
68
+ autoSize = "right";
69
+ break;
70
+ }
71
+ const textSetting = {
72
+ "width": width,
73
+ "height": height,
74
+ "autoSize": autoSize,
75
+ "stopIndex": render_queue[index++],
76
+ "scrollX": render_queue[index++],
77
+ "scrollY": render_queue[index++],
78
+ "textWidth": render_queue[index++],
79
+ "textHeight": render_queue[index++],
80
+ "rawWidth": render_queue[index++],
81
+ "rawHeight": render_queue[index++],
82
+ "focusIndex": render_queue[index++],
83
+ "selectIndex": render_queue[index++],
84
+ "focusVisible": Boolean(render_queue[index++]),
85
+ "thickness": render_queue[index++],
86
+ "thicknessColor": render_queue[index++],
87
+ "wordWrap": Boolean(render_queue[index++]),
88
+ "border": Boolean(render_queue[index++]),
89
+ "borderColor": render_queue[index++],
90
+ "background": Boolean(render_queue[index++]),
91
+ "backgroundColor": render_queue[index++],
92
+ "defaultColor": render_queue[index++],
93
+ "defaultSize": render_queue[index++]
94
+ };
95
+ const canvas = textFieldDrawOffscreenCanvasUseCase(JSON.parse($textDecoder.decode(buffer)), textSetting, xScale, yScale);
96
+ // fixed logic
97
+ const currentAttachment = $context.currentAttachmentObject;
98
+ $context.bind($context.atlasAttachmentObject);
99
+ $context.reset();
100
+ $context.beginNodeRendering(node);
101
+ const offsetY = $context.atlasAttachmentObject.height - node.y - height;
102
+ $context.setTransform(1, 0, 0, 1, node.x, offsetY);
103
+ $context.drawElement(node, canvas);
104
+ $context.endNodeRendering();
105
+ if (currentAttachment) {
106
+ $context.bind(currentAttachment);
107
+ }
108
+ }
109
+ else {
110
+ node = $cacheStore.get(uniqueKey, `${cacheKey}`);
111
+ if (!node) {
112
+ return index;
113
+ }
114
+ }
115
+ const blendMode = render_queue[index++];
116
+ // フィルター設定があればフィルターを実行
117
+ const useFilfer = Boolean(render_queue[index++]);
118
+ if (useFilfer) {
119
+ const updated = Boolean(render_queue[index++]);
120
+ const filterBounds = render_queue.subarray(index, index + 4);
121
+ index += 4;
122
+ const length = render_queue[index++];
123
+ const params = render_queue.subarray(index, index + length);
124
+ const width = Math.ceil(Math.abs(bounds[2] - bounds[0]));
125
+ const height = Math.ceil(Math.abs(bounds[3] - bounds[1]));
126
+ $context.applyFilter(node, uniqueKey, Boolean(Math.max(+changed, +updated)), width, height, false, matrix, colorTransform, displayObjectGetBlendModeService(blendMode), filterBounds, params);
127
+ index += length;
128
+ return index;
129
+ }
130
+ $context.globalAlpha = Math.min(Math.max(0, colorTransform[3] + colorTransform[7] / 255), 1);
131
+ $context.imageSmoothingEnabled = true;
132
+ $context.globalCompositeOperation = displayObjectGetBlendModeService(blendMode);
133
+ const radianX = Math.atan2(matrix[1], matrix[0]);
134
+ const radianY = Math.atan2(-matrix[2], matrix[3]);
135
+ if (radianX || radianY) {
136
+ const tx = xMin * xScale;
137
+ const ty = yMin * yScale;
138
+ const cosX = Math.cos(radianX);
139
+ const sinX = Math.sin(radianX);
140
+ const cosY = Math.cos(radianY);
141
+ const sinY = Math.sin(radianY);
142
+ $context.setTransform(cosX, sinX, -sinY, cosY, tx * cosX - ty * sinY + matrix[4], tx * sinX + ty * cosY + matrix[5]);
143
+ }
144
+ else {
145
+ $context.setTransform(1, 0, 0, 1, bounds[0], bounds[1]);
146
+ }
147
+ // 描画範囲をinstanced arrayに設定
148
+ $context.drawDisplayObject(node, bounds[0], bounds[1], bounds[2], bounds[3], colorTransform);
149
+ return index;
150
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @description Videoの描画を実行します。
3
+ * Execute the drawing of Video.
4
+ *
5
+ * @param {Float32Array} render_queue
6
+ * @param {number} index
7
+ * @param {ImageBitmap[]} image_bitmaps
8
+ * @return {number}
9
+ * @method
10
+ * @protected
11
+ */
12
+ export declare const execute: (render_queue: Float32Array, index: number, image_bitmaps: ImageBitmap[] | null) => number;
@@ -0,0 +1,88 @@
1
+ import { $cacheStore } from "@next2d/cache";
2
+ import { $context } from "../../RendererUtil";
3
+ import { execute as displayObjectGetBlendModeService } from "../../DisplayObject/service/DisplayObjectGetBlendModeService";
4
+ /**
5
+ * @description Videoの描画を実行します。
6
+ * Execute the drawing of Video.
7
+ *
8
+ * @param {Float32Array} render_queue
9
+ * @param {number} index
10
+ * @param {ImageBitmap[]} image_bitmaps
11
+ * @return {number}
12
+ * @method
13
+ * @protected
14
+ */
15
+ export const execute = (render_queue, index, image_bitmaps) => {
16
+ const matrix = render_queue.subarray(index, index + 6);
17
+ index += 6;
18
+ const colorTransform = render_queue.subarray(index, index + 8);
19
+ index += 8;
20
+ const bounds = render_queue.subarray(index, index + 4);
21
+ index += 4;
22
+ // baseBounds
23
+ const xMin = render_queue[index++];
24
+ const yMin = render_queue[index++];
25
+ const xMax = render_queue[index++];
26
+ const yMax = render_queue[index++];
27
+ // cache uniqueKey
28
+ const uniqueKey = `${render_queue[index++]}`;
29
+ const cacheKey = "0";
30
+ // video state
31
+ const changed = Boolean(render_queue[index++]);
32
+ let node;
33
+ const hasCache = render_queue[index++];
34
+ if (!hasCache) {
35
+ const width = Math.abs(xMax - xMin);
36
+ const height = Math.abs(yMax - yMin);
37
+ const hasNode = Boolean(render_queue[index++]);
38
+ node = hasNode
39
+ ? $cacheStore.get(uniqueKey, `${cacheKey}`)
40
+ : $context.createNode(width, height);
41
+ if (!hasNode) {
42
+ $cacheStore.set(uniqueKey, `${cacheKey}`, node);
43
+ }
44
+ if (image_bitmaps && image_bitmaps.length) {
45
+ // fixed logic
46
+ const currentAttachment = $context.currentAttachmentObject;
47
+ $context.bind($context.atlasAttachmentObject);
48
+ $context.reset();
49
+ $context.beginNodeRendering(node);
50
+ const offsetY = $context.atlasAttachmentObject.height - node.y - height;
51
+ $context.setTransform(1, 0, 0, 1, node.x, offsetY);
52
+ const imageBitmap = image_bitmaps.shift();
53
+ $context.drawElement(node, imageBitmap);
54
+ $context.endNodeRendering();
55
+ if (currentAttachment) {
56
+ $context.bind(currentAttachment);
57
+ }
58
+ }
59
+ }
60
+ else {
61
+ node = $cacheStore.get(uniqueKey, `${cacheKey}`);
62
+ if (!node) {
63
+ return index;
64
+ }
65
+ }
66
+ const blendMode = render_queue[index++];
67
+ // フィルター設定があればフィルターを実行
68
+ const useFilfer = Boolean(render_queue[index++]);
69
+ if (useFilfer) {
70
+ const updated = Boolean(render_queue[index++]);
71
+ const filterBounds = render_queue.subarray(index, index + 4);
72
+ index += 4;
73
+ const length = render_queue[index++];
74
+ const params = render_queue.subarray(index, index + length);
75
+ const width = Math.ceil(Math.abs(bounds[2] - bounds[0]));
76
+ const height = Math.ceil(Math.abs(bounds[3] - bounds[1]));
77
+ $context.applyFilter(node, uniqueKey, Boolean(Math.max(+changed, +updated)), width, height, true, matrix, colorTransform, displayObjectGetBlendModeService(blendMode), filterBounds, params);
78
+ index += length;
79
+ return index;
80
+ }
81
+ $context.globalAlpha = Math.min(Math.max(0, colorTransform[3] + colorTransform[7] / 255), 1);
82
+ $context.imageSmoothingEnabled = true;
83
+ $context.globalCompositeOperation = displayObjectGetBlendModeService(blendMode);
84
+ $context.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
85
+ // 描画範囲をinstanced arrayに設定
86
+ $context.drawDisplayObject(node, bounds[0], bounds[1], bounds[2], bounds[3], colorTransform);
87
+ return index;
88
+ };
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const _default: {};
2
+ export default _default;
package/src/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ import { CommandController } from "./CommandController";
3
+ /**
4
+ * @description CommandControllerのインスタンス
5
+ * Instance of CommandController
6
+ *
7
+ * @type {CommandController}
8
+ * @public
9
+ */
10
+ const command = new CommandController();
11
+ /**
12
+ * @description OffscreenCanvasのメッセージイベント
13
+ * OffscreenCanvas message event
14
+ *
15
+ * @params {MessageEvent} event
16
+ * @return {Promise<void>}
17
+ * @method
18
+ * @public
19
+ */
20
+ self.addEventListener("message", async (event) => {
21
+ command.queue.push(event.data);
22
+ if (command.state === "deactivate") {
23
+ await command.execute();
24
+ }
25
+ });
26
+ export default {};
@@ -0,0 +1 @@
1
+ export type IBlendMode = "copy" | "add" | "alpha" | "darken" | "difference" | "erase" | "hardlight" | "invert" | "layer" | "lighten" | "multiply" | "normal" | "overlay" | "screen" | "subtract";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export interface IMessage {
2
+ command: string;
3
+ buffer: Float32Array;
4
+ width?: number;
5
+ height?: number;
6
+ length?: number;
7
+ imageBitmaps?: ImageBitmap[] | null;
8
+ canvas?: OffscreenCanvas;
9
+ devicePixelRatio?: number;
10
+ id?: string;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export interface INode {
2
+ index: number;
3
+ x: number;
4
+ y: number;
5
+ w: number;
6
+ h: number;
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export interface IRGBA {
2
+ A: number;
3
+ R: number;
4
+ G: number;
5
+ B: number;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { ITextObject } from "./ITextObject";
2
+ export interface ITextData {
3
+ ascentTable: number[];
4
+ heightTable: number[];
5
+ lineTable: ITextObject[];
6
+ textTable: ITextObject[];
7
+ widthTable: number[];
8
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type ITextFieldAutoSize = "center" | "left" | "none" | "right";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { ITextFormatAlign } from "./ITextFormatAlign";
2
+ export interface ITextFormat {
3
+ align: ITextFormatAlign | null;
4
+ bold: boolean | null;
5
+ color: number | null;
6
+ font: string | null;
7
+ italic: boolean | null;
8
+ leading: number | null;
9
+ leftMargin: number | null;
10
+ letterSpacing: number | null;
11
+ rightMargin: number | null;
12
+ size: number | null;
13
+ underline: boolean | null;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type ITextFormatAlign = "center" | "left" | "right";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { ITextFormat } from "./ITextFormat";
2
+ import type { ITextObjectMode } from "./ITextObjectMode";
3
+ export interface ITextObject {
4
+ mode: ITextObjectMode;
5
+ text: string;
6
+ textFormat: ITextFormat;
7
+ x: number;
8
+ y: number;
9
+ w: number;
10
+ h: number;
11
+ line: number;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type ITextObjectMode = "break" | "wrap" | "image" | "text";