Mercurial > MadButterfly
changeset 854:eff2f580b536 abs_n_rel_center
Use accessor to return bbox values
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Mon, 20 Sep 2010 22:43:43 +0800 |
parents | 13e0953c3fb3 |
children | c385493e04b6 |
files | nodejs/animate.js nodejs/mbapp.js nodejs/svg.js |
diffstat | 3 files changed, 350 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/nodejs/animate.js Mon Sep 20 22:43:43 2010 +0800 +++ b/nodejs/animate.js Mon Sep 20 22:43:43 2010 +0800 @@ -11,6 +11,7 @@ function linear_draw() { var percent; + var x, y; percent = (Date.now() - this._start_tm) / this.duration; if(percent >= 1) { @@ -20,8 +21,9 @@ delete this.obj.timer; } } - this.obj.x = (this.targetx-this.startposx)*percent+this.startposx; - this.obj.y = (this.targety-this.startposy)*percent+this.startposy; + x = (this.targetx-this.startposx)*percent+this.startposx; + y = (this.targety-this.startposy)*percent+this.startposy; + this.obj.center.move(x, y); this.app.refresh(); } @@ -41,10 +43,10 @@ this.app = app; this.obj = obj; this.end = 0; - this.targetx = shiftx + obj.x; - this.targety = shifty + obj.y; - this.startposx = obj.x; - this.startposy = obj.y; + this.targetx = shiftx + obj.center.x; + this.targety = shifty + obj.center.y; + this.startposx = obj.center.x; + this.startposy = obj.center.y; this.duration = duration*1000; }
--- a/nodejs/mbapp.js Mon Sep 20 22:43:43 2010 +0800 +++ b/nodejs/mbapp.js Mon Sep 20 22:43:43 2010 +0800 @@ -5,16 +5,73 @@ var sys = require("sys"); var ldr = mbfly.img_ldr_new("."); +function _reverse(m1) { + var rev = new Array(1, 0, 0, 0, 1, 0); + var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); + + rev[3] = -m[3] / m[0]; + m[3] = 0; + m[4] += rev[3] * m[1]; + m[5] += rev[3] * m[2]; + + rev[1] = -m[1] / m[4]; + rev[0] += rev[1] * rev[3]; + m[1] = 0; + m[2] += rev[1] * m[5]; + + rev[2] = -m[2]; + rev[5] = -m[5]; + + rev[0] = rev[0] / m[0]; + rev[1] = rev[1] / m[0]; + rev[2] = rev[2] / m[0]; + + rev[3] = rev[3] / m[4]; + rev[4] = rev[4] / m[4]; + rev[5] = rev[5] / m[4]; + + return rev; +} + function _decorate_mb_rt(mb_rt) { + var coord; + mb_rt._mbapp_saved_coord_new = mb_rt.coord_new; mb_rt.coord_new = function(parent) { var coord; coord = this._mbapp_saved_coord_new(parent); + coord.type = "coord"; coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]; + coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); + coord.parent = parent; + coord._mbapp_saved_add_shape = coord.add_shape; + coord.add_shape = function(shape) { + var coord; + + this._mbapp_saved_add_shape(shape); + shape.parent = this; + } + return coord; }; + + /* + * Decorate root coord + */ + coord = mb_rt.root; + coord.type = "coord"; + coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], + coord[3], coord[4], coord[5]]; + coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); + coord._mbapp_saved_add_shape = coord.add_shape; + coord.add_shape = function(shape) { + var coord; + + this._mbapp_saved_add_shape(shape); + shape.parent = this; + } } app=function(display, w, h) {
--- a/nodejs/svg.js Mon Sep 20 22:43:43 2010 +0800 +++ b/nodejs/svg.js Mon Sep 20 22:43:43 2010 +0800 @@ -246,6 +246,262 @@ coord.center.y = miny; }; +function _mul(m1, m2) { + var res = new Array(); + + res.push(m1[0] * m2[0] + m1[1] * m2[3]); + res.push(m1[0] * m2[1] + m1[1] * m2[4]); + res.push(m1[0] * m2[2] + m1[1] * m2[5] + m1[2]); + res.push(m1[3] * m2[0] + m1[4] * m2[3]); + res.push(m1[3] * m2[1] + m1[4] * m2[4]); + res.push(m1[3] * m2[2] + m1[4] * m2[5] + m1[5]); + + return res; +} + +function _pnt_transform(x, y, matrix) { + var rx, ry; + + rx = x * matrix[0] + y * matrix[1] + matrix[2]; + ry = x * matrix[3] + y * matrix[4] + matrix[5]; + return new Array(rx, ry); +} + +function _shift_transform(x, y, matrix) { + var rx, ry; + + rx = x * matrix[0] + y * matrix[1]; + ry = x * matrix[3] + y * matrix[4]; + return new Array(rx, ry); +} + +function _transform_bbox(bbox, matrix) { + var min_x, min_y, max_x, max_y; + var x, y; + var pnt; + var pnts = new Array(); + var i; + + pnt = _pnt_transform(bbox.x, bbox.y, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x + bbox.width, bbox.y, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x, bbox.y + bbox.height, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x + bbox.width, bbox.y + bbox.height, matrix); + pnts.push(pnt); + + min_x = max_x = pnts[0][0]; + min_y = max_y = pnts[0][1]; + for(i = 1; i < pnts.length; i++) { + pnt = pnts[i]; + if(pnt[0] < min_x) + min_x = pnt[0]; + if(pnt[1] < min_y) + min_y = pnt[1]; + if(pnt[0] > max_x) + max_x = pnt[0]; + if(pnt[1] > max_y) + max_y = pnt[1]; + } + + bbox.x = min_x; + bbox.y = min_y; + bbox.width = max_x - min_x; + bbox.height = max_y - min_y; +} + +function _reverse(m1) { + var rev = new Array(1, 0, 0, 0, 1, 0); + var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); + + rev[3] = -m[3] / m[0]; + m[3] = 0; + m[4] += rev[3] * m[1]; + m[5] += rev[3] * m[2]; + + rev[1] = -m[1] / m[4]; + rev[0] += rev[1] * rev[3]; + m[1] = 0; + m[2] += rev[1] * m[5]; + + rev[2] = -m[2]; + rev[5] = -m[5]; + + rev[0] = rev[0] / m[0]; + rev[1] = rev[1] / m[0]; + rev[2] = rev[2] / m[0]; + + rev[3] = rev[3] / m[4]; + rev[4] = rev[4] / m[4]; + rev[5] = rev[5] / m[4]; + + return rev; +} + +var _bbox_proto = { + _get_ac_saved_rev: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = c._mbapp_saved_rev_mtx; + while(c.parent && typeof c.parent != "undefined") { + c = c.parent; + mtx = _mul(mtx, c._mbapp_saved_rev_mtx); + } + + return mtx; + }, + + _get_ac_mtx: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; + while(c.parent) { + c = c.parent; + mtx = _mul(c, mtx); + } + + return mtx; + }, + + _saved_to_current: function() { + var r; + + r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); + + return r; + }, + + /*! \brief Update x, y, width, and height of the bbox. + */ + update: function() { + var mtx; + + this.x = this._svg_saved_x; + this.y = this._svg_saved_y; + this.width = this._svg_saved_width; + this.height = this._svg_saved_height; + + mtx = this._saved_to_current(); + _transform_bbox(this, mtx); + }, +}; + +var _center_proto = { + _get_ac_saved_rev: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = c._mbapp_saved_rev_mtx; + while(c.parent && typeof c.parent != "undefined") { + c = c.parent; + mtx = _mul(mtx, c._mbapp_saved_rev_mtx); + } + + return mtx; + }, + + _get_ac_mtx: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; + while(c.parent) { + c = c.parent; + mtx = _mul(c, mtx); + } + + return mtx; + }, + + _get_ac_rev: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = _reverse([c[0], c[1], c[2], c[3], c[4], c[5]]); + while(c.parent) { + c = c.parent; + mtx = _mul(mtx, _reverse([c[0], c[1], c[2], c[3], c[4], c[5]])); + } + + return mtx; + }, + + _saved_to_current: function() { + var r; + + r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); + + return r; + }, + + /*! \brief Update x, y of center point of an object. + */ + update: function() { + var mtx; + var xy; + + mtx = this._saved_to_current(); + xy = _pnt_transform(this._svg_saved_x, this._svg_saved_y, mtx); + + this._x = xy[0]; + this._y = xy[1]; + }, + + /*! \brief Move owner object to make center at (x, y). + */ + move: function(x, y) { + var mtx; + var xdiff = x - this._x; + var ydiff = y - this._y; + var shiftxy; + var c; + + mtx = this._get_ac_rev(); + shiftxy = _shift_transform(xdiff, ydiff, mtx); + + c = this.owner; + if(c.type != "coord") + c = c.parent; + + c[2] += shiftxy[0]; + c[5] += shiftxy[1]; + + this._x = x; + this._y = y; + }, + + /*! \brief Move owner object to make center at position specified by pnt. + */ + move_pnt: function(pnt) { + this.move(pnt.x, pnt.y); + }, + + /*! \brief Prevent user to modify value. + */ + get x() { return this._x; }, + + /*! \brief Prevent user to modify value. + */ + get y() { return this._y; }, +}; loadSVG.prototype._set_bbox = function(node, tgt) { var a; @@ -258,35 +514,42 @@ return 0; tgt.bbox = bbox = new Object(); + bbox.owner = tgt; + bbox.__proto__ = _bbox_proto; vstr = a.value(); - bbox.x = parseFloat(vstr); + bbox._svg_saved_x = parseFloat(vstr); a = node.attr("bbox-y"); vstr = a.value(); - bbox.y = this.height - parseFloat(vstr); + bbox._svg_saved_y = this.height - parseFloat(vstr); a = node.attr("bbox-width"); vstr = a.value(); - bbox.width = parseFloat(vstr); + bbox._svg_saved_width = parseFloat(vstr); a = node.attr("bbox-height"); vstr = a.value(); - bbox.height = parseFloat(vstr); - bbox.y -= bbox.height; + bbox._svg_saved_height = parseFloat(vstr); + bbox._svg_saved_y -= bbox._svg_saved_height; + + bbox.update(); tgt.center = center = new Object(); - center.x = bbox.width / 2 + bbox.x; - center.y = bbox.height / 2 + bbox.y; + center._svg_saved_x = bbox._svg_saved_width / 2 + bbox._svg_saved_x; + center._svg_saved_y = bbox._svg_saved_height / 2 + bbox._svg_saved_y; a = node.attr("transform-center-x"); - if(!a) - return 1; + if(a) { + vstr = a.value(); + center._svg_saved_x += parseFloat(vstr); + a = node.attr("transform-center-y"); + vstr = a.value(); + center._svg_saved_y -= parseFloat(vstr); + } + center.__proto__ = _center_proto; + center.owner = tgt; + center.update(); - vstr = a.value(); - center.x += parseFloat(vstr); - a = node.attr("transform-center-y"); - vstr = a.value(); - center.y -= parseFloat(vstr); return 1; } @@ -354,9 +617,9 @@ var path = this.mb_rt.path_new(d); guessPathBoundingBox(coord,d); - this._set_bbox(n, path); + coord.add_shape(path); this._set_paint(n, path); - coord.add_shape(path); + this._set_bbox(n, path); make_mbnames(this.mb_rt, n, path); }; @@ -391,15 +654,7 @@ } } sys.puts(y); - if (this._set_bbox(n, tcoord)) { - tcoord.center.x -= tcoord[2]; - tcoord.center.y -= tcoord[5]; - tcoord._x = tcoord.center.x; - tcoord._y = tcoord.center.y; - } else { - tcoord._x = coord.center.x; - tcoord._y = coord.center.y; - } + this._set_bbox(n, tcoord); make_mbnames(this.mb_rt, n, tcoord); }; @@ -476,25 +731,9 @@ parseTransform(tcoord,trans.value()); var rect = this.mb_rt.rect_new(x,y,w,h,10, 10); + tcoord.add_shape(rect); this._set_paint(n, rect); - if (this._set_bbox(n, tcoord)) { - tcoord.center.x -= tcoord[2]; - tcoord.center.y -= tcoord[5]; - } else { - if (trans) { - rx = tcoord[0]*x+tcoord[1]*y+tcoord[2]; - ry = tcoord[3]*x+tcoord[4]*y+tcoord[5]; - if (tcoord.center.x > rx) - tcoord.center.x = rx; - if (tcoord.center.y > ry) - tcoord.center.y = ry; - } - } - sys.puts("center.x="+tcoord.center.x); - sys.puts("center.y="+tcoord.center.y); - tcoord._x = tcoord.center.x; - tcoord._y = tcoord.center.y; - tcoord.add_shape(rect); + this._set_bbox(n, tcoord); make_mbnames(this.mb_rt, n, tcoord); }; @@ -581,13 +820,7 @@ if (root.center.y > coord.center.y) root.center.y = coord.center.y; - if (this._set_bbox(n, coord)) { - coord.center.x -= accu[2]; - coord.center.y -= accu[5]; - } - coord._x = coord.center.x; - coord._y = coord.center.y; - sys.puts("coord.center.x="+coord.center.x+",coord.center.y="+coord.center.y); + this._set_bbox(n, coord); make_mbnames(this.mb_rt, n, coord); }; @@ -639,11 +872,8 @@ paint.fill(img); tcoord.add_shape(img); - if (this._set_bbox(n, img)) { - img.center.x -= accu[2]+coord[2]; - img.center.y -= accu[5]+coord[5]; - } - + this._set_bbox(n, img); + make_mbnames(this.mb_rt, n, img); };