fix transformed center getter
Since reflection and inversion introductions, compute center only with the slides of the traslations is not correct. * `_getCenter` -> `_getOriginalCenter` * `_getCenterWithSlide` -> `_getTransformedCenter` * Use pango matrices to compute the new center position since matrices from Cairo, Graphene, ..., are not available with GJS. * Stock original center and transformed center to not compute it numerous time.
This commit is contained in:
parent
a33f7b8324
commit
5ca7a5e4a6
76
draw.js
76
draw.js
|
|
@ -29,6 +29,7 @@ const GObject = imports.gi.GObject;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
|
const PangoMatrix = imports.gi.Pango.Matrix;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
|
@ -1182,10 +1183,10 @@ const DrawingElement = new Lang.Class({
|
||||||
if (transformation.type == Transformations.TRANSLATION) {
|
if (transformation.type == Transformations.TRANSLATION) {
|
||||||
cr.translate(transformation.slideX, transformation.slideY);
|
cr.translate(transformation.slideX, transformation.slideY);
|
||||||
} else if (transformation.type == Transformations.ROTATION) {
|
} else if (transformation.type == Transformations.ROTATION) {
|
||||||
let center = this._getCenterWithSlideBefore(transformation);
|
let center = this._getTransformedCenter(transformation);
|
||||||
crRotate(cr, transformation.angle, center[0], center[1]);
|
crRotate(cr, transformation.angle, center[0], center[1]);
|
||||||
} else if (transformation.type == Transformations.SCALE_PRESERVE || transformation.type == Transformations.SCALE_DIRECTIONAL) {
|
} else if (transformation.type == Transformations.SCALE_PRESERVE || transformation.type == Transformations.SCALE_DIRECTIONAL) {
|
||||||
let center = this._getCenterWithSlideBefore(transformation);
|
let center = this._getTransformedCenter(transformation);
|
||||||
crRotate(cr, transformation.angle, center[0], center[1]);
|
crRotate(cr, transformation.angle, center[0], center[1]);
|
||||||
crScale(cr, transformation.scaleX, transformation.scaleY, center[0], center[1]);
|
crScale(cr, transformation.scaleX, transformation.scaleY, center[0], center[1]);
|
||||||
crRotate(cr, -transformation.angle, center[0], center[1]);
|
crRotate(cr, -transformation.angle, center[0], center[1]);
|
||||||
|
|
@ -1301,7 +1302,7 @@ const DrawingElement = new Lang.Class({
|
||||||
.reverse()
|
.reverse()
|
||||||
.forEach(transformation => {
|
.forEach(transformation => {
|
||||||
transAttribute += transAttribute ? ' ' : ' transform="';
|
transAttribute += transAttribute ? ' ' : ' transform="';
|
||||||
let center = this._getCenter();
|
let center = this._getOriginalCenter();
|
||||||
|
|
||||||
if (transformation.type == Transformations.ROTATION) {
|
if (transformation.type == Transformations.ROTATION) {
|
||||||
transAttribute += `rotate(${transformation.angle * 180 / Math.PI},${center[0]},${center[1]})`;
|
transAttribute += `rotate(${transformation.angle * 180 / Math.PI},${center[0]},${center[1]})`;
|
||||||
|
|
@ -1418,7 +1419,7 @@ const DrawingElement = new Lang.Class({
|
||||||
if (points.length < 2)
|
if (points.length < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let center = this._getCenter();
|
let center = this._getOriginalCenter();
|
||||||
this.transformations[0] = { type: Transformations.ROTATION, angle: getAngle(center[0], center[1], points[points.length - 1][0], points[points.length - 1][1], x, y) };
|
this.transformations[0] = { type: Transformations.ROTATION, angle: getAngle(center[0], center[1], points[points.length - 1][0], points[points.length - 1][1], x, y) };
|
||||||
|
|
||||||
} else if (this.shape == Shapes.ELLIPSE && transform) {
|
} else if (this.shape == Shapes.ELLIPSE && transform) {
|
||||||
|
|
@ -1426,7 +1427,7 @@ const DrawingElement = new Lang.Class({
|
||||||
return;
|
return;
|
||||||
|
|
||||||
points[2] = [x, y];
|
points[2] = [x, y];
|
||||||
let center = this._getCenter();
|
let center = this._getOriginalCenter();
|
||||||
this.transformations[0] = { type: Transformations.ROTATION, angle: getAngle(center[0], center[1], center[0] + 1, center[1], x, y) };
|
this.transformations[0] = { type: Transformations.ROTATION, angle: getAngle(center[0], center[1], center[0] + 1, center[1], x, y) };
|
||||||
|
|
||||||
} else if (this.shape == Shapes.LINE && transform) {
|
} else if (this.shape == Shapes.LINE && transform) {
|
||||||
|
|
@ -1482,14 +1483,14 @@ const DrawingElement = new Lang.Class({
|
||||||
transformation.slideX = x - transformation.startX;
|
transformation.slideX = x - transformation.startX;
|
||||||
transformation.slideY = y - transformation.startY;
|
transformation.slideY = y - transformation.startY;
|
||||||
} else if (transformation.type == Transformations.ROTATION) {
|
} else if (transformation.type == Transformations.ROTATION) {
|
||||||
let center = this._getCenterWithSlideBefore(transformation);
|
let center = this._getTransformedCenter(transformation);
|
||||||
transformation.angle = getAngle(center[0], center[1], transformation.startX, transformation.startY, x, y);
|
transformation.angle = getAngle(center[0], center[1], transformation.startX, transformation.startY, x, y);
|
||||||
} else if (transformation.type == Transformations.SCALE_PRESERVE) {
|
} else if (transformation.type == Transformations.SCALE_PRESERVE) {
|
||||||
let center = this._getCenterWithSlideBefore(transformation);
|
let center = this._getTransformedCenter(transformation);
|
||||||
let scale = Math.hypot(x - center[0], y - center[1]) / Math.hypot(transformation.startX - center[0], transformation.startY - center[1]) || 1;
|
let scale = Math.hypot(x - center[0], y - center[1]) / Math.hypot(transformation.startX - center[0], transformation.startY - center[1]) || 1;
|
||||||
[transformation.scaleX, transformation.scaleY] = [scale, scale];
|
[transformation.scaleX, transformation.scaleY] = [scale, scale];
|
||||||
} else if (transformation.type == Transformations.SCALE_DIRECTIONAL) {
|
} else if (transformation.type == Transformations.SCALE_DIRECTIONAL) {
|
||||||
let center = this._getCenterWithSlideBefore(transformation);
|
let center = this._getTransformedCenter(transformation);
|
||||||
let startAngle = getAngle(center[0], center[1], center[0] + 1, center[1], transformation.startX, transformation.startY);
|
let startAngle = getAngle(center[0], center[1], center[0] + 1, center[1], transformation.startX, transformation.startY);
|
||||||
let vertical = Math.abs(Math.sin(startAngle)) >= Math.sin(3 * Math.PI / 8);
|
let vertical = Math.abs(Math.sin(startAngle)) >= Math.sin(3 * Math.PI / 8);
|
||||||
let horizontal = Math.abs(Math.cos(startAngle)) >= Math.cos(Math.PI / 8);
|
let horizontal = Math.abs(Math.cos(startAngle)) >= Math.cos(Math.PI / 8);
|
||||||
|
|
@ -1549,43 +1550,54 @@ const DrawingElement = new Lang.Class({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getTotalSlideBefore: function(transformation) {
|
|
||||||
let totalSlide = [0, 0];
|
|
||||||
|
|
||||||
this.transformations.slice(0, this.transformations.indexOf(transformation))
|
|
||||||
.filter(transformation => transformation.type == Transformations.TRANSLATION)
|
|
||||||
.forEach(transformation => totalSlide = [totalSlide[0] + transformation.slideX, totalSlide[1] + transformation.slideY]);
|
|
||||||
|
|
||||||
return totalSlide;
|
|
||||||
},
|
|
||||||
|
|
||||||
// When rotating grouped lines, lineOffset is used to retrieve the rotation center of the first line.
|
// When rotating grouped lines, lineOffset is used to retrieve the rotation center of the first line.
|
||||||
_getLineOffset: function() {
|
_getLineOffset: function() {
|
||||||
return (this.lineIndex || 0) * Math.abs(this.points[1][1] - this.points[0][1]);
|
return (this.lineIndex || 0) * Math.abs(this.points[1][1] - this.points[0][1]);
|
||||||
},
|
},
|
||||||
|
|
||||||
// The figure rotation center before transformations (original).
|
// The figure rotation center before transformations (original).
|
||||||
_getCenter: function() {
|
_getOriginalCenter: function() {
|
||||||
|
if (!this._originalCenter) {
|
||||||
let points = this.points;
|
let points = this.points;
|
||||||
|
this._originalCenter = this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] :
|
||||||
return this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] :
|
|
||||||
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[1], points[2]) :
|
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[1], points[2]) :
|
||||||
this.shape == Shapes.TEXT && this.textWidth ? [Math.min(points[0][0], points[1][0]), Math.max(points[0][1], points[1][1]) - this._getLineOffset()] :
|
this.shape == Shapes.TEXT && this.textWidth ? [Math.min(points[0][0], points[1][0]),
|
||||||
|
Math.max(points[0][1], points[1][1]) - this._getLineOffset()] :
|
||||||
points.length >= 3 ? getCentroid(points) :
|
points.length >= 3 ? getCentroid(points) :
|
||||||
getNaiveCenter(points);
|
getNaiveCenter(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._originalCenter;
|
||||||
},
|
},
|
||||||
|
|
||||||
// The figure rotation center that takes previous translations into account.
|
// The figure rotation center, whose position is affected by all transformations done before 'transformation'.
|
||||||
_getCenterWithSlideBefore: function(transformation) {
|
_getTransformedCenter: function(transformation) {
|
||||||
let [center, totalSlide] = [this._getCenter(), this._getTotalSlideBefore(transformation)];
|
if (!transformation.elementTransformedCenter) {
|
||||||
return [center[0] + totalSlide[0], center[1] + totalSlide[1]];
|
let matrix = new PangoMatrix({ xx: 1, xy: 0, yx: 0, yy: 1, x0: 0, y0: 0 });
|
||||||
},
|
|
||||||
|
|
||||||
_getCenterWithSlide: function() {
|
// Apply transformations to the matrice in reverse order
|
||||||
if (this.transformations.length)
|
// because Pango multiply matrices by the left when applying a transformation
|
||||||
return this._getCenterWithSlideBefore(this.lastTransformation);
|
this.transformations.slice(0, this.transformations.indexOf(transformation)).reverse().forEach(transformation => {
|
||||||
else
|
if (transformation.type == Transformations.TRANSLATION) {
|
||||||
return this._getCenter();
|
matrix.translate(transformation.slideX, transformation.slideY);
|
||||||
|
} else if (transformation.type == Transformations.ROTATION) {
|
||||||
|
// nothing, the center position is preserved.
|
||||||
|
} else if (transformation.type == Transformations.SCALE_PRESERVE || transformation.type == Transformations.SCALE_DIRECTIONAL) {
|
||||||
|
// nothing, the center position is preserved.
|
||||||
|
} else if (transformation.type == Transformations.REFLECTION || transformation.type == Transformations.INVERSION) {
|
||||||
|
matrix.translate(transformation.slideX, transformation.slideY);
|
||||||
|
matrix.rotate(-transformation.angle * 180 / Math.PI);
|
||||||
|
matrix.scale(transformation.scaleX, transformation.scaleY);
|
||||||
|
matrix.rotate(transformation.angle * 180 / Math.PI);
|
||||||
|
matrix.translate(-transformation.slideX, -transformation.slideY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let originalCenter = this._getOriginalCenter();
|
||||||
|
transformation.elementTransformedCenter = matrix.transform_point(originalCenter[0], originalCenter[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformation.elementTransformedCenter;
|
||||||
},
|
},
|
||||||
|
|
||||||
_addPoint: function(x, y, smoothedStroke) {
|
_addPoint: function(x, y, smoothedStroke) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue