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-75d572ba1ddd
master
Alexis Deveria 2010-04-30 15:06:47 +00:00
parent d0d499f259
commit fa44f7d2ef
3 changed files with 333 additions and 165 deletions

View File

@ -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;
}
}
}
}
}

View File

@ -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?",

View File

@ -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();