@babylonjs/gui 9.15.0 → 9.16.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/2D/controls/checkbox.pure.js +164 -153
- package/2D/controls/checkbox.pure.js.map +1 -1
- package/2D/controls/colorpicker.pure.js +1300 -1289
- package/2D/controls/colorpicker.pure.js.map +1 -1
- package/2D/controls/container.pure.js +597 -582
- package/2D/controls/container.pure.js.map +1 -1
- package/2D/controls/control.pure.js +2474 -2434
- package/2D/controls/control.pure.js.map +1 -1
- package/2D/controls/displayGrid.pure.js +201 -190
- package/2D/controls/displayGrid.pure.js.map +1 -1
- package/2D/controls/ellipse.pure.js +96 -85
- package/2D/controls/ellipse.pure.js.map +1 -1
- package/2D/controls/grid.pure.js +511 -500
- package/2D/controls/grid.pure.js.map +1 -1
- package/2D/controls/image.pure.js +888 -877
- package/2D/controls/image.pure.js.map +1 -1
- package/2D/controls/inputText.pure.js +988 -973
- package/2D/controls/inputText.pure.js.map +1 -1
- package/2D/controls/inputTextArea.pure.js +955 -944
- package/2D/controls/inputTextArea.pure.js.map +1 -1
- package/2D/controls/line.pure.js +237 -226
- package/2D/controls/line.pure.js.map +1 -1
- package/2D/controls/multiLine.pure.js +233 -222
- package/2D/controls/multiLine.pure.js.map +1 -1
- package/2D/controls/radioButton.pure.js +182 -169
- package/2D/controls/radioButton.pure.js.map +1 -1
- package/2D/controls/rectangle.pure.js +211 -200
- package/2D/controls/rectangle.pure.js.map +1 -1
- package/2D/controls/scrollViewers/scrollViewer.pure.js +579 -567
- package/2D/controls/scrollViewers/scrollViewer.pure.js.map +1 -1
- package/2D/controls/sliders/baseSlider.js +291 -280
- package/2D/controls/sliders/baseSlider.js.map +1 -1
- package/2D/controls/sliders/imageBasedSlider.pure.js +158 -147
- package/2D/controls/sliders/imageBasedSlider.pure.js.map +1 -1
- package/2D/controls/sliders/imageScrollBar.js +237 -223
- package/2D/controls/sliders/imageScrollBar.js.map +1 -1
- package/2D/controls/sliders/scrollBar.pure.js +169 -158
- package/2D/controls/sliders/scrollBar.pure.js.map +1 -1
- package/2D/controls/sliders/slider.pure.js +251 -240
- package/2D/controls/sliders/slider.pure.js.map +1 -1
- package/2D/controls/stackPanel.pure.js +236 -221
- package/2D/controls/stackPanel.pure.js.map +1 -1
- package/2D/controls/textBlock.pure.js +637 -626
- package/2D/controls/textBlock.pure.js.map +1 -1
- package/3D/materials/fluent/fluentMaterial.pure.d.ts +4 -4
- package/3D/materials/fluent/fluentMaterial.pure.js +322 -273
- package/3D/materials/fluent/fluentMaterial.pure.js.map +1 -1
- package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js +510 -454
- package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js.map +1 -1
- package/3D/materials/fluentButton/fluentButtonMaterial.pure.js +612 -529
- package/3D/materials/fluentButton/fluentButtonMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js +313 -274
- package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js +462 -405
- package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js +583 -501
- package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js +226 -203
- package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js +961 -825
- package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js +961 -825
- package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __esDecorate, __runInitializers } from "@babylonjs/core/tslib.es6.js";
|
|
2
2
|
import { Observable } from "@babylonjs/core/Misc/observable.js";
|
|
3
3
|
import { Tools } from "@babylonjs/core/Misc/tools.pure.js";
|
|
4
4
|
import { Control } from "./control.pure.js";
|
|
@@ -8,910 +8,921 @@ import { EngineStore } from "@babylonjs/core/Engines/engineStore.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* Class used to create 2D images
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
set sliceTop(value) {
|
|
67
|
-
if (this._sliceTop === value) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this._sliceTop = value;
|
|
71
|
-
this._markAsDirty();
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Gets or sets the bottom value for slicing (9-patch)
|
|
75
|
-
*/
|
|
76
|
-
get sliceBottom() {
|
|
77
|
-
return this._sliceBottom;
|
|
78
|
-
}
|
|
79
|
-
set sliceBottom(value) {
|
|
80
|
-
if (this._sliceBottom === value) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
this._sliceBottom = value;
|
|
84
|
-
this._markAsDirty();
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Gets or sets the left coordinate in the source image
|
|
88
|
-
*/
|
|
89
|
-
get sourceLeft() {
|
|
90
|
-
return this._sourceLeft;
|
|
91
|
-
}
|
|
92
|
-
set sourceLeft(value) {
|
|
93
|
-
if (this._sourceLeft === value) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
this._sourceLeft = value;
|
|
97
|
-
this._markAsDirty();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Gets or sets the top coordinate in the source image
|
|
101
|
-
*/
|
|
102
|
-
get sourceTop() {
|
|
103
|
-
return this._sourceTop;
|
|
104
|
-
}
|
|
105
|
-
set sourceTop(value) {
|
|
106
|
-
if (this._sourceTop === value) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
this._sourceTop = value;
|
|
110
|
-
this._markAsDirty();
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Gets or sets the width to capture in the source image
|
|
114
|
-
*/
|
|
115
|
-
get sourceWidth() {
|
|
116
|
-
return this._sourceWidth;
|
|
117
|
-
}
|
|
118
|
-
set sourceWidth(value) {
|
|
119
|
-
if (this._sourceWidth === value) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
this._sourceWidth = value;
|
|
123
|
-
this._markAsDirty();
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Gets or sets the height to capture in the source image
|
|
127
|
-
*/
|
|
128
|
-
get sourceHeight() {
|
|
129
|
-
return this._sourceHeight;
|
|
130
|
-
}
|
|
131
|
-
set sourceHeight(value) {
|
|
132
|
-
if (this._sourceHeight === value) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
this._sourceHeight = value;
|
|
136
|
-
this._markAsDirty();
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Gets the image width
|
|
140
|
-
*/
|
|
141
|
-
get imageWidth() {
|
|
142
|
-
return this._imageWidth;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Gets the image height
|
|
146
|
-
*/
|
|
147
|
-
get imageHeight() {
|
|
148
|
-
return this._imageHeight;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Gets or sets a boolean indicating if nine patch slices (left, top, right, bottom) should be read from image data
|
|
152
|
-
*/
|
|
153
|
-
get populateNinePatchSlicesFromImage() {
|
|
154
|
-
return this._populateNinePatchSlicesFromImage;
|
|
155
|
-
}
|
|
156
|
-
set populateNinePatchSlicesFromImage(value) {
|
|
157
|
-
if (this._populateNinePatchSlicesFromImage === value) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
this._populateNinePatchSlicesFromImage = value;
|
|
161
|
-
if (this._populateNinePatchSlicesFromImage && this._loaded) {
|
|
162
|
-
this._extractNinePatchSliceDataFromImage();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/** Indicates if the format of the image is SVG */
|
|
166
|
-
get isSVG() {
|
|
167
|
-
return this._isSVG;
|
|
168
|
-
}
|
|
169
|
-
/** Gets the status of the SVG attributes computation (sourceLeft, sourceTop, sourceWidth, sourceHeight) */
|
|
170
|
-
get svgAttributesComputationCompleted() {
|
|
171
|
-
return this._svgAttributesComputationCompleted;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Gets or sets a boolean indicating if the image can force its container to adapt its size
|
|
175
|
-
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
176
|
-
*/
|
|
177
|
-
get autoScale() {
|
|
178
|
-
return this._autoScale;
|
|
179
|
-
}
|
|
180
|
-
set autoScale(value) {
|
|
181
|
-
if (this._autoScale === value) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
this._autoScale = value;
|
|
185
|
-
if (value && this._loaded) {
|
|
186
|
-
this.synchronizeSizeWithContent();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/** Gets or sets the stretching mode used by the image */
|
|
190
|
-
get stretch() {
|
|
191
|
-
return this._stretch;
|
|
192
|
-
}
|
|
193
|
-
set stretch(value) {
|
|
194
|
-
if (this._stretch === value) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
this._stretch = value;
|
|
198
|
-
this._markAsDirty();
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* @internal
|
|
202
|
-
*/
|
|
203
|
-
_rotate90(n, preserveProperties = false) {
|
|
204
|
-
const width = this._domImage.width;
|
|
205
|
-
const height = this._domImage.height;
|
|
206
|
-
// Should abstract platform instead of using LastCreatedEngine
|
|
207
|
-
const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
|
|
208
|
-
if (!engine) {
|
|
209
|
-
throw new Error("Invalid engine. Unable to create a canvas.");
|
|
210
|
-
}
|
|
211
|
-
const canvas = engine.createCanvas(height, width);
|
|
212
|
-
const context = canvas.getContext("2d");
|
|
213
|
-
context.translate(canvas.width / 2, canvas.height / 2);
|
|
214
|
-
context.rotate((n * Math.PI) / 2);
|
|
215
|
-
context.drawImage(this._domImage, 0, 0, width, height, -width / 2, -height / 2, width, height);
|
|
216
|
-
const dataUrl = canvas.toDataURL("image/jpg");
|
|
217
|
-
const rotatedImage = new Image(this.name + "rotated", dataUrl);
|
|
218
|
-
if (preserveProperties) {
|
|
219
|
-
rotatedImage._stretch = this._stretch;
|
|
220
|
-
rotatedImage._autoScale = this._autoScale;
|
|
221
|
-
rotatedImage._cellId = this._cellId;
|
|
222
|
-
rotatedImage._cellWidth = n % 1 ? this._cellHeight : this._cellWidth;
|
|
223
|
-
rotatedImage._cellHeight = n % 1 ? this._cellWidth : this._cellHeight;
|
|
224
|
-
}
|
|
225
|
-
this._handleRotationForSVGImage(this, rotatedImage, n);
|
|
226
|
-
this._imageDataCache.data = null;
|
|
227
|
-
return rotatedImage;
|
|
228
|
-
}
|
|
229
|
-
_handleRotationForSVGImage(srcImage, dstImage, n) {
|
|
230
|
-
if (!srcImage._isSVG) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
if (srcImage._svgAttributesComputationCompleted) {
|
|
234
|
-
this._rotate90SourceProperties(srcImage, dstImage, n);
|
|
235
|
-
this._markAsDirty();
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
srcImage.onSVGAttributesComputedObservable.addOnce(() => {
|
|
239
|
-
this._rotate90SourceProperties(srcImage, dstImage, n);
|
|
11
|
+
let Image = (() => {
|
|
12
|
+
var _a;
|
|
13
|
+
let _classSuper = Control;
|
|
14
|
+
let _instanceExtraInitializers = [];
|
|
15
|
+
let _get_detectPointerOnOpaqueOnly_decorators;
|
|
16
|
+
let _get_sliceLeft_decorators;
|
|
17
|
+
let _get_sliceRight_decorators;
|
|
18
|
+
let _get_sliceTop_decorators;
|
|
19
|
+
let _get_sliceBottom_decorators;
|
|
20
|
+
let _get_sourceLeft_decorators;
|
|
21
|
+
let _get_sourceTop_decorators;
|
|
22
|
+
let _get_sourceWidth_decorators;
|
|
23
|
+
let _get_sourceHeight_decorators;
|
|
24
|
+
let _get_populateNinePatchSlicesFromImage_decorators;
|
|
25
|
+
let _get_autoScale_decorators;
|
|
26
|
+
let _get_stretch_decorators;
|
|
27
|
+
let _get_source_decorators;
|
|
28
|
+
let _get_cellWidth_decorators;
|
|
29
|
+
let _get_cellHeight_decorators;
|
|
30
|
+
let _get_cellId_decorators;
|
|
31
|
+
return _a = class Image extends _classSuper {
|
|
32
|
+
/**
|
|
33
|
+
* Gets a boolean indicating that the content is loaded
|
|
34
|
+
*/
|
|
35
|
+
get isLoaded() {
|
|
36
|
+
return this._loaded;
|
|
37
|
+
}
|
|
38
|
+
isReady() {
|
|
39
|
+
return this.isLoaded;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Gets or sets a boolean indicating if pointers should only be validated on pixels with alpha > 0.
|
|
43
|
+
* Beware using this as this will consume more memory as the image has to be stored twice
|
|
44
|
+
*/
|
|
45
|
+
get detectPointerOnOpaqueOnly() {
|
|
46
|
+
return this._detectPointerOnOpaqueOnly;
|
|
47
|
+
}
|
|
48
|
+
set detectPointerOnOpaqueOnly(value) {
|
|
49
|
+
if (this._detectPointerOnOpaqueOnly === value) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this._detectPointerOnOpaqueOnly = value;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Gets or sets the left value for slicing (9-patch)
|
|
56
|
+
*/
|
|
57
|
+
get sliceLeft() {
|
|
58
|
+
return this._sliceLeft;
|
|
59
|
+
}
|
|
60
|
+
set sliceLeft(value) {
|
|
61
|
+
if (this._sliceLeft === value) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this._sliceLeft = value;
|
|
240
65
|
this._markAsDirty();
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Gets or sets the right value for slicing (9-patch)
|
|
69
|
+
*/
|
|
70
|
+
get sliceRight() {
|
|
71
|
+
return this._sliceRight;
|
|
72
|
+
}
|
|
73
|
+
set sliceRight(value) {
|
|
74
|
+
if (this._sliceRight === value) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this._sliceRight = value;
|
|
78
|
+
this._markAsDirty();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Gets or sets the top value for slicing (9-patch)
|
|
82
|
+
*/
|
|
83
|
+
get sliceTop() {
|
|
84
|
+
return this._sliceTop;
|
|
85
|
+
}
|
|
86
|
+
set sliceTop(value) {
|
|
87
|
+
if (this._sliceTop === value) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this._sliceTop = value;
|
|
91
|
+
this._markAsDirty();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Gets or sets the bottom value for slicing (9-patch)
|
|
95
|
+
*/
|
|
96
|
+
get sliceBottom() {
|
|
97
|
+
return this._sliceBottom;
|
|
98
|
+
}
|
|
99
|
+
set sliceBottom(value) {
|
|
100
|
+
if (this._sliceBottom === value) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this._sliceBottom = value;
|
|
104
|
+
this._markAsDirty();
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Gets or sets the left coordinate in the source image
|
|
108
|
+
*/
|
|
109
|
+
get sourceLeft() {
|
|
110
|
+
return this._sourceLeft;
|
|
111
|
+
}
|
|
112
|
+
set sourceLeft(value) {
|
|
113
|
+
if (this._sourceLeft === value) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this._sourceLeft = value;
|
|
117
|
+
this._markAsDirty();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Gets or sets the top coordinate in the source image
|
|
121
|
+
*/
|
|
122
|
+
get sourceTop() {
|
|
123
|
+
return this._sourceTop;
|
|
124
|
+
}
|
|
125
|
+
set sourceTop(value) {
|
|
126
|
+
if (this._sourceTop === value) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this._sourceTop = value;
|
|
130
|
+
this._markAsDirty();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Gets or sets the width to capture in the source image
|
|
134
|
+
*/
|
|
135
|
+
get sourceWidth() {
|
|
136
|
+
return this._sourceWidth;
|
|
137
|
+
}
|
|
138
|
+
set sourceWidth(value) {
|
|
139
|
+
if (this._sourceWidth === value) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this._sourceWidth = value;
|
|
143
|
+
this._markAsDirty();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Gets or sets the height to capture in the source image
|
|
147
|
+
*/
|
|
148
|
+
get sourceHeight() {
|
|
149
|
+
return this._sourceHeight;
|
|
150
|
+
}
|
|
151
|
+
set sourceHeight(value) {
|
|
152
|
+
if (this._sourceHeight === value) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this._sourceHeight = value;
|
|
156
|
+
this._markAsDirty();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Gets the image width
|
|
160
|
+
*/
|
|
161
|
+
get imageWidth() {
|
|
162
|
+
return this._imageWidth;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets the image height
|
|
166
|
+
*/
|
|
167
|
+
get imageHeight() {
|
|
168
|
+
return this._imageHeight;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Gets or sets a boolean indicating if nine patch slices (left, top, right, bottom) should be read from image data
|
|
172
|
+
*/
|
|
173
|
+
get populateNinePatchSlicesFromImage() {
|
|
174
|
+
return this._populateNinePatchSlicesFromImage;
|
|
175
|
+
}
|
|
176
|
+
set populateNinePatchSlicesFromImage(value) {
|
|
177
|
+
if (this._populateNinePatchSlicesFromImage === value) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this._populateNinePatchSlicesFromImage = value;
|
|
181
|
+
if (this._populateNinePatchSlicesFromImage && this._loaded) {
|
|
182
|
+
this._extractNinePatchSliceDataFromImage();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** Indicates if the format of the image is SVG */
|
|
186
|
+
get isSVG() {
|
|
187
|
+
return this._isSVG;
|
|
188
|
+
}
|
|
189
|
+
/** Gets the status of the SVG attributes computation (sourceLeft, sourceTop, sourceWidth, sourceHeight) */
|
|
190
|
+
get svgAttributesComputationCompleted() {
|
|
191
|
+
return this._svgAttributesComputationCompleted;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Gets or sets a boolean indicating if the image can force its container to adapt its size
|
|
195
|
+
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
196
|
+
*/
|
|
197
|
+
get autoScale() {
|
|
198
|
+
return this._autoScale;
|
|
199
|
+
}
|
|
200
|
+
set autoScale(value) {
|
|
201
|
+
if (this._autoScale === value) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this._autoScale = value;
|
|
205
|
+
if (value && this._loaded) {
|
|
206
|
+
this.synchronizeSizeWithContent();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** Gets or sets the stretching mode used by the image */
|
|
210
|
+
get stretch() {
|
|
211
|
+
return this._stretch;
|
|
212
|
+
}
|
|
213
|
+
set stretch(value) {
|
|
214
|
+
if (this._stretch === value) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this._stretch = value;
|
|
218
|
+
this._markAsDirty();
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* @internal
|
|
222
|
+
*/
|
|
223
|
+
_rotate90(n, preserveProperties = false) {
|
|
224
|
+
const width = this._domImage.width;
|
|
225
|
+
const height = this._domImage.height;
|
|
226
|
+
// Should abstract platform instead of using LastCreatedEngine
|
|
227
|
+
const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
|
|
228
|
+
if (!engine) {
|
|
229
|
+
throw new Error("Invalid engine. Unable to create a canvas.");
|
|
230
|
+
}
|
|
231
|
+
const canvas = engine.createCanvas(height, width);
|
|
232
|
+
const context = canvas.getContext("2d");
|
|
233
|
+
context.translate(canvas.width / 2, canvas.height / 2);
|
|
234
|
+
context.rotate((n * Math.PI) / 2);
|
|
235
|
+
context.drawImage(this._domImage, 0, 0, width, height, -width / 2, -height / 2, width, height);
|
|
236
|
+
const dataUrl = canvas.toDataURL("image/jpg");
|
|
237
|
+
const rotatedImage = new _a(this.name + "rotated", dataUrl);
|
|
238
|
+
if (preserveProperties) {
|
|
239
|
+
rotatedImage._stretch = this._stretch;
|
|
240
|
+
rotatedImage._autoScale = this._autoScale;
|
|
241
|
+
rotatedImage._cellId = this._cellId;
|
|
242
|
+
rotatedImage._cellWidth = n % 1 ? this._cellHeight : this._cellWidth;
|
|
243
|
+
rotatedImage._cellHeight = n % 1 ? this._cellWidth : this._cellHeight;
|
|
244
|
+
}
|
|
245
|
+
this._handleRotationForSVGImage(this, rotatedImage, n);
|
|
246
|
+
this._imageDataCache.data = null;
|
|
247
|
+
return rotatedImage;
|
|
248
|
+
}
|
|
249
|
+
_handleRotationForSVGImage(srcImage, dstImage, n) {
|
|
250
|
+
if (!srcImage._isSVG) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (srcImage._svgAttributesComputationCompleted) {
|
|
254
|
+
this._rotate90SourceProperties(srcImage, dstImage, n);
|
|
255
|
+
this._markAsDirty();
|
|
256
256
|
}
|
|
257
257
|
else {
|
|
258
|
-
|
|
258
|
+
srcImage.onSVGAttributesComputedObservable.addOnce(() => {
|
|
259
|
+
this._rotate90SourceProperties(srcImage, dstImage, n);
|
|
260
|
+
this._markAsDirty();
|
|
261
|
+
});
|
|
259
262
|
}
|
|
260
|
-
srcLeft = dstLeft;
|
|
261
|
-
srcTop = dstTop;
|
|
262
|
-
[srcWidth, srcHeight] = [srcHeight, srcWidth];
|
|
263
263
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (cachedData) {
|
|
426
|
-
cachedData.loaded = true;
|
|
427
|
-
for (const waitingCallback of cachedData.waitingForLoadCallback) {
|
|
428
|
-
waitingCallback();
|
|
264
|
+
_rotate90SourceProperties(srcImage, dstImage, n) {
|
|
265
|
+
let srcLeft = srcImage.sourceLeft, srcTop = srcImage.sourceTop, srcWidth = srcImage.domImage.width, srcHeight = srcImage.domImage.height;
|
|
266
|
+
let dstLeft = srcLeft, dstTop = srcTop, dstWidth = srcImage.sourceWidth, dstHeight = srcImage.sourceHeight;
|
|
267
|
+
if (n != 0) {
|
|
268
|
+
const mult = n < 0 ? -1 : 1;
|
|
269
|
+
n = n % 4;
|
|
270
|
+
for (let i = 0; i < Math.abs(n); ++i) {
|
|
271
|
+
dstLeft = -(srcTop - srcHeight / 2) * mult + srcHeight / 2;
|
|
272
|
+
dstTop = (srcLeft - srcWidth / 2) * mult + srcWidth / 2;
|
|
273
|
+
[dstWidth, dstHeight] = [dstHeight, dstWidth];
|
|
274
|
+
if (n < 0) {
|
|
275
|
+
dstTop -= dstHeight;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
dstLeft -= dstWidth;
|
|
279
|
+
}
|
|
280
|
+
srcLeft = dstLeft;
|
|
281
|
+
srcTop = dstTop;
|
|
282
|
+
[srcWidth, srcHeight] = [srcHeight, srcWidth];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
dstImage.sourceLeft = dstLeft;
|
|
286
|
+
dstImage.sourceTop = dstTop;
|
|
287
|
+
dstImage.sourceWidth = dstWidth;
|
|
288
|
+
dstImage.sourceHeight = dstHeight;
|
|
289
|
+
}
|
|
290
|
+
_extractNinePatchSliceDataFromImage() {
|
|
291
|
+
const width = this._domImage.width;
|
|
292
|
+
const height = this._domImage.height;
|
|
293
|
+
if (!this._workingCanvas) {
|
|
294
|
+
const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
|
|
295
|
+
if (!engine) {
|
|
296
|
+
throw new Error("Invalid engine. Unable to create a canvas.");
|
|
297
|
+
}
|
|
298
|
+
this._workingCanvas = engine.createCanvas(width, height);
|
|
299
|
+
}
|
|
300
|
+
const canvas = this._workingCanvas;
|
|
301
|
+
const context = canvas.getContext("2d");
|
|
302
|
+
context.drawImage(this._domImage, 0, 0, width, height);
|
|
303
|
+
const imageData = context.getImageData(0, 0, width, height);
|
|
304
|
+
// Left and right
|
|
305
|
+
this._sliceLeft = -1;
|
|
306
|
+
this._sliceRight = -1;
|
|
307
|
+
for (let x = 0; x < width; x++) {
|
|
308
|
+
const alpha = imageData.data[x * 4 + 3];
|
|
309
|
+
if (alpha > 127 && this._sliceLeft === -1) {
|
|
310
|
+
this._sliceLeft = x;
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
if (alpha < 127 && this._sliceLeft > -1) {
|
|
314
|
+
this._sliceRight = x;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// top and bottom
|
|
319
|
+
this._sliceTop = -1;
|
|
320
|
+
this._sliceBottom = -1;
|
|
321
|
+
for (let y = 0; y < height; y++) {
|
|
322
|
+
const alpha = imageData.data[y * width * 4 + 3];
|
|
323
|
+
if (alpha > 127 && this._sliceTop === -1) {
|
|
324
|
+
this._sliceTop = y;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (alpha < 127 && this._sliceTop > -1) {
|
|
328
|
+
this._sliceBottom = y;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Gets or sets the internal DOM image used to render the control
|
|
335
|
+
*/
|
|
336
|
+
set domImage(value) {
|
|
337
|
+
this._domImage = value;
|
|
338
|
+
this._loaded = false;
|
|
339
|
+
this._imageDataCache.data = null;
|
|
340
|
+
if (this._domImage.width) {
|
|
341
|
+
this._onImageLoaded();
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
this._domImage.onload = () => {
|
|
345
|
+
this._onImageLoaded();
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
get domImage() {
|
|
350
|
+
return this._domImage;
|
|
351
|
+
}
|
|
352
|
+
_onImageLoaded() {
|
|
353
|
+
this._imageDataCache.data = null;
|
|
354
|
+
this._imageWidth = this._domImage.width;
|
|
355
|
+
this._imageHeight = this._domImage.height;
|
|
356
|
+
this._loaded = true;
|
|
357
|
+
if (this._populateNinePatchSlicesFromImage) {
|
|
358
|
+
this._extractNinePatchSliceDataFromImage();
|
|
359
|
+
}
|
|
360
|
+
if (this._autoScale) {
|
|
361
|
+
this.synchronizeSizeWithContent();
|
|
362
|
+
}
|
|
363
|
+
this.onImageLoadedObservable.notifyObservers(this);
|
|
364
|
+
this._markAsDirty();
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Gets the image source url
|
|
368
|
+
*/
|
|
369
|
+
get source() {
|
|
370
|
+
return this._source;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Resets the internal Image Element cache. Can reduce memory usage.
|
|
374
|
+
*/
|
|
375
|
+
static ResetImageCache() {
|
|
376
|
+
_a.SourceImgCache.clear();
|
|
377
|
+
}
|
|
378
|
+
_removeCacheUsage(source) {
|
|
379
|
+
const value = source && _a.SourceImgCache.get(source);
|
|
380
|
+
if (value) {
|
|
381
|
+
value.timesUsed -= 1;
|
|
382
|
+
// Remove from DOM
|
|
383
|
+
const htmlElement = value.img;
|
|
384
|
+
if (htmlElement.parentNode) {
|
|
385
|
+
htmlElement.parentNode.removeChild(htmlElement);
|
|
386
|
+
}
|
|
387
|
+
// Since the image isn't being used anymore, we can clean it from the cache
|
|
388
|
+
if (value.timesUsed === 0) {
|
|
389
|
+
_a.SourceImgCache.delete(source);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Gets or sets image source url
|
|
395
|
+
*/
|
|
396
|
+
set source(value) {
|
|
397
|
+
if (this._urlRewriter && value) {
|
|
398
|
+
value = this._urlRewriter(value);
|
|
399
|
+
}
|
|
400
|
+
if (this._source === value) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
this._removeCacheUsage(this._source);
|
|
404
|
+
this._loaded = false;
|
|
405
|
+
this._source = value;
|
|
406
|
+
this._imageDataCache.data = null;
|
|
407
|
+
if (value) {
|
|
408
|
+
value = this._svgCheck(value);
|
|
409
|
+
}
|
|
410
|
+
// Should abstract platform instead of using LastCreatedEngine
|
|
411
|
+
const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
|
|
412
|
+
// If no engine, skip all other DOM operations.
|
|
413
|
+
if (!engine) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (value && _a.SourceImgCache.has(value)) {
|
|
417
|
+
const cachedData = _a.SourceImgCache.get(value);
|
|
418
|
+
this._domImage = cachedData.img;
|
|
419
|
+
cachedData.timesUsed += 1;
|
|
420
|
+
if (cachedData.loaded) {
|
|
421
|
+
this._onImageLoaded();
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
cachedData.waitingForLoadCallback.push(this._onImageLoaded.bind(this));
|
|
429
425
|
}
|
|
430
|
-
cachedData.waitingForLoadCallback.length = 0;
|
|
431
|
-
addedToDom && imgElement.remove();
|
|
432
426
|
return;
|
|
433
427
|
}
|
|
428
|
+
this._domImage = engine.createCanvasImage();
|
|
429
|
+
// need to add to enforce rendering
|
|
430
|
+
const imgElement = this._domImage;
|
|
431
|
+
let addedToDom = false;
|
|
432
|
+
if (imgElement.style && this._source?.endsWith(".svg")) {
|
|
433
|
+
imgElement.style.visibility = "hidden";
|
|
434
|
+
imgElement.style.position = "absolute";
|
|
435
|
+
imgElement.style.top = "0";
|
|
436
|
+
engine.getRenderingCanvas()?.parentNode?.appendChild(imgElement);
|
|
437
|
+
addedToDom = true;
|
|
438
|
+
}
|
|
439
|
+
if (value) {
|
|
440
|
+
_a.SourceImgCache.set(value, { img: this._domImage, timesUsed: 1, loaded: false, waitingForLoadCallback: [this._onImageLoaded.bind(this)] });
|
|
441
|
+
}
|
|
442
|
+
this._domImage.onload = () => {
|
|
443
|
+
if (value) {
|
|
444
|
+
const cachedData = _a.SourceImgCache.get(value);
|
|
445
|
+
if (cachedData) {
|
|
446
|
+
cachedData.loaded = true;
|
|
447
|
+
for (const waitingCallback of cachedData.waitingForLoadCallback) {
|
|
448
|
+
waitingCallback();
|
|
449
|
+
}
|
|
450
|
+
cachedData.waitingForLoadCallback.length = 0;
|
|
451
|
+
addedToDom && imgElement.remove();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
this._onImageLoaded();
|
|
456
|
+
addedToDom && imgElement.remove();
|
|
457
|
+
};
|
|
458
|
+
if (value) {
|
|
459
|
+
Tools.SetCorsBehavior(value, this._domImage);
|
|
460
|
+
Tools.SetReferrerPolicyBehavior(this.referrerPolicy, this._domImage);
|
|
461
|
+
this._domImage.src = value;
|
|
462
|
+
}
|
|
434
463
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
// Remove dangerous attributes
|
|
467
|
-
if (dangerousAttrs.some((regex) => regex.test(name))) {
|
|
468
|
-
el.removeAttribute(name);
|
|
464
|
+
_sanitizeSVG(svgString) {
|
|
465
|
+
if (svgString.indexOf("<svg") === -1) {
|
|
466
|
+
return svgString; // Not an SVG, return as is
|
|
467
|
+
}
|
|
468
|
+
const parser = new DOMParser();
|
|
469
|
+
const doc = parser.parseFromString(svgString, "image/svg+xml");
|
|
470
|
+
const dangerousTags = ["script", "iframe", "foreignObject", "object", "embed", "link", "style"];
|
|
471
|
+
const dangerousAttrs = [/^on/i, /^xlink:href$/, /^href$/];
|
|
472
|
+
// Remove dangerous elements
|
|
473
|
+
dangerousTags.forEach((tag) => {
|
|
474
|
+
const elements = doc.getElementsByTagName(tag);
|
|
475
|
+
for (let i = elements.length - 1; i >= 0; i--) {
|
|
476
|
+
elements[i].remove();
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
// Recursively sanitize attributes
|
|
480
|
+
function sanitizeElement(el) {
|
|
481
|
+
if (el.attributes) {
|
|
482
|
+
for (let i = el.attributes.length - 1; i >= 0; i--) {
|
|
483
|
+
const attr = el.attributes[i];
|
|
484
|
+
const name = attr.name;
|
|
485
|
+
const value = attr.value;
|
|
486
|
+
// Remove dangerous attributes
|
|
487
|
+
if (dangerousAttrs.some((regex) => regex.test(name))) {
|
|
488
|
+
el.removeAttribute(name);
|
|
489
|
+
}
|
|
490
|
+
// Remove javascript: links
|
|
491
|
+
if (typeof value === "string" && value.trim().toLowerCase().startsWith("javascript:")) {
|
|
492
|
+
el.removeAttribute(name);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
469
495
|
}
|
|
470
|
-
//
|
|
471
|
-
|
|
472
|
-
el.
|
|
496
|
+
// Recursively sanitize children
|
|
497
|
+
for (let i = 0; i < el.children.length; i++) {
|
|
498
|
+
sanitizeElement(el.children[i]);
|
|
473
499
|
}
|
|
474
500
|
}
|
|
501
|
+
sanitizeElement(doc.documentElement);
|
|
502
|
+
return new XMLSerializer().serializeToString(doc);
|
|
475
503
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Checks for svg document with icon id present
|
|
506
|
+
* @param value the source svg
|
|
507
|
+
* @returns the svg
|
|
508
|
+
*/
|
|
509
|
+
_svgCheck(value) {
|
|
510
|
+
// Skip SVG processing if no window/document or SVG support
|
|
511
|
+
if (typeof window === "undefined" || typeof document === "undefined" || !window.SVGSVGElement) {
|
|
512
|
+
return value;
|
|
513
|
+
}
|
|
514
|
+
if (window.SVGSVGElement && value.search(/(\.svg|\.svg?[?|#].*)$/gi) !== -1 && value.indexOf("#") === value.lastIndexOf("#")) {
|
|
515
|
+
this._isSVG = true;
|
|
516
|
+
value = this._sanitizeSVG(value);
|
|
517
|
+
const svgsrc = value.split("#")[0];
|
|
518
|
+
const elemid = value.split("#")[1];
|
|
519
|
+
// check if object alr exist in document
|
|
520
|
+
const svgExist = document.body.querySelector('object[data="' + svgsrc + '"]');
|
|
521
|
+
if (svgExist) {
|
|
522
|
+
const svgDoc = svgExist.contentDocument;
|
|
523
|
+
// get viewbox width and height, get svg document width and height in px
|
|
524
|
+
if (svgDoc && svgDoc.documentElement) {
|
|
525
|
+
const vb = svgDoc.documentElement.getAttribute("viewBox");
|
|
526
|
+
const docwidth = Number(svgDoc.documentElement.getAttribute("width"));
|
|
527
|
+
const docheight = Number(svgDoc.documentElement.getAttribute("height"));
|
|
528
|
+
const elem = svgDoc.getElementById(elemid);
|
|
529
|
+
if (elem && vb && docwidth && docheight) {
|
|
530
|
+
this._getSVGAttribs(svgExist, elemid);
|
|
531
|
+
return value;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// wait for object to load
|
|
535
|
+
svgExist.addEventListener("load", () => {
|
|
536
|
+
this._getSVGAttribs(svgExist, elemid);
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
// create document object
|
|
541
|
+
const svgImage = document.createElement("object");
|
|
542
|
+
svgImage.data = svgsrc;
|
|
543
|
+
svgImage.type = "image/svg+xml";
|
|
544
|
+
svgImage.width = "0%";
|
|
545
|
+
svgImage.height = "0%";
|
|
546
|
+
document.body.appendChild(svgImage);
|
|
547
|
+
// when the object has loaded, get the element attribs
|
|
548
|
+
svgImage.onload = () => {
|
|
549
|
+
const svgobj = document.body.querySelector('object[data="' + svgsrc + '"]');
|
|
550
|
+
if (svgobj) {
|
|
551
|
+
this._getSVGAttribs(svgobj, elemid);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
return svgsrc;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
479
560
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
*/
|
|
489
|
-
_svgCheck(value) {
|
|
490
|
-
// Skip SVG processing if no window/document or SVG support
|
|
491
|
-
if (typeof window === "undefined" || typeof document === "undefined" || !window.SVGSVGElement) {
|
|
492
|
-
return value;
|
|
493
|
-
}
|
|
494
|
-
if (window.SVGSVGElement && value.search(/(\.svg|\.svg?[?|#].*)$/gi) !== -1 && value.indexOf("#") === value.lastIndexOf("#")) {
|
|
495
|
-
this._isSVG = true;
|
|
496
|
-
value = this._sanitizeSVG(value);
|
|
497
|
-
const svgsrc = value.split("#")[0];
|
|
498
|
-
const elemid = value.split("#")[1];
|
|
499
|
-
// check if object alr exist in document
|
|
500
|
-
const svgExist = document.body.querySelector('object[data="' + svgsrc + '"]');
|
|
501
|
-
if (svgExist) {
|
|
502
|
-
const svgDoc = svgExist.contentDocument;
|
|
561
|
+
/**
|
|
562
|
+
* Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
|
|
563
|
+
* given external svg file and icon id
|
|
564
|
+
* @param svgsrc
|
|
565
|
+
* @param elemid
|
|
566
|
+
*/
|
|
567
|
+
_getSVGAttribs(svgsrc, elemid) {
|
|
568
|
+
const svgDoc = svgsrc.contentDocument;
|
|
503
569
|
// get viewbox width and height, get svg document width and height in px
|
|
504
570
|
if (svgDoc && svgDoc.documentElement) {
|
|
505
571
|
const vb = svgDoc.documentElement.getAttribute("viewBox");
|
|
506
572
|
const docwidth = Number(svgDoc.documentElement.getAttribute("width"));
|
|
507
573
|
const docheight = Number(svgDoc.documentElement.getAttribute("height"));
|
|
574
|
+
// get element bbox and matrix transform
|
|
508
575
|
const elem = svgDoc.getElementById(elemid);
|
|
509
|
-
if (
|
|
510
|
-
|
|
511
|
-
|
|
576
|
+
if (vb && docwidth && docheight && elem) {
|
|
577
|
+
const vbWidth = Number(vb.split(" ")[2]);
|
|
578
|
+
const vbHeight = Number(vb.split(" ")[3]);
|
|
579
|
+
const elemBbox = elem.getBBox();
|
|
580
|
+
let elemMatrixA = 1;
|
|
581
|
+
let elemMatrixD = 1;
|
|
582
|
+
let elemMatrixE = 0;
|
|
583
|
+
let elemMatrixF = 0;
|
|
584
|
+
const consolidatedTransform = elem.transform?.baseVal.consolidate();
|
|
585
|
+
if (consolidatedTransform) {
|
|
586
|
+
const mainMatrix = consolidatedTransform.matrix;
|
|
587
|
+
elemMatrixA = mainMatrix.a;
|
|
588
|
+
elemMatrixD = mainMatrix.d;
|
|
589
|
+
elemMatrixE = mainMatrix.e;
|
|
590
|
+
elemMatrixF = mainMatrix.f;
|
|
591
|
+
}
|
|
592
|
+
// compute source coordinates and dimensions
|
|
593
|
+
this.sourceLeft = ((elemMatrixA * elemBbox.x + elemMatrixE) * docwidth) / vbWidth;
|
|
594
|
+
this.sourceTop = ((elemMatrixD * elemBbox.y + elemMatrixF) * docheight) / vbHeight;
|
|
595
|
+
this.sourceWidth = elemBbox.width * elemMatrixA * (docwidth / vbWidth);
|
|
596
|
+
this.sourceHeight = elemBbox.height * elemMatrixD * (docheight / vbHeight);
|
|
597
|
+
this._svgAttributesComputationCompleted = true;
|
|
598
|
+
this.onSVGAttributesComputedObservable.notifyObservers(this);
|
|
512
599
|
}
|
|
513
600
|
}
|
|
514
|
-
// wait for object to load
|
|
515
|
-
svgExist.addEventListener("load", () => {
|
|
516
|
-
this._getSVGAttribs(svgExist, elemid);
|
|
517
|
-
});
|
|
518
601
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Gets or sets the cell width to use when animation sheet is enabled
|
|
604
|
+
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
605
|
+
*/
|
|
606
|
+
get cellWidth() {
|
|
607
|
+
return this._cellWidth;
|
|
608
|
+
}
|
|
609
|
+
set cellWidth(value) {
|
|
610
|
+
if (this._cellWidth === value) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
this._cellWidth = value;
|
|
614
|
+
this._markAsDirty();
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Gets or sets the cell height to use when animation sheet is enabled
|
|
618
|
+
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
619
|
+
*/
|
|
620
|
+
get cellHeight() {
|
|
621
|
+
return this._cellHeight;
|
|
622
|
+
}
|
|
623
|
+
set cellHeight(value) {
|
|
624
|
+
if (this._cellHeight === value) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
this._cellHeight = value;
|
|
628
|
+
this._markAsDirty();
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Gets or sets the cell id to use (this will turn on the animation sheet mode)
|
|
632
|
+
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
633
|
+
*/
|
|
634
|
+
get cellId() {
|
|
635
|
+
return this._cellId;
|
|
636
|
+
}
|
|
637
|
+
set cellId(value) {
|
|
638
|
+
if (this._cellId === value) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
this._cellId = value;
|
|
642
|
+
this._markAsDirty();
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Creates a new Image
|
|
646
|
+
* @param name defines the control name
|
|
647
|
+
* @param url defines the image url
|
|
648
|
+
*/
|
|
649
|
+
constructor(name, url = null) {
|
|
650
|
+
super(name);
|
|
651
|
+
this.name = (__runInitializers(this, _instanceExtraInitializers), name);
|
|
652
|
+
this._workingCanvas = null;
|
|
653
|
+
this._loaded = false;
|
|
654
|
+
this._stretch = _a.STRETCH_FILL;
|
|
655
|
+
this._source = null;
|
|
656
|
+
this._autoScale = false;
|
|
657
|
+
this._sourceLeft = 0;
|
|
658
|
+
this._sourceTop = 0;
|
|
659
|
+
this._sourceWidth = 0;
|
|
660
|
+
this._sourceHeight = 0;
|
|
661
|
+
this._svgAttributesComputationCompleted = false;
|
|
662
|
+
this._isSVG = false;
|
|
663
|
+
this._cellWidth = 0;
|
|
664
|
+
this._cellHeight = 0;
|
|
665
|
+
this._cellId = -1;
|
|
666
|
+
this._populateNinePatchSlicesFromImage = false;
|
|
667
|
+
this._imageDataCache = { data: null, key: "" };
|
|
668
|
+
/**
|
|
669
|
+
* Observable notified when the content is loaded
|
|
670
|
+
*/
|
|
671
|
+
this.onImageLoadedObservable = new Observable();
|
|
672
|
+
/**
|
|
673
|
+
* Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
|
|
674
|
+
*/
|
|
675
|
+
this.onSVGAttributesComputedObservable = new Observable();
|
|
676
|
+
this.source = url;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Tests if a given coordinates belong to the current control
|
|
680
|
+
* @param x defines x coordinate to test
|
|
681
|
+
* @param y defines y coordinate to test
|
|
682
|
+
* @returns true if the coordinates are inside the control
|
|
683
|
+
*/
|
|
684
|
+
contains(x, y) {
|
|
685
|
+
if (!super.contains(x, y)) {
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
if (!this._detectPointerOnOpaqueOnly || !this._workingCanvas) {
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
const width = this._currentMeasure.width | 0;
|
|
692
|
+
const height = this._currentMeasure.height | 0;
|
|
693
|
+
const key = width + "_" + height;
|
|
694
|
+
let imageData = this._imageDataCache.data;
|
|
695
|
+
if (!imageData || this._imageDataCache.key !== key) {
|
|
696
|
+
const canvas = this._workingCanvas;
|
|
697
|
+
const context = canvas.getContext("2d");
|
|
698
|
+
this._imageDataCache.data = imageData = context.getImageData(0, 0, width, height).data;
|
|
699
|
+
this._imageDataCache.key = key;
|
|
700
|
+
}
|
|
701
|
+
x = (x - this._currentMeasure.left) | 0;
|
|
702
|
+
y = (y - this._currentMeasure.top) | 0;
|
|
703
|
+
const pickedPixel = imageData[(x + y * width) * 4 + 3];
|
|
704
|
+
return pickedPixel > 0;
|
|
705
|
+
}
|
|
706
|
+
_getTypeName() {
|
|
707
|
+
return "Image";
|
|
708
|
+
}
|
|
709
|
+
/** Force the control to synchronize with its content */
|
|
710
|
+
synchronizeSizeWithContent() {
|
|
711
|
+
if (!this._loaded) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
this.width = this._domImage.width + "px";
|
|
715
|
+
this.height = this._domImage.height + "px";
|
|
716
|
+
}
|
|
717
|
+
_processMeasures(parentMeasure, context) {
|
|
718
|
+
if (this._loaded) {
|
|
719
|
+
switch (this._stretch) {
|
|
720
|
+
case _a.STRETCH_NONE:
|
|
721
|
+
break;
|
|
722
|
+
case _a.STRETCH_FILL:
|
|
723
|
+
break;
|
|
724
|
+
case _a.STRETCH_UNIFORM:
|
|
725
|
+
break;
|
|
726
|
+
case _a.STRETCH_NINE_PATCH:
|
|
727
|
+
break;
|
|
728
|
+
case _a.STRETCH_EXTEND:
|
|
729
|
+
if (this._autoScale) {
|
|
730
|
+
this.synchronizeSizeWithContent();
|
|
731
|
+
}
|
|
732
|
+
if (this.parent && this.parent.parent) {
|
|
733
|
+
// Will update root size if root is not the top root
|
|
734
|
+
this.parent.adaptWidthToChildren = true;
|
|
735
|
+
this.parent.adaptHeightToChildren = true;
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
532
738
|
}
|
|
533
|
-
}
|
|
739
|
+
}
|
|
740
|
+
super._processMeasures(parentMeasure, context);
|
|
534
741
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
* @param elemid
|
|
546
|
-
*/
|
|
547
|
-
_getSVGAttribs(svgsrc, elemid) {
|
|
548
|
-
const svgDoc = svgsrc.contentDocument;
|
|
549
|
-
// get viewbox width and height, get svg document width and height in px
|
|
550
|
-
if (svgDoc && svgDoc.documentElement) {
|
|
551
|
-
const vb = svgDoc.documentElement.getAttribute("viewBox");
|
|
552
|
-
const docwidth = Number(svgDoc.documentElement.getAttribute("width"));
|
|
553
|
-
const docheight = Number(svgDoc.documentElement.getAttribute("height"));
|
|
554
|
-
// get element bbox and matrix transform
|
|
555
|
-
const elem = svgDoc.getElementById(elemid);
|
|
556
|
-
if (vb && docwidth && docheight && elem) {
|
|
557
|
-
const vbWidth = Number(vb.split(" ")[2]);
|
|
558
|
-
const vbHeight = Number(vb.split(" ")[3]);
|
|
559
|
-
const elemBbox = elem.getBBox();
|
|
560
|
-
let elemMatrixA = 1;
|
|
561
|
-
let elemMatrixD = 1;
|
|
562
|
-
let elemMatrixE = 0;
|
|
563
|
-
let elemMatrixF = 0;
|
|
564
|
-
const consolidatedTransform = elem.transform?.baseVal.consolidate();
|
|
565
|
-
if (consolidatedTransform) {
|
|
566
|
-
const mainMatrix = consolidatedTransform.matrix;
|
|
567
|
-
elemMatrixA = mainMatrix.a;
|
|
568
|
-
elemMatrixD = mainMatrix.d;
|
|
569
|
-
elemMatrixE = mainMatrix.e;
|
|
570
|
-
elemMatrixF = mainMatrix.f;
|
|
571
|
-
}
|
|
572
|
-
// compute source coordinates and dimensions
|
|
573
|
-
this.sourceLeft = ((elemMatrixA * elemBbox.x + elemMatrixE) * docwidth) / vbWidth;
|
|
574
|
-
this.sourceTop = ((elemMatrixD * elemBbox.y + elemMatrixF) * docheight) / vbHeight;
|
|
575
|
-
this.sourceWidth = elemBbox.width * elemMatrixA * (docwidth / vbWidth);
|
|
576
|
-
this.sourceHeight = elemBbox.height * elemMatrixD * (docheight / vbHeight);
|
|
577
|
-
this._svgAttributesComputationCompleted = true;
|
|
578
|
-
this.onSVGAttributesComputedObservable.notifyObservers(this);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Gets or sets the cell width to use when animation sheet is enabled
|
|
584
|
-
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
585
|
-
*/
|
|
586
|
-
get cellWidth() {
|
|
587
|
-
return this._cellWidth;
|
|
588
|
-
}
|
|
589
|
-
set cellWidth(value) {
|
|
590
|
-
if (this._cellWidth === value) {
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
this._cellWidth = value;
|
|
594
|
-
this._markAsDirty();
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Gets or sets the cell height to use when animation sheet is enabled
|
|
598
|
-
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
599
|
-
*/
|
|
600
|
-
get cellHeight() {
|
|
601
|
-
return this._cellHeight;
|
|
602
|
-
}
|
|
603
|
-
set cellHeight(value) {
|
|
604
|
-
if (this._cellHeight === value) {
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
this._cellHeight = value;
|
|
608
|
-
this._markAsDirty();
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Gets or sets the cell id to use (this will turn on the animation sheet mode)
|
|
612
|
-
* @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#image
|
|
613
|
-
*/
|
|
614
|
-
get cellId() {
|
|
615
|
-
return this._cellId;
|
|
616
|
-
}
|
|
617
|
-
set cellId(value) {
|
|
618
|
-
if (this._cellId === value) {
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
this._cellId = value;
|
|
622
|
-
this._markAsDirty();
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* Creates a new Image
|
|
626
|
-
* @param name defines the control name
|
|
627
|
-
* @param url defines the image url
|
|
628
|
-
*/
|
|
629
|
-
constructor(name, url = null) {
|
|
630
|
-
super(name);
|
|
631
|
-
this.name = name;
|
|
632
|
-
this._workingCanvas = null;
|
|
633
|
-
this._loaded = false;
|
|
634
|
-
this._stretch = Image.STRETCH_FILL;
|
|
635
|
-
this._source = null;
|
|
636
|
-
this._autoScale = false;
|
|
637
|
-
this._sourceLeft = 0;
|
|
638
|
-
this._sourceTop = 0;
|
|
639
|
-
this._sourceWidth = 0;
|
|
640
|
-
this._sourceHeight = 0;
|
|
641
|
-
this._svgAttributesComputationCompleted = false;
|
|
642
|
-
this._isSVG = false;
|
|
643
|
-
this._cellWidth = 0;
|
|
644
|
-
this._cellHeight = 0;
|
|
645
|
-
this._cellId = -1;
|
|
646
|
-
this._populateNinePatchSlicesFromImage = false;
|
|
647
|
-
this._imageDataCache = { data: null, key: "" };
|
|
648
|
-
/**
|
|
649
|
-
* Observable notified when the content is loaded
|
|
650
|
-
*/
|
|
651
|
-
this.onImageLoadedObservable = new Observable();
|
|
652
|
-
/**
|
|
653
|
-
* Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
|
|
654
|
-
*/
|
|
655
|
-
this.onSVGAttributesComputedObservable = new Observable();
|
|
656
|
-
this.source = url;
|
|
657
|
-
}
|
|
658
|
-
/**
|
|
659
|
-
* Tests if a given coordinates belong to the current control
|
|
660
|
-
* @param x defines x coordinate to test
|
|
661
|
-
* @param y defines y coordinate to test
|
|
662
|
-
* @returns true if the coordinates are inside the control
|
|
663
|
-
*/
|
|
664
|
-
contains(x, y) {
|
|
665
|
-
if (!super.contains(x, y)) {
|
|
666
|
-
return false;
|
|
667
|
-
}
|
|
668
|
-
if (!this._detectPointerOnOpaqueOnly || !this._workingCanvas) {
|
|
669
|
-
return true;
|
|
670
|
-
}
|
|
671
|
-
const width = this._currentMeasure.width | 0;
|
|
672
|
-
const height = this._currentMeasure.height | 0;
|
|
673
|
-
const key = width + "_" + height;
|
|
674
|
-
let imageData = this._imageDataCache.data;
|
|
675
|
-
if (!imageData || this._imageDataCache.key !== key) {
|
|
676
|
-
const canvas = this._workingCanvas;
|
|
677
|
-
const context = canvas.getContext("2d");
|
|
678
|
-
this._imageDataCache.data = imageData = context.getImageData(0, 0, width, height).data;
|
|
679
|
-
this._imageDataCache.key = key;
|
|
680
|
-
}
|
|
681
|
-
x = (x - this._currentMeasure.left) | 0;
|
|
682
|
-
y = (y - this._currentMeasure.top) | 0;
|
|
683
|
-
const pickedPixel = imageData[(x + y * width) * 4 + 3];
|
|
684
|
-
return pickedPixel > 0;
|
|
685
|
-
}
|
|
686
|
-
_getTypeName() {
|
|
687
|
-
return "Image";
|
|
688
|
-
}
|
|
689
|
-
/** Force the control to synchronize with its content */
|
|
690
|
-
synchronizeSizeWithContent() {
|
|
691
|
-
if (!this._loaded) {
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
this.width = this._domImage.width + "px";
|
|
695
|
-
this.height = this._domImage.height + "px";
|
|
696
|
-
}
|
|
697
|
-
_processMeasures(parentMeasure, context) {
|
|
698
|
-
if (this._loaded) {
|
|
699
|
-
switch (this._stretch) {
|
|
700
|
-
case Image.STRETCH_NONE:
|
|
701
|
-
break;
|
|
702
|
-
case Image.STRETCH_FILL:
|
|
703
|
-
break;
|
|
704
|
-
case Image.STRETCH_UNIFORM:
|
|
705
|
-
break;
|
|
706
|
-
case Image.STRETCH_NINE_PATCH:
|
|
707
|
-
break;
|
|
708
|
-
case Image.STRETCH_EXTEND:
|
|
709
|
-
if (this._autoScale) {
|
|
710
|
-
this.synchronizeSizeWithContent();
|
|
742
|
+
_prepareWorkingCanvasForOpaqueDetection() {
|
|
743
|
+
if (!this._detectPointerOnOpaqueOnly) {
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
const width = this._currentMeasure.width;
|
|
747
|
+
const height = this._currentMeasure.height;
|
|
748
|
+
if (!this._workingCanvas) {
|
|
749
|
+
const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
|
|
750
|
+
if (!engine) {
|
|
751
|
+
throw new Error("Invalid engine. Unable to create a canvas.");
|
|
711
752
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
753
|
+
this._workingCanvas = engine.createCanvas(width, height);
|
|
754
|
+
}
|
|
755
|
+
const canvas = this._workingCanvas;
|
|
756
|
+
const context = canvas.getContext("2d");
|
|
757
|
+
context.clearRect(0, 0, width, height);
|
|
758
|
+
}
|
|
759
|
+
_drawImage(context, sx, sy, sw, sh, tx, ty, tw, th) {
|
|
760
|
+
context.drawImage(this._domImage, sx, sy, sw, sh, tx, ty, tw, th);
|
|
761
|
+
if (!this._detectPointerOnOpaqueOnly) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
const transform = context.getTransform();
|
|
765
|
+
const canvas = this._workingCanvas;
|
|
766
|
+
const workingCanvasContext = canvas.getContext("2d");
|
|
767
|
+
workingCanvasContext.save();
|
|
768
|
+
const ttx = tx - this._currentMeasure.left;
|
|
769
|
+
const tty = ty - this._currentMeasure.top;
|
|
770
|
+
workingCanvasContext.setTransform(transform.a, transform.b, transform.c, transform.d, (ttx + tw) / 2, (tty + th) / 2);
|
|
771
|
+
workingCanvasContext.translate(-(ttx + tw) / 2, -(tty + th) / 2);
|
|
772
|
+
workingCanvasContext.drawImage(this._domImage, sx, sy, sw, sh, ttx, tty, tw, th);
|
|
773
|
+
workingCanvasContext.restore();
|
|
774
|
+
}
|
|
775
|
+
_draw(context) {
|
|
776
|
+
context.save();
|
|
777
|
+
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
778
|
+
context.shadowColor = this.shadowColor;
|
|
779
|
+
context.shadowBlur = this.shadowBlur;
|
|
780
|
+
context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
|
|
781
|
+
context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
|
|
782
|
+
}
|
|
783
|
+
let x, y, width, height;
|
|
784
|
+
if (this.cellId == -1) {
|
|
785
|
+
x = this._sourceLeft;
|
|
786
|
+
y = this._sourceTop;
|
|
787
|
+
width = this._sourceWidth ? this._sourceWidth : this._imageWidth;
|
|
788
|
+
height = this._sourceHeight ? this._sourceHeight : this._imageHeight;
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
const rowCount = this._domImage.naturalWidth / this.cellWidth;
|
|
792
|
+
const column = (this.cellId / rowCount) >> 0;
|
|
793
|
+
const row = this.cellId % rowCount;
|
|
794
|
+
x = this.cellWidth * row;
|
|
795
|
+
y = this.cellHeight * column;
|
|
796
|
+
width = this.cellWidth;
|
|
797
|
+
height = this.cellHeight;
|
|
798
|
+
}
|
|
799
|
+
this._prepareWorkingCanvasForOpaqueDetection();
|
|
800
|
+
this._applyStates(context);
|
|
801
|
+
if (this._loaded) {
|
|
802
|
+
switch (this._stretch) {
|
|
803
|
+
case _a.STRETCH_NONE:
|
|
804
|
+
this._drawImage(context, x, y, width, height, this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
805
|
+
break;
|
|
806
|
+
case _a.STRETCH_FILL:
|
|
807
|
+
this._drawImage(context, x, y, width, height, this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
808
|
+
break;
|
|
809
|
+
case _a.STRETCH_UNIFORM: {
|
|
810
|
+
const hRatio = this._currentMeasure.width / width;
|
|
811
|
+
const vRatio = this._currentMeasure.height / height;
|
|
812
|
+
const ratio = Math.min(hRatio, vRatio);
|
|
813
|
+
const centerX = (this._currentMeasure.width - width * ratio) / 2;
|
|
814
|
+
const centerY = (this._currentMeasure.height - height * ratio) / 2;
|
|
815
|
+
this._drawImage(context, x, y, width, height, this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, width * ratio, height * ratio);
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
case _a.STRETCH_EXTEND:
|
|
819
|
+
this._drawImage(context, x, y, width, height, this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
820
|
+
break;
|
|
821
|
+
case _a.STRETCH_NINE_PATCH:
|
|
822
|
+
this._renderNinePatch(context, x, y, width, height);
|
|
823
|
+
break;
|
|
716
824
|
}
|
|
717
|
-
|
|
825
|
+
}
|
|
826
|
+
context.restore();
|
|
718
827
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const topHeightAdjusted = Math.round(topHeight * idealRatio);
|
|
818
|
-
const bottomHeightAdjusted = Math.round(bottomHeight * idealRatio);
|
|
819
|
-
const rightWidthAdjusted = Math.round(rightWidth * idealRatio);
|
|
820
|
-
const targetCenterWidth = Math.round(this._currentMeasure.width) - rightWidthAdjusted - leftWidthAdjusted + 2;
|
|
821
|
-
const targetCenterHeight = Math.round(this._currentMeasure.height) - bottomHeightAdjusted - topHeightAdjusted + 2;
|
|
822
|
-
const centerLeftOffset = Math.round(this._currentMeasure.left) + leftWidthAdjusted - 1;
|
|
823
|
-
const centerTopOffset = Math.round(this._currentMeasure.top) + topHeightAdjusted - 1;
|
|
824
|
-
const rightOffset = Math.round(this._currentMeasure.left + this._currentMeasure.width) - rightWidthAdjusted;
|
|
825
|
-
const bottomOffset = Math.round(this._currentMeasure.top + this._currentMeasure.height) - bottomHeightAdjusted;
|
|
826
|
-
//Top Left
|
|
827
|
-
this._drawImage(context, sx, sy, leftWidth, topHeight, this._currentMeasure.left, this._currentMeasure.top, leftWidthAdjusted, topHeightAdjusted);
|
|
828
|
-
//Top
|
|
829
|
-
this._drawImage(context, sx + this._sliceLeft, sy, centerWidth, topHeight, centerLeftOffset + 1, this._currentMeasure.top, targetCenterWidth - 2, topHeightAdjusted);
|
|
830
|
-
//Top Right
|
|
831
|
-
this._drawImage(context, sx + this._sliceRight, sy, rightWidth, topHeight, rightOffset, this._currentMeasure.top, rightWidthAdjusted, topHeightAdjusted);
|
|
832
|
-
//Left
|
|
833
|
-
this._drawImage(context, sx, sy + this._sliceTop, leftWidth, centerHeight, this._currentMeasure.left, centerTopOffset + 1, leftWidthAdjusted, targetCenterHeight - 2);
|
|
834
|
-
// Center
|
|
835
|
-
this._drawImage(context, sx + this._sliceLeft, sy + this._sliceTop, centerWidth, centerHeight, centerLeftOffset + 1, centerTopOffset + 1, targetCenterWidth - 2, targetCenterHeight - 2);
|
|
836
|
-
//Right
|
|
837
|
-
this._drawImage(context, sx + this._sliceRight, sy + this._sliceTop, rightWidth, centerHeight, rightOffset, centerTopOffset + 1, rightWidthAdjusted, targetCenterHeight - 2);
|
|
838
|
-
//Bottom Left
|
|
839
|
-
this._drawImage(context, sx, sy + this._sliceBottom, leftWidth, bottomHeight, this._currentMeasure.left, bottomOffset, leftWidthAdjusted, bottomHeightAdjusted);
|
|
840
|
-
//Bottom
|
|
841
|
-
this._drawImage(context, sx + this.sliceLeft, sy + this._sliceBottom, centerWidth, bottomHeight, centerLeftOffset + 1, bottomOffset, targetCenterWidth - 2, bottomHeightAdjusted);
|
|
842
|
-
//Bottom Right
|
|
843
|
-
this._drawImage(context, sx + this._sliceRight, sy + this._sliceBottom, rightWidth, bottomHeight, rightOffset, bottomOffset, rightWidthAdjusted, bottomHeightAdjusted);
|
|
844
|
-
}
|
|
845
|
-
dispose() {
|
|
846
|
-
super.dispose();
|
|
847
|
-
this.onImageLoadedObservable.clear();
|
|
848
|
-
this.onSVGAttributesComputedObservable.clear();
|
|
849
|
-
this._removeCacheUsage(this._source);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* Cache of images to avoid loading the same image multiple times
|
|
854
|
-
*/
|
|
855
|
-
Image.SourceImgCache = new Map();
|
|
856
|
-
// Static
|
|
857
|
-
/** STRETCH_NONE */
|
|
858
|
-
Image.STRETCH_NONE = 0;
|
|
859
|
-
/** STRETCH_FILL */
|
|
860
|
-
Image.STRETCH_FILL = 1;
|
|
861
|
-
/** STRETCH_UNIFORM */
|
|
862
|
-
Image.STRETCH_UNIFORM = 2;
|
|
863
|
-
/** STRETCH_EXTEND */
|
|
864
|
-
Image.STRETCH_EXTEND = 3;
|
|
865
|
-
/** NINE_PATCH */
|
|
866
|
-
Image.STRETCH_NINE_PATCH = 4;
|
|
867
|
-
__decorate([
|
|
868
|
-
serialize()
|
|
869
|
-
], Image.prototype, "detectPointerOnOpaqueOnly", null);
|
|
870
|
-
__decorate([
|
|
871
|
-
serialize()
|
|
872
|
-
], Image.prototype, "sliceLeft", null);
|
|
873
|
-
__decorate([
|
|
874
|
-
serialize()
|
|
875
|
-
], Image.prototype, "sliceRight", null);
|
|
876
|
-
__decorate([
|
|
877
|
-
serialize()
|
|
878
|
-
], Image.prototype, "sliceTop", null);
|
|
879
|
-
__decorate([
|
|
880
|
-
serialize()
|
|
881
|
-
], Image.prototype, "sliceBottom", null);
|
|
882
|
-
__decorate([
|
|
883
|
-
serialize()
|
|
884
|
-
], Image.prototype, "sourceLeft", null);
|
|
885
|
-
__decorate([
|
|
886
|
-
serialize()
|
|
887
|
-
], Image.prototype, "sourceTop", null);
|
|
888
|
-
__decorate([
|
|
889
|
-
serialize()
|
|
890
|
-
], Image.prototype, "sourceWidth", null);
|
|
891
|
-
__decorate([
|
|
892
|
-
serialize()
|
|
893
|
-
], Image.prototype, "sourceHeight", null);
|
|
894
|
-
__decorate([
|
|
895
|
-
serialize()
|
|
896
|
-
], Image.prototype, "populateNinePatchSlicesFromImage", null);
|
|
897
|
-
__decorate([
|
|
898
|
-
serialize()
|
|
899
|
-
], Image.prototype, "autoScale", null);
|
|
900
|
-
__decorate([
|
|
901
|
-
serialize()
|
|
902
|
-
], Image.prototype, "stretch", null);
|
|
903
|
-
__decorate([
|
|
904
|
-
serialize()
|
|
905
|
-
], Image.prototype, "source", null);
|
|
906
|
-
__decorate([
|
|
907
|
-
serialize()
|
|
908
|
-
], Image.prototype, "cellWidth", null);
|
|
909
|
-
__decorate([
|
|
910
|
-
serialize()
|
|
911
|
-
], Image.prototype, "cellHeight", null);
|
|
912
|
-
__decorate([
|
|
913
|
-
serialize()
|
|
914
|
-
], Image.prototype, "cellId", null);
|
|
828
|
+
_renderNinePatch(context, sx, sy, sw, sh) {
|
|
829
|
+
const idealRatio = this.host.idealRatio;
|
|
830
|
+
const leftWidth = this._sliceLeft;
|
|
831
|
+
const topHeight = this._sliceTop;
|
|
832
|
+
const bottomHeight = sh - this._sliceBottom;
|
|
833
|
+
const rightWidth = sw - this._sliceRight;
|
|
834
|
+
const centerWidth = this._sliceRight - this._sliceLeft;
|
|
835
|
+
const centerHeight = this._sliceBottom - this._sliceTop;
|
|
836
|
+
const leftWidthAdjusted = Math.round(leftWidth * idealRatio);
|
|
837
|
+
const topHeightAdjusted = Math.round(topHeight * idealRatio);
|
|
838
|
+
const bottomHeightAdjusted = Math.round(bottomHeight * idealRatio);
|
|
839
|
+
const rightWidthAdjusted = Math.round(rightWidth * idealRatio);
|
|
840
|
+
const targetCenterWidth = Math.round(this._currentMeasure.width) - rightWidthAdjusted - leftWidthAdjusted + 2;
|
|
841
|
+
const targetCenterHeight = Math.round(this._currentMeasure.height) - bottomHeightAdjusted - topHeightAdjusted + 2;
|
|
842
|
+
const centerLeftOffset = Math.round(this._currentMeasure.left) + leftWidthAdjusted - 1;
|
|
843
|
+
const centerTopOffset = Math.round(this._currentMeasure.top) + topHeightAdjusted - 1;
|
|
844
|
+
const rightOffset = Math.round(this._currentMeasure.left + this._currentMeasure.width) - rightWidthAdjusted;
|
|
845
|
+
const bottomOffset = Math.round(this._currentMeasure.top + this._currentMeasure.height) - bottomHeightAdjusted;
|
|
846
|
+
//Top Left
|
|
847
|
+
this._drawImage(context, sx, sy, leftWidth, topHeight, this._currentMeasure.left, this._currentMeasure.top, leftWidthAdjusted, topHeightAdjusted);
|
|
848
|
+
//Top
|
|
849
|
+
this._drawImage(context, sx + this._sliceLeft, sy, centerWidth, topHeight, centerLeftOffset + 1, this._currentMeasure.top, targetCenterWidth - 2, topHeightAdjusted);
|
|
850
|
+
//Top Right
|
|
851
|
+
this._drawImage(context, sx + this._sliceRight, sy, rightWidth, topHeight, rightOffset, this._currentMeasure.top, rightWidthAdjusted, topHeightAdjusted);
|
|
852
|
+
//Left
|
|
853
|
+
this._drawImage(context, sx, sy + this._sliceTop, leftWidth, centerHeight, this._currentMeasure.left, centerTopOffset + 1, leftWidthAdjusted, targetCenterHeight - 2);
|
|
854
|
+
// Center
|
|
855
|
+
this._drawImage(context, sx + this._sliceLeft, sy + this._sliceTop, centerWidth, centerHeight, centerLeftOffset + 1, centerTopOffset + 1, targetCenterWidth - 2, targetCenterHeight - 2);
|
|
856
|
+
//Right
|
|
857
|
+
this._drawImage(context, sx + this._sliceRight, sy + this._sliceTop, rightWidth, centerHeight, rightOffset, centerTopOffset + 1, rightWidthAdjusted, targetCenterHeight - 2);
|
|
858
|
+
//Bottom Left
|
|
859
|
+
this._drawImage(context, sx, sy + this._sliceBottom, leftWidth, bottomHeight, this._currentMeasure.left, bottomOffset, leftWidthAdjusted, bottomHeightAdjusted);
|
|
860
|
+
//Bottom
|
|
861
|
+
this._drawImage(context, sx + this.sliceLeft, sy + this._sliceBottom, centerWidth, bottomHeight, centerLeftOffset + 1, bottomOffset, targetCenterWidth - 2, bottomHeightAdjusted);
|
|
862
|
+
//Bottom Right
|
|
863
|
+
this._drawImage(context, sx + this._sliceRight, sy + this._sliceBottom, rightWidth, bottomHeight, rightOffset, bottomOffset, rightWidthAdjusted, bottomHeightAdjusted);
|
|
864
|
+
}
|
|
865
|
+
dispose() {
|
|
866
|
+
super.dispose();
|
|
867
|
+
this.onImageLoadedObservable.clear();
|
|
868
|
+
this.onSVGAttributesComputedObservable.clear();
|
|
869
|
+
this._removeCacheUsage(this._source);
|
|
870
|
+
}
|
|
871
|
+
},
|
|
872
|
+
(() => {
|
|
873
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
874
|
+
_get_detectPointerOnOpaqueOnly_decorators = [serialize()];
|
|
875
|
+
_get_sliceLeft_decorators = [serialize()];
|
|
876
|
+
_get_sliceRight_decorators = [serialize()];
|
|
877
|
+
_get_sliceTop_decorators = [serialize()];
|
|
878
|
+
_get_sliceBottom_decorators = [serialize()];
|
|
879
|
+
_get_sourceLeft_decorators = [serialize()];
|
|
880
|
+
_get_sourceTop_decorators = [serialize()];
|
|
881
|
+
_get_sourceWidth_decorators = [serialize()];
|
|
882
|
+
_get_sourceHeight_decorators = [serialize()];
|
|
883
|
+
_get_populateNinePatchSlicesFromImage_decorators = [serialize()];
|
|
884
|
+
_get_autoScale_decorators = [serialize()];
|
|
885
|
+
_get_stretch_decorators = [serialize()];
|
|
886
|
+
_get_source_decorators = [serialize()];
|
|
887
|
+
_get_cellWidth_decorators = [serialize()];
|
|
888
|
+
_get_cellHeight_decorators = [serialize()];
|
|
889
|
+
_get_cellId_decorators = [serialize()];
|
|
890
|
+
__esDecorate(_a, null, _get_detectPointerOnOpaqueOnly_decorators, { kind: "getter", name: "detectPointerOnOpaqueOnly", static: false, private: false, access: { has: obj => "detectPointerOnOpaqueOnly" in obj, get: obj => obj.detectPointerOnOpaqueOnly }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
891
|
+
__esDecorate(_a, null, _get_sliceLeft_decorators, { kind: "getter", name: "sliceLeft", static: false, private: false, access: { has: obj => "sliceLeft" in obj, get: obj => obj.sliceLeft }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
892
|
+
__esDecorate(_a, null, _get_sliceRight_decorators, { kind: "getter", name: "sliceRight", static: false, private: false, access: { has: obj => "sliceRight" in obj, get: obj => obj.sliceRight }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
893
|
+
__esDecorate(_a, null, _get_sliceTop_decorators, { kind: "getter", name: "sliceTop", static: false, private: false, access: { has: obj => "sliceTop" in obj, get: obj => obj.sliceTop }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
894
|
+
__esDecorate(_a, null, _get_sliceBottom_decorators, { kind: "getter", name: "sliceBottom", static: false, private: false, access: { has: obj => "sliceBottom" in obj, get: obj => obj.sliceBottom }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
895
|
+
__esDecorate(_a, null, _get_sourceLeft_decorators, { kind: "getter", name: "sourceLeft", static: false, private: false, access: { has: obj => "sourceLeft" in obj, get: obj => obj.sourceLeft }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
896
|
+
__esDecorate(_a, null, _get_sourceTop_decorators, { kind: "getter", name: "sourceTop", static: false, private: false, access: { has: obj => "sourceTop" in obj, get: obj => obj.sourceTop }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
897
|
+
__esDecorate(_a, null, _get_sourceWidth_decorators, { kind: "getter", name: "sourceWidth", static: false, private: false, access: { has: obj => "sourceWidth" in obj, get: obj => obj.sourceWidth }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
898
|
+
__esDecorate(_a, null, _get_sourceHeight_decorators, { kind: "getter", name: "sourceHeight", static: false, private: false, access: { has: obj => "sourceHeight" in obj, get: obj => obj.sourceHeight }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
899
|
+
__esDecorate(_a, null, _get_populateNinePatchSlicesFromImage_decorators, { kind: "getter", name: "populateNinePatchSlicesFromImage", static: false, private: false, access: { has: obj => "populateNinePatchSlicesFromImage" in obj, get: obj => obj.populateNinePatchSlicesFromImage }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
900
|
+
__esDecorate(_a, null, _get_autoScale_decorators, { kind: "getter", name: "autoScale", static: false, private: false, access: { has: obj => "autoScale" in obj, get: obj => obj.autoScale }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
901
|
+
__esDecorate(_a, null, _get_stretch_decorators, { kind: "getter", name: "stretch", static: false, private: false, access: { has: obj => "stretch" in obj, get: obj => obj.stretch }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
902
|
+
__esDecorate(_a, null, _get_source_decorators, { kind: "getter", name: "source", static: false, private: false, access: { has: obj => "source" in obj, get: obj => obj.source }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
903
|
+
__esDecorate(_a, null, _get_cellWidth_decorators, { kind: "getter", name: "cellWidth", static: false, private: false, access: { has: obj => "cellWidth" in obj, get: obj => obj.cellWidth }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
904
|
+
__esDecorate(_a, null, _get_cellHeight_decorators, { kind: "getter", name: "cellHeight", static: false, private: false, access: { has: obj => "cellHeight" in obj, get: obj => obj.cellHeight }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
905
|
+
__esDecorate(_a, null, _get_cellId_decorators, { kind: "getter", name: "cellId", static: false, private: false, access: { has: obj => "cellId" in obj, get: obj => obj.cellId }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
906
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
907
|
+
})(),
|
|
908
|
+
/**
|
|
909
|
+
* Cache of images to avoid loading the same image multiple times
|
|
910
|
+
*/
|
|
911
|
+
_a.SourceImgCache = new Map(),
|
|
912
|
+
// Static
|
|
913
|
+
/** STRETCH_NONE */
|
|
914
|
+
_a.STRETCH_NONE = 0,
|
|
915
|
+
/** STRETCH_FILL */
|
|
916
|
+
_a.STRETCH_FILL = 1,
|
|
917
|
+
/** STRETCH_UNIFORM */
|
|
918
|
+
_a.STRETCH_UNIFORM = 2,
|
|
919
|
+
/** STRETCH_EXTEND */
|
|
920
|
+
_a.STRETCH_EXTEND = 3,
|
|
921
|
+
/** NINE_PATCH */
|
|
922
|
+
_a.STRETCH_NINE_PATCH = 4,
|
|
923
|
+
_a;
|
|
924
|
+
})();
|
|
925
|
+
export { Image };
|
|
915
926
|
let _Registered = false;
|
|
916
927
|
/**
|
|
917
928
|
* Registers the Image class with the type store for serialization support.
|