Text elements as a separated class
This commit is contained in:
parent
96efac1e3f
commit
e8140eae88
34
area.js
34
area.js
|
|
@ -471,7 +471,7 @@ var DrawingArea = new Lang.Class({
|
||||||
|
|
||||||
if (duplicate) {
|
if (duplicate) {
|
||||||
// deep cloning
|
// deep cloning
|
||||||
let copy = new Elements.DrawingElement(JSON.parse(JSON.stringify(this.grabbedElement)));
|
let copy = new this.grabbedElement.constructor(JSON.parse(JSON.stringify(this.grabbedElement)));
|
||||||
this.elements.push(copy);
|
this.elements.push(copy);
|
||||||
this.grabbedElement = copy;
|
this.grabbedElement = copy;
|
||||||
}
|
}
|
||||||
|
|
@ -554,28 +554,32 @@ var DrawingArea = new Lang.Class({
|
||||||
this._stopDrawing();
|
this._stopDrawing();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.currentTool == Shapes.TEXT) {
|
||||||
this.currentElement = new Elements.DrawingElement({
|
this.currentElement = new Elements.DrawingElement({
|
||||||
shape: this.currentTool,
|
shape: this.currentTool,
|
||||||
color: this.currentColor.to_string(),
|
color: this.currentColor.to_string(),
|
||||||
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
|
||||||
dash: { active: this.dashedLine, array: this.dashedLine ? [this.dashArray[0] || this.currentLineWidth, this.dashArray[1] || this.currentLineWidth * 3] : [0, 0] , offset: this.dashOffset },
|
|
||||||
fill: this.fill,
|
|
||||||
fillRule: this.currentFillRule,
|
|
||||||
eraser: eraser,
|
eraser: eraser,
|
||||||
transform: { active: false, center: [0, 0], angle: 0, startAngle: 0, ratio: 1 },
|
font: {
|
||||||
points: []
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.currentTool == Shapes.TEXT) {
|
|
||||||
this.currentElement.fill = false;
|
|
||||||
this.currentElement.font = {
|
|
||||||
family: (this.currentFontGeneric == 0 ? this.currentThemeFontFamily : FontGenericNames[this.currentFontGeneric]),
|
family: (this.currentFontGeneric == 0 ? this.currentThemeFontFamily : FontGenericNames[this.currentFontGeneric]),
|
||||||
weight: this.currentFontWeight,
|
weight: this.currentFontWeight,
|
||||||
style: this.currentFontStyle,
|
style: this.currentFontStyle,
|
||||||
stretch: this.currentFontStretch,
|
stretch: this.currentFontStretch,
|
||||||
variant: this.currentFontVariant };
|
variant: this.currentFontVariant },
|
||||||
this.currentElement.text = _("Text");
|
text: _("Text"),
|
||||||
this.currentElement.textRightAligned = this.currentTextRightAligned;
|
textRightAligned: this.currentTextRightAligned,
|
||||||
|
points: []
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.currentElement = new Elements.DrawingElement({
|
||||||
|
shape: this.currentTool,
|
||||||
|
color: this.currentColor.to_string(),
|
||||||
|
eraser: eraser,
|
||||||
|
fill: this.fill,
|
||||||
|
fillRule: this.currentFillRule,
|
||||||
|
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
||||||
|
dash: { active: this.dashedLine, array: this.dashedLine ? [this.dashArray[0] || this.currentLineWidth, this.dashArray[1] || this.currentLineWidth * 3] : [0, 0] , offset: this.dashOffset },
|
||||||
|
points: []
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentElement.startDrawing(startX, startY);
|
this.currentElement.startDrawing(startX, startY);
|
||||||
|
|
|
||||||
293
elements.js
293
elements.js
|
|
@ -57,10 +57,14 @@ const MIN_TRANSLATION_DISTANCE = 1; // px
|
||||||
const MIN_ROTATION_ANGLE = Math.PI / 1000; // rad
|
const MIN_ROTATION_ANGLE = Math.PI / 1000; // rad
|
||||||
const MIN_DRAWING_SIZE = 3; // px
|
const MIN_DRAWING_SIZE = 3; // px
|
||||||
|
|
||||||
|
var DrawingElement = function(params) {
|
||||||
|
return params.shape == Shapes.TEXT ? new TextElement(params) : new _DrawingElement(params);
|
||||||
|
};
|
||||||
|
|
||||||
// DrawingElement represents a "brushstroke".
|
// DrawingElement represents a "brushstroke".
|
||||||
// It can be converted into a cairo path as well as a svg element.
|
// It can be converted into a cairo path as well as a svg element.
|
||||||
// See DrawingArea._startDrawing() to know its params.
|
// See DrawingArea._startDrawing() to know its params.
|
||||||
var DrawingElement = new Lang.Class({
|
const _DrawingElement = new Lang.Class({
|
||||||
Name: 'DrawOnYourScreenDrawingElement',
|
Name: 'DrawOnYourScreenDrawingElement',
|
||||||
|
|
||||||
_init: function(params) {
|
_init: function(params) {
|
||||||
|
|
@ -69,16 +73,12 @@ var DrawingElement = new Lang.Class({
|
||||||
|
|
||||||
// compatibility with json generated by old extension versions
|
// compatibility with json generated by old extension versions
|
||||||
|
|
||||||
if (params.fillRule === undefined)
|
|
||||||
this.fillRule = Cairo.FillRule.WINDING;
|
|
||||||
if (params.transformations === undefined)
|
if (params.transformations === undefined)
|
||||||
this.transformations = [];
|
this.transformations = [];
|
||||||
if (params.shape == Shapes.TEXT) {
|
|
||||||
if (params.font && params.font.weight === 0)
|
if (params.font && params.font.weight === 0)
|
||||||
this.font.weight = 400;
|
this.font.weight = 400;
|
||||||
if (params.font && params.font.weight === 1)
|
if (params.font && params.font.weight === 1)
|
||||||
this.font.weight = 700;
|
this.font.weight = 700;
|
||||||
}
|
|
||||||
|
|
||||||
if (params.transform && params.transform.center) {
|
if (params.transform && params.transform.center) {
|
||||||
let angle = (params.transform.angle || 0) + (params.transform.startAngle || 0);
|
let angle = (params.transform.angle || 0) + (params.transform.startAngle || 0);
|
||||||
|
|
@ -104,10 +104,6 @@ var DrawingElement = new Lang.Class({
|
||||||
fillRule: this.fillRule,
|
fillRule: this.fillRule,
|
||||||
eraser: this.eraser,
|
eraser: this.eraser,
|
||||||
transformations: this.transformations,
|
transformations: this.transformations,
|
||||||
text: this.text,
|
|
||||||
lineIndex: this.lineIndex !== undefined ? this.lineIndex : undefined,
|
|
||||||
textRightAligned: this.textRightAligned,
|
|
||||||
font: this.font,
|
|
||||||
points: this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100])
|
points: this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100])
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -129,9 +125,12 @@ var DrawingElement = new Lang.Class({
|
||||||
cr.stroke();
|
cr.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.line) {
|
||||||
cr.setLineCap(this.line.lineCap);
|
cr.setLineCap(this.line.lineCap);
|
||||||
cr.setLineJoin(this.line.lineJoin);
|
cr.setLineJoin(this.line.lineJoin);
|
||||||
cr.setLineWidth(this.line.lineWidth);
|
cr.setLineWidth(this.line.lineWidth);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.fillRule)
|
if (this.fillRule)
|
||||||
cr.setFillRule(this.fillRule);
|
cr.setFillRule(this.fillRule);
|
||||||
|
|
||||||
|
|
@ -175,6 +174,12 @@ var DrawingElement = new Lang.Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._drawCairo(cr, params);
|
||||||
|
|
||||||
|
cr.identityMatrix();
|
||||||
|
},
|
||||||
|
|
||||||
|
_drawCairo: function(cr, params) {
|
||||||
let [points, shape] = [this.points, this.shape];
|
let [points, shape] = [this.points, this.shape];
|
||||||
|
|
||||||
if (shape == Shapes.LINE && points.length == 3) {
|
if (shape == Shapes.LINE && points.length == 3) {
|
||||||
|
|
@ -218,51 +223,10 @@ var DrawingElement = new Lang.Class({
|
||||||
if (shape == Shapes.POLYGON)
|
if (shape == Shapes.POLYGON)
|
||||||
cr.closePath();
|
cr.closePath();
|
||||||
|
|
||||||
} else if (shape == Shapes.TEXT && points.length == 2) {
|
|
||||||
let layout = PangoCairo.create_layout(cr);
|
|
||||||
let fontSize = Math.abs(points[1][1] - points[0][1]) * Pango.SCALE;
|
|
||||||
let fontDescription = new Pango.FontDescription();
|
|
||||||
fontDescription.set_absolute_size(fontSize);
|
|
||||||
['family', 'weight', 'style', 'stretch', 'variant'].forEach(attribute => {
|
|
||||||
if (this.font[attribute] !== undefined)
|
|
||||||
try {
|
|
||||||
fontDescription[`set_${attribute}`](this.font[attribute]);
|
|
||||||
} catch(e) {}
|
|
||||||
});
|
|
||||||
layout.set_font_description(fontDescription);
|
|
||||||
layout.set_text(this.text, -1);
|
|
||||||
this.textWidth = layout.get_pixel_size()[0];
|
|
||||||
cr.moveTo(points[1][0] - (this.textRightAligned ? this.textWidth : 0), Math.max(points[0][1],points[1][1]) - layout.get_baseline() / Pango.SCALE);
|
|
||||||
layout.set_text(this.text, -1);
|
|
||||||
PangoCairo.show_layout(cr, layout);
|
|
||||||
|
|
||||||
if (params.showTextCursor) {
|
|
||||||
let cursorPosition = this.cursorPosition == -1 ? this.text.length : this.cursorPosition;
|
|
||||||
layout.set_text(this.text.slice(0, cursorPosition), -1);
|
|
||||||
let width = layout.get_pixel_size()[0];
|
|
||||||
cr.rectangle(points[1][0] - (this.textRightAligned ? this.textWidth : 0) + width, Math.max(points[0][1],points[1][1]),
|
|
||||||
Math.abs(points[1][1] - points[0][1]) / 25, - Math.abs(points[1][1] - points[0][1]));
|
|
||||||
cr.fill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.showTextRectangle || params.drawTextRectangle) {
|
|
||||||
cr.rectangle(points[1][0] - (this.textRightAligned ? this.textWidth : 0), Math.max(points[0][1], points[1][1]),
|
|
||||||
this.textWidth, - Math.abs(points[1][1] - points[0][1]));
|
|
||||||
if (params.showTextRectangle)
|
|
||||||
setDummyStroke(cr);
|
|
||||||
else
|
|
||||||
// Only draw the rectangle to find the element, not to show it.
|
|
||||||
cr.setLineWidth(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cr.identityMatrix();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getContainsPoint: function(cr, x, y) {
|
getContainsPoint: function(cr, x, y) {
|
||||||
if (this.shape == Shapes.TEXT)
|
|
||||||
return cr.inFill(x, y);
|
|
||||||
|
|
||||||
cr.save();
|
cr.save();
|
||||||
cr.setLineWidth(Math.max(this.line.lineWidth, 25));
|
cr.setLineWidth(Math.max(this.line.lineWidth, 25));
|
||||||
cr.setDash([], 0);
|
cr.setDash([], 0);
|
||||||
|
|
@ -274,33 +238,6 @@ var DrawingElement = new Lang.Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
buildSVG: function(bgColor) {
|
buildSVG: function(bgColor) {
|
||||||
let row = "\n ";
|
|
||||||
let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]);
|
|
||||||
let color = this.eraser ? bgColor : this.color;
|
|
||||||
let fill = this.fill && !this.isStraightLine;
|
|
||||||
let attributes = '';
|
|
||||||
|
|
||||||
if (fill) {
|
|
||||||
attributes = `fill="${color}"`;
|
|
||||||
if (this.fillRule)
|
|
||||||
attributes += ` fill-rule="${FillRuleNames[this.fillRule].toLowerCase()}"`;
|
|
||||||
} else {
|
|
||||||
attributes = `fill="none"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.line && this.line.lineWidth) {
|
|
||||||
attributes += ` stroke="${color}"` +
|
|
||||||
` stroke-width="${this.line.lineWidth}"`;
|
|
||||||
if (this.line.lineCap)
|
|
||||||
attributes += ` stroke-linecap="${LineCapNames[this.line.lineCap].toLowerCase()}"`;
|
|
||||||
if (this.line.lineJoin && !this.isStraightLine)
|
|
||||||
attributes += ` stroke-linejoin="${LineJoinNames[this.line.lineJoin].toLowerCase()}"`;
|
|
||||||
if (this.dash && this.dash.active && this.dash.array && this.dash.array[0] && this.dash.array[1])
|
|
||||||
attributes += ` stroke-dasharray="${this.dash.array[0]} ${this.dash.array[1]}" stroke-dashoffset="${this.dash.offset}"`;
|
|
||||||
} else {
|
|
||||||
attributes += ` stroke="none"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
let transAttribute = '';
|
let transAttribute = '';
|
||||||
this.transformations.slice(0).reverse().forEach(transformation => {
|
this.transformations.slice(0).reverse().forEach(transformation => {
|
||||||
transAttribute += transAttribute ? ' ' : ' transform="';
|
transAttribute += transAttribute ? ' ' : ' transform="';
|
||||||
|
|
@ -328,6 +265,37 @@ var DrawingElement = new Lang.Class({
|
||||||
});
|
});
|
||||||
transAttribute += transAttribute ? '"' : '';
|
transAttribute += transAttribute ? '"' : '';
|
||||||
|
|
||||||
|
return this._drawSvg(transAttribute);
|
||||||
|
},
|
||||||
|
|
||||||
|
_drawSvg: function(transAttribute) {
|
||||||
|
let row = "\n ";
|
||||||
|
let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]);
|
||||||
|
let color = this.eraser ? bgColor : this.color;
|
||||||
|
let fill = this.fill && !this.isStraightLine;
|
||||||
|
let attributes = '';
|
||||||
|
|
||||||
|
if (fill) {
|
||||||
|
attributes = `fill="${color}"`;
|
||||||
|
if (this.fillRule)
|
||||||
|
attributes += ` fill-rule="${FillRuleNames[this.fillRule].toLowerCase()}"`;
|
||||||
|
} else {
|
||||||
|
attributes = `fill="none"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.line && this.line.lineWidth) {
|
||||||
|
attributes += ` stroke="${color}"` +
|
||||||
|
` stroke-width="${this.line.lineWidth}"`;
|
||||||
|
if (this.line.lineCap)
|
||||||
|
attributes += ` stroke-linecap="${LineCapNames[this.line.lineCap].toLowerCase()}"`;
|
||||||
|
if (this.line.lineJoin && !this.isStraightLine)
|
||||||
|
attributes += ` stroke-linejoin="${LineJoinNames[this.line.lineJoin].toLowerCase()}"`;
|
||||||
|
if (this.dash && this.dash.active && this.dash.array && this.dash.array[0] && this.dash.array[1])
|
||||||
|
attributes += ` stroke-dasharray="${this.dash.array[0]} ${this.dash.array[1]}" stroke-dashoffset="${this.dash.offset}"`;
|
||||||
|
} else {
|
||||||
|
attributes += ` stroke="none"`;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.shape == Shapes.LINE && points.length == 4) {
|
if (this.shape == Shapes.LINE && points.length == 4) {
|
||||||
row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`;
|
row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`;
|
||||||
row += ` C ${points[1][0]} ${points[1][1]}, ${points[2][0]} ${points[2][1]}, ${points[3][0]} ${points[3][1]}`;
|
row += ` C ${points[1][0]} ${points[1][1]}, ${points[2][0]} ${points[2][1]}, ${points[3][0]} ${points[3][1]}`;
|
||||||
|
|
@ -372,26 +340,6 @@ var DrawingElement = new Lang.Class({
|
||||||
row += ` ${points[i][0]},${points[i][1]}`;
|
row += ` ${points[i][0]},${points[i][1]}`;
|
||||||
row += `"${transAttribute}/>`;
|
row += `"${transAttribute}/>`;
|
||||||
|
|
||||||
} else if (this.shape == Shapes.TEXT && points.length == 2) {
|
|
||||||
attributes = `fill="${color}" ` +
|
|
||||||
`stroke="transparent" ` +
|
|
||||||
`stroke-opacity="0" ` +
|
|
||||||
`font-size="${Math.abs(points[1][1] - points[0][1])}"`;
|
|
||||||
|
|
||||||
if (this.font.family)
|
|
||||||
attributes += ` font-family="${this.font.family}"`;
|
|
||||||
if (this.font.weight && this.font.weight != Pango.Weight.NORMAL)
|
|
||||||
attributes += ` font-weight="${this.font.weight}"`;
|
|
||||||
if (this.font.style && FontStyleNames[this.font.style])
|
|
||||||
attributes += ` font-style="${FontStyleNames[this.font.style].toLowerCase()}"`;
|
|
||||||
if (FontStretchNames[this.font.stretch] && this.font.stretch != Pango.Stretch.NORMAL)
|
|
||||||
attributes += ` font-stretch="${FontStretchNames[this.font.stretch].toLowerCase()}"`;
|
|
||||||
if (this.font.variant && FontVariantNames[this.font.variant])
|
|
||||||
attributes += ` font-variant="${FontVariantNames[this.font.variant].toLowerCase()}"`;
|
|
||||||
|
|
||||||
// this.textWidth is computed during Cairo building.
|
|
||||||
row += `<text ${attributes} x="${points[1][0] - (this.textRightAligned ? this.textWidth : 0)}" `;
|
|
||||||
row += `y="${Math.max(points[0][1], points[1][1])}"${transAttribute}>${this.text}</text>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
|
|
@ -469,14 +417,6 @@ var DrawingElement = new Lang.Class({
|
||||||
} else if (this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) {
|
} else if (this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) {
|
||||||
points[points.length - 1] = [x, y];
|
points[points.length - 1] = [x, y];
|
||||||
|
|
||||||
} else if (this.shape == Shapes.TEXT && transform) {
|
|
||||||
if (points.length < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let [slideX, slideY] = [x - points[1][0], y - points[1][1]];
|
|
||||||
points[0] = [points[0][0] + slideX, points[0][1] + slideY];
|
|
||||||
points[1] = [x, y];
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
points[1] = [x, y];
|
points[1] = [x, y];
|
||||||
|
|
||||||
|
|
@ -590,11 +530,6 @@ var DrawingElement = new Lang.Class({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// When rotating grouped lines, lineOffset is used to retrieve the rotation center of the first line.
|
|
||||||
_getLineOffset: function() {
|
|
||||||
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).
|
||||||
// this.textWidth is computed during Cairo building.
|
// this.textWidth is computed during Cairo building.
|
||||||
_getOriginalCenter: function() {
|
_getOriginalCenter: function() {
|
||||||
|
|
@ -603,7 +538,6 @@ var DrawingElement = new Lang.Class({
|
||||||
this._originalCenter = this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] :
|
this._originalCenter = this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] :
|
||||||
this.shape == Shapes.LINE && points.length == 4 ? getCurveCenter(points[0], points[1], points[2], points[3]) :
|
this.shape == Shapes.LINE && points.length == 4 ? getCurveCenter(points[0], points[1], points[2], points[3]) :
|
||||||
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[0], points[1], points[2]) :
|
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[0], points[1], points[2]) :
|
||||||
this.shape == Shapes.TEXT && this.textWidth ? [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);
|
||||||
}
|
}
|
||||||
|
|
@ -648,6 +582,139 @@ var DrawingElement = new Lang.Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const TextElement = new Lang.Class({
|
||||||
|
Name: 'DrawOnYourScreenTextElement',
|
||||||
|
Extends: _DrawingElement,
|
||||||
|
|
||||||
|
toJSON: function() {
|
||||||
|
return {
|
||||||
|
shape: this.shape,
|
||||||
|
color: this.color,
|
||||||
|
eraser: this.eraser,
|
||||||
|
transformations: this.transformations,
|
||||||
|
text: this.text,
|
||||||
|
lineIndex: this.lineIndex !== undefined ? this.lineIndex : undefined,
|
||||||
|
textRightAligned: this.textRightAligned,
|
||||||
|
font: this.font,
|
||||||
|
points: this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100])
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_drawCairo: function(cr, params) {
|
||||||
|
let points = this.points;
|
||||||
|
|
||||||
|
if (points.length == 2) {
|
||||||
|
let layout = PangoCairo.create_layout(cr);
|
||||||
|
let fontSize = Math.abs(points[1][1] - points[0][1]) * Pango.SCALE;
|
||||||
|
let fontDescription = new Pango.FontDescription();
|
||||||
|
fontDescription.set_absolute_size(fontSize);
|
||||||
|
['family', 'weight', 'style', 'stretch', 'variant'].forEach(attribute => {
|
||||||
|
if (this.font[attribute] !== undefined)
|
||||||
|
try {
|
||||||
|
fontDescription[`set_${attribute}`](this.font[attribute]);
|
||||||
|
} catch(e) {}
|
||||||
|
});
|
||||||
|
layout.set_font_description(fontDescription);
|
||||||
|
layout.set_text(this.text, -1);
|
||||||
|
this.textWidth = layout.get_pixel_size()[0];
|
||||||
|
cr.moveTo(points[1][0] - (this.textRightAligned ? this.textWidth : 0), Math.max(points[0][1],points[1][1]) - layout.get_baseline() / Pango.SCALE);
|
||||||
|
layout.set_text(this.text, -1);
|
||||||
|
PangoCairo.show_layout(cr, layout);
|
||||||
|
|
||||||
|
if (params.showTextCursor) {
|
||||||
|
let cursorPosition = this.cursorPosition == -1 ? this.text.length : this.cursorPosition;
|
||||||
|
layout.set_text(this.text.slice(0, cursorPosition), -1);
|
||||||
|
let width = layout.get_pixel_size()[0];
|
||||||
|
cr.rectangle(points[1][0] - (this.textRightAligned ? this.textWidth : 0) + width, Math.max(points[0][1],points[1][1]),
|
||||||
|
Math.abs(points[1][1] - points[0][1]) / 25, - Math.abs(points[1][1] - points[0][1]));
|
||||||
|
cr.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.showTextRectangle || params.drawTextRectangle) {
|
||||||
|
cr.rectangle(points[1][0] - (this.textRightAligned ? this.textWidth : 0), Math.max(points[0][1], points[1][1]),
|
||||||
|
this.textWidth, - Math.abs(points[1][1] - points[0][1]));
|
||||||
|
if (params.showTextRectangle)
|
||||||
|
setDummyStroke(cr);
|
||||||
|
else
|
||||||
|
// Only draw the rectangle to find the element, not to show it.
|
||||||
|
cr.setLineWidth(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getContainsPoint: function(cr, x, y) {
|
||||||
|
return cr.inFill(x, y);
|
||||||
|
},
|
||||||
|
|
||||||
|
_drawSvg: function(transAttribute) {
|
||||||
|
let row = "\n ";
|
||||||
|
let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]);
|
||||||
|
let color = this.eraser ? bgColor : this.color;
|
||||||
|
let attributes = '';
|
||||||
|
|
||||||
|
if (points.length == 2) {
|
||||||
|
attributes = `fill="${color}" ` +
|
||||||
|
`stroke="transparent" ` +
|
||||||
|
`stroke-opacity="0" ` +
|
||||||
|
`font-size="${Math.abs(points[1][1] - points[0][1])}"`;
|
||||||
|
|
||||||
|
if (this.font.family)
|
||||||
|
attributes += ` font-family="${this.font.family}"`;
|
||||||
|
if (this.font.weight && this.font.weight != Pango.Weight.NORMAL)
|
||||||
|
attributes += ` font-weight="${this.font.weight}"`;
|
||||||
|
if (this.font.style && FontStyleNames[this.font.style])
|
||||||
|
attributes += ` font-style="${FontStyleNames[this.font.style].toLowerCase()}"`;
|
||||||
|
if (FontStretchNames[this.font.stretch] && this.font.stretch != Pango.Stretch.NORMAL)
|
||||||
|
attributes += ` font-stretch="${FontStretchNames[this.font.stretch].toLowerCase()}"`;
|
||||||
|
if (this.font.variant && FontVariantNames[this.font.variant])
|
||||||
|
attributes += ` font-variant="${FontVariantNames[this.font.variant].toLowerCase()}"`;
|
||||||
|
|
||||||
|
// this.textWidth is computed during Cairo building.
|
||||||
|
row += `<text ${attributes} x="${points[1][0] - (this.textRightAligned ? this.textWidth : 0)}" `;
|
||||||
|
row += `y="${Math.max(points[0][1], points[1][1])}"${transAttribute}>${this.text}</text>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDrawing: function(x, y, transform) {
|
||||||
|
let points = this.points;
|
||||||
|
if (x == points[points.length - 1][0] && y == points[points.length - 1][1])
|
||||||
|
return;
|
||||||
|
|
||||||
|
transform = transform || this.transformations.length >= 1;
|
||||||
|
|
||||||
|
if (transform) {
|
||||||
|
if (points.length < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let [slideX, slideY] = [x - points[1][0], y - points[1][1]];
|
||||||
|
points[0] = [points[0][0] + slideX, points[0][1] + slideY];
|
||||||
|
points[1] = [x, y];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
points[1] = [x, y];
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// When rotating grouped lines, lineOffset is used to retrieve the rotation center of the first line.
|
||||||
|
_getLineOffset: function() {
|
||||||
|
return (this.lineIndex || 0) * Math.abs(this.points[1][1] - this.points[0][1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getOriginalCenter: function() {
|
||||||
|
if (!this._originalCenter) {
|
||||||
|
let points = this.points;
|
||||||
|
this._originalCenter = this.textWidth ? [points[1][0], Math.max(points[0][1], points[1][1]) - this._getLineOffset()] :
|
||||||
|
points.length >= 3 ? getCentroid(points) :
|
||||||
|
getNaiveCenter(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._originalCenter;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const setDummyStroke = function(cr) {
|
const setDummyStroke = function(cr) {
|
||||||
cr.setLineWidth(2);
|
cr.setLineWidth(2);
|
||||||
cr.setLineCap(0);
|
cr.setLineCap(0);
|
||||||
|
|
@ -655,10 +722,6 @@ const setDummyStroke = function(cr) {
|
||||||
cr.setDash([1, 2], 0);
|
cr.setDash([1, 2], 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Some geometric utils
|
|
||||||
*/
|
|
||||||
|
|
||||||
const getNearness = function(pointA, pointB, distance) {
|
const getNearness = function(pointA, pointB, distance) {
|
||||||
return Math.hypot(pointB[0] - pointA[0], pointB[1] - pointA[1]) < distance;
|
return Math.hypot(pointB[0] - pointA[0], pointB[1] - pointA[1]) < distance;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue