ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/background.C
(Generate patch)

Comparing rxvt-unicode/src/background.C (file contents):
Revision 1.205 by sf-exg, Wed Apr 11 10:06:45 2012 UTC vs.
Revision 1.212 by sf-exg, Sun May 13 15:50:18 2012 UTC

3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * 4 *
5 * All portions of code are copyright by their respective author/s. 5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2005-2008 Marc Lehmann <schmorp@schmorp.de> 6 * Copyright (c) 2005-2008 Marc Lehmann <schmorp@schmorp.de>
7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net> 7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net>
8 * Copyright (c) 2010 Emanuele Giaquinta <e.giaquinta@glauco.it> 8 * Copyright (c) 2010-2012 Emanuele Giaquinta <e.giaquinta@glauco.it>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. 13 * (at your option) any later version.
123 123
124# ifdef BG_IMAGE_FROM_FILE 124# ifdef BG_IMAGE_FROM_FILE
125static inline int 125static inline int
126make_align_position (int align, int window_size, int image_size) 126make_align_position (int align, int window_size, int image_size)
127{ 127{
128 int diff = window_size - image_size;
129 int smaller = min (image_size, window_size);
130
131 if (align >= 0 && align <= 100) 128 if (align >= 0 && align <= 100)
132 return diff * align / 100; 129 return lerp (0, window_size - image_size, align);
133 else if (align > 100) 130 else if (align > 100)
134 return (align - 100) * smaller / 100 + window_size - smaller; 131 return lerp (window_size - image_size, window_size, align - 100);
135 else 132 else
136 return (align + 100) * smaller / 100 - image_size; 133 return lerp (-image_size, 0, align + 100);
137} 134}
138 135
139static inline int 136static inline int
140make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size) 137make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size)
141{ 138{
349rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc, 346rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc,
350 int src_x, int src_y, int dst_x, int dst_y, 347 int src_x, int src_y, int dst_x, int dst_y,
351 unsigned int width, unsigned int height) 348 unsigned int width, unsigned int height)
352{ 349{
353 XImage *ximage; 350 XImage *ximage;
354 char *data, *line; 351 char *line;
355 int bytes_per_pixel;
356 int width_r, width_g, width_b; 352 int width_r, width_g, width_b, width_a;
357 int sh_r, sh_g, sh_b; 353 int sh_r, sh_g, sh_b, sh_a;
354 uint32_t alpha_mask;
358 int rowstride; 355 int rowstride;
359 int channels; 356 int channels;
360 unsigned char *row; 357 unsigned char *row;
361 358
362 if (visual->c_class != TrueColor) 359 if (visual->c_class != TrueColor)
363 return false; 360 return false;
364 361
365 if (depth == 24 || depth == 32) 362#if XRENDER
366 bytes_per_pixel = 4; 363 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
367 else if (depth == 15 || depth == 16) 364 if (format)
368 bytes_per_pixel = 2; 365 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha;
369 else 366 else
370 return false; 367#endif
368 alpha_mask = 0;
371 369
372 width_r = ecb_popcount32 (visual->red_mask); 370 width_r = ecb_popcount32 (visual->red_mask);
373 width_g = ecb_popcount32 (visual->green_mask); 371 width_g = ecb_popcount32 (visual->green_mask);
374 width_b = ecb_popcount32 (visual->blue_mask); 372 width_b = ecb_popcount32 (visual->blue_mask);
373 width_a = ecb_popcount32 (alpha_mask);
375 374
376 if (width_r > 8 || width_g > 8 || width_b > 8) 375 if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
377 return false; 376 return false;
378 377
379 sh_r = ecb_ctz32 (visual->red_mask); 378 sh_r = ecb_ctz32 (visual->red_mask);
380 sh_g = ecb_ctz32 (visual->green_mask); 379 sh_g = ecb_ctz32 (visual->green_mask);
381 sh_b = ecb_ctz32 (visual->blue_mask); 380 sh_b = ecb_ctz32 (visual->blue_mask);
381 sh_a = ecb_ctz32 (alpha_mask);
382 382
383 if (width > INT_MAX / height / bytes_per_pixel) 383 if (width > 32767 || height > 32767)
384 return false; 384 return false;
385 385
386 data = (char *)malloc (width * height * bytes_per_pixel); 386 ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, 0,
387 if (!data) 387 width, height, 32, 0);
388 if (!ximage)
388 return false; 389 return false;
389 390
390 ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, data, 391 if (height > INT_MAX / ximage->bytes_per_line
391 width, height, bytes_per_pixel * 8, 0); 392 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line)))
392 if (!ximage)
393 { 393 {
394 free (data); 394 XDestroyImage (ximage);
395 return false; 395 return false;
396 } 396 }
397 397
398 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 398 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
399 399
400 rowstride = gdk_pixbuf_get_rowstride (pixbuf); 400 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
401 channels = gdk_pixbuf_get_n_channels (pixbuf); 401 channels = gdk_pixbuf_get_n_channels (pixbuf);
402 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; 402 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
403 line = data; 403 line = ximage->data;
404
405 rgba c (0, 0, 0);
406
407 if (channels == 4 && alpha_mask == 0)
408 {
409 pix_colors[Color_bg].get (c);
410 c.r >>= 8;
411 c.g >>= 8;
412 c.b >>= 8;
413 }
404 414
405 for (int y = 0; y < height; y++) 415 for (int y = 0; y < height; y++)
406 { 416 {
407 for (int x = 0; x < width; x++) 417 for (int x = 0; x < width; x++)
408 { 418 {
409 unsigned char *pixel = row + x * channels; 419 unsigned char *pixel = row + x * channels;
410 uint32_t value; 420 uint32_t value;
421 unsigned char r, g, b, a;
411 422
423 if (channels == 4)
424 {
425 a = pixel[3];
426 r = (pixel[0] * a + c.r * (0xff - a)) / 0xff;
427 g = (pixel[1] * a + c.g * (0xff - a)) / 0xff;
428 b = (pixel[2] * a + c.b * (0xff - a)) / 0xff;
429 }
430 else
431 {
432 a = 0xff;
433 r = pixel[0];
434 g = pixel[1];
435 b = pixel[2];
436 }
437
412 value = ((pixel[0] >> (8 - width_r)) << sh_r) 438 value = ((r >> (8 - width_r)) << sh_r)
413 | ((pixel[1] >> (8 - width_g)) << sh_g) 439 | ((g >> (8 - width_g)) << sh_g)
414 | ((pixel[2] >> (8 - width_b)) << sh_b); 440 | ((b >> (8 - width_b)) << sh_b)
441 | ((a >> (8 - width_a)) << sh_a);
415 442
416 if (bytes_per_pixel == 4) 443 if (ximage->bits_per_pixel == 32)
417 ((uint32_t *)line)[x] = value; 444 ((uint32_t *)line)[x] = value;
418 else 445 else
419 ((uint16_t *)line)[x] = value; 446 XPutPixel (ximage, x, y, value);
420 } 447 }
421 448
422 row += rowstride; 449 row += rowstride;
423 line += ximage->bytes_per_line; 450 line += ximage->bytes_per_line;
424 } 451 }
636 663
637# endif /* BG_IMAGE_FROM_FILE */ 664# endif /* BG_IMAGE_FROM_FILE */
638 665
639# ifdef ENABLE_TRANSPARENCY 666# ifdef ENABLE_TRANSPARENCY
640bool 667bool
641rxvt_term::bg_set_transparent ()
642{
643 if (!(bg_flags & BG_IS_TRANSPARENT))
644 {
645 bg_flags |= BG_IS_TRANSPARENT;
646 return true;
647 }
648
649 return false;
650}
651
652bool
653rxvt_term::bg_set_blur (const char *geom) 668rxvt_term::bg_set_blur (const char *geom)
654{ 669{
655 bool changed = false; 670 bool changed = false;
656 unsigned int hr, vr; 671 unsigned int hr, vr;
657 int junk; 672 int junk;
675 { 690 {
676 changed = true; 691 changed = true;
677 v_blurRadius = vr; 692 v_blurRadius = vr;
678 } 693 }
679 694
680 if (h_blurRadius && v_blurRadius)
681 bg_flags |= BG_NEEDS_BLUR;
682 else
683 bg_flags &= ~BG_NEEDS_BLUR;
684
685 return changed; 695 return changed;
686}
687
688void
689rxvt_term::set_tint_shade_flags ()
690{
691 if (shade != 100 || (bg_flags & BG_TINT_SET))
692 bg_flags |= BG_NEEDS_TINT;
693 else
694 bg_flags &= ~BG_NEEDS_TINT;
695} 696}
696 697
697bool 698bool
698rxvt_term::bg_set_tint (rxvt_color &new_tint) 699rxvt_term::bg_set_tint (rxvt_color &new_tint)
699{ 700{
709 && (c.b <= 0x00ff || c.b >= 0xff00)) 710 && (c.b <= 0x00ff || c.b >= 0xff00))
710 bg_flags |= BG_TINT_BITAND; 711 bg_flags |= BG_TINT_BITAND;
711 else 712 else
712 bg_flags &= ~BG_TINT_BITAND; 713 bg_flags &= ~BG_TINT_BITAND;
713 714
714 set_tint_shade_flags ();
715 return true; 715 return true;
716 } 716 }
717 717
718 return false; 718 return false;
719} 719}
728 new_shade = 200 - (100 + new_shade); 728 new_shade = 200 - (100 + new_shade);
729 729
730 if (new_shade != shade) 730 if (new_shade != shade)
731 { 731 {
732 shade = new_shade; 732 shade = new_shade;
733 set_tint_shade_flags ();
734 return true; 733 return true;
735 } 734 }
736 735
737 return false; 736 return false;
738} 737}
1014 1013
1015 if (gc) 1014 if (gc)
1016 { 1015 {
1017 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1016 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1018 ret = true; 1017 ret = true;
1019 unsigned long tr_flags = bg_flags & BG_EFFECTS_FLAGS; 1018 bool need_blur = h_blurRadius && v_blurRadius;
1019 bool need_tint = shade != 100 || (bg_flags & BG_TINT_SET);
1020 1020
1021 if (!(bg_flags & BG_CLIENT_RENDER)) 1021 if (!(bg_flags & BG_CLIENT_RENDER))
1022 { 1022 {
1023 if (bg_flags & BG_NEEDS_BLUR) 1023 if (need_blur)
1024 { 1024 {
1025 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth)) 1025 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth))
1026 tr_flags &= ~BG_NEEDS_BLUR; 1026 need_blur = false;
1027 } 1027 }
1028 if (bg_flags & BG_NEEDS_TINT) 1028 if (need_tint)
1029 { 1029 {
1030 if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) 1030 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1031 tr_flags &= ~BG_NEEDS_TINT; 1031 need_tint = false;
1032 } 1032 }
1033 if (tr_flags & BG_NEEDS_TINT) 1033 if (need_tint)
1034 { 1034 {
1035 XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap); 1035 XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1036 if (ximage) 1036 if (ximage)
1037 { 1037 {
1038 /* our own client-side tinting */ 1038 /* our own client-side tinting */
1147} 1147}
1148 1148
1149void 1149void
1150rxvt_term::tint_ximage (Visual *visual, XImage *ximage) 1150rxvt_term::tint_ximage (Visual *visual, XImage *ximage)
1151{ 1151{
1152 unsigned int size_r, size_g, size_b;
1152 int sh_r, sh_g, sh_b; 1153 int sh_r, sh_g, sh_b;
1153 uint32_t mask_r, mask_g, mask_b; 1154 uint32_t mask_r, mask_g, mask_b;
1154 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1155 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1155 unsigned short low; 1156 unsigned short low;
1156 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 1157 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1161 mask_r = visual->red_mask; 1162 mask_r = visual->red_mask;
1162 mask_g = visual->green_mask; 1163 mask_g = visual->green_mask;
1163 mask_b = visual->blue_mask; 1164 mask_b = visual->blue_mask;
1164 1165
1165 /* boring lookup table pre-initialization */ 1166 /* boring lookup table pre-initialization */
1166 switch (ximage->depth) 1167 sh_r = ecb_ctz32 (mask_r);
1167 { 1168 sh_g = ecb_ctz32 (mask_g);
1168 case 15: 1169 sh_b = ecb_ctz32 (mask_b);
1169 if ((mask_r != 0x7c00) || 1170
1170 (mask_g != 0x03e0) || 1171 size_r = mask_r >> sh_r;
1171 (mask_b != 0x001f)) 1172 size_g = mask_g >> sh_g;
1173 size_b = mask_b >> sh_b;
1174
1175 if (size_r++ > 255 || size_g++ > 255 || size_b++ > 255)
1172 return; 1176 return;
1173 lookup = (uint32_t *) malloc (sizeof (uint32_t)*(32+32+32)); 1177
1178 lookup = (uint32_t *)malloc (sizeof (uint32_t) * (size_r + size_g + size_b));
1174 lookup_r = lookup; 1179 lookup_r = lookup;
1175 lookup_g = lookup+32; 1180 lookup_g = lookup + size_r;
1176 lookup_b = lookup+32+32; 1181 lookup_b = lookup + size_r + size_g;
1177 sh_r = 10;
1178 sh_g = 5;
1179 sh_b = 0;
1180 break;
1181 case 16:
1182 if ((mask_r != 0xf800) ||
1183 (mask_g != 0x07e0) ||
1184 (mask_b != 0x001f))
1185 return;
1186 lookup = (uint32_t *) malloc (sizeof (uint32_t)*(32+64+32));
1187 lookup_r = lookup;
1188 lookup_g = lookup+32;
1189 lookup_b = lookup+32+64;
1190 sh_r = 11;
1191 sh_g = 5;
1192 sh_b = 0;
1193 break;
1194 case 24:
1195 if ((mask_r != 0xff0000) ||
1196 (mask_g != 0x00ff00) ||
1197 (mask_b != 0x0000ff))
1198 return;
1199 lookup = (uint32_t *) malloc (sizeof (uint32_t)*(256+256+256));
1200 lookup_r = lookup;
1201 lookup_g = lookup+256;
1202 lookup_b = lookup+256+256;
1203 sh_r = 16;
1204 sh_g = 8;
1205 sh_b = 0;
1206 break;
1207 case 32:
1208 if ((mask_r != 0xff0000) ||
1209 (mask_g != 0x00ff00) ||
1210 (mask_b != 0x0000ff))
1211 return;
1212 lookup = (uint32_t *) malloc (sizeof (uint32_t)*(256+256+256));
1213 lookup_r = lookup;
1214 lookup_g = lookup+256;
1215 lookup_b = lookup+256+256;
1216 sh_r = 16;
1217 sh_g = 8;
1218 sh_b = 0;
1219 break;
1220 default:
1221 return; /* we do not support this color depth */
1222 }
1223 1182
1224 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 1183 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1225 1184
1226 if (bg_flags & BG_TINT_SET) 1185 if (bg_flags & BG_TINT_SET)
1227 tint.get (c); 1186 tint.get (c);
1249 fill_lut (lookup_g, mask_g, sh_g, low, c.g); 1208 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1250 fill_lut (lookup_b, mask_b, sh_b, low, c.b); 1209 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1251 1210
1252 /* apply table to input image (replacing colors by newly calculated ones) */ 1211 /* apply table to input image (replacing colors by newly calculated ones) */
1253 if (ximage->bits_per_pixel == 32 1212 if (ximage->bits_per_pixel == 32
1254 && (ximage->depth == 24 || ximage->depth == 32)
1255 && ximage->byte_order == host_byte_order) 1213 && ximage->byte_order == host_byte_order)
1256 { 1214 {
1257 uint32_t *p1, *pf, *p, *pl; 1215 char *line = ximage->data;
1258 p1 = (uint32_t *) ximage->data;
1259 pf = (uint32_t *) (ximage->data + ximage->height * ximage->bytes_per_line);
1260 1216
1261 while (p1 < pf) 1217 for (int y = 0; y < ximage->height; y++)
1262 {
1263 p = p1;
1264 pl = p1 + ximage->width;
1265 for (; p < pl; p++)
1266 { 1218 {
1267 *p = lookup_r[(*p & 0xff0000) >> 16] | 1219 uint32_t *p = (uint32_t *)line;
1268 lookup_g[(*p & 0x00ff00) >> 8] | 1220 for (int x = 0; x < ximage->width; x++)
1269 lookup_b[(*p & 0x0000ff)] |
1270 (*p & 0xff000000);
1271 } 1221 {
1272 p1 = (uint32_t *) ((char *) p1 + ximage->bytes_per_line); 1222 *p = lookup_r[(*p & mask_r) >> sh_r] |
1223 lookup_g[(*p & mask_g) >> sh_g] |
1224 lookup_b[(*p & mask_b) >> sh_b];
1225 p++;
1226 }
1227 line += ximage->bytes_per_line;
1273 } 1228 }
1274 } 1229 }
1275 else 1230 else
1276 { 1231 {
1277 for (int y = 0; y < ximage->height; y++) 1232 for (int y = 0; y < ximage->height; y++)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines