diff --git a/desktop/.gitignore b/desktop/.gitignore deleted file mode 100644 index d8b83df..0000000 --- a/desktop/.gitignore +++ /dev/null @@ -1 +0,0 @@ -package-lock.json diff --git a/desktop/sources/links/main.css b/desktop/sources/links/main.css index 47787f0..1257ec8 100644 --- a/desktop/sources/links/main.css +++ b/desktop/sources/links/main.css @@ -9,5 +9,5 @@ body { margin:0px; padding:0px; overflow:hidden; font-family:"input_mono_regular #ronin #wrapper #commander div#status { position: absolute; bottom: 0px; } #ronin #wrapper #commander.hidden { margin-left:-331px; } -#ronin canvas#surface,#ronin canvas#guide { position: absolute; right:0px; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,"); background-size: 10px 10px; background-position: -4px -4px; } +#ronin canvas#surface,#ronin canvas#guide { position: absolute; right:0px; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,"); background-size: 10px 10px; background-position: -4px -4px; width:100%; height:100%;} #ronin canvas#guide { background:none; } \ No newline at end of file diff --git a/desktop/sources/links/theme.css b/desktop/sources/links/theme.css index a1eb8c4..bd8b6b7 100644 --- a/desktop/sources/links/theme.css +++ b/desktop/sources/links/theme.css @@ -1,5 +1,5 @@ body { background:var(--background); } -#ronin #wrapper #commander { background:var(--background); } -#ronin #wrapper #commander { border-right-color: var(--f_low) } +#ronin #wrapper { background: var(--background); } +#ronin #wrapper #commander { background:var(--background);border-right-color: var(--f_low) } #ronin #wrapper #commander textarea { color:var(--f_high); } #ronin #wrapper #commander div#status { color:var(--f_med); } \ No newline at end of file diff --git a/desktop/sources/scripts/lib/controller.js b/desktop/sources/scripts/lib/controller.js index 6094222..52a3ee3 100644 --- a/desktop/sources/scripts/lib/controller.js +++ b/desktop/sources/scripts/lib/controller.js @@ -16,7 +16,9 @@ function Controller () { if (!this.menu[mode]) { this.menu[mode] = {} } if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } this.menu[mode][cat][label] = { fn: function (_menuItem, browserWindow) { - browserWindow.webContents.focus() + if (browserWindow) { + browserWindow.webContents.focus() + } fn.apply(this, arguments) }, accelerator: accelerator } diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js index 9e895ea..118a3c6 100644 --- a/desktop/sources/scripts/library.js +++ b/desktop/sources/scripts/library.js @@ -26,8 +26,9 @@ function Library (ronin) { return rect } - this.select = (rect = this.frame()) => { - return ronin.surface.select(rect) + this.resize = (rect) => { + ronin.surface.resize(rect, true) + return rect } this.exit = () => { @@ -136,6 +137,12 @@ function Library (ronin) { return { x, y, g, s, f, t } } + this.svg = (d, t = 'svg') => { + return { d, t } + } + + // Helpers + this.frame = () => { return ronin.surface.getFrame() } @@ -186,6 +193,32 @@ function Library (ronin) { return getComputedStyle(el).getPropertyValue(`--${variable}`) } + // Pixels + + this.pixels = (rect, fn, q) => { + const img = ronin.surface.context.getImageData(0, 0, rect.w, rect.h) + for (let i = 0, loop = img.data.length; i < loop; i += 4) { + const pixel = { r: img.data[i], g: img.data[i + 1], b: img.data[i + 2], a: img.data[i + 3] } + const processed = fn(pixel, q) + img.data[i] = processed[0] + img.data[i + 1] = processed[1] + img.data[i + 2] = processed[2] + img.data[i + 3] = processed[3] + } + ronin.surface.context.putImageData(img, 0, 0) + return rect + } + + this.saturation = (pixel, q = 1) => { + const color = 0.2126 * pixel.r + 0.7152 * pixel.g + 0.0722 * pixel.b + return [color, color, color, pixel.a] + } + + this.contrast = (pixel, q = 1) => { + const intercept = 128 * (1 - q) + return [pixel.r * q + intercept, pixel.g * q + intercept, pixel.b * q + intercept, pixel.a] + } + // Math this.add = (...args) => { diff --git a/desktop/sources/scripts/surface.js b/desktop/sources/scripts/surface.js index 73e7f53..dc9b72a 100644 --- a/desktop/sources/scripts/surface.js +++ b/desktop/sources/scripts/surface.js @@ -4,6 +4,8 @@ function Surface (ronin) { this._guide = document.createElement('canvas') this._guide.id = 'guide' this.ratio = window.devicePixelRatio + + // Contexts this.context = this.el.getContext('2d') this.guide = this.el.getContext('2d') @@ -14,6 +16,8 @@ function Surface (ronin) { this._guide.addEventListener('mousedown', ronin.commander.onMouseDown, false) this._guide.addEventListener('mousemove', ronin.commander.onMouseMove, false) this._guide.addEventListener('mouseup', ronin.commander.onMouseUp, false) + this.context.scale(this.ratio, this.ratio) + this.guide.scale(this.ratio, this.ratio) } this.start = function () { @@ -25,15 +29,6 @@ function Surface (ronin) { } - this.select = function (rect) { - const img = this.context.getImageData(rect.x, rect.y, rect.w, rect.h) - const pixels = [] - for (let i = 0, loop = img.data.length; i < loop; i += 4) { - pixels.push({ r: img.data[i], g: img.data[i + 1], b: img.data[i + 2], a: img.data[i + 3] }) - } - return pixels - } - // Shape this.stroke = (shape, width, color, context = this.context) => { @@ -44,6 +39,10 @@ function Surface (ronin) { if (shape.t === 'text') { context.font = `${shape.g}px ${shape.f}` context.strokeText(shape.s, shape.x, shape.y) + } else if (shape.t === 'svg') { + context.lineWidth = width + context.strokeStyle = color + context.stroke(new Path2D(shape.d)) } else { context.stroke() } @@ -59,6 +58,9 @@ function Surface (ronin) { if (shape.t === 'text') { context.font = `${shape.g}px ${shape.f}` context.fillText(shape.s, shape.x, shape.y) + } else if (shape.t === 'svg') { + context.fillStyle = color + context.fill(new Path2D(shape.d)) } else { context.fill() } @@ -76,6 +78,8 @@ function Surface (ronin) { this.traceCircle(shape, context) } else if (shape.t === 'text') { this.traceText(shape, context) + } else if (shape.t === 'svg') { + this.traceSVG(shape, context) } else { console.warn('Unknown type') } @@ -102,6 +106,10 @@ function Surface (ronin) { } + this.traceSVG = function (text, context) { + + } + // IO this.open = function (path, scale) { @@ -137,7 +145,7 @@ function Surface (ronin) { this.context.drawImage(this.el, a.x, a.y, a.w, a.h, b.x, b.y, b.w, b.h) } - this.resize = function (size) { + this.resize = function (size, fit = false) { this.el.width = size.w this.el.height = size.h this.el.style.width = size.w + 'px' @@ -146,6 +154,15 @@ function Surface (ronin) { this._guide.height = size.h this._guide.style.width = size.w + 'px' this._guide.style.height = size.h + 'px' + if (fit === true) { + this.fitWindow(size) + } + } + + this.fitWindow = function (size) { + const win = require('electron').remote.getCurrentWindow() + const pad = { w: 60, h: 60 } + win.setSize(size.w + pad.w, size.h + pad.h, false) } this.maximize = function () { diff --git a/examples/pixels.lisp b/examples/pixels.lisp index f599c38..e58fb38 100644 --- a/examples/pixels.lisp +++ b/examples/pixels.lisp @@ -1,10 +1,21 @@ ; pixels -((clear) +( + (clear) + + ; Filter + + (def filter-action + (lambda () (pixels + (rect 0 0 500 500) + saturation + 0.5) + )) ; Draw photo - (draw "../../PREVIEW.jpg" - (frame) - (lambda () (echo (select (rect 660 344 10 10)))) -)) \ No newline at end of file + (draw + "../../PREVIEW.jpg" + (frame) + filter-action) +) \ No newline at end of file diff --git a/examples/svg.lisp b/examples/svg.lisp new file mode 100644 index 0000000..2a81943 --- /dev/null +++ b/examples/svg.lisp @@ -0,0 +1,5 @@ +((fill + (svg "M255,60 L255,60 L135,180 L75,60 L195,210 L120,225 L105,225 L165,255 L225,195 L255,135 L285,150") "white") + +(stroke + (svg "M405,15 L405,15 L150,150 L195,90 L240,135 L120,195 L75,90 L135,165 L120,225 L90,240 L60,210 L90,150 L255,180 L285,180 L285,165 ") "pink")) \ No newline at end of file