shithub: blie

Download patch

ref: 2f61e9979e69ab014cdd44ea71fa787ea3454446
parent: f8d65f9f1c74b101cccfdc08250e31c5e554b899
author: sirjofri <sirjofri@sirjofri.de>
date: Mon Aug 26 09:25:10 EDT 2024

transparent background, filter layer/editor

diff: cannot open b/test/img/l/filter//null: file does not exist: 'b/test/img/l/filter//null'
--- a/blie.c
+++ b/blie.c
@@ -46,6 +46,20 @@
 	vdata.fontheight = p.y;
 	
 	vdata.gray = allocimagemix(display, DBlack, DWhite);
+	vdata.mgray = allocmemimage(Rect(0, 0, 1, 1), GREY8);
+	memfillcolor(vdata.mgray, 0xaaaaaaff);
+	vdata.mgray->flags |= Frepl|Fbytes|Fsimple;
+	
+	vdata.transparent = allocimage(display, Rect(0, 0, 50, 50), RGB24, 1, 0xccccccff);
+	draw(vdata.transparent, Rect(0, 25, 25, 50), vdata.gray, nil, ZP);
+	draw(vdata.transparent, Rect(25, 0, 50, 25), vdata.gray, nil, ZP);
+	
+	vdata.mtransparent = allocmemimage(Rect(0, 0, 50, 50), RGB24);
+	vdata.mtransparent->flags |= Frepl|Fbytes;
+	memfillcolor(vdata.mtransparent, 0xccccccff);
+	vdata.mgray->clipr = vdata.mtransparent->r;
+	memimagedraw(vdata.mtransparent, Rect(0, 25, 25, 50), vdata.mgray, ZP, nil, ZP, S);
+	memimagedraw(vdata.mtransparent, Rect(25, 0, 50, 25), vdata.mgray, ZP, nil, ZP, S);
 }
 
 Vstate vstate = {
@@ -197,6 +211,8 @@
 {
 	Memimage *img[2]; /* swapchain */
 	int i;
+	
+	draw(panels.drawing, panels.drawing->r, vdata.transparent, nil, ZP);
 	
 	if (estate.ed && estate.ed->overlay) {
 		if (estate.ed->overlay(estate.l, nil)) {
--- a/blie.h
+++ b/blie.h
@@ -39,7 +39,10 @@
 	int keyoffset; /* offset on key input */
 	float keyzoom; /* zoom change */
 	
+	Image *transparent;
 	Image *gray;
+	Memimage *mgray;
+	Memimage *mtransparent;
 };
 
 enum {
@@ -89,6 +92,7 @@
 };
 
 extern Editor p9image;
+extern Editor efilter;
 
 void loadeditors(void);
 int addeditor(Editor*);
@@ -100,6 +104,10 @@
 Memimage* ecomposite(Layer*, Memimage*);
 
 Point scalepos(Point);
+uchar rgb2k(uchar r, uchar g, uchar b);
+uchar ilerp(uchar A, uchar B, uchar α);
+double flerp(double A, double B, double α);
+uchar imul(uchar A, uchar B);
 
 Memimage* gencomposite(Memimage*, Memimage*, Memimage*, Drawop);
 Memimage* gencanvas(Memimage*);
--- a/editor.c
+++ b/editor.c
@@ -9,6 +9,7 @@
 loadeditors(void)
 {
 	addeditor(&p9image);
+	addeditor(&efilter);
 }
 
 typedef struct Leditor Leditor;
--- a/editor.txt
+++ b/editor.txt
@@ -1,5 +1,10 @@
 Editor functions and properties (blie.h:/^struct Editor)
 
+to add new editor:
+- add struct declaration to blie.h (blie.h:/^extern Editor)
+- add editor in loadeditors (editor.c:/^loadeditors)
+- see: p9image.c
+
 PROPERTY name
 
 short name of the editor. Works as an identifier, must be unique!
--- a/mkfile
+++ b/mkfile
@@ -11,6 +11,7 @@
 	db.$O\
 	util.$O\
 	p9image.$O\
+	efilter.$O\
 
 HFILES=blie.h
 
--- a/p9image.c
+++ b/p9image.c
@@ -127,6 +127,14 @@
 	memfillcolor(tstate.colorbrush, color);
 }
 
+static ulong
+getcurrentcolorval(void)
+{
+	if (tstate.curcolor < 0 || tstate.curcolor >= NUMCELLS)
+		return DTransparent;
+	return tstate.colordata[tstate.curcolor];
+}
+
 static Memimage*
 getcurrentcolor(void)
 {
@@ -351,9 +359,14 @@
 	double m;
 	uchar *p;
 	
+	if (d->imask) {
+		freememimage(d->imask);
+		d->imask = nil;
+	}
+	
 	if (d->maskdata->value == 255) {
 		d->imask = allocmemimage(d->img->r, GREY8);
-		memfillcolor(d->imask, 0);
+		memfillcolor(d->imask, DBlack);
 		memimagedraw(d->imask, d->imask->r, memwhite, ZP, d->img, ZP, SoverD);
 		return;
 	}
@@ -362,7 +375,7 @@
 	dx = Dx(d->img->r);
 	dy = Dy(d->img->r);
 	d->imask = allocmemimage(d->img->r, GREY8);
-	memfillcolor(d->imask, 0);
+	memfillcolor(d->imask, DBlack);
 	memimagedraw(d->imask, d->imask->r, memwhite, ZP, d->img, ZP, SoverD);
 	
 	for (y = 0; y < dy; y++) {
@@ -606,9 +619,55 @@
 }
 
 static Redrawwin
+drawalphabrush(Layer *l, Data *d, Brush *brush, ulong color, Rectangle r)
+{
+	int x, y;
+	uchar *f, *t;
+	uchar *col;
+	uchar alpha, a;
+	
+	col = (uchar*)&color;
+	alpha = rgb2k(col[0], col[1], col[2]);
+	
+	if (r.max.y > d->img->r.max.y)
+		r.max.y = d->img->r.max.y;
+	if (r.max.x > d->img->r.max.x)
+		r.max.x = d->img->r.max.x;
+	
+	for (y = r.min.y; y < r.max.y; y++) {
+		for (x = r.min.x; x < r.max.x; x++) {
+			if (x < d->img->r.min.x)
+				continue;
+			if (y < d->img->r.min.y)
+				continue;
+			t = byteaddr(d->img, Pt(x, y));
+			f = byteaddr(brush->i, Pt(x-r.min.x, y-r.min.y));
+			a = 0;
+			switch (brush->i->chan) {
+			case GREY8:
+				a = f[0];
+				break;
+			case RGB24:
+				a = rgb2k(f[3], f[2], f[1]);
+				break;
+			case RGBA32:
+				a = f[0];
+				break;
+			}
+			t[0] = ilerp(t[0], alpha, a);
+			t[1] = imul(t[0], t[1]);
+			t[2] = imul(t[0], t[2]);
+			t[3] = imul(t[0], t[3]);
+		}
+	}
+	updateimask(d);
+	dirtylayer(l);
+	return Rdrawing;
+}
+
+static Redrawwin
 drawbrush(Layer *l, int buttons, Point xy)
 {
-	Memimage *tgt;
 	Data *d;
 	Rectangle r;
 	Brush *brush;
@@ -625,28 +684,28 @@
 	if (!(brush && brush->i && color))
 		return Rnil;
 	
-	tgt = nil;
-	if (tstate.drawtarget == DTimg)
-		tgt = d->img;
-	else if (tstate.drawtarget == DTmask)
-		tgt = d->mask;
-	
-	if (!tgt)
-		return Rnil;
-	
-	r = insetrect(tgt->r, -brush->r);
+	r = insetrect(d->img->r, -brush->r);
 	if (!ptinrect(xy, r))
 		return Rnil;
 	
 	r = rectaddpt(brush->i->r,
 		subpt(
-			addpt(tgt->r.min, xy),
+			addpt(d->img->r.min, xy),
 			Pt(brush->r, brush->r)
 		)
 	);
 	
 	color->clipr = brush->i->r;
-	memimagedraw(tgt, r, color, ZP, brush->i, ZP, SoverD);
+
+	if (tstate.drawtarget == DTimg)
+		goto Imgdraw;
+	if (tstate.drawtarget == DTmask)
+		return drawalphabrush(l, d, brush, getcurrentcolorval(), r);
+	
+	return Rnil;
+	
+Imgdraw:
+	memimagedraw(d->img, r, color, ZP, brush->i, ZP, SoverD);
 	updateimask(d);
 	setdrawingdirty(Dcontent);
 	dirtylayer(l);
--- a/sample.c
+++ b/sample.c
@@ -229,11 +229,12 @@
 		src = lastsampled;
 	
 	tmi = allocmemimage(r, img->chan);
-	memfillcolor(tmi, DBlack);
-	memimagedraw(tmi, tmi->r, src, addpt(tmi->r.min, vstate.offset), nil, ZP, S);
+	vdata.mtransparent->clipr = tmi->r;
+	memimagedraw(tmi, tmi->r, vdata.mtransparent, ZP, nil, ZP, S);
+	memimagedraw(tmi, tmi->r, src, addpt(tmi->r.min, vstate.offset), nil, ZP, SoverD);
 	
 	nw = tmi->width * tmi->r.max.y * sizeof(ulong); // tmi->r.max.y == Dy(tmi->r)
-	draw(img, img->r, display->black, nil, ZP);
+	draw(img, img->r, vdata.transparent, nil, ZP);
 	loadimage(img, img->r, tmi->data->bdata, nw);
 	
 	freememimage(tmi);
--- /dev/null
+++ b/test/img/l/filter/meta
@@ -1,0 +1,3 @@
+filter
+Filter
+SoverD
--- /dev/null
+++ b/test/img/l/filter/params
@@ -1,0 +1,1 @@
+params width=20
--- /dev/null
+++ b/test/img/l/filter/script
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+crop -i $width | crop -i -$width -b 255 0 255
binary files a/test/img/l/layerA/img b/test/img/l/layerA/img differ
binary files a/test/img/l/layerA/mask /dev/null differ
binary files a/test/img/l/layerB/img b/test/img/l/layerB/img differ
--- a/test/img/layers
+++ b/test/img/layers
@@ -1,2 +1,3 @@
 layerA
 layerB
+filter
--- a/util.c
+++ b/util.c
@@ -6,6 +6,32 @@
 #include <keyboard.h>
 #include "blie.h"
 
+#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
+
+uchar
+rgb2k(uchar r, uchar g, uchar b)
+{
+	return RGB2K(r, g, b);
+}
+
+uchar
+ilerp(uchar A, uchar B, uchar α)
+{
+	return flerp((double)A / 255., (double)B / 255., (double)α / 255.) * 255;
+}
+
+uchar
+imul(uchar A, uchar B)
+{
+	return (((double)A * (double)B) / (255. * 255.)) * 255;
+}
+
+double
+flerp(double A, double B, double α)
+{
+	return (B * α) + (1.-α) * A;
+}
+
 Memimage*
 dupmemimage(Memimage *i)
 {
@@ -19,7 +45,9 @@
 Memimage*
 gencanvas(Memimage *i)
 {
-	return allocmemimage(i->r, RGBA32);
+	i = allocmemimage(i->r, RGBA32);
+	memfillcolor(i, DTransparent);
+	return i;
 }
 
 Memimage*
--- a/words
+++ b/words
@@ -118,3 +118,13 @@
 - left click to select
 - right click to configure
 - middle mouse to preview brush (not implemented yet)
+
+
+EDITOR filter
+
+Currently only files:
+
+- script: executable script file (or binary) to be executed
+- params: database file with parameters
+
+parameters are injected as environment variables