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 "JSCanvasGradient.h"
32 #include "JSCanvasPattern.h"
33 #include "JSHTMLCanvasElement.h"
34 #include "JSHTMLImageElement.h"
41 static JSValue* toJS(ExecState* exec, CanvasStyle* style)
43 if (style->gradient())
44 return toJS(exec, style->gradient());
46 return toJS(exec, style->pattern());
47 return jsString(style->color());
50 static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState* exec, JSValue* value)
52 if (value->isString())
53 return new CanvasStyle(value->toString(exec));
54 if (!value->isObject())
56 JSObject* object = static_cast<JSObject*>(value);
57 if (object->inherits(&JSCanvasGradient::info))
58 return new CanvasStyle(static_cast<JSCanvasGradient*>(object)->impl());
59 if (object->inherits(&JSCanvasPattern::info))
60 return new CanvasStyle(static_cast<JSCanvasPattern*>(object)->impl());
64 JSValue* JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const
66 return toJS(exec, impl()->strokeStyle());
69 void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue* value)
71 impl()->setStrokeStyle(toHTMLCanvasStyle(exec, value));
74 JSValue* JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const
76 return toJS(exec, impl()->fillStyle());
79 void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue* value)
81 impl()->setFillStyle(toHTMLCanvasStyle(exec, value));
84 JSValue* JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const List& args)
86 CanvasRenderingContext2D* context = impl();
88 // string arg = named color
89 // number arg = gray color
90 // string arg, number arg = named color, alpha
91 // number arg, number arg = gray color, alpha
92 // 4 args = r, g, b, a
93 // 5 args = c, m, y, k, a
94 switch (args.size()) {
96 if (args[0]->isString())
97 context->setFillColor(args[0]->toString(exec));
99 context->setFillColor(args[0]->toFloat(exec));
102 if (args[0]->isString())
103 context->setFillColor(args[0]->toString(exec), args[1]->toFloat(exec));
105 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
108 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
109 args[2]->toFloat(exec), args[3]->toFloat(exec));
112 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
113 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
116 return throwError(exec, SyntaxError);
118 return jsUndefined();
121 JSValue* JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const List& args)
123 CanvasRenderingContext2D* context = impl();
125 // string arg = named color
126 // number arg = gray color
127 // string arg, number arg = named color, alpha
128 // number arg, number arg = gray color, alpha
129 // 4 args = r, g, b, a
130 // 5 args = c, m, y, k, a
131 switch (args.size()) {
133 if (args[0]->isString())
134 context->setStrokeColor(args[0]->toString(exec));
136 context->setStrokeColor(args[0]->toFloat(exec));
139 if (args[0]->isString())
140 context->setStrokeColor(args[0]->toString(exec), args[1]->toFloat(exec));
142 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
145 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
146 args[2]->toFloat(exec), args[3]->toFloat(exec));
149 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
150 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
153 return throwError(exec, SyntaxError);
156 return jsUndefined();
159 JSValue* JSCanvasRenderingContext2D::strokeRect(ExecState* exec, const List& args)
161 CanvasRenderingContext2D* context = impl();
164 if (args.size() <= 4)
165 context->strokeRect(args[0]->toFloat(exec), args[1]->toFloat(exec),
166 args[2]->toFloat(exec), args[3]->toFloat(exec), ec);
168 context->strokeRect(args[0]->toFloat(exec), args[1]->toFloat(exec),
169 args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
170 setDOMException(exec, ec);
172 return jsUndefined();
175 JSValue* JSCanvasRenderingContext2D::drawImage(ExecState* exec, const List& args)
177 CanvasRenderingContext2D* context = impl();
179 // DrawImage has three variants:
180 // drawImage(img, dx, dy)
181 // drawImage(img, dx, dy, dw, dh)
182 // drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
183 // Composite operation is specified with globalCompositeOperation.
184 // The img parameter can be a <img> or <canvas> element.
185 JSValue* value = args[0];
186 if (!value->isObject())
187 return throwError(exec, TypeError);
188 JSObject* o = static_cast<JSObject*>(value);
190 ExceptionCode ec = 0;
191 if (o->inherits(&JSHTMLImageElement::info)) {
192 HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
193 switch (args.size()) {
195 context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec));
198 context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec),
199 args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
200 setDOMException(exec, ec);
203 context->drawImage(imgElt, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
204 args[3]->toFloat(exec), args[4]->toFloat(exec)),
205 FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
206 args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
207 setDOMException(exec, ec);
210 return throwError(exec, SyntaxError);
212 } else if (o->inherits(&JSHTMLCanvasElement::info)) {
213 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
214 switch (args.size()) {
216 context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec));
219 context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec),
220 args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
221 setDOMException(exec, ec);
224 context->drawImage(canvas, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
225 args[3]->toFloat(exec), args[4]->toFloat(exec)),
226 FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
227 args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
228 setDOMException(exec, ec);
231 return throwError(exec, SyntaxError);
234 setDOMException(exec, TYPE_MISMATCH_ERR);
238 return jsUndefined();
241 JSValue* JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const List& args)
243 CanvasRenderingContext2D* context = impl();
245 JSValue* value = args[0];
246 if (!value->isObject())
247 return throwError(exec, TypeError);
248 JSObject* o = static_cast<JSObject*>(value);
250 if (!o->inherits(&JSHTMLImageElement::info))
251 return throwError(exec, TypeError);
252 context->drawImageFromRect(static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
253 args[1]->toFloat(exec), args[2]->toFloat(exec),
254 args[3]->toFloat(exec), args[4]->toFloat(exec),
255 args[5]->toFloat(exec), args[6]->toFloat(exec),
256 args[7]->toFloat(exec), args[8]->toFloat(exec),
257 args[9]->toString(exec));
258 return jsUndefined();
261 JSValue* JSCanvasRenderingContext2D::setShadow(ExecState* exec, const List& args)
263 CanvasRenderingContext2D* context = impl();
265 switch (args.size()) {
267 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
268 args[2]->toFloat(exec));
271 if (args[3]->isString())
272 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
273 args[2]->toFloat(exec), args[3]->toString(exec));
275 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
276 args[2]->toFloat(exec), args[3]->toFloat(exec));
279 if (args[3]->isString())
280 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
281 args[2]->toFloat(exec), args[3]->toString(exec),
282 args[4]->toFloat(exec));
284 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
285 args[2]->toFloat(exec), args[3]->toFloat(exec),
286 args[4]->toFloat(exec));
289 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
290 args[2]->toFloat(exec), args[3]->toFloat(exec),
291 args[4]->toFloat(exec), args[5]->toFloat(exec),
292 args[6]->toFloat(exec));
295 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
296 args[2]->toFloat(exec), args[3]->toFloat(exec),
297 args[4]->toFloat(exec), args[5]->toFloat(exec),
298 args[6]->toFloat(exec), args[7]->toFloat(exec));
301 return throwError(exec, SyntaxError);
304 return jsUndefined();
307 JSValue* JSCanvasRenderingContext2D::createPattern(ExecState* exec, const List& args)
309 CanvasRenderingContext2D* context = impl();
311 JSValue* value = args[0];
312 if (!value->isObject())
313 return throwError(exec, TypeError);
314 JSObject* o = static_cast<JSObject*>(value);
316 if (o->inherits(&JSHTMLImageElement::info)) {
318 JSValue* pattern = toJS(exec,
319 context->createPattern(static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
320 args[1]->toString(exec), ec).get());
321 setDOMException(exec, ec);
324 if (o->inherits(&JSHTMLCanvasElement::info)) {
326 JSValue* pattern = toJS(exec,
327 context->createPattern(static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl()),
328 args[1]->toString(exec), ec).get());
329 setDOMException(exec, ec);
332 setDOMException(exec, TYPE_MISMATCH_ERR);
336 JSValue* JSCanvasRenderingContext2D::putImageData(ExecState* exec, const List& args)
338 return jsUndefined();
341 } // namespace WebCore