git.y1.nz

fbui

Framebuffer-based graphical environment
download: https://git.y1.nz/archives/fbui.tar.gz
README | Files | Log | Refs

libfbui/WindowManager/rect.c

      1 
      2 /*=========================================================================
      3  *
      4  * fbwm, a window manager for FBUI (in-kernel framebuffer UI)
      5  * Copyright (C) 2004 Zachary T Smith, fbui@comcast.net
      6  *
      7  * This module is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 2 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This module is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this module; if not, write to the Free Software
     19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  *
     21  * (See the file COPYING in the main directory of this archive for
     22  * more details.)
     23  *
     24  *=======================================================================*/
     25 
     26 #include <stdio.h>
     27 #include <linux/fb.h>
     28 #include <libfbui.h>
     29 #include <jpeglib.h>
     30 
     31 extern int window_count;
     32 extern struct fbui_wininfo *info;
     33 
     34 JSAMPLE * image_buffer;
     35 int image_height;
     36 int image_width;
     37 int image_ncomponents;
     38 
     39 extern short win_w, win_h;
     40 
     41 char grayscale=0; /* 1 forces bg image to grayscale */
     42 
     43 
     44 
     45 
     46 /* -----------------Rectangle subtraction code----------------- */
     47 
     48 typedef struct rect {
     49 	short x0,y0,x1,y1;
     50 	struct rect *next;
     51 } Rect;
     52 
     53 static Rect* Rect_new(short x0, short y0, short x1, short y1)
     54 {
     55 	Rect *nu = (Rect*) malloc (sizeof(Rect));
     56 	if (!nu) return NULL;
     57 
     58 	nu->x0 = x0;
     59 	nu->y0 = y0;
     60 	nu->x1 = x1;
     61 	nu->y1 = y1;
     62 	nu->next = NULL;
     63 
     64 	return nu;
     65 }
     66 
     67 static void Rect_sort (Rect *r)
     68 {
     69 	if (!r) return;
     70 	if (r->x0 > r->x1) {
     71 		short tmp = r->x0;
     72 		r->x0 = r->x1;
     73 		r->x1 = tmp;
     74 	}
     75 	if (r->y0 > r->y1) {
     76 		short tmp = r->y0;
     77 		r->y0 = r->y1;
     78 		r->y1 = tmp;
     79 	}
     80 }
     81 
     82 static Rect* Rect_dup (Rect *r)
     83 {
     84 	if (!r) return NULL;
     85 	return Rect_new (r->x0,r->y0,r->x1,r->y1);
     86 }
     87 
     88 static int Rect_subtract (Rect *a, Rect *b, Rect *rects[])
     89 {
     90 	int count=0;
     91 	if (!a || !b || !rects) return;
     92 
     93 	if (a->x0==b->x0 && a->x1==b->x1 && a->y0==b->y0 && a->y1==b->y1)
     94 		return 0;
     95 
     96 	Rect_sort(a);
     97 	Rect_sort(b);
     98 
     99 #define between(N,M,O) (N>=M && N<=O)
    100 
    101 	int i=-1, j=-1;
    102 	if (b->x1 < a->x0)
    103 		i=0;
    104 	else if (b->x0 <= a->x0 && between(b->x1,a->x0,a->x1))
    105 		i=1;
    106 	else if (between(b->x0,a->x0,a->x1) && b->x1 >= a->x1)
    107 		i=3;
    108 	else if (between(b->x0,a->x0,a->x1) && between(b->x1,a->x0,a->x1))
    109 		i=2;
    110 	else
    111 		i=4;
    112 
    113 	if (b->y1 < a->y0)
    114 		j=0;
    115 	else if (b->y0 <= a->y0 && between(b->y1,a->y0,a->y1))
    116 		j=1;
    117 	else if (between(b->y0,a->y0,a->y1) && b->y1 >= a->y1)
    118 		j=3;
    119 	else if (between(b->y0,a->y0,a->y1) && between(b->y1,a->y0,a->y1))
    120 		j=2;
    121 	else
    122 		j=4;
    123 
    124 /*
    125                                           j values
    126                                                  +-------+
    127                                                  |   0   |
    128                                                  +-------+
    129                                       +-------+
    130                   +--------------+    |       |
    131                   |              |    |   1   |  +-------+
    132                   |              |    |       |  |       |
    133                   |      a       |    +-------+  |   2   |
    134                   |              |               |       |
    135                   |              |               +-------+
    136                   |              |    +-------+
    137                   +--------------+    |   3   |
    138                                       +-------+  +-------+
    139    i values:                                     |   4   |
    140       +-------+      +--------+     +-------+    +-------+
    141       |   0   |      |    2   |     |   4   |
    142       +-------+      +--------+     +-------+
    143             +---------+     +--------+
    144             |    1    |     |    3   |
    145             +---------+     +--------+
    146  */
    147 	// totally outside
    148 	if (i==0 || i==4 || j==0 || j==4) {
    149 		rects[count++] = Rect_dup(a);
    150 		return count;
    151 	}
    152 	else
    153 	// totally inside
    154 	if (i==2 && j==2) {
    155 		if (a->x0 != b->x0)
    156 		 rects[count++] = Rect_new (a->x0,a->y0,b->x0-1,a->y1); //left
    157 		if (a->y0 != b->y0)
    158 		 rects[count++]  = Rect_new (b->x0,a->y0,b->x1,b->y0-1); //top
    159 		if (a->y1 != b->y1)
    160 		 rects[count++]  = Rect_new (b->x0,b->y1+1,b->x1,a->y1); //bottom
    161 		if (a->x1 != b->x1)
    162 		 rects[count++]  = Rect_new (b->x0+1,a->y0,a->x1,a->y1); //right
    163 		return count;
    164 	}
    165 	else
    166 	if (i==1 && j==2) {
    167 		if (a->y0 != b->y0)
    168 		 rects[count++] = Rect_new (a->x0,a->y0,b->x1,b->y0-1); // topleft
    169 		if (a->y1 != b->y1)
    170 		 rects[count++] = Rect_new (a->x0,b->y1+1,b->x1,a->y1); // bottomleft
    171 		if (a->x1 != b->x1)
    172 		 rects[count++] = Rect_new (b->x1+1,a->y0,a->x1,a->y1); // right
    173 		return count;
    174 	}
    175 	else
    176 	if (i==3 && j==2) {
    177 		if (a->y0 != b->y0)
    178 		 rects[count++] = Rect_new (a->x0,a->y0,a->x1,b->y0-1); // top
    179 		if (a->x0 != b->x0)
    180 		 rects[count++] = Rect_new (a->x0,b->y0,b->x0-1,b->y1); // middle
    181 		if (a->y1 != b->y1)
    182 		 rects[count++] = Rect_new (a->x0,b->y1+1,a->x1,a->y1); // bottom
    183 		return count;
    184 	}
    185 	else
    186 	if (i==2 && j==1) {
    187 		if (a->x0 != b->x0)
    188 		 rects[count++] = Rect_new (a->x0,a->y0,b->x0-1,b->y1); // topleft
    189 		if (a->x1 != b->x1)
    190  		 rects[count++] = Rect_new (b->x1+1,a->y0,a->x1,b->y1); // topright
    191 		if (a->y1 != b->y1)
    192 		 rects[count++] = Rect_new (a->x0,b->y1+1,a->x1,a->y1); //bottom
    193 		return count;
    194 	}
    195 	else
    196 	if (i==2 && j==3) {
    197 		if (a->y0 != b->y0)
    198 		 rects[count++] = Rect_new (a->x0,a->y0,a->x1,b->y0-1); // top
    199 		if (a->x0 != b->x0)
    200 		 rects[count++] = Rect_new (a->x0,b->y0,b->x0-1,a->y1); // bottomleft
    201 		if (a->x1 != b->x1)
    202 		 rects[count++] = Rect_new (b->x1+1,b->y0,a->x1,a->y1); // bottomright
    203 		return count;
    204 	}
    205 	else
    206 	if (i==3 && j==1) {
    207 		if (a->x0 != b->x0)
    208 		 rects[count++] = Rect_new (a->x0,a->y0,b->x0-1,a->y1); // left
    209 		if (a->y1 > b->y1)
    210 		 rects[count++] = Rect_new (b->x0,b->y1+1,a->x1,a->y1); // bottomright
    211 		return count;
    212 	}
    213 	else
    214 	if (i==3 && j==3) {
    215 		if (a->x0 != b->x0)
    216 		 rects[count++]  = Rect_new (a->x0,a->y0,b->x0-1,a->y1); // left
    217 		if (a->y0 < b->y0)
    218 		 rects[count++]  = Rect_new (b->x0,a->y0,a->x1,b->y0-1); //topright
    219 		return count;
    220 	}
    221 	else
    222 	if (i==1 && j==1) {
    223 		if (a->x1 != b->x1)
    224 		 rects[count++] = Rect_new (b->x1+1,a->y0,a->x1,a->y1); // right
    225 		if (a->y1 != b->y1)
    226 		 rects[count++] = Rect_new (a->x0,b->y1+1,b->x1,a->y1); // bottomleft
    227 		return count;
    228 	}
    229 	else
    230 	if (i==1 && j==3) {
    231 		if (a->x1 != b->x1)
    232 		 rects[count++] = Rect_new (b->x1+1,a->y0,a->x1,a->y1); // right
    233 		if (a->y0 < b->y0) 
    234 		 rects[count++] = Rect_new (a->x0,a->y0,b->x1,b->y0-1); // topleft
    235 		return count;
    236 	}
    237 	else
    238 		printf ("combo %d %d\n",i,j);
    239 }
    240 
    241 static void Rect_delete(Rect *r)
    242 {
    243 	if (r)
    244 		free((void*)r);
    245 }
    246 
    247 
    248 /* Draws a portion of the background
    249  * If an image has been loaded, it draws that.
    250  * Otherwise, a green gradient.
    251  */
    252 void
    253 draw_image (Display *dpy, Window *win, short x0, short y0, short x1, short y1)
    254 {
    255 	int i,j;
    256 	if (x0 > x1) {
    257 		short tmp=x0;x0=x1;x1=tmp;
    258 	}
    259 	if (y0 > y1) {
    260 		short tmp=y0;y0=y1;y1=tmp;
    261 	}
    262 	if (x1<0) return;
    263 	if (y1<0) return;
    264 	if (x0<0) x0=0;
    265 	if (y0<0) y0=0;
    266 
    267 	/* If we have no background image, don't sweat it, just draw
    268 	 * a gradient
    269 	 */
    270 	if (!image_buffer) {
    271 		for (i=x0; i<=x1; i++) {
    272 			unsigned long k = (191 * i) / win_w;
    273 			unsigned long color = (35 + k) + (90 << 8); 
    274 			fbui_draw_vline (dpy, win, i,y0,y1, color);
    275 		}
    276 		fbui_flush (dpy, win);
    277 		return;
    278 	}
    279 
    280 	if (x0>=image_width) return;
    281 	if (y0>=image_height) return;
    282 	if (x1>=image_width) x1=image_width-1;
    283 	if (y1>=image_height) y1=image_height-1;
    284 	
    285 	for (j=y0; j<=y1; j++) {
    286 		if (image_ncomponents == 1 || grayscale) {
    287 			for(i=x0; i<x1; i++) {
    288 				unsigned long pix=0;
    289 				unsigned char *p = image_buffer +
    290 					image_ncomponents*(i + j*image_width);
    291 
    292 				/* pixels are grayscale */
    293 				if (image_ncomponents == 1) {
    294 					pix = *p;
    295 					pix <<= 8;
    296 					pix |= *p;
    297 					pix <<= 8;
    298 					pix |= *p;
    299 				} else {
    300 					pix = *p++;
    301 					pix += *p++;
    302 					pix += *p;
    303 					pix /= 3;
    304 					pix |= (pix<<8) | (pix<<16);
    305 				}
    306 
    307 				fbui_draw_point (dpy, win, i, j, pix);
    308 			}
    309 		}
    310 		else
    311 		{
    312 			fbui_put_rgb3 (dpy, win, x0, j, x1-x0+1,
    313 				image_buffer + 3*(j*image_width+x0));
    314 		}
    315 	}
    316 
    317 	fbui_flush(dpy,win);
    318 }
    319 
    320 
    321 void
    322 draw_background (Display *dpy, Window *win, struct fbui_wininfo *info, int window_count)
    323 {
    324 	Rect *list1 = Rect_new (0,0,win_w-1,win_h-1);
    325 	Rect *list2 = NULL;
    326 	Rect *ptr;
    327 	int mypid = getpid();
    328 	int i;
    329 
    330 	for (i=0; i<window_count; i++) {
    331 		Rect *r0,*r1,*r2,*r3;
    332 		struct fbui_wininfo *wi = &info[i];
    333 		Rect *windowrect = Rect_new(wi->x,wi->y,
    334 			wi->x+wi->width-1,wi->y+wi->height-1);
    335 //printf ("subtracting %s\n", wi->name);
    336 		if (wi->pid != mypid) {
    337 			ptr = list1;
    338 			while(ptr) {
    339 				Rect *rects[4];
    340 				int count = Rect_subtract (ptr,windowrect,rects);
    341 				int j=0;
    342 				while (j < count) {
    343 					rects[j]->next = list2; 
    344 					list2 = rects[j];
    345 					j++;
    346 				}
    347 				ptr = ptr->next;
    348 			}
    349 			ptr = list1;
    350 			Rect *next;
    351 			while (ptr) {
    352 				next = ptr->next;
    353 				Rect_delete(ptr);
    354 				ptr=next;
    355 			}
    356 			list1 = list2;
    357 			list2 = NULL;
    358 
    359 #if 0
    360 int k=0;
    361 Rect *n = list1;
    362 while(n) { k++; 
    363 printf ("   rect: %d %d - %d %d\n", n->x0,n->y0,n->x1,n->y1);
    364 n=n->next; 
    365 }
    366 printf ("result list now has %d rectangles\n", k);
    367 #endif
    368 		}
    369 
    370 		Rect_delete (windowrect);
    371 	}
    372 
    373 	/* draw the background */
    374 	ptr=list1;
    375 	while(ptr) {
    376 		draw_image (dpy,win, ptr->x0,ptr->y0,ptr->x1,ptr->y1);
    377 		ptr=ptr->next;
    378 	}
    379 	fbui_flush (dpy, win);
    380 
    381 	/* remove the rectangle list */
    382 	ptr = list1;
    383 	while (ptr) {
    384 		Rect *next = ptr->next;
    385 		Rect_delete(ptr);
    386 		ptr=next;
    387 	}
    388 }
    389 

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.