Move getPathBBox() and getBBox() into svgutils.js

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1840 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
Jeff Schiller
2010-11-05 15:29:30 +00:00
parent 0ce7e2adb7
commit b104277fa1
2 changed files with 172 additions and 166 deletions

View File

@@ -1,5 +1,5 @@
/**
* SVG-edit Utilities
* Package: svgedit.Utilities
*
* Licensed under the Apache License, Version 2
*
@@ -9,6 +9,7 @@
// Dependencies:
// 1) jQuery
// 2) browsersupport.js
(function() {
@@ -26,6 +27,11 @@ if (!svgedit.Utilities) {
var KEYSTR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var XLINKNS = "http://www.w3.org/1999/xlink";
// Much faster than running getBBox() every time
var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';
var visElems_arr = visElems.split(',');
//var hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';
// Function: svgedit.Utilities.toXml
// Converts characters in a string to XML-friendly entities.
//
@@ -325,4 +331,136 @@ svgedit.Utilities.findDefs = function(svgElement) {
return defs;
};
// Function: svgedit.Utilities.getPathBBox
// Get correct BBox for a path in Webkit
// Converted from code found here:
// http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
//
// Parameters:
// path - The path DOM element to get the BBox for
//
// Returns:
// A BBox-like object
svgedit.Utilities.getPathBBox = function(path) {
var seglist = path.pathSegList;
var tot = seglist.numberOfItems;
var bounds = [[], []];
var start = seglist.getItem(0);
var P0 = [start.x, start.y];
for(var i=0; i < tot; i++) {
var seg = seglist.getItem(i);
if(!seg.x) continue;
// Add actual points to limits
bounds[0].push(P0[0]);
bounds[1].push(P0[1]);
if(seg.x1) {
var P1 = [seg.x1, seg.y1],
P2 = [seg.x2, seg.y2],
P3 = [seg.x, seg.y];
for(var j=0; j < 2; j++) {
var calc = function(t) {
return Math.pow(1-t,3) * P0[j]
+ 3 * Math.pow(1-t,2) * t * P1[j]
+ 3 * (1-t) * Math.pow(t,2) * P2[j]
+ Math.pow(t,3) * P3[j];
};
var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];
var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
var c = 3 * P1[j] - 3 * P0[j];
if(a == 0) {
if(b == 0) {
continue;
}
var t = -c / b;
if(0 < t && t < 1) {
bounds[j].push(calc(t));
}
continue;
}
var b2ac = Math.pow(b,2) - 4 * c * a;
if(b2ac < 0) continue;
var t1 = (-b + Math.sqrt(b2ac))/(2 * a);
if(0 < t1 && t1 < 1) bounds[j].push(calc(t1));
var t2 = (-b - Math.sqrt(b2ac))/(2 * a);
if(0 < t2 && t2 < 1) bounds[j].push(calc(t2));
}
P0 = P3;
} else {
bounds[0].push(seg.x);
bounds[1].push(seg.y);
}
}
var x = Math.min.apply(null, bounds[0]);
var w = Math.max.apply(null, bounds[0]) - x;
var y = Math.min.apply(null, bounds[1]);
var h = Math.max.apply(null, bounds[1]) - y;
return {
'x': x,
'y': y,
'width': w,
'height': h
};
};
// Function: svgedit.Utilities.getBBox
// Get the given/selected element's bounding box object, convert it to be more
// usable when necessary
//
// Parameters:
// elem - Optional DOM element to get the BBox for
svgedit.Utilities.getBBox = function(elem) {
var selected = elem || selectedElements[0];
if (elem.nodeType != 1) return null;
var ret = null;
var elname = selected.nodeName;
if(elname === 'text' && selected.textContent === '') {
selected.textContent = 'a'; // Some character needed for the selector to use.
ret = selected.getBBox();
selected.textContent = '';
} else if(elname === 'path' && svgedit.BrowserSupport.isWebkit) {
ret = svgedit.Utilities.getPathBBox(selected);
} else if(elname === 'use' && !svgedit.BrowserSupport.isWebkit || elname === 'foreignObject') {
ret = selected.getBBox();
var bb = {};
bb.width = ret.width;
bb.height = ret.height;
bb.x = ret.x + parseFloat(selected.getAttribute('x')||0);
bb.y = ret.y + parseFloat(selected.getAttribute('y')||0);
ret = bb;
} else if(~visElems_arr.indexOf(elname)) {
try { ret = selected.getBBox();}
catch(e) {
// Check if element is child of a foreignObject
var fo = $(selected).closest("foreignObject");
if(fo.length) {
try {
ret = fo[0].getBBox();
} catch(e) {
ret = null;
}
} else {
ret = null;
}
}
}
if(ret) {
ret = svgedit.Utilities.bboxToObj(ret);
}
// get the bounding box from the DOM (which is in that element's coordinate system)
return ret;
};
})();