Mercurial > MadButterfly
comparison nodejs/svg.js @ 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 | 0027379c962e |
children | ea1e88c40548 |
comparison
equal
deleted
inserted
replaced
853:13e0953c3fb3 | 854:eff2f580b536 |
---|---|
244 coord.center.x = minx; | 244 coord.center.x = minx; |
245 if (coord.center.y > miny) | 245 if (coord.center.y > miny) |
246 coord.center.y = miny; | 246 coord.center.y = miny; |
247 }; | 247 }; |
248 | 248 |
249 function _mul(m1, m2) { | |
250 var res = new Array(); | |
251 | |
252 res.push(m1[0] * m2[0] + m1[1] * m2[3]); | |
253 res.push(m1[0] * m2[1] + m1[1] * m2[4]); | |
254 res.push(m1[0] * m2[2] + m1[1] * m2[5] + m1[2]); | |
255 res.push(m1[3] * m2[0] + m1[4] * m2[3]); | |
256 res.push(m1[3] * m2[1] + m1[4] * m2[4]); | |
257 res.push(m1[3] * m2[2] + m1[4] * m2[5] + m1[5]); | |
258 | |
259 return res; | |
260 } | |
261 | |
262 function _pnt_transform(x, y, matrix) { | |
263 var rx, ry; | |
264 | |
265 rx = x * matrix[0] + y * matrix[1] + matrix[2]; | |
266 ry = x * matrix[3] + y * matrix[4] + matrix[5]; | |
267 return new Array(rx, ry); | |
268 } | |
269 | |
270 function _shift_transform(x, y, matrix) { | |
271 var rx, ry; | |
272 | |
273 rx = x * matrix[0] + y * matrix[1]; | |
274 ry = x * matrix[3] + y * matrix[4]; | |
275 return new Array(rx, ry); | |
276 } | |
277 | |
278 function _transform_bbox(bbox, matrix) { | |
279 var min_x, min_y, max_x, max_y; | |
280 var x, y; | |
281 var pnt; | |
282 var pnts = new Array(); | |
283 var i; | |
284 | |
285 pnt = _pnt_transform(bbox.x, bbox.y, matrix); | |
286 pnts.push(pnt); | |
287 pnt = _pnt_transform(bbox.x + bbox.width, bbox.y, matrix); | |
288 pnts.push(pnt); | |
289 pnt = _pnt_transform(bbox.x, bbox.y + bbox.height, matrix); | |
290 pnts.push(pnt); | |
291 pnt = _pnt_transform(bbox.x + bbox.width, bbox.y + bbox.height, matrix); | |
292 pnts.push(pnt); | |
293 | |
294 min_x = max_x = pnts[0][0]; | |
295 min_y = max_y = pnts[0][1]; | |
296 for(i = 1; i < pnts.length; i++) { | |
297 pnt = pnts[i]; | |
298 if(pnt[0] < min_x) | |
299 min_x = pnt[0]; | |
300 if(pnt[1] < min_y) | |
301 min_y = pnt[1]; | |
302 if(pnt[0] > max_x) | |
303 max_x = pnt[0]; | |
304 if(pnt[1] > max_y) | |
305 max_y = pnt[1]; | |
306 } | |
307 | |
308 bbox.x = min_x; | |
309 bbox.y = min_y; | |
310 bbox.width = max_x - min_x; | |
311 bbox.height = max_y - min_y; | |
312 } | |
313 | |
314 function _reverse(m1) { | |
315 var rev = new Array(1, 0, 0, 0, 1, 0); | |
316 var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); | |
317 | |
318 rev[3] = -m[3] / m[0]; | |
319 m[3] = 0; | |
320 m[4] += rev[3] * m[1]; | |
321 m[5] += rev[3] * m[2]; | |
322 | |
323 rev[1] = -m[1] / m[4]; | |
324 rev[0] += rev[1] * rev[3]; | |
325 m[1] = 0; | |
326 m[2] += rev[1] * m[5]; | |
327 | |
328 rev[2] = -m[2]; | |
329 rev[5] = -m[5]; | |
330 | |
331 rev[0] = rev[0] / m[0]; | |
332 rev[1] = rev[1] / m[0]; | |
333 rev[2] = rev[2] / m[0]; | |
334 | |
335 rev[3] = rev[3] / m[4]; | |
336 rev[4] = rev[4] / m[4]; | |
337 rev[5] = rev[5] / m[4]; | |
338 | |
339 return rev; | |
340 } | |
341 | |
342 var _bbox_proto = { | |
343 _get_ac_saved_rev: function() { | |
344 var c = this.owner; | |
345 var mtx; | |
346 | |
347 if(c.type != "coord") | |
348 c = c.parent; // is a shape! | |
349 | |
350 mtx = c._mbapp_saved_rev_mtx; | |
351 while(c.parent && typeof c.parent != "undefined") { | |
352 c = c.parent; | |
353 mtx = _mul(mtx, c._mbapp_saved_rev_mtx); | |
354 } | |
355 | |
356 return mtx; | |
357 }, | |
358 | |
359 _get_ac_mtx: function() { | |
360 var c = this.owner; | |
361 var mtx; | |
362 | |
363 if(c.type != "coord") | |
364 c = c.parent; // is a shape! | |
365 | |
366 mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; | |
367 while(c.parent) { | |
368 c = c.parent; | |
369 mtx = _mul(c, mtx); | |
370 } | |
371 | |
372 return mtx; | |
373 }, | |
374 | |
375 _saved_to_current: function() { | |
376 var r; | |
377 | |
378 r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); | |
379 | |
380 return r; | |
381 }, | |
382 | |
383 /*! \brief Update x, y, width, and height of the bbox. | |
384 */ | |
385 update: function() { | |
386 var mtx; | |
387 | |
388 this.x = this._svg_saved_x; | |
389 this.y = this._svg_saved_y; | |
390 this.width = this._svg_saved_width; | |
391 this.height = this._svg_saved_height; | |
392 | |
393 mtx = this._saved_to_current(); | |
394 _transform_bbox(this, mtx); | |
395 }, | |
396 }; | |
397 | |
398 var _center_proto = { | |
399 _get_ac_saved_rev: function() { | |
400 var c = this.owner; | |
401 var mtx; | |
402 | |
403 if(c.type != "coord") | |
404 c = c.parent; // is a shape! | |
405 | |
406 mtx = c._mbapp_saved_rev_mtx; | |
407 while(c.parent && typeof c.parent != "undefined") { | |
408 c = c.parent; | |
409 mtx = _mul(mtx, c._mbapp_saved_rev_mtx); | |
410 } | |
411 | |
412 return mtx; | |
413 }, | |
414 | |
415 _get_ac_mtx: function() { | |
416 var c = this.owner; | |
417 var mtx; | |
418 | |
419 if(c.type != "coord") | |
420 c = c.parent; // is a shape! | |
421 | |
422 mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; | |
423 while(c.parent) { | |
424 c = c.parent; | |
425 mtx = _mul(c, mtx); | |
426 } | |
427 | |
428 return mtx; | |
429 }, | |
430 | |
431 _get_ac_rev: function() { | |
432 var c = this.owner; | |
433 var mtx; | |
434 | |
435 if(c.type != "coord") | |
436 c = c.parent; // is a shape! | |
437 | |
438 mtx = _reverse([c[0], c[1], c[2], c[3], c[4], c[5]]); | |
439 while(c.parent) { | |
440 c = c.parent; | |
441 mtx = _mul(mtx, _reverse([c[0], c[1], c[2], c[3], c[4], c[5]])); | |
442 } | |
443 | |
444 return mtx; | |
445 }, | |
446 | |
447 _saved_to_current: function() { | |
448 var r; | |
449 | |
450 r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); | |
451 | |
452 return r; | |
453 }, | |
454 | |
455 /*! \brief Update x, y of center point of an object. | |
456 */ | |
457 update: function() { | |
458 var mtx; | |
459 var xy; | |
460 | |
461 mtx = this._saved_to_current(); | |
462 xy = _pnt_transform(this._svg_saved_x, this._svg_saved_y, mtx); | |
463 | |
464 this._x = xy[0]; | |
465 this._y = xy[1]; | |
466 }, | |
467 | |
468 /*! \brief Move owner object to make center at (x, y). | |
469 */ | |
470 move: function(x, y) { | |
471 var mtx; | |
472 var xdiff = x - this._x; | |
473 var ydiff = y - this._y; | |
474 var shiftxy; | |
475 var c; | |
476 | |
477 mtx = this._get_ac_rev(); | |
478 shiftxy = _shift_transform(xdiff, ydiff, mtx); | |
479 | |
480 c = this.owner; | |
481 if(c.type != "coord") | |
482 c = c.parent; | |
483 | |
484 c[2] += shiftxy[0]; | |
485 c[5] += shiftxy[1]; | |
486 | |
487 this._x = x; | |
488 this._y = y; | |
489 }, | |
490 | |
491 /*! \brief Move owner object to make center at position specified by pnt. | |
492 */ | |
493 move_pnt: function(pnt) { | |
494 this.move(pnt.x, pnt.y); | |
495 }, | |
496 | |
497 /*! \brief Prevent user to modify value. | |
498 */ | |
499 get x() { return this._x; }, | |
500 | |
501 /*! \brief Prevent user to modify value. | |
502 */ | |
503 get y() { return this._y; }, | |
504 }; | |
249 | 505 |
250 loadSVG.prototype._set_bbox = function(node, tgt) { | 506 loadSVG.prototype._set_bbox = function(node, tgt) { |
251 var a; | 507 var a; |
252 var vstr; | 508 var vstr; |
253 var bbox, center; | 509 var bbox, center; |
256 sys.puts("a="+a); | 512 sys.puts("a="+a); |
257 if(!a) | 513 if(!a) |
258 return 0; | 514 return 0; |
259 | 515 |
260 tgt.bbox = bbox = new Object(); | 516 tgt.bbox = bbox = new Object(); |
517 bbox.owner = tgt; | |
518 bbox.__proto__ = _bbox_proto; | |
261 vstr = a.value(); | 519 vstr = a.value(); |
262 bbox.x = parseFloat(vstr); | 520 bbox._svg_saved_x = parseFloat(vstr); |
263 | 521 |
264 a = node.attr("bbox-y"); | 522 a = node.attr("bbox-y"); |
265 vstr = a.value(); | 523 vstr = a.value(); |
266 bbox.y = this.height - parseFloat(vstr); | 524 bbox._svg_saved_y = this.height - parseFloat(vstr); |
267 | 525 |
268 a = node.attr("bbox-width"); | 526 a = node.attr("bbox-width"); |
269 vstr = a.value(); | 527 vstr = a.value(); |
270 bbox.width = parseFloat(vstr); | 528 bbox._svg_saved_width = parseFloat(vstr); |
271 | 529 |
272 a = node.attr("bbox-height"); | 530 a = node.attr("bbox-height"); |
273 vstr = a.value(); | 531 vstr = a.value(); |
274 bbox.height = parseFloat(vstr); | 532 bbox._svg_saved_height = parseFloat(vstr); |
275 bbox.y -= bbox.height; | 533 bbox._svg_saved_y -= bbox._svg_saved_height; |
534 | |
535 bbox.update(); | |
276 | 536 |
277 tgt.center = center = new Object(); | 537 tgt.center = center = new Object(); |
278 | 538 |
279 center.x = bbox.width / 2 + bbox.x; | 539 center._svg_saved_x = bbox._svg_saved_width / 2 + bbox._svg_saved_x; |
280 center.y = bbox.height / 2 + bbox.y; | 540 center._svg_saved_y = bbox._svg_saved_height / 2 + bbox._svg_saved_y; |
281 a = node.attr("transform-center-x"); | 541 a = node.attr("transform-center-x"); |
282 if(!a) | 542 if(a) { |
283 return 1; | 543 vstr = a.value(); |
284 | 544 center._svg_saved_x += parseFloat(vstr); |
285 vstr = a.value(); | 545 a = node.attr("transform-center-y"); |
286 center.x += parseFloat(vstr); | 546 vstr = a.value(); |
287 a = node.attr("transform-center-y"); | 547 center._svg_saved_y -= parseFloat(vstr); |
288 vstr = a.value(); | 548 } |
289 center.y -= parseFloat(vstr); | 549 center.__proto__ = _center_proto; |
550 center.owner = tgt; | |
551 center.update(); | |
552 | |
290 return 1; | 553 return 1; |
291 } | 554 } |
292 | 555 |
293 loadSVG.prototype._set_paint = function(node, tgt) { | 556 loadSVG.prototype._set_paint = function(node, tgt) { |
294 var style = node.attr('style'); | 557 var style = node.attr('style'); |
352 var d = n.attr('d').value(); | 615 var d = n.attr('d').value(); |
353 var style = n.attr('style'); | 616 var style = n.attr('style'); |
354 var path = this.mb_rt.path_new(d); | 617 var path = this.mb_rt.path_new(d); |
355 | 618 |
356 guessPathBoundingBox(coord,d); | 619 guessPathBoundingBox(coord,d); |
620 coord.add_shape(path); | |
621 this._set_paint(n, path); | |
357 this._set_bbox(n, path); | 622 this._set_bbox(n, path); |
358 this._set_paint(n, path); | |
359 coord.add_shape(path); | |
360 | 623 |
361 make_mbnames(this.mb_rt, n, path); | 624 make_mbnames(this.mb_rt, n, path); |
362 }; | 625 }; |
363 | 626 |
364 loadSVG.prototype.parseText=function(accu,coord,id, n) | 627 loadSVG.prototype.parseText=function(accu,coord,id, n) |
389 this.parseTSpan(tcoord,nodes[k],style); | 652 this.parseTSpan(tcoord,nodes[k],style); |
390 } else { | 653 } else { |
391 } | 654 } |
392 } | 655 } |
393 sys.puts(y); | 656 sys.puts(y); |
394 if (this._set_bbox(n, tcoord)) { | 657 this._set_bbox(n, tcoord); |
395 tcoord.center.x -= tcoord[2]; | |
396 tcoord.center.y -= tcoord[5]; | |
397 tcoord._x = tcoord.center.x; | |
398 tcoord._y = tcoord.center.y; | |
399 } else { | |
400 tcoord._x = coord.center.x; | |
401 tcoord._y = coord.center.y; | |
402 } | |
403 | 658 |
404 make_mbnames(this.mb_rt, n, tcoord); | 659 make_mbnames(this.mb_rt, n, tcoord); |
405 }; | 660 }; |
406 | 661 |
407 | 662 |
474 | 729 |
475 if (trans) | 730 if (trans) |
476 parseTransform(tcoord,trans.value()); | 731 parseTransform(tcoord,trans.value()); |
477 | 732 |
478 var rect = this.mb_rt.rect_new(x,y,w,h,10, 10); | 733 var rect = this.mb_rt.rect_new(x,y,w,h,10, 10); |
734 tcoord.add_shape(rect); | |
479 this._set_paint(n, rect); | 735 this._set_paint(n, rect); |
480 if (this._set_bbox(n, tcoord)) { | 736 this._set_bbox(n, tcoord); |
481 tcoord.center.x -= tcoord[2]; | |
482 tcoord.center.y -= tcoord[5]; | |
483 } else { | |
484 if (trans) { | |
485 rx = tcoord[0]*x+tcoord[1]*y+tcoord[2]; | |
486 ry = tcoord[3]*x+tcoord[4]*y+tcoord[5]; | |
487 if (tcoord.center.x > rx) | |
488 tcoord.center.x = rx; | |
489 if (tcoord.center.y > ry) | |
490 tcoord.center.y = ry; | |
491 } | |
492 } | |
493 sys.puts("center.x="+tcoord.center.x); | |
494 sys.puts("center.y="+tcoord.center.y); | |
495 tcoord._x = tcoord.center.x; | |
496 tcoord._y = tcoord.center.y; | |
497 tcoord.add_shape(rect); | |
498 | 737 |
499 make_mbnames(this.mb_rt, n, tcoord); | 738 make_mbnames(this.mb_rt, n, tcoord); |
500 }; | 739 }; |
501 | 740 |
502 // When we parse a group, we need to calculate the origin of the group | 741 // When we parse a group, we need to calculate the origin of the group |
579 if (root.center.x > coord.center.x) | 818 if (root.center.x > coord.center.x) |
580 root.center.x = coord.center.x; | 819 root.center.x = coord.center.x; |
581 if (root.center.y > coord.center.y) | 820 if (root.center.y > coord.center.y) |
582 root.center.y = coord.center.y; | 821 root.center.y = coord.center.y; |
583 | 822 |
584 if (this._set_bbox(n, coord)) { | 823 this._set_bbox(n, coord); |
585 coord.center.x -= accu[2]; | |
586 coord.center.y -= accu[5]; | |
587 } | |
588 coord._x = coord.center.x; | |
589 coord._y = coord.center.y; | |
590 sys.puts("coord.center.x="+coord.center.x+",coord.center.y="+coord.center.y); | |
591 | 824 |
592 make_mbnames(this.mb_rt, n, coord); | 825 make_mbnames(this.mb_rt, n, coord); |
593 }; | 826 }; |
594 | 827 |
595 loadSVG.prototype.parseImage=function(accu,coord,id, n) | 828 loadSVG.prototype.parseImage=function(accu,coord,id, n) |
637 var img_data = ldr.load(ref); | 870 var img_data = ldr.load(ref); |
638 var paint = this.mb_rt.paint_image_new(img_data); | 871 var paint = this.mb_rt.paint_image_new(img_data); |
639 paint.fill(img); | 872 paint.fill(img); |
640 tcoord.add_shape(img); | 873 tcoord.add_shape(img); |
641 | 874 |
642 if (this._set_bbox(n, img)) { | 875 this._set_bbox(n, img); |
643 img.center.x -= accu[2]+coord[2]; | 876 |
644 img.center.y -= accu[5]+coord[5]; | |
645 } | |
646 | |
647 make_mbnames(this.mb_rt, n, img); | 877 make_mbnames(this.mb_rt, n, img); |
648 }; | 878 }; |
649 | 879 |
650 loadSVG.prototype._MB_parseLinearGradient=function(root,n) | 880 loadSVG.prototype._MB_parseLinearGradient=function(root,n) |
651 { | 881 { |