4a6390f81f9d19338a96adeda022c9451e82c3b8
[WebKit-https.git] / WebCore / bindings / js / JSCanvasRenderingContext2DCustom.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "config.h"
21 #include "JSCanvasRenderingContext2D.h"
22
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"
35 #include "kjs_html.h"
36
37 using namespace KJS;
38
39 namespace WebCore {
40
41 static JSValue* toJS(ExecState* exec, CanvasStyle* style)
42 {
43     if (style->gradient())
44         return toJS(exec, style->gradient());
45     if (style->pattern())
46         return toJS(exec, style->pattern());
47     return jsString(style->color());
48 }
49
50 static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState* exec, JSValue* value)
51 {
52     if (value->isString())
53         return new CanvasStyle(value->toString(exec));
54     if (!value->isObject())
55         return 0;
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());
61     return 0;
62 }
63
64 JSValue* JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const
65 {
66     return toJS(exec, impl()->strokeStyle());        
67 }
68
69 void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue* value)
70 {
71     impl()->setStrokeStyle(toHTMLCanvasStyle(exec, value));
72 }
73
74 JSValue* JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const
75 {
76     return toJS(exec, impl()->fillStyle());
77 }
78
79 void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue* value)
80 {
81     impl()->setFillStyle(toHTMLCanvasStyle(exec, value));
82 }
83
84 JSValue* JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const List& args)
85 {
86     CanvasRenderingContext2D* context = impl();
87
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()) {
95         case 1:
96             if (args[0]->isString())
97                 context->setFillColor(args[0]->toString(exec));
98             else
99                 context->setFillColor(args[0]->toFloat(exec));
100             break;
101         case 2:
102             if (args[0]->isString())
103                 context->setFillColor(args[0]->toString(exec), args[1]->toFloat(exec));
104             else
105                 context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
106             break;
107         case 4:
108             context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
109                                   args[2]->toFloat(exec), args[3]->toFloat(exec));
110             break;
111         case 5:
112             context->setFillColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
113                                   args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
114             break;
115         default:
116             return throwError(exec, SyntaxError);
117     }
118     return jsUndefined();
119 }    
120
121 JSValue* JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const List& args)
122
123     CanvasRenderingContext2D* context = impl();
124
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()) {
132         case 1:
133             if (args[0]->isString())
134                 context->setStrokeColor(args[0]->toString(exec));
135             else
136                 context->setStrokeColor(args[0]->toFloat(exec));
137             break;
138         case 2:
139             if (args[0]->isString())
140                 context->setStrokeColor(args[0]->toString(exec), args[1]->toFloat(exec));
141             else
142                 context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec));
143             break;
144         case 4:
145             context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
146                                     args[2]->toFloat(exec), args[3]->toFloat(exec));
147             break;
148         case 5:
149             context->setStrokeColor(args[0]->toFloat(exec), args[1]->toFloat(exec),
150                                     args[2]->toFloat(exec), args[3]->toFloat(exec), args[4]->toFloat(exec));
151             break;
152         default:
153             return throwError(exec, SyntaxError);
154     }
155     
156     return jsUndefined();
157 }
158
159 JSValue* JSCanvasRenderingContext2D::strokeRect(ExecState* exec, const List& args)
160
161     CanvasRenderingContext2D* context = impl();    
162     ExceptionCode ec;
163     
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);
167     else
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);
171     
172     return jsUndefined();    
173 }
174
175 JSValue* JSCanvasRenderingContext2D::drawImage(ExecState* exec, const List& args)
176
177     CanvasRenderingContext2D* context = impl();
178
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);
189     
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()) {
194             case 3:
195                 context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec));
196                 break;
197             case 5:
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);
201                 break;
202             case 9:
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);
208                 break;
209             default:
210                 return throwError(exec, SyntaxError);
211         }
212     } else if (o->inherits(&JSHTMLCanvasElement::info)) {
213         HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
214         switch (args.size()) {
215             case 3:
216                 context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec));
217                 break;
218             case 5:
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);
222                 break;
223             case 9:
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);
229                 break;
230             default:
231                 return throwError(exec, SyntaxError);
232         }
233     } else {
234         setDOMException(exec, TYPE_MISMATCH_ERR);
235         return 0;
236     }
237     
238     return jsUndefined();    
239 }
240
241 JSValue* JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const List& args)
242
243     CanvasRenderingContext2D* context = impl();
244     
245     JSValue* value = args[0];
246     if (!value->isObject())
247         return throwError(exec, TypeError);
248     JSObject* o = static_cast<JSObject*>(value);
249     
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();    
259 }
260
261 JSValue* JSCanvasRenderingContext2D::setShadow(ExecState* exec, const List& args)
262
263     CanvasRenderingContext2D* context = impl();
264
265     switch (args.size()) {
266         case 3:
267             context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
268                                args[2]->toFloat(exec));
269             break;
270         case 4:
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));
274             else
275                 context->setShadow(args[0]->toFloat(exec), args[1]->toFloat(exec),
276                                    args[2]->toFloat(exec), args[3]->toFloat(exec));
277             break;
278         case 5:
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));
283             else
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));
287             break;
288         case 7:
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));
293             break;
294         case 8:
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));
299             break;
300         default:
301             return throwError(exec, SyntaxError);
302     }
303     
304     return jsUndefined();    
305 }
306
307 JSValue* JSCanvasRenderingContext2D::createPattern(ExecState* exec, const List& args)
308
309     CanvasRenderingContext2D* context = impl();
310
311     JSValue* value = args[0];
312     if (!value->isObject())
313         return throwError(exec, TypeError);
314     JSObject* o = static_cast<JSObject*>(value);
315     
316     if (o->inherits(&JSHTMLImageElement::info)) {
317         ExceptionCode ec;
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);
322         return pattern;
323     }
324     if (o->inherits(&JSHTMLCanvasElement::info)) {
325         ExceptionCode ec;
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);
330         return pattern;
331     }
332     setDOMException(exec, TYPE_MISMATCH_ERR);
333     return 0;
334 }
335
336 JSValue* JSCanvasRenderingContext2D::putImageData(ExecState* exec, const List& args)
337 {
338     return jsUndefined();
339 }
340
341 } // namespace WebCore