big merge from master, fix rpm creation, drop fetching swfdec
[gnash.git] / libcore / asobj / flash / geom / Rectangle_as.cpp
blob1f8f2e182dca2927215ebf609247088ab5d8c2d4
1 // Rectangle_as.cpp: ActionScript "Rectangle" class, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 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.
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.
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
21 #include "Rectangle_as.h"
23 #include <sstream>
25 #include "as_object.h" // for inheritance
26 #include "log.h"
27 #include "fn_call.h"
28 #include "Global_as.h"
29 #include "smart_ptr.h" // for boost intrusive_ptr
30 #include "GnashException.h" // for ActionException
31 #include "VM.h"
32 #include "as_value.h"
33 #include "namedStrings.h"
34 #include "GnashNumeric.h" // isFinite
35 #include "as_function.h"
37 namespace gnash {
39 namespace {
40 as_value Rectangle_clone(const fn_call& fn);
41 as_value Rectangle_contains(const fn_call& fn);
42 as_value Rectangle_containsPoint(const fn_call& fn);
43 as_value Rectangle_containsRectangle(const fn_call& fn);
44 as_value Rectangle_equals(const fn_call& fn);
45 as_value Rectangle_inflate(const fn_call& fn);
46 as_value Rectangle_inflatePoint(const fn_call& fn);
47 as_value Rectangle_intersection(const fn_call& fn);
48 as_value Rectangle_intersects(const fn_call& fn);
49 as_value Rectangle_isEmpty(const fn_call& fn);
50 as_value Rectangle_offset(const fn_call& fn);
51 as_value Rectangle_offsetPoint(const fn_call& fn);
52 as_value Rectangle_setEmpty(const fn_call& fn);
53 as_value Rectangle_toString(const fn_call& fn);
54 as_value Rectangle_union(const fn_call& fn);
55 as_value Rectangle_bottom(const fn_call& fn);
56 as_value Rectangle_bottomRight(const fn_call& fn);
57 as_value Rectangle_left(const fn_call& fn);
58 as_value Rectangle_right(const fn_call& fn);
59 as_value Rectangle_size(const fn_call& fn);
60 as_value Rectangle_top(const fn_call& fn);
61 as_value Rectangle_topLeft(const fn_call& fn);
62 as_value Rectangle_ctor(const fn_call& fn);
63 as_value get_flash_geom_rectangle_constructor(const fn_call& fn);
67 void
68 rectangle_class_init(as_object& where, const ObjectURI& uri)
70 // TODO: this may not be correct, but it should be enumerable.
71 const int flags = 0;
72 where.init_destructive_property(uri, get_flash_geom_rectangle_constructor,
73 flags);
77 namespace {
79 void
80 attachRectangleInterface(as_object& o)
82 Global_as& gl = getGlobal(o);
83 o.init_member("clone", gl.createFunction(Rectangle_clone), 0);
84 o.init_member("contains", gl.createFunction(Rectangle_contains), 0);
85 o.init_member("containsPoint",
86 gl.createFunction(Rectangle_containsPoint), 0);
87 o.init_member("containsRectangle",
88 gl.createFunction(Rectangle_containsRectangle), 0);
89 o.init_member("equals", gl.createFunction(Rectangle_equals), 0);
90 o.init_member("inflate", gl.createFunction(Rectangle_inflate), 0);
91 o.init_member("inflatePoint",
92 gl.createFunction(Rectangle_inflatePoint), 0);
93 o.init_member("intersection",
94 gl.createFunction(Rectangle_intersection), 0);
95 o.init_member("intersects", gl.createFunction(Rectangle_intersects), 0);
96 o.init_member("isEmpty", gl.createFunction(Rectangle_isEmpty), 0);
97 o.init_member("offset", gl.createFunction(Rectangle_offset), 0);
98 o.init_member("offsetPoint", gl.createFunction(Rectangle_offsetPoint), 0);
99 o.init_member("setEmpty", gl.createFunction(Rectangle_setEmpty), 0);
100 o.init_member("toString", gl.createFunction(Rectangle_toString), 0);
101 o.init_member("union", gl.createFunction(Rectangle_union), 0);
102 o.init_property("bottom",
103 Rectangle_bottom, Rectangle_bottom, 0);
104 o.init_property("bottomRight", Rectangle_bottomRight,
105 Rectangle_bottomRight, 0);
106 o.init_property("left", Rectangle_left,
107 Rectangle_left, 0);
108 o.init_property("right", Rectangle_right,
109 Rectangle_right, 0);
110 o.init_property("size", Rectangle_size,
111 Rectangle_size, 0);
112 o.init_property("top", Rectangle_top,
113 Rectangle_top, 0);
114 o.init_property("topLeft", Rectangle_topLeft,
115 Rectangle_topLeft, 0);
119 as_value
120 Rectangle_clone(const fn_call& fn)
122 // The object will be interpreted as a rectangle. Any Rectangle
123 // properties that the object has (width, height, x, y) are used.
124 as_object* ptr = ensure<ValidThis>(fn);
126 as_value x = getMember(*ptr, NSV::PROP_X);
127 as_value y = getMember(*ptr, NSV::PROP_Y);
128 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
129 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
131 as_function* ctor = getClassConstructor(fn, "flash.geom.Rectangle");
132 if (!ctor) return as_value();
134 fn_call::Args args;
135 args += x, y, w, h;
137 return constructInstance(*ctor, fn.env(), args);
140 as_value
141 Rectangle_contains(const fn_call& fn)
143 as_object* ptr = ensure<ValidThis>(fn);
145 as_value rect_x_as = getMember(*ptr, NSV::PROP_X);
146 as_value rect_width_as = getMember(*ptr, NSV::PROP_WIDTH);
147 as_value rect_y_as = getMember(*ptr, NSV::PROP_Y);
148 as_value rect_height_as = getMember(*ptr, NSV::PROP_HEIGHT);
150 if (fn.nargs < 2) {
151 IF_VERBOSE_ASCODING_ERRORS(
152 std::stringstream ss;
153 fn.dump_args(ss);
154 log_aserror("flash.geom.Rectangle(%s): %s", ss.str(),
155 _("missing arguments"));
157 return as_value();
160 const as_value& x_as = fn.arg(0);
161 const as_value& y_as = fn.arg(1);
163 VM& vm = getVM(fn);
165 as_value rect_x1_as = rect_x_as;
166 newAdd(rect_x1_as, rect_width_as, vm);
168 as_value rect_y1_as = rect_y_as;
169 newAdd(rect_y1_as, rect_height_as, vm);
171 // Points are contained within the Rectangle IFF they lie
172 // on the top or left borders of the rectangle, but not the right or
173 // bottom borders, or they are not on a border but between all.
175 // NOTE: order of tests is important, see actionscript.all/Rectangle.as
177 as_value ret = newLessThan(x_as, rect_x_as, vm);
178 if (ret.is_undefined()) return as_value();
179 if (toBool(ret, vm)) return as_value(false);
181 ret = newLessThan(x_as, rect_x1_as, vm);
182 if (ret.is_undefined()) return as_value();
183 if (!toBool(ret, vm)) return as_value(false);
185 ret = newLessThan(y_as, rect_y_as, vm);
186 if (ret.is_undefined()) return as_value();
187 if (toBool(ret, vm)) return as_value(false);
189 ret = newLessThan(y_as, rect_y1_as, vm);
190 if (ret.is_undefined()) return as_value();
191 if (!toBool(ret, vm)) return as_value(false);
193 return as_value(true);
198 // This is horrible ActionScript implemented in C++.
199 as_value
200 Rectangle_containsPoint(const fn_call& fn)
202 as_object* ptr = ensure<ValidThis>(fn);
204 as_object* arg = (fn.nargs > 0) ? toObject(fn.arg(0), getVM(fn)) : 0;
206 VM& vm = getVM(fn);
208 as_value thisx = getMember(*ptr, NSV::PROP_X);
209 as_value argx = arg ? getMember(*arg, NSV::PROP_X) : as_value();
211 // argx >= thisx
212 as_value ret = newLessThan(argx, thisx, vm);
213 if (ret.is_undefined()) return as_value();
214 if (toBool(ret, vm)) return as_value(false);
216 as_value thisw = getMember(*ptr, NSV::PROP_WIDTH);
218 newAdd(thisx, thisw, vm);
219 ret = newLessThan(argx, thisx, vm);
220 if (ret.is_undefined()) return as_value();
221 if (!toBool(ret, vm)) return as_value(false);
223 as_value thisy = getMember(*ptr, NSV::PROP_Y);
224 as_value argy = arg ? getMember(*arg, NSV::PROP_Y) : as_value();
226 // argy >= thisy
227 ret = newLessThan(argy, thisy, vm);
228 if (ret.is_undefined()) return as_value();
229 if (toBool(ret, vm)) return as_value(false);
231 as_value thish = getMember(*ptr, NSV::PROP_HEIGHT);
233 newAdd(thisy, thish, vm);
234 ret = newLessThan(argy, thisy, vm);
235 if (ret.is_undefined()) return as_value();
236 if (!toBool(ret, vm)) return as_value(false);
238 return as_value(true);
243 as_value
244 Rectangle_containsRectangle(const fn_call& fn)
246 as_object* ptr = ensure<ValidThis>(fn);
247 UNUSED(ptr);
248 LOG_ONCE( log_unimpl (__FUNCTION__) );
249 return as_value();
252 as_value
253 Rectangle_equals(const fn_call& fn)
255 as_object* ptr = ensure<ValidThis>(fn);
257 if (!fn.nargs) return as_value(false);
258 as_object* comp = toObject(fn.arg(0), getVM(fn));
260 if (!comp) return as_value(false);
262 if (!comp->instanceOf(getClassConstructor(fn, "flash.geom.Rectangle"))) {
263 return as_value(false);
266 if (!equals(getMember(*comp, NSV::PROP_X),
267 getMember(*ptr, NSV::PROP_X), getVM(fn))) {
268 return as_value(false);
271 if (!equals(getMember(*comp, NSV::PROP_Y),
272 getMember(*ptr, NSV::PROP_Y), getVM(fn))) {
273 return as_value(false);
276 if (!equals(getMember(*comp, NSV::PROP_WIDTH),
277 getMember(*ptr, NSV::PROP_WIDTH), getVM(fn))) {
278 return as_value(false);
281 if (!equals(getMember(*comp, NSV::PROP_HEIGHT),
282 getMember(*ptr, NSV::PROP_HEIGHT), getVM(fn))) {
283 return as_value(false);
286 return as_value(true);
289 as_value
290 Rectangle_inflate(const fn_call& fn)
292 as_object* ptr = ensure<ValidThis>(fn);
293 UNUSED(ptr);
294 LOG_ONCE( log_unimpl (__FUNCTION__) );
295 return as_value();
298 as_value
299 Rectangle_inflatePoint(const fn_call& fn)
301 as_object* ptr = ensure<ValidThis>(fn);
302 UNUSED(ptr);
303 LOG_ONCE( log_unimpl (__FUNCTION__) );
304 return as_value();
307 as_value
308 Rectangle_intersection(const fn_call& fn)
310 as_object* ptr = ensure<ValidThis>(fn);
311 UNUSED(ptr);
312 LOG_ONCE( log_unimpl (__FUNCTION__) );
313 return as_value();
316 as_value
317 Rectangle_intersects(const fn_call& fn)
319 as_object* ptr = ensure<ValidThis>(fn);
320 UNUSED(ptr);
321 LOG_ONCE( log_unimpl (__FUNCTION__) );
322 return as_value();
325 as_value
326 Rectangle_isEmpty(const fn_call& fn)
328 as_object* ptr = ensure<ValidThis>(fn);
330 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
331 if (w.is_undefined() || w.is_null()) return as_value(true);
333 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
334 if (h.is_undefined() || h.is_null()) return as_value(true);
336 double wn = toNumber(w, getVM(fn));
337 if (!isFinite(wn) || wn <= 0) return as_value(true);
339 double hn = toNumber(h, getVM(fn));
340 if (!isFinite(hn) || hn <= 0) return as_value(true);
342 return as_value(false);
345 as_value
346 Rectangle_offset(const fn_call& fn)
348 as_object* ptr = ensure<ValidThis>(fn);
350 as_value xdelta = fn.nargs > 0 ? fn.arg(0) : as_value();
351 as_value ydelta = fn.nargs > 1 ? fn.arg(1) : as_value();
353 as_value x = getMember(*ptr, NSV::PROP_X);
354 newAdd(x, xdelta, getVM(fn));
355 ptr->set_member(NSV::PROP_X, x);
357 as_value y = getMember(*ptr, NSV::PROP_Y);
358 newAdd(y, ydelta, getVM(fn));
359 ptr->set_member(NSV::PROP_Y, y);
361 return as_value();
364 as_value
365 Rectangle_offsetPoint(const fn_call& fn)
367 as_object* ptr = ensure<ValidThis>(fn);
369 as_object* arg = (fn.nargs > 0) ? toObject(fn.arg(0), getVM(fn)) : 0;
370 if (!arg) return as_value();
372 as_value xdelta = getMember(*arg, NSV::PROP_X);
373 as_value ydelta = getMember(*arg, NSV::PROP_Y);
375 as_value x = getMember(*ptr, NSV::PROP_X);
376 newAdd(x, xdelta, getVM(fn));
377 ptr->set_member(NSV::PROP_X, x);
379 as_value y = getMember(*ptr, NSV::PROP_Y);
380 newAdd(y, ydelta, getVM(fn));
381 ptr->set_member(NSV::PROP_Y, y);
383 return as_value();
386 as_value
387 Rectangle_setEmpty(const fn_call& fn)
389 as_object* ptr = ensure<ValidThis>(fn);
390 ptr->set_member(NSV::PROP_X, 0.0);
391 ptr->set_member(NSV::PROP_Y, 0.0);
392 ptr->set_member(NSV::PROP_WIDTH, 0.0);
393 ptr->set_member(NSV::PROP_HEIGHT, 0.0);
394 return as_value();
397 as_value
398 Rectangle_toString(const fn_call& fn)
400 as_object* ptr = ensure<ValidThis>(fn);
402 as_value x = getMember(*ptr, NSV::PROP_X);
403 as_value y = getMember(*ptr, NSV::PROP_Y);
404 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
405 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
407 VM& vm = getVM(fn);
409 as_value ret("(x=");
410 newAdd(ret, x, vm);
411 newAdd(ret, ", y=", vm);
412 newAdd(ret, y, vm);
413 newAdd(ret, ", w=", vm);
414 newAdd(ret, w, vm);
415 newAdd(ret, ", h=", vm);
416 newAdd(ret, h, vm);
417 newAdd(ret, ")", vm);
419 return ret;
422 as_value
423 Rectangle_union(const fn_call& fn)
425 as_object* ptr = ensure<ValidThis>(fn);
426 UNUSED(ptr);
427 LOG_ONCE( log_unimpl (__FUNCTION__) );
428 return as_value();
431 as_value
432 Rectangle_bottom(const fn_call& fn)
434 as_object* ptr = ensure<ValidThis>(fn);
436 if (!fn.nargs) {
437 as_value b = getMember(*ptr, NSV::PROP_Y);
438 as_value height = getMember(*ptr, NSV::PROP_HEIGHT);
439 newAdd(b, height, getVM(fn));
440 return b;
442 as_value y = getMember(*ptr, NSV::PROP_Y);
443 as_value height = fn.arg(0);
444 subtract(height, y, getVM(fn));
445 ptr->set_member(NSV::PROP_HEIGHT, height);
447 return as_value();
450 as_value
451 Rectangle_bottomRight(const fn_call& fn)
453 as_object* ptr = ensure<ValidThis>(fn);
455 if (!fn.nargs) {
457 as_value x = getMember(*ptr, NSV::PROP_X);
458 as_value y = getMember(*ptr, NSV::PROP_Y);
459 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
460 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
462 VM& vm = getVM(fn);
463 newAdd(x, w, vm);
464 newAdd(y, h, vm);
466 as_value point(findObject(fn.env(), "flash.geom.Point"));
468 as_function* pointCtor = point.to_function();
470 if (!pointCtor) {
471 IF_VERBOSE_ASCODING_ERRORS(
472 log_aserror("Failed to construct flash.geom.Point!");
474 return as_value();
477 fn_call::Args args;
478 args += x, y;
480 return constructInstance(*pointCtor, fn.env(), args);
483 IF_VERBOSE_ASCODING_ERRORS(
484 log_aserror(_("Attempt to set read-only property %s"),
485 "Rectangle.bottomRight");
487 return as_value();
491 as_value
492 Rectangle_left(const fn_call& fn)
494 as_object* ptr = ensure<ValidThis>(fn);
496 if (!fn.nargs) {
497 return getMember(*ptr, NSV::PROP_X);
499 as_value oldx = getMember(*ptr, NSV::PROP_X);
501 as_value newx = fn.arg(0);
502 ptr->set_member(NSV::PROP_X, newx);
504 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
506 VM& vm = getVM(fn);
507 subtract(oldx, newx, vm);
508 newAdd(w, oldx, vm);
509 ptr->set_member(NSV::PROP_WIDTH, w);
511 return as_value();
514 as_value
515 Rectangle_right(const fn_call& fn)
517 as_object* ptr = ensure<ValidThis>(fn);
519 if (!fn.nargs) {
520 as_value r = getMember(*ptr, NSV::PROP_X);
521 as_value width = getMember(*ptr, NSV::PROP_WIDTH);
522 newAdd(r, width, getVM(fn));
523 return r;
526 as_value x = getMember(*ptr, NSV::PROP_X);
528 as_value width = fn.arg(0);
529 subtract(width, x, getVM(fn));
530 ptr->set_member(NSV::PROP_WIDTH, width);
531 return as_value();
534 as_value
535 Rectangle_size(const fn_call& fn)
537 as_object* ptr = ensure<ValidThis>(fn);
539 if (!fn.nargs) {
540 as_value w = getMember(*ptr, NSV::PROP_WIDTH);
541 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
543 as_function* pointCtor = getClassConstructor(fn, "flash.geom.Point");
544 if (!pointCtor) {
545 IF_VERBOSE_ASCODING_ERRORS(
546 log_aserror("Failed to construct flash.geom.Point!");
548 return as_value();
551 fn_call::Args args;
552 args += w, h;
554 return constructInstance(*pointCtor, fn.env(), args);
557 IF_VERBOSE_ASCODING_ERRORS(
558 log_aserror(_("Attempt to set read-only property %s"),
559 "Rectangle.size");
562 return as_value();
565 as_value
566 Rectangle_top(const fn_call& fn)
568 as_object* ptr = ensure<ValidThis>(fn);
570 if (!fn.nargs) {
571 // getter
572 return getMember(*ptr, NSV::PROP_Y);
575 // setter
576 as_value oldy = getMember(*ptr, NSV::PROP_Y);
578 as_value newy = fn.arg(0);
579 ptr->set_member(NSV::PROP_Y, newy);
581 as_value h = getMember(*ptr, NSV::PROP_HEIGHT);
583 VM& vm = getVM(fn);
584 subtract(oldy, newy, vm);
585 newAdd(h, oldy, vm);
586 ptr->set_member(NSV::PROP_HEIGHT, h);
588 return as_value();
591 as_value
592 Rectangle_topLeft(const fn_call& fn)
594 as_object* ptr = ensure<ValidThis>(fn);
596 // getter
597 if (!fn.nargs) {
598 as_value x = getMember(*ptr, NSV::PROP_X);
599 as_value y = getMember(*ptr, NSV::PROP_Y);
601 as_function* pointCtor = getClassConstructor(fn, "flash.geom.Point");
602 if (!pointCtor) {
603 IF_VERBOSE_ASCODING_ERRORS(
604 log_aserror("Failed to construct flash.geom.Point!");
606 return as_value();
609 fn_call::Args args;
610 args += x, y;
612 return constructInstance(*pointCtor, fn.env(), args);
616 IF_VERBOSE_ASCODING_ERRORS(
617 log_aserror(_("Attempt to set read-only property %s"),
618 "Rectangle.topLeft");
621 return as_value();
625 as_value
626 Rectangle_ctor(const fn_call& fn)
629 as_object* obj = ensure<ValidThis>(fn);
631 if (!fn.nargs) {
632 // TODO: use NSV !
633 const ObjectURI& setEmpty = getURI(getVM(fn), "setEmpty");
634 callMethod(obj, setEmpty);
635 return as_value();
638 // At least one arg
639 obj->set_member(NSV::PROP_X, fn.arg(0));
640 obj->set_member(NSV::PROP_Y, fn.nargs > 1 ? fn.arg(1) : as_value());
641 obj->set_member(NSV::PROP_WIDTH, fn.nargs > 2 ? fn.arg(2) : as_value());
642 obj->set_member(NSV::PROP_HEIGHT, fn.nargs > 3 ? fn.arg(3) : as_value());
644 return as_value();
647 as_value
648 get_flash_geom_rectangle_constructor(const fn_call& fn)
650 log_debug("Loading flash.geom.Rectangle class");
651 Global_as& gl = getGlobal(fn);
652 as_object* proto = createObject(gl);
653 attachRectangleInterface(*proto);
654 return gl.createClass(&Rectangle_ctor, proto);
657 } // anonymous namespace
658 } // end of gnash namespace