1 // Rectangle_as.cpp:  ActionScript "Rectangle" class, for Gnash.
2 //
3 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 //   Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 //
20 
21 #include "Rectangle_as.h"
22 
23 #include <sstream>
24 
25 #include "as_object.h" // for inheritance
26 #include "log.h"
27 #include "fn_call.h"
28 #include "Global_as.h"
29 #include "GnashException.h" // for ActionException
30 #include "VM.h"
31 #include "as_value.h"
32 #include "namedStrings.h"
33 #include "GnashNumeric.h" // isFinite
34 #include "as_function.h"
35 
36 namespace gnash {
37 
38 namespace {
39     as_value Rectangle_clone(const fn_call& fn);
40     as_value Rectangle_contains(const fn_call& fn);
41     as_value Rectangle_containsPoint(const fn_call& fn);
42     as_value Rectangle_containsRectangle(const fn_call& fn);
43     as_value Rectangle_equals(const fn_call& fn);
44     as_value Rectangle_inflate(const fn_call& fn);
45     as_value Rectangle_inflatePoint(const fn_call& fn);
46     as_value Rectangle_intersection(const fn_call& fn);
47     as_value Rectangle_intersects(const fn_call& fn);
48     as_value Rectangle_isEmpty(const fn_call& fn);
49     as_value Rectangle_offset(const fn_call& fn);
50     as_value Rectangle_offsetPoint(const fn_call& fn);
51     as_value Rectangle_setEmpty(const fn_call& fn);
52     as_value Rectangle_toString(const fn_call& fn);
53     as_value Rectangle_union(const fn_call& fn);
54     as_value Rectangle_bottom(const fn_call& fn);
55     as_value Rectangle_bottomRight(const fn_call& fn);
56     as_value Rectangle_left(const fn_call& fn);
57     as_value Rectangle_right(const fn_call& fn);
58     as_value Rectangle_size(const fn_call& fn);
59     as_value Rectangle_top(const fn_call& fn);
60     as_value Rectangle_topLeft(const fn_call& fn);
61     as_value Rectangle_ctor(const fn_call& fn);
62     as_value get_flash_geom_rectangle_constructor(const fn_call& fn);
63 
64 }
65 
66 void
rectangle_class_init(as_object & where,const ObjectURI & uri)67 rectangle_class_init(as_object& where, const ObjectURI& uri)
68 {
69     // TODO: this may not be correct, but it should be enumerable.
70     const int flags = 0;
71     where.init_destructive_property(uri, get_flash_geom_rectangle_constructor,
72             flags);
73 }
74 
75 
76 namespace {
77 
78 void
attachRectangleInterface(as_object & o)79 attachRectangleInterface(as_object& o)
80 {
81     Global_as& gl = getGlobal(o);
82     o.init_member("clone", gl.createFunction(Rectangle_clone), 0);
83     o.init_member("contains", gl.createFunction(Rectangle_contains), 0);
84     o.init_member("containsPoint",
85             gl.createFunction(Rectangle_containsPoint), 0);
86     o.init_member("containsRectangle",
87             gl.createFunction(Rectangle_containsRectangle), 0);
88     o.init_member("equals", gl.createFunction(Rectangle_equals), 0);
89     o.init_member("inflate", gl.createFunction(Rectangle_inflate), 0);
90     o.init_member("inflatePoint",
91             gl.createFunction(Rectangle_inflatePoint), 0);
92     o.init_member("intersection",
93             gl.createFunction(Rectangle_intersection), 0);
94     o.init_member("intersects", gl.createFunction(Rectangle_intersects), 0);
95     o.init_member("isEmpty", gl.createFunction(Rectangle_isEmpty), 0);
96     o.init_member("offset", gl.createFunction(Rectangle_offset), 0);
97     o.init_member("offsetPoint", gl.createFunction(Rectangle_offsetPoint), 0);
98     o.init_member("setEmpty", gl.createFunction(Rectangle_setEmpty), 0);
99     o.init_member("toString", gl.createFunction(Rectangle_toString), 0);
100     o.init_member("union", gl.createFunction(Rectangle_union), 0);
101     o.init_property("bottom",
102             Rectangle_bottom, Rectangle_bottom, 0);
103     o.init_property("bottomRight", Rectangle_bottomRight,
104             Rectangle_bottomRight, 0);
105     o.init_property("left", Rectangle_left,
106             Rectangle_left, 0);
107     o.init_property("right", Rectangle_right,
108             Rectangle_right, 0);
109     o.init_property("size", Rectangle_size,
110             Rectangle_size, 0);
111     o.init_property("top", Rectangle_top,
112             Rectangle_top, 0);
113     o.init_property("topLeft", Rectangle_topLeft,
114             Rectangle_topLeft, 0);
115 }
116 
117 
118 as_value
Rectangle_clone(const fn_call & fn)119 Rectangle_clone(const fn_call& fn)
120 {
121     // The object will be interpreted as a rectangle. Any Rectangle
122     // properties that the object has (width, height, x, y) are used.
123     as_object* ptr = ensure<ValidThis>(fn);
124 
125     as_value x = getMember(*ptr, NSV::PROP_X);
126     as_value y = getMember(*ptr, NSV::PROP_Y);
127     as_value w = getMember(*ptr, NSV::PROP_WIDTH);
128     as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
129 
130     as_function* ctor = getClassConstructor(fn, "flash.geom.Rectangle");
131     if (!ctor) return as_value();
132 
133     fn_call::Args args;
134     args += x, y, w, h;
135 
136     return constructInstance(*ctor, fn.env(), args);
137 }
138 
139 as_value
Rectangle_contains(const fn_call & fn)140 Rectangle_contains(const fn_call& fn)
141 {
142     as_object* ptr = ensure<ValidThis>(fn);
143 
144     as_value rect_x_as = getMember(*ptr, NSV::PROP_X);
145     as_value rect_width_as = getMember(*ptr, NSV::PROP_WIDTH);
146     as_value rect_y_as = getMember(*ptr, NSV::PROP_Y);
147     as_value rect_height_as = getMember(*ptr, NSV::PROP_HEIGHT);
148 
149     if (fn.nargs < 2) {
150         IF_VERBOSE_ASCODING_ERRORS(
151             std::stringstream ss;
152             fn.dump_args(ss);
153             log_aserror(_("flash.geom.Rectangle(%s): %s"), ss.str(),
154                 _("missing arguments"));
155         );
156         return as_value();
157     }
158 
159     const as_value& x_as = fn.arg(0);
160     const as_value& y_as = fn.arg(1);
161 
162     VM& vm = getVM(fn);
163 
164     as_value rect_x1_as = rect_x_as;
165     newAdd(rect_x1_as, rect_width_as, vm);
166 
167     as_value rect_y1_as = rect_y_as;
168     newAdd(rect_y1_as, rect_height_as, vm);
169 
170     // Points are contained within the Rectangle IFF they lie
171     // on the top or left borders of the rectangle, but not the right or
172     // bottom borders, or they are not on a border but between all.
173 
174     // NOTE: order of tests is important, see actionscript.all/Rectangle.as
175 
176     as_value ret = newLessThan(x_as, rect_x_as, vm);
177     if (ret.is_undefined()) return as_value();
178     if (toBool(ret, vm)) return as_value(false);
179 
180     ret = newLessThan(x_as, rect_x1_as, vm);
181     if (ret.is_undefined()) return as_value();
182     if (!toBool(ret, vm)) return as_value(false);
183 
184     ret = newLessThan(y_as, rect_y_as, vm);
185     if (ret.is_undefined()) return as_value();
186     if (toBool(ret, vm)) return as_value(false);
187 
188     ret = newLessThan(y_as, rect_y1_as, vm);
189     if (ret.is_undefined()) return as_value();
190     if (!toBool(ret, vm)) return as_value(false);
191 
192     return as_value(true);
193 
194 }
195 
196 
197 // This is horrible ActionScript implemented in C++.
198 as_value
Rectangle_containsPoint(const fn_call & fn)199 Rectangle_containsPoint(const fn_call& fn)
200 {
201     as_object* ptr = ensure<ValidThis>(fn);
202 
203     as_object* arg = (fn.nargs > 0) ? toObject(fn.arg(0), getVM(fn)) : nullptr;
204 
205     VM& vm = getVM(fn);
206 
207     as_value thisx = getMember(*ptr, NSV::PROP_X);
208     as_value argx = arg ? getMember(*arg, NSV::PROP_X) : as_value();
209 
210     // argx >= thisx
211     as_value ret = newLessThan(argx, thisx, vm);
212     if (ret.is_undefined()) return as_value();
213     if (toBool(ret, vm)) return as_value(false);
214 
215     as_value thisw = getMember(*ptr, NSV::PROP_WIDTH);
216 
217     newAdd(thisx, thisw, vm);
218     ret = newLessThan(argx, thisx, vm);
219     if (ret.is_undefined()) return as_value();
220     if (!toBool(ret, vm)) return as_value(false);
221 
222     as_value thisy = getMember(*ptr, NSV::PROP_Y);
223     as_value argy = arg ? getMember(*arg, NSV::PROP_Y) : as_value();
224 
225     // argy >= thisy
226     ret = newLessThan(argy, thisy, vm);
227     if (ret.is_undefined()) return as_value();
228     if (toBool(ret, vm)) return as_value(false);
229 
230     as_value thish = getMember(*ptr, NSV::PROP_HEIGHT);
231 
232     newAdd(thisy, thish, vm);
233     ret = newLessThan(argy, thisy, vm);
234     if (ret.is_undefined()) return as_value();
235     if (!toBool(ret, vm)) return as_value(false);
236 
237     return as_value(true);
238 
239 
240 }
241 
242 as_value
Rectangle_containsRectangle(const fn_call & fn)243 Rectangle_containsRectangle(const fn_call& fn)
244 {
245     as_object* ptr = ensure<ValidThis>(fn);
246     UNUSED(ptr);
247     LOG_ONCE(log_unimpl(__FUNCTION__) );
248     return as_value();
249 }
250 
251 as_value
Rectangle_equals(const fn_call & fn)252 Rectangle_equals(const fn_call& fn)
253 {
254     as_object* ptr = ensure<ValidThis>(fn);
255 
256     if (!fn.nargs) return as_value(false);
257     as_object* comp = toObject(fn.arg(0), getVM(fn));
258 
259     if (!comp) return as_value(false);
260 
261     if (!comp->instanceOf(getClassConstructor(fn, "flash.geom.Rectangle"))) {
262         return as_value(false);
263     }
264 
265     if (!equals(getMember(*comp, NSV::PROP_X),
266                 getMember(*ptr, NSV::PROP_X), getVM(fn))) {
267         return as_value(false);
268     }
269 
270     if (!equals(getMember(*comp, NSV::PROP_Y),
271                 getMember(*ptr, NSV::PROP_Y), getVM(fn))) {
272         return as_value(false);
273     }
274 
275     if (!equals(getMember(*comp, NSV::PROP_WIDTH),
276                 getMember(*ptr, NSV::PROP_WIDTH), getVM(fn))) {
277         return as_value(false);
278     }
279 
280     if (!equals(getMember(*comp, NSV::PROP_HEIGHT),
281                 getMember(*ptr, NSV::PROP_HEIGHT), getVM(fn))) {
282         return as_value(false);
283     }
284 
285     return as_value(true);
286 }
287 
288 as_value
Rectangle_inflate(const fn_call & fn)289 Rectangle_inflate(const fn_call& fn)
290 {
291     as_object* ptr = ensure<ValidThis>(fn);
292     UNUSED(ptr);
293     LOG_ONCE(log_unimpl(__FUNCTION__) );
294     return as_value();
295 }
296 
297 as_value
Rectangle_inflatePoint(const fn_call & fn)298 Rectangle_inflatePoint(const fn_call& fn)
299 {
300     as_object* ptr = ensure<ValidThis>(fn);
301     UNUSED(ptr);
302     LOG_ONCE(log_unimpl(__FUNCTION__) );
303     return as_value();
304 }
305 
306 as_value
Rectangle_intersection(const fn_call & fn)307 Rectangle_intersection(const fn_call& fn)
308 {
309     as_object* ptr = ensure<ValidThis>(fn);
310     UNUSED(ptr);
311     LOG_ONCE(log_unimpl(__FUNCTION__) );
312     return as_value();
313 }
314 
315 as_value
Rectangle_intersects(const fn_call & fn)316 Rectangle_intersects(const fn_call& fn)
317 {
318     as_object* ptr = ensure<ValidThis>(fn);
319     UNUSED(ptr);
320     LOG_ONCE(log_unimpl(__FUNCTION__) );
321     return as_value();
322 }
323 
324 as_value
Rectangle_isEmpty(const fn_call & fn)325 Rectangle_isEmpty(const fn_call& fn)
326 {
327     as_object* ptr = ensure<ValidThis>(fn);
328 
329     as_value w = getMember(*ptr, NSV::PROP_WIDTH);
330     if (w.is_undefined() || w.is_null()) return as_value(true);
331 
332     as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
333     if (h.is_undefined() || h.is_null()) return as_value(true);
334 
335     double wn = toNumber(w, getVM(fn));
336     if (!isFinite(wn) || wn <= 0) return as_value(true);
337 
338     double hn = toNumber(h, getVM(fn));
339     if (!isFinite(hn) || hn <= 0) return as_value(true);
340 
341     return as_value(false);
342 }
343 
344 as_value
Rectangle_offset(const fn_call & fn)345 Rectangle_offset(const fn_call& fn)
346 {
347     as_object* ptr = ensure<ValidThis>(fn);
348 
349     as_value xdelta = fn.nargs > 0 ? fn.arg(0) : as_value();
350     as_value ydelta = fn.nargs > 1 ? fn.arg(1) : as_value();
351 
352     as_value x = getMember(*ptr, NSV::PROP_X);
353     newAdd(x, xdelta, getVM(fn));
354     ptr->set_member(NSV::PROP_X, x);
355 
356     as_value y = getMember(*ptr, NSV::PROP_Y);
357     newAdd(y, ydelta, getVM(fn));
358     ptr->set_member(NSV::PROP_Y, y);
359 
360     return as_value();
361 }
362 
363 as_value
Rectangle_offsetPoint(const fn_call & fn)364 Rectangle_offsetPoint(const fn_call& fn)
365 {
366     as_object* ptr = ensure<ValidThis>(fn);
367 
368     as_object* arg = (fn.nargs > 0) ? toObject(fn.arg(0), getVM(fn)) : nullptr;
369     if (!arg) return as_value();
370 
371     as_value xdelta = getMember(*arg, NSV::PROP_X);
372     as_value ydelta = getMember(*arg, NSV::PROP_Y);
373 
374     as_value x = getMember(*ptr, NSV::PROP_X);
375     newAdd(x, xdelta, getVM(fn));
376     ptr->set_member(NSV::PROP_X, x);
377 
378     as_value y = getMember(*ptr, NSV::PROP_Y);
379     newAdd(y, ydelta, getVM(fn));
380     ptr->set_member(NSV::PROP_Y, y);
381 
382     return as_value();
383 }
384 
385 as_value
Rectangle_setEmpty(const fn_call & fn)386 Rectangle_setEmpty(const fn_call& fn)
387 {
388     as_object* ptr = ensure<ValidThis>(fn);
389     ptr->set_member(NSV::PROP_X, 0.0);
390     ptr->set_member(NSV::PROP_Y, 0.0);
391     ptr->set_member(NSV::PROP_WIDTH, 0.0);
392     ptr->set_member(NSV::PROP_HEIGHT, 0.0);
393     return as_value();
394 }
395 
396 as_value
Rectangle_toString(const fn_call & fn)397 Rectangle_toString(const fn_call& fn)
398 {
399     as_object* ptr = ensure<ValidThis>(fn);
400 
401     as_value x = getMember(*ptr, NSV::PROP_X);
402     as_value y = getMember(*ptr, NSV::PROP_Y);
403     as_value w = getMember(*ptr, NSV::PROP_WIDTH);
404     as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
405 
406     VM& vm = getVM(fn);
407 
408     as_value ret("(x=");
409     newAdd(ret, x, vm);
410     newAdd(ret, ", y=", vm);
411     newAdd(ret, y, vm);
412     newAdd(ret, ", w=", vm);
413     newAdd(ret, w, vm);
414     newAdd(ret, ", h=", vm);
415     newAdd(ret, h, vm);
416     newAdd(ret, ")", vm);
417 
418     return ret;
419 }
420 
421 as_value
Rectangle_union(const fn_call & fn)422 Rectangle_union(const fn_call& fn)
423 {
424     as_object* ptr = ensure<ValidThis>(fn);
425     UNUSED(ptr);
426     LOG_ONCE(log_unimpl(__FUNCTION__) );
427     return as_value();
428 }
429 
430 as_value
Rectangle_bottom(const fn_call & fn)431 Rectangle_bottom(const fn_call& fn)
432 {
433     as_object* ptr = ensure<ValidThis>(fn);
434 
435     if (!fn.nargs) {
436         as_value b = getMember(*ptr, NSV::PROP_Y);
437         as_value height = getMember(*ptr, NSV::PROP_HEIGHT);
438         newAdd(b, height, getVM(fn));
439         return b;
440     }
441     as_value y = getMember(*ptr, NSV::PROP_Y);
442     as_value height = fn.arg(0);
443     subtract(height, y, getVM(fn));
444     ptr->set_member(NSV::PROP_HEIGHT, height);
445 
446     return as_value();
447 }
448 
449 as_value
Rectangle_bottomRight(const fn_call & fn)450 Rectangle_bottomRight(const fn_call& fn)
451 {
452     as_object* ptr = ensure<ValidThis>(fn);
453 
454     if (!fn.nargs) {
455 
456         as_value x = getMember(*ptr, NSV::PROP_X);
457         as_value y = getMember(*ptr, NSV::PROP_Y);
458         as_value w = getMember(*ptr, NSV::PROP_WIDTH);
459         as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
460 
461         VM& vm = getVM(fn);
462         newAdd(x, w, vm);
463         newAdd(y, h, vm);
464 
465         as_value point(findObject(fn.env(), "flash.geom.Point"));
466 
467         as_function* pointCtor = point.to_function();
468 
469         if (!pointCtor) {
470             IF_VERBOSE_ASCODING_ERRORS(
471                 log_aserror(_("Failed to construct flash.geom.Point!"));
472             );
473             return as_value();
474         }
475 
476         fn_call::Args args;
477         args += x, y;
478 
479         return constructInstance(*pointCtor, fn.env(), args);
480     }
481 
482     IF_VERBOSE_ASCODING_ERRORS(
483     log_aserror(_("Attempt to set read-only property %s"),
484         "Rectangle.bottomRight");
485     );
486     return as_value();
487 
488 }
489 
490 as_value
Rectangle_left(const fn_call & fn)491 Rectangle_left(const fn_call& fn)
492 {
493     as_object* ptr = ensure<ValidThis>(fn);
494 
495     if (!fn.nargs) {
496         return getMember(*ptr, NSV::PROP_X);
497     }
498     as_value oldx = getMember(*ptr, NSV::PROP_X);
499 
500     as_value newx = fn.arg(0);
501     ptr->set_member(NSV::PROP_X, newx);
502 
503     as_value w = getMember(*ptr, NSV::PROP_WIDTH);
504 
505     VM& vm = getVM(fn);
506     subtract(oldx, newx, vm);
507     newAdd(w, oldx, vm);
508     ptr->set_member(NSV::PROP_WIDTH, w);
509 
510     return as_value();
511 }
512 
513 as_value
Rectangle_right(const fn_call & fn)514 Rectangle_right(const fn_call& fn)
515 {
516     as_object* ptr = ensure<ValidThis>(fn);
517 
518     if (!fn.nargs) {
519         as_value r = getMember(*ptr, NSV::PROP_X);
520         as_value width = getMember(*ptr, NSV::PROP_WIDTH);
521         newAdd(r, width, getVM(fn));
522         return r;
523     }
524 
525     as_value x = getMember(*ptr, NSV::PROP_X);
526 
527     as_value width = fn.arg(0);
528     subtract(width, x, getVM(fn));
529     ptr->set_member(NSV::PROP_WIDTH, width);
530     return as_value();
531 }
532 
533 as_value
Rectangle_size(const fn_call & fn)534 Rectangle_size(const fn_call& fn)
535 {
536     as_object* ptr = ensure<ValidThis>(fn);
537 
538     if (!fn.nargs) {
539         as_value w = getMember(*ptr, NSV::PROP_WIDTH);
540         as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
541 
542         as_function* pointCtor = getClassConstructor(fn, "flash.geom.Point");
543         if (!pointCtor) {
544             IF_VERBOSE_ASCODING_ERRORS(
545                 log_aserror(_("Failed to construct flash.geom.Point!"));
546             );
547             return as_value();
548         }
549 
550         fn_call::Args args;
551         args += w, h;
552 
553         return constructInstance(*pointCtor, fn.env(), args);
554     }
555 
556     IF_VERBOSE_ASCODING_ERRORS(
557         log_aserror(_("Attempt to set read-only property %s"),
558             "Rectangle.size");
559     );
560 
561     return as_value();
562 }
563 
564 as_value
Rectangle_top(const fn_call & fn)565 Rectangle_top(const fn_call& fn)
566 {
567     as_object* ptr = ensure<ValidThis>(fn);
568 
569     if (!fn.nargs) {
570         // getter
571         return getMember(*ptr, NSV::PROP_Y);
572     }
573 
574     // setter
575     as_value oldy = getMember(*ptr, NSV::PROP_Y);
576 
577     as_value newy = fn.arg(0);
578     ptr->set_member(NSV::PROP_Y, newy);
579 
580     as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
581 
582     VM& vm = getVM(fn);
583     subtract(oldy, newy, vm);
584     newAdd(h, oldy, vm);
585     ptr->set_member(NSV::PROP_HEIGHT, h);
586 
587     return as_value();
588 }
589 
590 as_value
Rectangle_topLeft(const fn_call & fn)591 Rectangle_topLeft(const fn_call& fn)
592 {
593     as_object* ptr = ensure<ValidThis>(fn);
594 
595     // getter
596     if (!fn.nargs) {
597         as_value x = getMember(*ptr, NSV::PROP_X);
598         as_value y = getMember(*ptr, NSV::PROP_Y);
599 
600         as_function* pointCtor = getClassConstructor(fn, "flash.geom.Point");
601         if (!pointCtor) {
602             IF_VERBOSE_ASCODING_ERRORS(
603                 log_aserror(_("Failed to construct flash.geom.Point!"));
604             );
605             return as_value();
606         }
607 
608         fn_call::Args args;
609         args += x, y;
610 
611         return constructInstance(*pointCtor, fn.env(), args);
612 
613     }
614 
615     IF_VERBOSE_ASCODING_ERRORS(
616         log_aserror(_("Attempt to set read-only property %s"),
617             "Rectangle.topLeft");
618     );
619 
620     return as_value();
621 }
622 
623 
624 as_value
Rectangle_ctor(const fn_call & fn)625 Rectangle_ctor(const fn_call& fn)
626 {
627 
628     as_object* obj = ensure<ValidThis>(fn);
629 
630     if (!fn.nargs) {
631         // TODO: use NSV !
632         const ObjectURI& setEmpty = getURI(getVM(fn), "setEmpty");
633         callMethod(obj, setEmpty);
634         return as_value();
635     }
636 
637     // At least one arg
638     obj->set_member(NSV::PROP_X, fn.arg(0));
639     obj->set_member(NSV::PROP_Y, fn.nargs > 1 ? fn.arg(1) : as_value());
640     obj->set_member(NSV::PROP_WIDTH, fn.nargs > 2 ? fn.arg(2) : as_value());
641     obj->set_member(NSV::PROP_HEIGHT, fn.nargs > 3 ? fn.arg(3) : as_value());
642 
643     return as_value();
644 }
645 
646 as_value
get_flash_geom_rectangle_constructor(const fn_call & fn)647 get_flash_geom_rectangle_constructor(const fn_call& fn)
648 {
649     log_debug("Loading flash.geom.Rectangle class");
650     Global_as& gl = getGlobal(fn);
651     as_object* proto = createObject(gl);
652     attachRectangleInterface(*proto);
653     return gl.createClass(&Rectangle_ctor, proto);
654 }
655 
656 } // anonymous namespace
657 } // end of gnash namespace
658