1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.canvas;
16
17 import java.nio.ByteBuffer;
18
19 import org.htmlunit.corejs.javascript.Context;
20 import org.htmlunit.corejs.javascript.Function;
21 import org.htmlunit.corejs.javascript.ScriptableObject;
22 import org.htmlunit.corejs.javascript.VarScope;
23 import org.htmlunit.corejs.javascript.typedarrays.NativeArrayBuffer;
24 import org.htmlunit.corejs.javascript.typedarrays.NativeUint8ClampedArray;
25 import org.htmlunit.javascript.HtmlUnitScriptable;
26 import org.htmlunit.javascript.JavaScriptEngine;
27 import org.htmlunit.javascript.configuration.JsxClass;
28 import org.htmlunit.javascript.configuration.JsxConstructor;
29 import org.htmlunit.javascript.configuration.JsxGetter;
30 import org.htmlunit.javascript.host.dom.DOMException;
31 import org.htmlunit.platform.canvas.rendering.RenderingBackend;
32
33
34
35
36
37
38
39
40
41 @JsxClass
42 public class ImageData extends HtmlUnitScriptable {
43
44 private final byte[] bytes_;
45 private final int width_;
46 private final int height_;
47 private NativeUint8ClampedArray data_;
48
49
50
51
52 public ImageData() {
53 this(null, 0, 0, 0, 0);
54 }
55
56
57
58
59
60
61
62
63
64
65 @JsxConstructor
66 public static ImageData jsConstructor(final Context cx, final VarScope scope,
67 final Object[] args, final Function ctorObj, final boolean inNewExpr) {
68 if (args.length < 2) {
69 throw JavaScriptEngine.typeError("ImageData ctor - too less arguments");
70 }
71
72 NativeUint8ClampedArray data = null;
73 final int width;
74 final int height;
75 if (args[0] instanceof NativeUint8ClampedArray array) {
76 data = array;
77 if (data.getArrayLength() % 4 != 0) {
78 throw JavaScriptEngine.asJavaScriptException(
79 (HtmlUnitScriptable) getTopLevelScope(scope).getGlobalThis(),
80 "ImageData ctor - data length mod 4 not zero",
81 DOMException.INVALID_STATE_ERR);
82 }
83
84 width = (int) JavaScriptEngine.toInteger(args[1]);
85 if (args.length < 3) {
86 height = data.getArrayLength() / 4 / width;
87
88 if (data.getArrayLength() != 4 * width * height) {
89 throw JavaScriptEngine.asJavaScriptException(
90 (HtmlUnitScriptable) getTopLevelScope(scope).getGlobalThis(),
91 "ImageData ctor - width not correct",
92 DOMException.INDEX_SIZE_ERR);
93 }
94 }
95 else {
96 height = (int) JavaScriptEngine.toInteger(args[2]);
97 }
98
99 if (data.getArrayLength() != 4 * width * height) {
100 throw JavaScriptEngine.asJavaScriptException(
101 (HtmlUnitScriptable) getTopLevelScope(scope).getGlobalThis(),
102 "ImageData ctor - width/height not correct",
103 DOMException.INDEX_SIZE_ERR);
104 }
105 }
106 else {
107 width = (int) JavaScriptEngine.toInteger(args[0]);
108 height = (int) JavaScriptEngine.toInteger(args[1]);
109 }
110
111 if (width < 0) {
112 throw JavaScriptEngine.asJavaScriptException(
113 (HtmlUnitScriptable) getTopLevelScope(scope).getGlobalThis(),
114 "ImageData ctor - width negative",
115 DOMException.INDEX_SIZE_ERR);
116 }
117 if (height < 0) {
118 throw JavaScriptEngine.asJavaScriptException(
119 (HtmlUnitScriptable) getTopLevelScope(scope).getGlobalThis(),
120 "ImageData ctor - height negative",
121 DOMException.INDEX_SIZE_ERR);
122 }
123
124 final ImageData result = new ImageData(null, 0, 0, width, height);
125 if (data != null) {
126 final ByteBuffer buffer = data.getBuffer().getByteBuffer();
127 final int bytesToCopy = Math.min(buffer.remaining(), result.bytes_.length);
128 buffer.get(result.bytes_, 0, bytesToCopy);
129 }
130 return result;
131 }
132
133 ImageData(final RenderingBackend context, final int x, final int y, final int width, final int height) {
134 super();
135 if (context == null) {
136 bytes_ = new byte[width * height * 4];
137 }
138 else {
139 bytes_ = context.getBytes(width, height, x, y);
140 }
141
142 width_ = width;
143 height_ = height;
144 }
145
146
147
148
149
150 @JsxGetter
151 public int getWidth() {
152 return width_;
153 }
154
155
156
157
158
159 @JsxGetter
160 public int getHeight() {
161 return height_;
162 }
163
164
165
166
167
168
169 @JsxGetter
170 public NativeUint8ClampedArray getData() {
171 if (data_ == null) {
172 final NativeArrayBuffer arrayBuffer = new NativeArrayBuffer(bytes_.length);
173 arrayBuffer.getByteBuffer().put(bytes_);
174
175 data_ = new NativeUint8ClampedArray(arrayBuffer, 0, bytes_.length);
176 data_.setParentScope(getParentScope());
177 data_.setPrototype(ScriptableObject.getClassPrototype(getParentScope(), data_.getClassName()));
178 }
179
180 return data_;
181 }
182
183 }