2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #include "JSCanvasRenderingContext2D.h"
23 #include "CanvasGradient.h"
24 #include "CanvasPattern.h"
25 #include "CanvasRenderingContext2D.h"
26 #include "CanvasStyle.h"
27 #include "ExceptionCode.h"
28 #include "FloatRect.h"
29 #include "HTMLCanvasElement.h"
30 #include "HTMLImageElement.h"
31 #include "ImageData.h"
32 #include "JSCanvasGradient.h"
33 #include "JSCanvasPattern.h"
34 #include "JSHTMLCanvasElement.h"
35 #include "JSHTMLImageElement.h"
36 #include "JSImageData.h"
43 static JSValue* toJS(ExecState* exec, CanvasStyle* style)
45 if (style->gradient())
46 return toJS(exec, style->gradient());
48 return toJS(exec, style->pattern());
49 return jsString(style->color());
52 static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState* exec, JSValue* value)
54 if (value->isString())
55 return new CanvasStyle(value->toString(exec));
56 if (!value->isObject())
58 JSObject* object = static_cast<JSObject*>(value);
59 if (object->inherits(&JSCanvasGradient::info))
60 return new CanvasStyle(static_cast<JSCanvasGradient*>(object)->impl());
61 if (object->inherits(&JSCanvasPattern::info))
62 return new CanvasStyle(static_cast<JSCanvasPattern*>(object)->impl());
66 JSValue* JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const
68 return toJS(exec, impl()->strokeStyle());
71 void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue* value)
73 impl()->setStrokeStyle(toHTMLCanvasStyle(exec, value));
76 JSValue* JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const
78 return toJS(exec, impl()->fillStyle());
81 void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue* value)
83 impl()->setFillStyle(toHTMLCanvasStyle(exec, value));
86 JSValue* JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const List& args)
88 CanvasRenderingContext2D* context = impl();
90 // string arg = named color
91 // number arg = gray color
92 // string arg, number arg = named color, alpha
93 // number arg, number arg = gray color, alpha
94 // 4 args = r, g, b, a
95 // 5 args = c, m, y, k, a
96 switch (args.size()) {
98 if (args[0]->isString())
99 context->setFillColor(args[0]->toString(exec));
101 context->setFillColor(args[0]->toFloat(exec));
104 if (args[0]->isString())
105 context->setFillColor(args[0]->toString(exec), args[1]->toFloat(exec));
107 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
110 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
111 args[2]->toFloat(exec), args[3]->toFloat(exec));
114 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
115 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
118 return throwError(exec, SyntaxError);
120 return jsUndefined();
123 JSValue* JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const List& args)
125 CanvasRenderingContext2D* context = impl();
127 // string arg = named color
128 // number arg = gray color
129 // string arg, number arg = named color, alpha
130 // number arg, number arg = gray color, alpha
131 // 4 args = r, g, b, a
132 // 5 args = c, m, y, k, a
133 switch (args.size()) {
135 if (args[0]->isString())
136 context->setStrokeColor(args[0]->toString(exec));
138 context->setStrokeColor(args[0]->toFloat(exec));
141 if (args[0]->isString())
142 context->setStrokeColor(args[0]->toString(exec), args[1]->toFloat(exec));
144 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
147 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
148 args[2]->toFloat(exec), args[3]->toFloat(exec));
151 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
152 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
155 return throwError(exec, SyntaxError);
158 return jsUndefined();
161 JSValue* JSCanvasRenderingContext2D::strokeRect(ExecState* exec, const List& args)
163 CanvasRenderingContext2D* context = impl();
166 if (args.size() <= 4)
167 context->strokeRect(args[0]->toFloat(exec), args[1]->toFloat(exec),
168 args[2]->toFloat(exec), args[3]->toFloat(exec), ec);
170 context->strokeRect(args[0]->toFloat(exec), args[1]->toFloat(exec),
171 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
172 setDOMException(exec, ec);
174 return jsUndefined();
177 JSValue* JSCanvasRenderingContext2D::drawImage(ExecState* exec, const List& args)
179 CanvasRenderingContext2D* context = impl();
181 // DrawImage has three variants:
182 // drawImage(img, dx, dy)
183 // drawImage(img, dx, dy, dw, dh)
184 // drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
185 // Composite operation is specified with globalCompositeOperation.
186 // The img parameter can be a <img> or <canvas> element.
187 JSValue* value = args[0];
188 if (!value->isObject())
189 return throwError(exec, TypeError);
190 JSObject* o = static_cast<JSObject*>(value);
192 ExceptionCode ec = 0;
193 if (o->inherits(&JSHTMLImageElement::info)) {
194 HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
195 switch (args.size()) {
197 context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec));
200 context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec),
201 args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
202 setDOMException(exec, ec);
205 context->drawImage(imgElt, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
206 args[3]->toFloat(exec), args[4]->toFloat(exec)),
207 FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
208 args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
209 setDOMException(exec, ec);
212 return throwError(exec, SyntaxError);
214 } else if (o->inherits(&JSHTMLCanvasElement::info)) {
215 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
216 switch (args.size()) {
218 context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec));
221 context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec),
222 args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
223 setDOMException(exec, ec);
226 context->drawImage(canvas, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
227 args[3]->toFloat(exec), args[4]->toFloat(exec)),
228 FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
229 args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
230 setDOMException(exec, ec);
233 return throwError(exec, SyntaxError);
236 setDOMException(exec, TYPE_MISMATCH_ERR);
240 return jsUndefined();
243 JSValue* JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const List& args)
245 CanvasRenderingContext2D* context = impl();
247 JSValue* value = args[0];
248 if (!value->isObject())
249 return throwError(exec, TypeError);
250 JSObject* o = static_cast<JSObject*>(value);
252 if (!o->inherits(&JSHTMLImageElement::info))
253 return throwError(exec, TypeError);
254 context->drawImageFromRect(static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
255 args[1]->toFloat(exec), args[2]->toFloat(exec),
256 args[3]->toFloat(exec), args[4]->toFloat(exec),
257 args[5]->toFloat(exec), args[6]->toFloat(exec),
258 args[7]->toFloat(exec), args[8]->toFloat(exec),
259 args[9]->toString(exec));
260 return jsUndefined();
263 JSValue* JSCanvasRenderingContext2D::setShadow(ExecState* exec, const List& args)
265 CanvasRenderingContext2D* context = impl();
267 switch (args.size()) {
269 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
270 args[2]->toFloat(exec));
273 if (args[3]->isString())
274 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
275 args[2]->toFloat(exec), args[3]->toString(exec));
277 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
278 args[2]->toFloat(exec), args[3]->toFloat(exec));
281 if (args[3]->isString())
282 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
283 args[2]->toFloat(exec), args[3]->toString(exec),
284 args[4]->toFloat(exec));
286 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
287 args[2]->toFloat(exec), args[3]->toFloat(exec),
288 args[4]->toFloat(exec));
291 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
292 args[2]->toFloat(exec), args[3]->toFloat(exec),
293 args[4]->toFloat(exec), args[5]->toFloat(exec),
294 args[6]->toFloat(exec));
297 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
298 args[2]->toFloat(exec), args[3]->toFloat(exec),
299 args[4]->toFloat(exec), args[5]->toFloat(exec),
300 args[6]->toFloat(exec), args[7]->toFloat(exec));
303 return throwError(exec, SyntaxError);
306 return jsUndefined();
309 JSValue* JSCanvasRenderingContext2D::createPattern(ExecState* exec, const List& args)
311 CanvasRenderingContext2D* context = impl();
313 JSValue* value = args[0];
314 if (!value->isObject())
315 return throwError(exec, TypeError);
316 JSObject* o = static_cast<JSObject*>(value);
318 if (o->inherits(&JSHTMLImageElement::info)) {
320 JSValue* pattern = toJS(exec,
321 context->createPattern(static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
322 args[1]->toString(exec), ec).get());
323 setDOMException(exec, ec);
326 if (o->inherits(&JSHTMLCanvasElement::info)) {
328 JSValue* pattern = toJS(exec,
329 context->createPattern(static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
330 args[1]->toString(exec), ec).get());
331 setDOMException(exec, ec);
334 setDOMException(exec, TYPE_MISMATCH_ERR);
338 JSValue* JSCanvasRenderingContext2D::putImageData(ExecState* exec, const List& args)
340 // putImageData has two variants
341 // putImageData(ImageData, x, y)
342 // putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight)
343 CanvasRenderingContext2D* context = impl();
345 ExceptionCode ec = 0;
346 if (args.size() >= 7)
347 context->putImageData(toImageData(args[0]), args[1]->toFloat(exec), args[2]->toFloat(exec),
348 args[3]->toFloat(exec), args[4]->toFloat(exec), args[5]->toFloat(exec), args[6]->toFloat(exec), ec);
350 context->putImageData(toImageData(args[0]), args[1]->toFloat(exec), args[2]->toFloat(exec), ec);
352 setDOMException(exec, ec);
353 return jsUndefined();
356 } // namespace WebCore