#240: borders type migrated to effects.

This commit is contained in:
viliusle 2021-06-19 20:02:29 +03:00
parent 1dab3914a2
commit 8a27ce1656
18 changed files with 283 additions and 177 deletions

View File

@ -712,7 +712,7 @@
"rotate": 0,
"data": null,
"params": {
"size": 7,
"size": 15,
"shadow": false
},
"status": null,
@ -1588,7 +1588,7 @@
{
"id": 43,
"parent_id": 0,
"name": "Cog #43",
"name": "Cog",
"type": "cog",
"link": null,
"x": 50,
@ -1617,7 +1617,7 @@
{
"id": 44,
"parent_id": 0,
"name": "Tear #44",
"name": "Tear",
"type": "tear",
"link": null,
"x": 140,
@ -1652,7 +1652,7 @@
{
"id": 45,
"parent_id": 0,
"name": "Moon #45",
"name": "Moon",
"type": "moon",
"link": null,
"x": 220,
@ -1687,7 +1687,7 @@
{
"id": 46,
"parent_id": 0,
"name": "Callout #46",
"name": "Callout",
"type": "callout",
"link": null,
"x": 300,

View File

@ -1,6 +1,6 @@
{
"name": "miniPaint",
"version": "4.7.1",
"version": "4.8",
"author": "Vilius L.",
"description": "Online graphics editing tool lets create, edit images using HTML5 technologies.",
"keywords": [

View File

@ -472,6 +472,11 @@ const menuDefinition = [
ellipsis: true,
target: 'effects/black_and_white.black_and_white'
},
{
name: 'Borders',
ellipsis: true,
target: 'effects/borders.borders'
},
{
name: 'Blueprint',
target: 'effects/blueprint.blueprint'
@ -575,11 +580,6 @@ const menuDefinition = [
{
name: 'Tools',
children: [
{
name: 'Borders',
ellipsis: true,
target: 'tools/borders.borders'
},
{
name: 'Sprites',
target: 'tools/sprites.sprites'

View File

@ -329,6 +329,9 @@ class Base_layers_class {
//apply post-filters
for (var i in object.filters) {
var filter = object.filters[i];
if(filter.id == this.disabled_filter_id){
continue;
}
filter.name = filter.name.replace('drop-shadow', 'shadow');
//find filter
@ -722,6 +725,32 @@ class Base_layers_class {
this.disabled_filter_id = filter_id;
}
/**
* finds layer filter by filter ID
*
* @param filter_id
* @param filter_name
* @param layer_id
* @returns {object}
*/
find_filter_by_id(filter_id, filter_name, layer_id) {
if(typeof layer_id == 'undefined'){
var layer = config.layer;
}
else{
var layer = this.get_layer(layer_id);
}
var filter = {};
for(var i in layer.filters){
if(layer.filters[i].name == filter_name && layer.filters[i].id == filter_id) {
return layer.filters[i].params;
}
}
return filter;
}
}
export default Base_layers_class;

View File

@ -66,17 +66,6 @@ class Effects_common_class {
return value;
}
find_filter_by_id(filter_id, filter_name) {
var filter = {};
for(var i in config.layer.filters){
if(config.layer.filters[i].name == filter_name && config.layer.filters[i].id == filter_id) {
return config.layer.filters[i].params;
}
}
return {};
}
}
export default Effects_common_class;

View File

@ -0,0 +1,107 @@
import app from './../../app.js';
import config from './../../config.js';
import Base_layers_class from './../../core/base-layers.js';
import Dialog_class from './../../libs/popup.js';
import alertify from './../../../../node_modules/alertifyjs/build/alertify.min.js';
import Effects_browser_class from "./browser";
class Effects_borders_class {
constructor() {
this.POP = new Dialog_class();
this.Base_layers = new Base_layers_class();
this.Effects_browser = new Effects_browser_class();
}
borders(filter_id) {
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var _this = this;
var filter = this.Base_layers.find_filter_by_id(filter_id, 'borders');
var settings = {
title: 'Borders',
params: [
{name: "color", title: "Color:", value: filter.color ??= config.COLOR, type: 'color'},
{name: "size", title: "Size:", value: filter.size ??= 10},
],
on_finish: function (params) {
var target = Math.min(config.WIDTH, config.HEIGHT);
_this.add_borders(params, filter_id);
},
};
var rotate = config.layer.rotate;
config.layer.rotate = 0;
this.Base_layers.disable_filter(filter_id);
this.POP.show(settings);
config.layer.rotate = rotate;
this.Base_layers.disable_filter(null);
}
demo(canvas_id, canvas_thumb){
var canvas = document.getElementById(canvas_id);
var ctx = canvas.getContext("2d");
//draw
ctx.drawImage(canvas_thumb,
5, 5,
this.Effects_browser.preview_width - 10, this.Effects_browser.preview_height - 10);
//add borders
ctx.strokeStyle = '#000000';
ctx.lineWidth = 10;
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.stroke();
}
render_pre(ctx, data) {
}
render_post(ctx, data, layer){
var size = Math.max(0, data.params.size);
var x = layer.x;
var y = layer.y;
var width = parseInt(layer.width);
var height = parseInt(layer.height);
//legacy check
if(x == null) x = 0;
if(y == null) y = 0;
if(!width) width = config.WIDTH;
if(!height) height = config.HEIGHT;
ctx.save();
//set styles
ctx.strokeStyle = data.params.color;
ctx.lineWidth = size;
//draw with rotation support
ctx.translate(layer.x + width / 2, layer.y + height / 2);
ctx.rotate(layer.rotate * Math.PI / 180);
var x_new = -width / 2;
var y_new = -height / 2;
ctx.beginPath();
ctx.rect(x_new - size * 0.5, y_new - size * 0.5, width + size, height + size);
ctx.stroke();
ctx.restore();
}
add_borders(params, filter_id) {
//apply effect
return app.State.do_action(
new app.Actions.Add_layer_filter_action(config.layer.id, 'borders', params, filter_id)
);
}
}
export default Effects_borders_class;

View File

@ -1,16 +1,24 @@
import config from '../../../config.js';
import Effects_common_class from '../abstract/css.js';
import Dialog_class from '../../../libs/popup.js';
import Base_layers_class from './../../../core/base-layers.js';
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_blur_class extends Effects_common_class {
constructor() {
super();
this.POP = new Dialog_class();
this.Base_layers = new Base_layers_class();
}
blur(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'blur');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'blur');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 5, range: [0, 50]},

View File

@ -1,9 +1,21 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_brightness_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
brightness(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'brightness');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'brightness');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 50, range: [-100, 100]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_contrast_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
contrast(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'contrast');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'contrast');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 40, range: [-100, 100]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_grayscale_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
grayscale(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'grayscale');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'grayscale');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 100, range: [0, 100]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_hueRotate_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
hue_rotate(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'hue-rotate');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'hue-rotate');
var params = [
{name: "value", title: "Degree:", value: filter.value ??= 90, range: [0, 360]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_invert_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
invert(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'invert');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'invert');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 100, range: [0, 100]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_saturate_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
saturate(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'saturate');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'saturate');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= -50, range: [-100, 100]},

View File

@ -1,9 +1,22 @@
import Effects_common_class from '../abstract/css.js';
import Base_layers_class from './../../../core/base-layers.js';
import config from "../../../config";
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_sepia_class extends Effects_common_class {
constructor() {
super();
this.Base_layers = new Base_layers_class();
}
sepia(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'sepia');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'sepia');
var params = [
{name: "value", title: "Percentage:", value: filter.value ??= 60, range: [0, 100]},

View File

@ -2,6 +2,8 @@ import config from '../../../config.js';
import Effects_common_class from '../abstract/css.js';
import Dialog_class from '../../../libs/popup.js';
import Effects_browser_class from '../browser.js';
import Base_layers_class from './../../../core/base-layers.js';
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
class Effects_brightness_class extends Effects_common_class {
@ -9,11 +11,17 @@ class Effects_brightness_class extends Effects_common_class {
super();
this.POP = new Dialog_class();
this.Effects_browser = new Effects_browser_class();
this.Base_layers = new Base_layers_class();
this.preview_padding = 20;
}
shadow(filter_id) {
var filter = this.find_filter_by_id(filter_id, 'shadow');
if (config.layer.type == null) {
alertify.error('Layer is empty.');
return;
}
var filter = this.Base_layers.find_filter_by_id(filter_id, 'shadow');
var params = [
{name: "x", title: "Offset X:", value: filter.x ??= 10, range: [-100, 100]},

View File

@ -555,6 +555,27 @@ class File_open_class {
}
}
}
if(json.info.version < "4.8"){
//migrate "borders" layer to rectangle
for (var i in json.layers) {
var old_type = json.layers[i].type;
if(old_type == 'borders'){
json.layers[i].type = 'rectangle';
json.layers[i].name += ' (legacy)';
json.layers[i].params = {
radius: 0,
fill: false,
square: false,
border_size: json.layers[i].params.size,
border: true,
border_color: json.layers[i].color,
fill_color: "#000000",
};
json.layers[i].render_function = ["rectangle", "render"];
}
}
}
const actions = [];

View File

@ -1,86 +0,0 @@
import app from './../../app.js';
import config from './../../config.js';
import Base_layers_class from './../../core/base-layers.js';
import Dialog_class from './../../libs/popup.js';
class Tools_borders_class {
constructor() {
this.POP = new Dialog_class();
this.Base_layers = new Base_layers_class();
}
borders() {
var _this = this;
var settings = {
title: 'Borders',
preview: true,
on_change: function (params, canvas_preview, w, h) {
var target = Math.min(w, h);
params.size = Math.round(target / 100 * params.size);
_this.preview_borders(params, canvas_preview, w, h);
},
params: [
{name: "color", title: "Color:", value: config.COLOR, type: 'color'},
{name: "shadow", title: "Shadow:", value: false},
{name: "size", title: "Size:", value: "5", range: [1, 100]},
],
on_finish: function (params) {
var target = Math.min(config.WIDTH, config.HEIGHT);
params.size = Math.round(target / 100 * params.size);
_this.add_borders(params);
},
};
this.POP.show(settings);
}
preview_borders(params, ctx, width, height) {
var size = params.size;
var color = params.color;
var color = params.color;
ctx.save();
ctx.lineWidth = size;
if (params.shadow === true) {
//with shadow
ctx.beginPath();
ctx.shadowColor = color;
ctx.shadowBlur = size;
ctx.rect(-size / 2, -size / 2, width + size, height + size);
ctx.stroke();
ctx.stroke();
ctx.stroke();
}
else {
ctx.strokeStyle = color;
ctx.rect(0, 0, width, height);
ctx.stroke();
}
ctx.restore();
}
add_borders(params) {
//create borders layer
this.layer = {
name: 'Borders',
type: 'borders',
render_function: ['borders', 'render'],
params: {size: params.size, shadow: params.shadow},
color: params.color,
x: 0,
y: 0,
width: config.WIDTH,
height: config.HEIGHT,
is_vector: true,
};
app.State.do_action(
new app.Actions.Bundle_action('add_borders', 'Add Borders', [
new app.Actions.Insert_layer_action(this.layer)
])
);
}
}
export default Tools_borders_class;

View File

@ -1,60 +0,0 @@
import config from './../config.js';
import Base_tools_class from './../core/base-tools.js';
import Base_layers_class from './../core/base-layers.js';
class Borders_class extends Base_tools_class {
constructor(ctx) {
super();
this.Base_layers = new Base_layers_class();
this.ctx = ctx;
this.name = 'borders';
this.layer = {};
}
load() {
//nothing
}
render(ctx, layer) {
var params = layer.params;
var size = params.size;
var x = layer.x;
var y = layer.y;
var width = parseInt(layer.width);
var height = parseInt(layer.height);
//legcy check
if(x == null) x = 0;
if(y == null) y = 0;
if(!width) width = config.WIDTH;
if(!height) height = config.HEIGHT;
ctx.save();
//set styles
ctx.strokeStyle = layer.color;
ctx.lineWidth = size;
if (params.shadow === true) {
//with shadow
ctx.beginPath();
ctx.shadowColor = layer.color;
ctx.shadowBlur = size * config.ZOOM;
ctx.rect(x -size / 2, y -size / 2, width + size, height + size);
ctx.stroke();
ctx.stroke();
ctx.stroke();
}
else {
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.stroke();
}
ctx.restore();
}
}
;
export default Borders_class;