colored SVG images
Color (fill) SVG images by pressing the `Shift` key.
This commit is contained in:
parent
532b9242c9
commit
3c67bf3398
8
area.js
8
area.js
|
|
@ -603,7 +603,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this._redisplay();
|
this._redisplay();
|
||||||
},
|
},
|
||||||
|
|
||||||
_startDrawing: function(stageX, stageY, eraser) {
|
_startDrawing: function(stageX, stageY, shiftPressed) {
|
||||||
let [success, startX, startY] = this.transform_stage_point(stageX, stageY);
|
let [success, startX, startY] = this.transform_stage_point(stageX, stageY);
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
|
|
@ -617,7 +617,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this.currentElement = new Elements.DrawingElement({
|
this.currentElement = new Elements.DrawingElement({
|
||||||
shape: this.currentTool,
|
shape: this.currentTool,
|
||||||
color: this.currentColor,
|
color: this.currentColor,
|
||||||
eraser: eraser,
|
eraser: shiftPressed,
|
||||||
font: this.currentFont.copy(),
|
font: this.currentFont.copy(),
|
||||||
// Translators: initial content of the text area
|
// Translators: initial content of the text area
|
||||||
text: pgettext("text-area-content", "Text"),
|
text: pgettext("text-area-content", "Text"),
|
||||||
|
|
@ -628,7 +628,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this.currentElement = new Elements.DrawingElement({
|
this.currentElement = new Elements.DrawingElement({
|
||||||
shape: this.currentTool,
|
shape: this.currentTool,
|
||||||
color: this.currentColor,
|
color: this.currentColor,
|
||||||
eraser: eraser,
|
colored: shiftPressed,
|
||||||
image: this.currentImage,
|
image: this.currentImage,
|
||||||
points: []
|
points: []
|
||||||
});
|
});
|
||||||
|
|
@ -636,7 +636,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this.currentElement = new Elements.DrawingElement({
|
this.currentElement = new Elements.DrawingElement({
|
||||||
shape: this.currentTool,
|
shape: this.currentTool,
|
||||||
color: this.currentColor,
|
color: this.currentColor,
|
||||||
eraser: eraser,
|
eraser: shiftPressed,
|
||||||
fill: this.fill,
|
fill: this.fill,
|
||||||
fillRule: this.currentFillRule,
|
fillRule: this.currentFillRule,
|
||||||
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
||||||
|
|
|
||||||
|
|
@ -771,7 +771,7 @@ const ImageElement = new Lang.Class({
|
||||||
return {
|
return {
|
||||||
shape: this.shape,
|
shape: this.shape,
|
||||||
color: this.color,
|
color: this.color,
|
||||||
eraser: this.eraser,
|
colored: this.colored,
|
||||||
transformations: this.transformations,
|
transformations: this.transformations,
|
||||||
image: this.image,
|
image: this.image,
|
||||||
preserveAspectRatio: this.preserveAspectRatio,
|
preserveAspectRatio: this.preserveAspectRatio,
|
||||||
|
|
@ -791,7 +791,7 @@ const ImageElement = new Lang.Class({
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cr.save();
|
cr.save();
|
||||||
this.image.setCairoSource(cr, x, y, width, height, this.preserveAspectRatio);
|
this.image.setCairoSource(cr, x, y, width, height, this.preserveAspectRatio, this.colored ? this.color.toJSON() : null);
|
||||||
cr.rectangle(x, y, width, height);
|
cr.rectangle(x, y, width, height);
|
||||||
cr.fill();
|
cr.fill();
|
||||||
cr.restore();
|
cr.restore();
|
||||||
|
|
@ -813,14 +813,15 @@ const ImageElement = new Lang.Class({
|
||||||
_drawSvg: function(transAttribute) {
|
_drawSvg: function(transAttribute) {
|
||||||
let points = this.points;
|
let points = this.points;
|
||||||
let row = "\n ";
|
let row = "\n ";
|
||||||
let attributes = this.eraser ? `class="eraser" ` : '';
|
let attributes = '';
|
||||||
|
|
||||||
if (points.length == 2) {
|
if (points.length == 2) {
|
||||||
attributes += `fill="none"`;
|
attributes += `fill="none"`;
|
||||||
|
let base64 = this.image.getBase64ForColor(this.colored ? this.color.toJSON() : null);
|
||||||
row += `<image ${attributes} x="${Math.min(points[0][0], points[1][0])}" y="${Math.min(points[0][1], points[1][1])}" ` +
|
row += `<image ${attributes} x="${Math.min(points[0][0], points[1][0])}" y="${Math.min(points[0][1], points[1][1])}" ` +
|
||||||
`width="${Math.abs(points[1][0] - points[0][0])}" height="${Math.abs(points[1][1] - points[0][1])}"${transAttribute} ` +
|
`width="${Math.abs(points[1][0] - points[0][0])}" height="${Math.abs(points[1][1] - points[0][1])}"${transAttribute} ` +
|
||||||
`preserveAspectRatio="${this.preserveAspectRatio ? 'xMinYMin' : 'none'}" ` +
|
`preserveAspectRatio="${this.preserveAspectRatio ? 'xMinYMin' : 'none'}" ` +
|
||||||
`id="${this.image.displayName}" xlink:href="data:${this.image.contentType};base64,${this.image.base64}"/>`;
|
`id="${this.image.displayName}" xlink:href="data:${this.image.contentType};base64,${base64}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
|
|
|
||||||
49
files.js
49
files.js
|
|
@ -83,6 +83,18 @@ Object.keys(ThemedIconNames).forEach(key => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const replaceColor = function (contents, color) {
|
||||||
|
if (contents instanceof Uint8Array)
|
||||||
|
contents = ByteArray.toString(contents);
|
||||||
|
else
|
||||||
|
contents = contents.toString();
|
||||||
|
|
||||||
|
return contents.replace(/fill(?=="transparent"|="none"|:transparent|:none)/gi, 'filll')
|
||||||
|
.replace(/fill="[^"]+"/gi, `fill="${color}"`)
|
||||||
|
.replace(/fill:[^";]+/gi, `fill:${color};`)
|
||||||
|
.replace(/filll/gi, 'fill');
|
||||||
|
};
|
||||||
|
|
||||||
// Wrapper around image data. If not subclassed, it is used when loading in the area an image element for a drawing file (.json)
|
// Wrapper around image data. If not subclassed, it is used when loading in the area an image element for a drawing file (.json)
|
||||||
// and it takes { displayName, contentType, base64, hash } as params.
|
// and it takes { displayName, contentType, base64, hash } as params.
|
||||||
var Image = new Lang.Class({
|
var Image = new Lang.Class({
|
||||||
|
|
@ -122,6 +134,14 @@ var Image = new Lang.Class({
|
||||||
this._base64 = base64;
|
this._base64 = base64;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getBase64ForColor: function(color) {
|
||||||
|
if (!color || this.contentType != 'image/svg+xml')
|
||||||
|
return this.base64;
|
||||||
|
|
||||||
|
let contents = GLib.base64_decode(this.base64);
|
||||||
|
return GLib.base64_encode(replaceColor(contents, color));
|
||||||
|
},
|
||||||
|
|
||||||
// hash is not used
|
// hash is not used
|
||||||
get hash() {
|
get hash() {
|
||||||
if (!this._hash)
|
if (!this._hash)
|
||||||
|
|
@ -133,7 +153,22 @@ var Image = new Lang.Class({
|
||||||
this._hash = hash;
|
this._hash = hash;
|
||||||
},
|
},
|
||||||
|
|
||||||
get pixbuf() {
|
getBytesForColor: function(color) {
|
||||||
|
if (!color || this.contentType != 'image/svg+xml')
|
||||||
|
return this.bytes;
|
||||||
|
|
||||||
|
let contents = this.bytes.get_data();
|
||||||
|
return new GLib.Bytes(replaceColor(contents, color));
|
||||||
|
},
|
||||||
|
|
||||||
|
getPixbuf: function(color) {
|
||||||
|
if (color) {
|
||||||
|
let stream = Gio.MemoryInputStream.new_from_bytes(this.getBytesForColor(color));
|
||||||
|
let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, null);
|
||||||
|
stream.close(null);
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this._pixbuf) {
|
if (!this._pixbuf) {
|
||||||
let stream = Gio.MemoryInputStream.new_from_bytes(this.bytes);
|
let stream = Gio.MemoryInputStream.new_from_bytes(this.bytes);
|
||||||
this._pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, null);
|
this._pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, null);
|
||||||
|
|
@ -142,16 +177,16 @@ var Image = new Lang.Class({
|
||||||
return this._pixbuf;
|
return this._pixbuf;
|
||||||
},
|
},
|
||||||
|
|
||||||
getPixbufAtScale: function(width, height) {
|
getPixbufAtScale: function(width, height, color) {
|
||||||
let stream = Gio.MemoryInputStream.new_from_bytes(this.bytes);
|
let stream = Gio.MemoryInputStream.new_from_bytes(this.getBytesForColor(color));
|
||||||
let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, width, height, true, null);
|
let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, width, height, true, null);
|
||||||
stream.close(null);
|
stream.close(null);
|
||||||
return pixbuf;
|
return pixbuf;
|
||||||
},
|
},
|
||||||
|
|
||||||
setCairoSource: function(cr, x, y, width, height, preserveAspectRatio) {
|
setCairoSource: function(cr, x, y, width, height, preserveAspectRatio, color) {
|
||||||
let pixbuf = preserveAspectRatio ? this.getPixbufAtScale(width, height)
|
let pixbuf = preserveAspectRatio ? this.getPixbufAtScale(width, height, color)
|
||||||
: this.pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR);
|
: this.getPixbuf(color).scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR);
|
||||||
Gdk.cairo_set_source_pixbuf(cr, pixbuf, x, y);
|
Gdk.cairo_set_source_pixbuf(cr, pixbuf, x, y);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -552,7 +587,7 @@ var Jsons = {
|
||||||
|
|
||||||
var getDateString = function() {
|
var getDateString = function() {
|
||||||
let date = GLib.DateTime.new_now_local();
|
let date = GLib.DateTime.new_now_local();
|
||||||
return `${date.format("%F")} ${date.format("%X")}`;
|
return `${date.format("%F")} ${date.format("%T")}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
var saveSvg = function(content) {
|
var saveSvg = function(content) {
|
||||||
|
|
|
||||||
2
menu.js
2
menu.js
|
|
@ -315,8 +315,6 @@ var DrawingMenu = new Lang.Class({
|
||||||
this.lineSection.actor.visible = !isText && !isImage;
|
this.lineSection.actor.visible = !isText && !isImage;
|
||||||
this.fontSection.actor.visible = isText;
|
this.fontSection.actor.visible = isText;
|
||||||
this.imageSection.actor.visible = isImage;
|
this.imageSection.actor.visible = isImage;
|
||||||
this.colorItem.setSensitive(!isImage);
|
|
||||||
this.paletteItem.setSensitive(!isImage);
|
|
||||||
this.fillItem.setSensitive(!isText && !isImage);
|
this.fillItem.setSensitive(!isText && !isImage);
|
||||||
this.fillSection.setSensitive(!isText && !isImage);
|
this.fillSection.setSensitive(!isText && !isImage);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue