Fixed issue 545: Cursor/selection block are positioned incorrectly when zoomed in/out on transformed text. Also updated canvg to version supporting arrows
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1557 eee81c28-f429-11dd-99c0-75d572ba1dddmaster
parent
d0d499f259
commit
fa44f7d2ef
|
@ -165,11 +165,19 @@ if(!window.console) {
|
|||
return that.value.indexOf('url(') == 0
|
||||
},
|
||||
|
||||
getGradient: function(e) {
|
||||
var grad = this.getDefinition();
|
||||
if (grad != null && grad.createGradient) {
|
||||
return grad.createGradient(svg.ctx, e);
|
||||
getFillStyle: function(e) {
|
||||
var def = this.getDefinition();
|
||||
|
||||
// gradient
|
||||
if (def != null && def.createGradient) {
|
||||
return def.createGradient(svg.ctx, e);
|
||||
}
|
||||
|
||||
// pattern
|
||||
if (def != null && def.createPattern) {
|
||||
return def.createPattern(svg.ctx, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -278,6 +286,10 @@ if(!window.console) {
|
|||
svg.Point = function(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
this.angleTo = function(p) {
|
||||
return Math.atan2(p.y - this.y, p.x - this.x);
|
||||
}
|
||||
}
|
||||
svg.CreatePoint = function(s) {
|
||||
var a = svg.ToNumberArray(s);
|
||||
|
@ -516,16 +528,19 @@ if(!window.console) {
|
|||
this.children[i].render(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
this.addChild = function(childNode, create) {
|
||||
var child = childNode;
|
||||
if (create) child = svg.CreateElement(childNode);
|
||||
child.parent = this;
|
||||
this.children.push(child);
|
||||
}
|
||||
|
||||
if (node != null) {
|
||||
if (node != null && node.nodeType == 1) { //ELEMENT_NODE
|
||||
// add children
|
||||
for (var i=0; i<node.childNodes.length; i++) {
|
||||
var childNode = node.childNodes[i];
|
||||
if (childNode.nodeType == 1) { //ELEMENT_NODE
|
||||
var child = svg.CreateElement(childNode);
|
||||
child.parent = this;
|
||||
this.children.push(child);
|
||||
}
|
||||
if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE
|
||||
}
|
||||
|
||||
// add attributes
|
||||
|
@ -580,8 +595,8 @@ if(!window.console) {
|
|||
this.setContext = function(ctx) {
|
||||
// fill
|
||||
if (this.style('fill').Definition.isUrl()) {
|
||||
var grad = this.style('fill').Definition.getGradient(this);
|
||||
if (grad != null) ctx.fillStyle = grad;
|
||||
var fs = this.style('fill').Definition.getFillStyle(this);
|
||||
if (fs != null) ctx.fillStyle = fs;
|
||||
}
|
||||
else if (this.style('fill').hasValue()) {
|
||||
var fillStyle = this.style('fill');
|
||||
|
@ -591,8 +606,8 @@ if(!window.console) {
|
|||
|
||||
// stroke
|
||||
if (this.style('stroke').Definition.isUrl()) {
|
||||
var grad = this.style('stroke').Definition.getGradient(this);
|
||||
if (grad != null) ctx.strokeStyle = grad;
|
||||
var fs = this.style('stroke').Definition.getFillStyle(this);
|
||||
if (fs != null) ctx.strokeStyle = fs;
|
||||
}
|
||||
else if (this.style('stroke').hasValue()) {
|
||||
var strokeStyle = this.style('stroke');
|
||||
|
@ -647,26 +662,31 @@ if(!window.console) {
|
|||
this.path(ctx);
|
||||
if (ctx.fillStyle != '') ctx.fill();
|
||||
if (ctx.strokeStyle != '') ctx.stroke();
|
||||
|
||||
if (this.attribute('marker-end').Definition.isUrl()) {
|
||||
var marker = this.attribute('marker-end').Definition.getDefinition();
|
||||
var endPoint = this.getEndPoint();
|
||||
var endAngle = this.getEndAngle();
|
||||
if (endPoint != null && endAngle != null) {
|
||||
marker.render(ctx, endPoint, endAngle);
|
||||
|
||||
var markers = this.getMarkers();
|
||||
if (markers != null) {
|
||||
if (this.attribute('marker-start').Definition.isUrl()) {
|
||||
var marker = this.attribute('marker-start').Definition.getDefinition();
|
||||
marker.render(ctx, markers[0][0], markers[0][1]);
|
||||
}
|
||||
}
|
||||
if (this.attribute('marker-mid').Definition.isUrl()) {
|
||||
var marker = this.attribute('marker-mid').Definition.getDefinition();
|
||||
for (var i=1;i<markers.length-1;i++) {
|
||||
marker.render(ctx, markers[i][0], markers[i][1]);
|
||||
}
|
||||
}
|
||||
if (this.attribute('marker-end').Definition.isUrl()) {
|
||||
var marker = this.attribute('marker-end').Definition.getDefinition();
|
||||
marker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.getBoundingBox = function() {
|
||||
return this.path();
|
||||
}
|
||||
|
||||
this.getEndPoint = function() {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.getEndAngle = function() {
|
||||
this.getMarkers = function() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -852,34 +872,29 @@ if(!window.console) {
|
|||
svg.Element.line = function(node) {
|
||||
this.base = svg.Element.PathElementBase;
|
||||
this.base(node);
|
||||
|
||||
|
||||
this.getPoints = function() {
|
||||
return [
|
||||
new svg.Point(this.attribute('x1').Length.toPixels('x'), this.attribute('y1').Length.toPixels('y')),
|
||||
new svg.Point(this.attribute('x2').Length.toPixels('x'), this.attribute('y2').Length.toPixels('y'))];
|
||||
}
|
||||
|
||||
this.path = function(ctx) {
|
||||
var x1 = this.attribute('x1').Length.toPixels('x');
|
||||
var y1 = this.attribute('y1').Length.toPixels('y');
|
||||
var x2 = this.attribute('x2').Length.toPixels('x');
|
||||
var y2 = this.attribute('y2').Length.toPixels('y');
|
||||
var points = this.getPoints();
|
||||
|
||||
if (ctx != null) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.lineTo(x2, y2);
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
ctx.lineTo(points[1].x, points[1].y);
|
||||
}
|
||||
|
||||
return new svg.BoundingBox(x1, y1, x2, y2);
|
||||
return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
|
||||
}
|
||||
|
||||
this.getEndPoint = function() {
|
||||
var x2 = this.attribute('x2').Length.toPixels('x');
|
||||
var y2 = this.attribute('y2').Length.toPixels('y');
|
||||
return new svg.Point(x2, y2);
|
||||
}
|
||||
|
||||
this.getEndAngle = function() {
|
||||
var x1 = this.attribute('x1').Length.toPixels('x');
|
||||
var y1 = this.attribute('y1').Length.toPixels('y');
|
||||
var x2 = this.attribute('x2').Length.toPixels('x');
|
||||
var y2 = this.attribute('y2').Length.toPixels('y');
|
||||
return Math.atan((y2-y1)/(x2-x1));
|
||||
this.getMarkers = function() {
|
||||
var points = this.getPoints();
|
||||
var a = points[0].angleTo(points[1]);
|
||||
return [[points[0], a], [points[1], a]];
|
||||
}
|
||||
}
|
||||
svg.Element.line.prototype = new svg.Element.PathElementBase;
|
||||
|
@ -902,6 +917,15 @@ if(!window.console) {
|
|||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
this.getMarkers = function() {
|
||||
var markers = [];
|
||||
for (var i=0; i<this.points.length - 1; i++) {
|
||||
markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);
|
||||
}
|
||||
markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);
|
||||
return markers;
|
||||
}
|
||||
}
|
||||
svg.Element.polyline.prototype = new svg.Element.PathElementBase;
|
||||
|
||||
|
@ -946,19 +970,11 @@ if(!window.console) {
|
|||
this.i = -1;
|
||||
this.command = '';
|
||||
this.control = new svg.Point(0, 0);
|
||||
this.last = new svg.Point(0, 0);
|
||||
this.current = new svg.Point(0, 0);
|
||||
this.points = [];
|
||||
this.angles = [];
|
||||
}
|
||||
|
||||
this.angle = function() {
|
||||
return Math.atan((this.current.y - this.last.y) / (this.current.x - this.last.x));
|
||||
}
|
||||
|
||||
this.setCurrent = function(p) {
|
||||
this.last = this.current;
|
||||
this.current = p;
|
||||
}
|
||||
|
||||
|
||||
this.isEnd = function() {
|
||||
return this.i == this.tokens.length - 1;
|
||||
}
|
||||
|
@ -998,7 +1014,7 @@ if(!window.console) {
|
|||
|
||||
this.getAsCurrentPoint = function() {
|
||||
var p = this.getPoint();
|
||||
this.setCurrent(p);
|
||||
this.current = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1014,6 +1030,30 @@ if(!window.console) {
|
|||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
this.addMarker = function(p, from) {
|
||||
this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
|
||||
}
|
||||
|
||||
this.addMarkerAngle = function(p, a) {
|
||||
this.points.push(p);
|
||||
this.angles.push(a);
|
||||
}
|
||||
|
||||
this.getMarkerPoints = function() { return this.points; }
|
||||
this.getMarkerAngles = function() {
|
||||
for (var i=0; i<this.angles.length; i++) {
|
||||
if (this.angles[i] == null) {
|
||||
for (var j=i+1; j<this.angles.length; j++) {
|
||||
if (this.angles[j] != null) {
|
||||
this.angles[i] = this.angles[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.angles;
|
||||
}
|
||||
})(d);
|
||||
|
||||
this.path = function(ctx) {
|
||||
|
@ -1026,33 +1066,39 @@ if(!window.console) {
|
|||
pp.nextCommand();
|
||||
if (pp.command.toUpperCase() == 'M') {
|
||||
var p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.moveTo(p.x, p.y);
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
var p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
}
|
||||
else if (pp.command.toUpperCase() == 'L') {
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
var c = pp.current;
|
||||
var p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p, c);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
}
|
||||
else if (pp.command.toUpperCase() == 'H') {
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
pp.current.x = (pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar();
|
||||
pp.setCurrent(pp.current);
|
||||
var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
|
||||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
}
|
||||
else if (pp.command.toUpperCase() == 'V') {
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
pp.current.y = (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar();
|
||||
pp.setCurrent(pp.current);
|
||||
var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
|
||||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
|
@ -1063,6 +1109,7 @@ if(!window.console) {
|
|||
var p1 = pp.getPoint();
|
||||
var cntrl = pp.getAsControlPoint();
|
||||
var cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
|
@ -1073,6 +1120,7 @@ if(!window.console) {
|
|||
var p1 = pp.getReflectedControlPoint();
|
||||
var cntrl = pp.getAsControlPoint();
|
||||
var cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
|
@ -1082,6 +1130,7 @@ if(!window.console) {
|
|||
var curr = pp.current;
|
||||
var cntrl = pp.getAsControlPoint();
|
||||
var cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
|
@ -1092,10 +1141,12 @@ if(!window.console) {
|
|||
var cntrl = pp.getReflectedControlPoint();
|
||||
pp.control = cntrl;
|
||||
var cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
}
|
||||
|
||||
else if (pp.command.toUpperCase() == 'A') {
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
var curr = pp.current;
|
||||
|
@ -1113,6 +1164,12 @@ if(!window.console) {
|
|||
Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,
|
||||
-Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0
|
||||
);
|
||||
// adjust radii
|
||||
var l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2);
|
||||
if (l > 1) {
|
||||
rx *= Math.sqrt(l);
|
||||
ry *= Math.sqrt(l);
|
||||
}
|
||||
// cx', cy'
|
||||
var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(
|
||||
((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /
|
||||
|
@ -1127,15 +1184,30 @@ if(!window.console) {
|
|||
);
|
||||
// vector magnitude
|
||||
var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }
|
||||
// ratio between two vectors
|
||||
var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }
|
||||
// angle between two vectors
|
||||
var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos((u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v))); }
|
||||
var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }
|
||||
// initial angle
|
||||
var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);
|
||||
// angle delta
|
||||
var ad = a([(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry], [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry]);
|
||||
var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];
|
||||
var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];
|
||||
var ad = a(u, v);
|
||||
if (r(u,v) <= -1) ad = Math.PI;
|
||||
if (r(u,v) >= 1) ad = 0;
|
||||
|
||||
if (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI;
|
||||
if (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI;
|
||||
|
||||
// for markers
|
||||
var halfWay = new svg.Point(
|
||||
centp.x - rx * Math.cos((a1 + ad) / 2),
|
||||
centp.y - ry * Math.sin((a1 + ad) / 2)
|
||||
);
|
||||
pp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);
|
||||
pp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);
|
||||
|
||||
bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
|
||||
if (ctx != null) {
|
||||
var r = rx > ry ? rx : ry;
|
||||
|
@ -1160,24 +1232,52 @@ if(!window.console) {
|
|||
return bb;
|
||||
}
|
||||
|
||||
this.getEndPoint = function() {
|
||||
return this.PathParser.current;
|
||||
}
|
||||
|
||||
this.getEndAngle = function() {
|
||||
return this.PathParser.angle();
|
||||
this.getMarkers = function() {
|
||||
var points = this.PathParser.getMarkerPoints();
|
||||
var angles = this.PathParser.getMarkerAngles();
|
||||
|
||||
var markers = [];
|
||||
for (var i=0; i<points.length; i++) {
|
||||
markers.push([points[i], angles[i]]);
|
||||
}
|
||||
return markers;
|
||||
}
|
||||
}
|
||||
svg.Element.path.prototype = new svg.Element.PathElementBase;
|
||||
|
||||
// pattern element
|
||||
svg.Element.pattern = function(node) {
|
||||
this.base = svg.Element.ElementBase;
|
||||
this.base(node);
|
||||
|
||||
this.createPattern = function(ctx, element) {
|
||||
// render me using a temporary svg element
|
||||
var tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes['x'] = new svg.Property('x', this.attribute('x').value);
|
||||
tempSvg.attributes['y'] = new svg.Property('y', this.attribute('y').value);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
|
||||
tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
|
||||
tempSvg.children = this.children;
|
||||
|
||||
var c = document.createElement('canvas');
|
||||
c.width = this.attribute('width').Length.toPixels();
|
||||
c.height = this.attribute('height').Length.toPixels();
|
||||
tempSvg.render(c.getContext('2d'));
|
||||
return ctx.createPattern(c, 'repeat');
|
||||
}
|
||||
}
|
||||
svg.Element.pattern.prototype = new svg.Element.ElementBase;
|
||||
|
||||
// marker element
|
||||
svg.Element.marker = function(node) {
|
||||
this.base = svg.Element.ElementBase;
|
||||
this.base(node);
|
||||
|
||||
this.baseRender = this.render;
|
||||
this.render = function(ctx, endPoint, endAngle) {
|
||||
ctx.translate(endPoint.x, endPoint.y);
|
||||
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(endAngle);
|
||||
this.render = function(ctx, point, angle) {
|
||||
ctx.translate(point.x, point.y);
|
||||
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);
|
||||
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);
|
||||
ctx.save();
|
||||
|
||||
|
@ -1195,8 +1295,8 @@ if(!window.console) {
|
|||
|
||||
ctx.restore();
|
||||
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth);
|
||||
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-endAngle);
|
||||
ctx.translate(-endPoint.x, -endPoint.y);
|
||||
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);
|
||||
ctx.translate(-point.x, -point.y);
|
||||
}
|
||||
}
|
||||
svg.Element.marker.prototype = new svg.Element.ElementBase;
|
||||
|
@ -1427,14 +1527,19 @@ if(!window.console) {
|
|||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
|
||||
// accumulate all the child text nodes, then trim them
|
||||
this.text = '';
|
||||
for (var i=0; i<node.childNodes.length; i++) {
|
||||
if (node.childNodes[i].nodeType == 3) { // TEXT
|
||||
this.text = this.text + node.childNodes[i].nodeValue;
|
||||
if (node != null) {
|
||||
// add children
|
||||
this.children = [];
|
||||
for (var i=0; i<node.childNodes.length; i++) {
|
||||
var childNode = node.childNodes[i];
|
||||
if (childNode.nodeType == 1) { // capture tspan and tref nodes
|
||||
this.addChild(childNode, true);
|
||||
}
|
||||
else if (childNode.nodeType == 3) { // capture text
|
||||
this.addChild(new svg.Element.tspan(childNode), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.text = svg.trim(this.text);
|
||||
|
||||
this.baseSetContext = this.setContext;
|
||||
this.setContext = function(ctx) {
|
||||
|
@ -1449,11 +1554,60 @@ if(!window.console) {
|
|||
this.renderChildren = function(ctx) {
|
||||
var x = this.attribute('x').Length.toPixels('x');
|
||||
var y = this.attribute('y').Length.toPixels('y');
|
||||
if (ctx.fillText) ctx.fillText(this.text, x, y);
|
||||
for (var i=0; i<this.children.length; i++) {
|
||||
this.children[i].x = x;
|
||||
this.children[i].y = y;
|
||||
this.children[i].render(ctx);
|
||||
x += this.children[i].measureText(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
svg.Element.text.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// text base
|
||||
svg.Element.TextElementBase = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
|
||||
this.renderChildren = function(ctx) {
|
||||
ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
|
||||
}
|
||||
|
||||
this.getText = function() {
|
||||
// OVERRIDE ME
|
||||
}
|
||||
|
||||
this.measureText = function(ctx) {
|
||||
return ctx.measureText(svg.compressSpaces(this.getText())).width;
|
||||
}
|
||||
}
|
||||
svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// tspan
|
||||
svg.Element.tspan = function(node) {
|
||||
this.base = svg.Element.TextElementBase;
|
||||
this.base(node);
|
||||
|
||||
// TEXT ELEMENT
|
||||
this.text = node.nodeType == 3 ? node.nodeValue : node.childNodes[0].nodeValue;
|
||||
this.getText = function() {
|
||||
return this.text;
|
||||
}
|
||||
}
|
||||
svg.Element.tspan.prototype = new svg.Element.TextElementBase;
|
||||
|
||||
// tref
|
||||
svg.Element.tref = function(node) {
|
||||
this.base = svg.Element.TextElementBase;
|
||||
this.base(node);
|
||||
|
||||
this.getText = function() {
|
||||
var element = this.attribute('xlink:href').Definition.getDefinition();
|
||||
if (element != null) return element.children[0].getText();
|
||||
}
|
||||
}
|
||||
svg.Element.tref.prototype = new svg.Element.TextElementBase;
|
||||
|
||||
// group element
|
||||
svg.Element.g = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
|
@ -1461,12 +1615,21 @@ if(!window.console) {
|
|||
}
|
||||
svg.Element.g.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// symbol element
|
||||
svg.Element.symbol = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
}
|
||||
svg.Element.symbol.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// a element
|
||||
svg.Element.a = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
}
|
||||
svg.Element.a.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// style element
|
||||
svg.Element.style = function(node) {
|
||||
this.base = svg.Element.ElementBase;
|
||||
this.base(node);
|
||||
|
@ -1495,6 +1658,7 @@ if(!window.console) {
|
|||
svg.Styles[cssClass] = props;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,35 @@
|
|||
[
|
||||
{"id": "align_relative_to", "title": "Align relative to ..."},
|
||||
{"id": "tool_angle", "title": "Change rotation angle"},
|
||||
{"id": "angleLabel", "textContent": "angle:"},
|
||||
{"id": "bkgnd_color", "title": "Change background color/opacity"},
|
||||
{"id": "circle_cx", "title": "Change circle's cx coordinate"},
|
||||
{"id": "circle_cy", "title": "Change circle's cy coordinate"},
|
||||
{"id": "circle_r", "title": "Change circle's radius"},
|
||||
{"id": "cornerRadiusLabel", "textContent": "Corner Radius:"},
|
||||
{"id": "connector_no_arrow", "textContent": "No arrow"},
|
||||
{"id": "copyrightLabel", "textContent": "Powered by"},
|
||||
{"id": "cornerRadiusLabel", "title": "Change Rectangle Corner Radius"},
|
||||
{"id": "curve_segments", "textContent": "Curve"},
|
||||
{"id": "ellipse_cx", "title": "Change ellipse's cx coordinate"},
|
||||
{"id": "ellipse_cy", "title": "Change ellipse's cy coordinate"},
|
||||
{"id": "ellipse_rx", "title": "Change ellipse's x radius"},
|
||||
{"id": "ellipse_ry", "title": "Change ellipse's y radius"},
|
||||
{"id": "fill_color", "title": "Change fill color"},
|
||||
{"id": "fill_tool_bottom", "textContent": "fill:"},
|
||||
{"id": "fitToContent", "textContent": "Fit to Content"},
|
||||
{"id": "fit_to_all", "textContent": "Fit to all content"},
|
||||
{"id": "fit_to_canvas", "textContent": "Fit to canvas"},
|
||||
{"id": "fit_to_layer_content", "textContent": "Fit to layer content"},
|
||||
{"id": "fit_to_sel", "textContent": "Fit to selection"},
|
||||
{"id": "fitToContent", "textContent": "Fit to Content"},
|
||||
{"id": "font_family", "title": "Change Font Family"},
|
||||
{"id": "tool_font_size", "title": "Change Font Size"},
|
||||
{"id": "tool_opacity", "title": "Change selected item opacity"},
|
||||
{"id": "icon_large", "textContent": "Large"},
|
||||
{"id": "icon_medium", "textContent": "Medium"},
|
||||
{"id": "icon_small", "textContent": "Small"},
|
||||
{"id": "icon_xlarge", "textContent": "Extra Large"},
|
||||
{"id": "iheightLabel", "textContent": "height:"},
|
||||
{"id": "idLabel", "title": "Identify the element"},
|
||||
{"id": "image_height", "title": "Change image height"},
|
||||
{"id": "image_opt_embed", "textContent": "Embed data (local files)"},
|
||||
{"id": "image_opt_ref", "textContent": "Use file reference"},
|
||||
{"id": "image_url", "title": "Change URL"},
|
||||
{"id": "image_width", "title": "Change image width"},
|
||||
{"id": "includedImages", "textContent": "Included Images"},
|
||||
{"id": "iwidthLabel", "textContent": "width:"},
|
||||
{"id": "largest_object", "textContent": "largest object"},
|
||||
{"id": "layer_delete", "title": "Delete Layer"},
|
||||
{"id": "layer_down", "title": "Move Layer Down"},
|
||||
|
@ -43,30 +39,33 @@
|
|||
{"id": "layersLabel", "textContent": "Layers:"},
|
||||
{"id": "line_x1", "title": "Change line's starting x coordinate"},
|
||||
{"id": "line_x2", "title": "Change line's ending x coordinate"},
|
||||
{"id": "line_y1", "title": "Change line's starting y coordinate"},
|
||||
{"id": "line_y2", "title": "Change line's ending y coordinate"},
|
||||
{"id": "linecap_butt", "title": "Linecap: Butt"},
|
||||
{"id": "linecap_round", "title": "Linecap: Round"},
|
||||
{"id": "linecap_square", "title": "Linecap: Square"},
|
||||
{"id": "linejoin_bevel", "title": "Linejoin: Bevel"},
|
||||
{"id": "linejoin_miter", "title": "Linejoin: Miter"},
|
||||
{"id": "linejoin_round", "title": "Linejoin: Round"},
|
||||
{"id": "main_icon", "title": "Main Menu"},
|
||||
{"id": "mode_connect", "title": "Connect two objects"},
|
||||
{"id": "page", "textContent": "page"},
|
||||
{"id": "palette", "title": "Click to change fill color, shift-click to change stroke color"},
|
||||
{"id": "path_node_x", "title": "Change node's x coordinate"},
|
||||
{"id": "path_node_y", "title": "Change node's y coordinate"},
|
||||
{"id": "rect_height_tool", "title": "Change rectangle height"},
|
||||
{"id": "cornerRadiusLabel", "title": "Change Rectangle Corner Radius"},
|
||||
{"id": "rect_width_tool", "title": "Change rectangle width"},
|
||||
{"id": "relativeToLabel", "textContent": "relative to:"},
|
||||
{"id": "rheightLabel", "textContent": "height:"},
|
||||
{"id": "rwidthLabel", "textContent": "width:"},
|
||||
{"id": "seg_type", "title": "Change Segment type"},
|
||||
{"id": "selLayerLabel", "textContent": "Move elements to:"},
|
||||
{"id": "selLayerNames", "title": "Move selected elements to a different layer"},
|
||||
{"id": "selectedPredefined", "textContent": "Select predefined:"},
|
||||
{"id": "selected_objects", "textContent": "selected objects"},
|
||||
{"id": "selected_x", "title": "Change X coordinate"},
|
||||
{"id": "selected_y", "title": "Change Y coordinate"},
|
||||
{"id": "selectedPredefined", "textContent": "Select predefined:"},
|
||||
{"id": "selLayerLabel", "textContent": "Move elements to:"},
|
||||
{"id": "selLayerNames", "title": "Move selected elements to a different layer"},
|
||||
{"id": "sidepanel_handle", "textContent": "L a y e r s", "title": "Drag left/right to resize side panel"},
|
||||
{"id": "smallest_object", "textContent": "smallest object"},
|
||||
{"id": "straight_segments", "textContent": "Straight"},
|
||||
{"id": "stroke_color", "title": "Change stroke color"},
|
||||
{"id": "stroke_style", "title": "Change stroke dash style"},
|
||||
{"id": "stroke_tool_bottom", "textContent": "stroke:"},
|
||||
{"id": "stroke_width", "title": "Change stroke width by 1, shift-click to change by 0.1"},
|
||||
{"id": "svginfo_bg_note", "textContent": "Note: Background will not be saved with image."},
|
||||
{"id": "svginfo_change_background", "textContent": "Editor Background"},
|
||||
|
@ -79,6 +78,7 @@
|
|||
{"id": "svginfo_title", "textContent": "Title"},
|
||||
{"id": "svginfo_width", "textContent": "Width:"},
|
||||
{"id": "text", "title": "Change text contents"},
|
||||
{"id": "toggle_stroke_tools", "title": "Show/hide more stroke tools"},
|
||||
{"id": "tool_add_subpath", "title": "Add sub-path"},
|
||||
{"id": "tool_alignbottom", "title": "Align Bottom"},
|
||||
{"id": "tool_aligncenter", "title": "Align Center"},
|
||||
|
@ -86,24 +86,28 @@
|
|||
{"id": "tool_alignmiddle", "title": "Align Middle"},
|
||||
{"id": "tool_alignright", "title": "Align Right"},
|
||||
{"id": "tool_aligntop", "title": "Align Top"},
|
||||
{"id": "tool_angle", "title": "Change rotation angle"},
|
||||
{"id": "tool_blur", "title": "Change gaussian blur value"},
|
||||
{"id": "tool_bold", "title": "Bold Text"},
|
||||
{"id": "tool_circle", "title": "Circle"},
|
||||
{"id": "tool_clear", "textContent": "New Image"},
|
||||
{"id": "tool_clone", "title": "Clone Element"},
|
||||
{"id": "tool_clone_multi", "title": "Clone Elements"},
|
||||
{"id": "tool_delete", "title": "Delete Element"},
|
||||
{"id": "tool_clone", "title": "Clone Element"},
|
||||
{"id": "tool_delete_multi", "title": "Delete Selected Elements"},
|
||||
{"id": "tool_docprops", "textContent": "Document Properties"},
|
||||
{"id": "tool_delete", "title": "Delete Element"},
|
||||
{"id": "tool_docprops_cancel", "textContent": "Cancel"},
|
||||
{"id": "tool_docprops_save", "textContent": "OK"},
|
||||
{"id": "tool_docprops", "textContent": "Document Properties"},
|
||||
{"id": "tool_ellipse", "title": "Ellipse"},
|
||||
{"id": "tool_export", "textContent": "Export as PNG"},
|
||||
{"id": "tool_eyedropper", "title": "Eye Dropper Tool"},
|
||||
{"id": "tool_fhellipse", "title": "Free-Hand Ellipse"},
|
||||
{"id": "tool_fhpath", "title": "Pencil Tool"},
|
||||
{"id": "tool_fhrect", "title": "Free-Hand Rectangle"},
|
||||
{"id": "tool_font_size", "title": "Change Font Size"},
|
||||
{"id": "tool_group", "title": "Group Elements"},
|
||||
{"id": "tool_image", "title": "Image Tool"},
|
||||
{"id": "tool_import", "textContent": "Import Image"},
|
||||
{"id": "tool_import", "textContent": "Import SVG"},
|
||||
{"id": "tool_italic", "title": "Italic Text"},
|
||||
{"id": "tool_line", "title": "Line Tool"},
|
||||
{"id": "tool_move_bottom", "title": "Move to Bottom"},
|
||||
|
@ -111,17 +115,19 @@
|
|||
{"id": "tool_node_clone", "title": "Clone Node"},
|
||||
{"id": "tool_node_delete", "title": "Delete Node"},
|
||||
{"id": "tool_node_link", "title": "Link Control Points"},
|
||||
{"id": "tool_opacity", "title": "Change selected item opacity"},
|
||||
{"id": "tool_open", "textContent": "Open Image"},
|
||||
{"id": "tool_openclose_path", "textContent": "Open/close sub-path"},
|
||||
{"id": "tool_openclose_path", "title": "Open/close sub-path"},
|
||||
{"id": "tool_path", "title": "Path Tool"},
|
||||
{"id": "tool_position", "title": "Align Element to Page"},
|
||||
{"id": "tool_rect", "title": "Rectangle"},
|
||||
{"id": "tool_redo", "title": "Redo"},
|
||||
{"id": "tool_reorient", "title": "Reorient path"},
|
||||
{"id": "tool_save", "textContent": "Save Image"},
|
||||
{"id": "tool_select", "title": "Select Tool"},
|
||||
{"id": "tool_source", "title": "Edit Source"},
|
||||
{"id": "tool_source_cancel", "textContent": "Cancel"},
|
||||
{"id": "tool_source_save", "textContent": "Apply Changes"},
|
||||
{"id": "tool_source", "title": "Edit Source"},
|
||||
{"id": "tool_square", "title": "Square"},
|
||||
{"id": "tool_text", "title": "Text Tool"},
|
||||
{"id": "tool_topath", "title": "Convert to Path"},
|
||||
|
@ -129,29 +135,8 @@
|
|||
{"id": "tool_ungroup", "title": "Ungroup Elements"},
|
||||
{"id": "tool_wireframe", "title": "Wireframe Mode"},
|
||||
{"id": "tool_zoom", "title": "Zoom Tool"},
|
||||
{"id": "zoom_panel", "title": "Change zoom level"},
|
||||
{"id": "zoomLabel", "textContent": "zoom:"},
|
||||
{"id": "sidepanel_handle", "textContent": "L a y e r s", "title": "Drag left/right to resize side panel"},
|
||||
{"id": "main_icon", "title": "Main Menu"},
|
||||
{"id": "tool_blur", "title": "Change gaussian blur value"},
|
||||
{"id": "tool_position", "title": "Align Element to Page"},
|
||||
{"id": "idLabel", "title": "Identify the element"},
|
||||
{"id": "tool_openclose_path", "title": "Open/close sub-path"},
|
||||
{"id": "tool_add_subpath", "title": "Add sub-path"},
|
||||
{"id": "toggle_stroke_tools", "title": "Show/hide more stroke tools"},
|
||||
{"id": "linejoin_miter", "title": "Linejoin: Miter"},
|
||||
{"id": "linejoin_round", "title": "Linejoin: Round"},
|
||||
{"id": "linejoin_bevel", "title": "Linejoin: Bevel"},
|
||||
{"id": "linecap_butt", "title": "Linecap: Butt"},
|
||||
{"id": "linecap_square", "title": "Linecap: Square"},
|
||||
{"id": "linecap_round", "title": "Linecap: Round"},
|
||||
{"id": "tool_import", "textContent": "Import SVG"},
|
||||
{"id": "tool_export", "textContent": "Export as PNG"},
|
||||
{"id": "tool_eyedropper", "title": "Eye Dropper Tool"},
|
||||
{"id": "mode_connect", "title": "Connect two objects"},
|
||||
{"id": "connector_no_arrow", "textContent": "No arrow"},
|
||||
{"id": "copyrightLabel", "textContent": "Powered by"},
|
||||
{"id": "url_notice", "title": "NOTE: This image cannot be embedded. It will depend on this path to be displayed"},
|
||||
{"id": "zoom_panel", "title": "Change zoom level"},
|
||||
{
|
||||
"js_strings": {
|
||||
"QerrorsRevertToSource": "There were parsing errors in your SVG source.\nRevert back to original SVG source?",
|
||||
|
|
|
@ -3924,7 +3924,7 @@ function BatchCommand(text) {
|
|||
var blinker;
|
||||
var chardata = [];
|
||||
var textbb, transbb;
|
||||
var xform, imatrix;
|
||||
var matrix;
|
||||
var last_x, last_y;
|
||||
var allow_dbl;
|
||||
|
||||
|
@ -3963,18 +3963,21 @@ function BatchCommand(text) {
|
|||
}, 600);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var start_pt = ptToScreen(charbb.x, textbb.y);
|
||||
var end_pt = ptToScreen(charbb.x, (textbb.y + textbb.height));
|
||||
|
||||
assignAttributes(cursor, {
|
||||
x1: charbb.x * current_zoom,
|
||||
y1: textbb.y * current_zoom,
|
||||
x2: charbb.x * current_zoom,
|
||||
y2: (textbb.y + textbb.height) * current_zoom,
|
||||
x1: start_pt.x,
|
||||
y1: start_pt.y,
|
||||
x2: end_pt.x,
|
||||
y2: end_pt.y,
|
||||
visibility: 'visible',
|
||||
display: 'inline',
|
||||
transform: (xform || '')
|
||||
display: 'inline'
|
||||
});
|
||||
|
||||
if(selblock) selblock.setAttribute('width', 0);
|
||||
if(selblock) selblock.setAttribute('d', '');
|
||||
}
|
||||
|
||||
function setSelection(start, end, skipInput) {
|
||||
|
@ -3989,28 +3992,38 @@ function BatchCommand(text) {
|
|||
|
||||
selblock = getElem("text_selectblock");
|
||||
if (!selblock) {
|
||||
selblock = document.createElementNS(svgns, "rect");
|
||||
|
||||
selblock = document.createElementNS(svgns, "path");
|
||||
assignAttributes(selblock, {
|
||||
'id': "text_selectblock",
|
||||
'fill': "green",
|
||||
'opacity': .5,
|
||||
'style': "pointer-events:none"
|
||||
});
|
||||
selblock = getElem("selectorParentGroup").appendChild(selblock);
|
||||
getElem("selectorParentGroup").appendChild(selblock);
|
||||
}
|
||||
|
||||
|
||||
var startbb = chardata[start];
|
||||
|
||||
var endbb = chardata[end];
|
||||
|
||||
cursor.setAttribute('visibility', 'hidden');
|
||||
|
||||
var tl = ptToScreen(startbb.x, textbb.y),
|
||||
tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y),
|
||||
bl = ptToScreen(startbb.x, textbb.y + textbb.height),
|
||||
br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height);
|
||||
|
||||
|
||||
var dstr = "M" + tl.x + "," + tl.y
|
||||
+ " L" + tr.x + "," + tr.y
|
||||
+ " " + br.x + "," + br.y
|
||||
+ " " + bl.x + "," + bl.y + "z";
|
||||
|
||||
assignAttributes(selblock, {
|
||||
'x': startbb.x * current_zoom,
|
||||
'y': textbb.y * current_zoom,
|
||||
'width': (endbb.x - startbb.x) * current_zoom,
|
||||
'height': textbb.height * current_zoom,
|
||||
'display': 'inline',
|
||||
'transform': (xform || '')
|
||||
d: dstr,
|
||||
'display': 'inline'
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4061,14 +4074,32 @@ function BatchCommand(text) {
|
|||
y: y_in
|
||||
}
|
||||
|
||||
if(xform) {
|
||||
var pt = transformPoint(out.x, out.y, imatrix);
|
||||
out.x /= current_zoom;
|
||||
out.y /= current_zoom;
|
||||
|
||||
if(matrix) {
|
||||
var pt = transformPoint(out.x, out.y, matrix.inverse());
|
||||
out.x = pt.x;
|
||||
out.y = pt.y;
|
||||
}
|
||||
|
||||
out.x /= current_zoom;
|
||||
out.y /= current_zoom;
|
||||
return out;
|
||||
}
|
||||
|
||||
function ptToScreen(x_in, y_in) {
|
||||
var out = {
|
||||
x: x_in,
|
||||
y: y_in
|
||||
}
|
||||
|
||||
if(matrix) {
|
||||
var pt = transformPoint(out.x, out.y, matrix);
|
||||
out.x = pt.x;
|
||||
out.y = pt.y;
|
||||
}
|
||||
|
||||
out.x *= current_zoom;
|
||||
out.y *= current_zoom;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -4136,6 +4167,7 @@ function BatchCommand(text) {
|
|||
},
|
||||
mouseUp: function(evt, mouse_x, mouse_y) {
|
||||
var pt = screenToPt(mouse_x, mouse_y);
|
||||
|
||||
setEndSelectionFromPoint(pt.x, pt.y, true);
|
||||
|
||||
// TODO: Find a way to make this work: Use transformed BBox instead of evt.target
|
||||
|
@ -4211,24 +4243,11 @@ function BatchCommand(text) {
|
|||
var str = curtext.textContent;
|
||||
var len = str.length;
|
||||
|
||||
xform = curtext.getAttribute('transform');
|
||||
var xform = curtext.getAttribute('transform');
|
||||
|
||||
textbb = canvas.getBBox(curtext);
|
||||
|
||||
if(xform) {
|
||||
var matrix = getMatrix(curtext);
|
||||
|
||||
imatrix = matrix.inverse();
|
||||
// var tbox = transformBox(textbb.x, textbb.y, textbb.width, textbb.height, matrix);
|
||||
// transbb = {
|
||||
// width: tbox.tr.x - tbox.tl.x,
|
||||
// height: tbox.bl.y - tbox.tl.y,
|
||||
// x: tbox.tl.x,
|
||||
// y: tbox.tl.y
|
||||
// }
|
||||
} else {
|
||||
// transbb = textbb;
|
||||
}
|
||||
matrix = xform?getMatrix(curtext):null;
|
||||
|
||||
chardata = Array(len);
|
||||
textinput.focus();
|
||||
|
|
Loading…
Reference in New Issue