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