7 * This software is released under the GNU General Public License (GNU GPL).
8 * Please read the included file COPYING for more information.
9 * This software comes with no warranty of any kind, use at your own risk!
14 #include "pixbuf_util.h"
16 #include "icons/icons_inline.h"
22 *-----------------------------------------------------------------------------
24 *-----------------------------------------------------------------------------
27 gboolean pixbuf_to_file_as_png (GdkPixbuf *pixbuf, const char *filename)
32 if (!pixbuf || !filename) return FALSE;
34 ret = gdk_pixbuf_save(pixbuf, filename, "png", &error,
35 "tEXt::Software", "GQview "VERSION, NULL);
39 printf("Error saving png file: %s\n", error->message);
47 *-----------------------------------------------------------------------------
49 *-----------------------------------------------------------------------------
52 gboolean pixbuf_to_file_as_jpg(GdkPixbuf *pixbuf, const gchar *filename, gint quality)
58 if (!pixbuf || !filename) return FALSE;
60 if (quality == -1) quality = 75;
61 if (quality < 1 || quality > 100)
63 printf("Jpeg not saved, invalid quality %d\n", quality);
67 qbuf = g_strdup_printf("%d", quality);
68 ret = gdk_pixbuf_save(pixbuf, filename, "jpeg", &error, "quality", qbuf, NULL);
73 printf("Error saving jpeg to %s\n%s\n", filename, error->message);
81 *-----------------------------------------------------------------------------
83 *-----------------------------------------------------------------------------
86 typedef struct _PixbufInline PixbufInline;
93 static PixbufInline inline_pixbuf_data[] = {
94 { PIXBUF_INLINE_FOLDER_CLOSED, folder_closed },
95 { PIXBUF_INLINE_FOLDER_LOCKED, folder_locked },
96 { PIXBUF_INLINE_FOLDER_OPEN, folder_open },
97 { PIXBUF_INLINE_FOLDER_UP, folder_up },
98 { PIXBUF_INLINE_SCROLLER, icon_scroller },
99 { PIXBUF_INLINE_BROKEN, icon_broken },
100 { PIXBUF_INLINE_LOGO, gqview_logo },
101 { PIXBUF_INLINE_ICON_FLOAT, icon_float },
102 { PIXBUF_INLINE_ICON_THUMB, icon_thumb },
106 GdkPixbuf *pixbuf_inline(const gchar *key)
110 if (!key) return NULL;
113 while (inline_pixbuf_data[i].key)
115 if (strcmp(inline_pixbuf_data[i].key, key) == 0)
117 return gdk_pixbuf_new_from_inline(-1, inline_pixbuf_data[i].data, FALSE, NULL);
122 printf("warning: inline pixbuf key \"%s\" not found.\n", key);
128 *-----------------------------------------------------------------------------
130 *-----------------------------------------------------------------------------
133 gint util_clip_region(gint x, gint y, gint w, gint h,
134 gint clip_x, gint clip_y, gint clip_w, gint clip_h,
135 gint *rx, gint *ry, gint *rw, gint *rh)
137 if (clip_x + clip_w <= x ||
139 clip_y + clip_h <= y ||
145 *rx = MAX(x, clip_x);
146 *rw = MIN((x + w), (clip_x + clip_w)) - *rx;
148 *ry = MAX(y, clip_y);
149 *rh = MIN((y + h), (clip_y + clip_h)) - *ry;
155 *-----------------------------------------------------------------------------
157 *-----------------------------------------------------------------------------
160 static void pixbuf_copy_block_rotate(guchar *src, gint src_row_stride, gint x, gint y,
161 guchar *dest, gint dest_row_stride, gint w, gint h,
162 gint bytes_per_pixel, gint counter_clockwise)
168 for (i = 0; i < h; i++)
170 sp = src + ((i + y) * src_row_stride) + (x * bytes_per_pixel);
171 for (j = 0; j < w; j++)
173 if (counter_clockwise)
175 dp = dest + ((w - j - 1) * dest_row_stride) + (i * bytes_per_pixel);
179 dp = dest + (j * dest_row_stride) + ((h - i - 1) * bytes_per_pixel);
181 *(dp++) = *(sp++); /* r */
182 *(dp++) = *(sp++); /* g */
183 *(dp++) = *(sp++); /* b */
184 if (bytes_per_pixel == 4) *(dp) = *(sp++); /* a */
190 static void pixbuf_copy_block(guchar *src, gint src_row_stride, gint w, gint h,
191 guchar *dest, gint dest_row_stride, gint x, gint y, gint bytes_per_pixel)
197 for (i = 0; i < h; i++)
199 sp = src + (i * src_row_stride);
200 dp = dest + ((y + i) * dest_row_stride) + (x * bytes_per_pixel);
201 memcpy(dp, sp, w * bytes_per_pixel);
205 #define ROTATE_BUFFER_WIDTH 48
206 #define ROTATE_BUFFER_HEIGHT 48
209 * Returns a copy of pixbuf src rotated 90 degrees clockwise or 90 counterclockwise
212 GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gint counter_clockwise)
231 if (!src) return NULL;
233 sw = gdk_pixbuf_get_width(src);
234 sh = gdk_pixbuf_get_height(src);
235 has_alpha = gdk_pixbuf_get_has_alpha(src);
236 srs = gdk_pixbuf_get_rowstride(src);
237 s_pix = gdk_pixbuf_get_pixels(src);
241 dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, dw, dh);
242 drs = gdk_pixbuf_get_rowstride(dest);
243 d_pix = gdk_pixbuf_get_pixels(dest);
245 a = (has_alpha ? 4 : 3);
247 buffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8,
248 ROTATE_BUFFER_WIDTH, ROTATE_BUFFER_HEIGHT);
249 b_pix = gdk_pixbuf_get_pixels(buffer);
250 brs = gdk_pixbuf_get_rowstride(buffer);
252 for (i = 0; i < sh; i+= ROTATE_BUFFER_WIDTH)
254 w = MIN(ROTATE_BUFFER_WIDTH, (sh - i));
255 for (j = 0; j < sw; j += ROTATE_BUFFER_HEIGHT)
259 h = MIN(ROTATE_BUFFER_HEIGHT, (sw - j));
260 pixbuf_copy_block_rotate(s_pix, srs, j, i,
262 a, counter_clockwise);
264 if (counter_clockwise)
274 pixbuf_copy_block(b_pix, brs, w, h,
275 d_pix, drs, x, y, a);
279 gdk_pixbuf_unref(buffer);
282 /* this is the simple version of rotation (roughly 2-4x slower) */
284 for (i = 0; i < sh; i++)
286 sp = s_pix + (i * srs);
287 for (j = 0; j < sw; j++)
289 if (counter_clockwise)
291 dp = d_pix + ((dh - j - 1) * drs) + (i * a);
295 dp = d_pix + (j * drs) + ((dw - i - 1) * a);
298 *(dp++) = *(sp++); /* r */
299 *(dp++) = *(sp++); /* g */
300 *(dp++) = *(sp++); /* b */
301 if (has_alpha) *(dp) = *(sp++); /* a */
310 * Returns a copy of pixbuf mirrored and or flipped.
311 * TO do a 180 degree rotations set both mirror and flipped TRUE
312 * if mirror and flip are FALSE, result is a simple copy.
314 GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gint mirror, gint flip)
327 if (!src) return NULL;
329 w = gdk_pixbuf_get_width(src);
330 h = gdk_pixbuf_get_height(src);
331 has_alpha = gdk_pixbuf_get_has_alpha(src);
332 srs = gdk_pixbuf_get_rowstride(src);
333 s_pix = gdk_pixbuf_get_pixels(src);
335 dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, w, h);
336 drs = gdk_pixbuf_get_rowstride(dest);
337 d_pix = gdk_pixbuf_get_pixels(dest);
339 a = has_alpha ? 4 : 3;
341 for (i = 0; i < h; i++)
343 sp = s_pix + (i * srs);
346 dp = d_pix + ((h - i - 1) * drs);
350 dp = d_pix + (i * drs);
355 for (j = 0; j < w; j++)
357 *(dp++) = *(sp++); /* r */
358 *(dp++) = *(sp++); /* g */
359 *(dp++) = *(sp++); /* b */
360 if (has_alpha) *(dp) = *(sp++); /* a */
366 for (j = 0; j < w; j++)
368 *(dp++) = *(sp++); /* r */
369 *(dp++) = *(sp++); /* g */
370 *(dp++) = *(sp++); /* b */
371 if (has_alpha) *(dp++) = *(sp++); /* a */
381 *-----------------------------------------------------------------------------
382 * pixbuf drawing (rectangles)
383 *-----------------------------------------------------------------------------
387 * Fills region of pixbuf at x,y over w,h
388 * with colors red (r), green (g), blue (b)
389 * applying alpha (a), use a=255 for solid.
391 void pixbuf_draw_rect_fill(GdkPixbuf *pb,
392 gint x, gint y, gint w, gint h,
393 gint r, gint g, gint b, gint a)
403 pw = gdk_pixbuf_get_width(pb);
404 ph = gdk_pixbuf_get_height(pb);
406 if (x < 0 || x + w > pw) return;
407 if (y < 0 || y + h > ph) return;
409 p_alpha = gdk_pixbuf_get_has_alpha(pb);
410 prs = gdk_pixbuf_get_rowstride(pb);
411 p_pix = gdk_pixbuf_get_pixels(pb);
413 for (i = 0; i < h; i++)
415 pp = p_pix + (y + i) * prs + (x * (p_alpha ? 4 : 3));
416 for (j = 0; j < w; j++)
418 *pp = (r * a + *pp * (256-a)) >> 8;
420 *pp = (g * a + *pp * (256-a)) >> 8;
422 *pp = (b * a + *pp * (256-a)) >> 8;
429 void pixbuf_draw_rect(GdkPixbuf *pb,
430 gint x, gint y, gint w, gint h,
431 gint r, gint g, gint b, gint a,
432 gint left, gint right, gint top, gint bottom)
434 pixbuf_draw_rect_fill(pb, x + left, y, w - left - right, top,
436 pixbuf_draw_rect_fill(pb, x + w - right, y, right, h,
438 pixbuf_draw_rect_fill(pb, x + left, y + h - bottom, w - left - right, bottom,
440 pixbuf_draw_rect_fill(pb, x, y, left, h,
444 void pixbuf_set_rect_fill(GdkPixbuf *pb,
445 gint x, gint y, gint w, gint h,
446 gint r, gint g, gint b, gint a)
456 pw = gdk_pixbuf_get_width(pb);
457 ph = gdk_pixbuf_get_height(pb);
459 if (x < 0 || x + w > pw) return;
460 if (y < 0 || y + h > ph) return;
462 p_alpha = gdk_pixbuf_get_has_alpha(pb);
463 prs = gdk_pixbuf_get_rowstride(pb);
464 p_pix = gdk_pixbuf_get_pixels(pb);
466 for (i = 0; i < h; i++)
468 pp = p_pix + (y + i) * prs + (x * (p_alpha ? 4 : 3));
469 for (j = 0; j < w; j++)
474 if (p_alpha) { *pp = a; pp++; }
479 void pixbuf_set_rect(GdkPixbuf *pb,
480 gint x, gint y, gint w, gint h,
481 gint r, gint g, gint b, gint a,
482 gint left, gint right, gint top, gint bottom)
484 pixbuf_set_rect_fill(pb, x + left, y, w - left - right, top,
486 pixbuf_set_rect_fill(pb, x + w - right, y, right, h,
488 pixbuf_set_rect_fill(pb, x + left, y + h - bottom, w - left - right, bottom,
490 pixbuf_set_rect_fill(pb, x, y, left, h,
494 void pixbuf_pixel_set(GdkPixbuf *pb, gint x, gint y, gint r, gint g, gint b, gint a)
501 if (x < 0 || x >= gdk_pixbuf_get_width(pb) ||
502 y < 0 || y >= gdk_pixbuf_get_height(pb)) return;
504 buf = gdk_pixbuf_get_pixels(pb);
505 has_alpha = gdk_pixbuf_get_has_alpha(pb);
506 rowstride = gdk_pixbuf_get_rowstride(pb);
508 p = buf + (y * rowstride) + (x * (has_alpha ? 4 : 3));
512 if (has_alpha) *p = a;
517 *-----------------------------------------------------------------------------
518 * pixbuf text rendering
519 *-----------------------------------------------------------------------------
522 static void pixbuf_copy_font(GdkPixbuf *src, gint sx, gint sy,
523 GdkPixbuf *dest, gint dx, gint dy,
525 guint8 r, guint8 g, guint8 b, guint8 a)
540 if (!src || !dest) return;
542 sw = gdk_pixbuf_get_width(src);
543 sh = gdk_pixbuf_get_height(src);
545 if (sx < 0 || sx + w > sw) return;
546 if (sy < 0 || sy + h > sh) return;
548 dw = gdk_pixbuf_get_width(dest);
549 dh = gdk_pixbuf_get_height(dest);
551 if (dx < 0 || dx + w > dw) return;
552 if (dy < 0 || dy + h > dh) return;
554 s_alpha = gdk_pixbuf_get_has_alpha(src);
555 d_alpha = gdk_pixbuf_get_has_alpha(dest);
556 srs = gdk_pixbuf_get_rowstride(src);
557 drs = gdk_pixbuf_get_rowstride(dest);
558 s_pix = gdk_pixbuf_get_pixels(src);
559 d_pix = gdk_pixbuf_get_pixels(dest);
561 s_step = (s_alpha) ? 4 : 3;
562 d_step = (d_alpha) ? 4 : 3;
564 for (i = 0; i < h; i++)
566 sp = s_pix + (sy + i) * srs + sx * s_step;
567 dp = d_pix + (dy + i) * drs + dx * d_step;
568 for (j = 0; j < w; j++)
574 asub = a * sp[0] / 255;
575 *dp = (r * asub + *dp * (256-asub)) >> 8;
577 asub = a * sp[1] / 255;
578 *dp = (g * asub + *dp * (256-asub)) >> 8;
580 asub = a * sp[2] / 255;
581 *dp = (b * asub + *dp * (256-asub)) >> 8;
586 *dp = MAX(*dp, a * ((sp[0] + sp[1] + sp[2]) / 3) / 255);
600 void pixbuf_draw_layout(GdkPixbuf *pixbuf, PangoLayout *layout, GtkWidget *widget,
602 guint8 r, guint8 g, guint8 b, guint8 a)
611 if (!widget || !widget->window) return;
613 pango_layout_get_pixel_size(layout, &w, &h);
614 pixmap = gdk_pixmap_new(widget->window, w, h, -1);
616 gc = gdk_gc_new(widget->window);
617 gdk_gc_copy(gc, widget->style->black_gc);
618 gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, w, h);
619 gdk_gc_copy(gc, widget->style->white_gc);
620 gdk_draw_layout(pixmap, gc, 0, 0, layout);
623 buffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
624 gdk_pixbuf_get_from_drawable(buffer, pixmap,
625 gdk_drawable_get_colormap(widget->window),
627 g_object_unref(pixmap);
631 dw = gdk_pixbuf_get_width(pixbuf);
632 dh = gdk_pixbuf_get_height(pixbuf);
648 if (x + w > dw) w = dw - x;
649 if (y + h > dh) h = dh - y;
651 pixbuf_copy_font(buffer, sx, sy,
655 g_object_unref(buffer);
659 *-----------------------------------------------------------------------------
660 * pixbuf drawing (triangle)
661 *-----------------------------------------------------------------------------
664 void util_clip_triangle(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
665 gint *rx, gint *ry, gint *rw, gint *rh)
673 tw = MAX(abs(x1 - x2), abs(x2 - x3));
674 tw = MAX(tw, abs(x3 - x1));
675 th = MAX(abs(y1 - y2), abs(y2 - y3));
676 th = MAX(th, abs(y3 - y1));
684 void pixbuf_draw_triangle(GdkPixbuf *pb,
685 gint clip_x, gint clip_y, gint clip_w, gint clip_h,
686 gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
687 guint8 r, guint8 g, guint8 b, guint8 a)
699 gdouble slope1, slope2;
700 gint slope1_x, slope1_y;
707 pw = gdk_pixbuf_get_width(pb);
708 ph = gdk_pixbuf_get_height(pb);
710 if (!util_clip_region(0, 0, pw, ph,
711 clip_x, clip_y, clip_w, clip_h,
712 &rx, &ry, &rw, &rh)) return;
714 util_clip_triangle(x1, y1, x2, y2, x3, y3,
717 if (!util_clip_region(rx, ry, rw, rh,
719 &fx1, &fy1, &fw, &fh)) return;
723 p_alpha = gdk_pixbuf_get_has_alpha(pb);
724 prs = gdk_pixbuf_get_rowstride(pb);
725 p_pix = gdk_pixbuf_get_pixels(pb);
727 p_step = (p_alpha) ? 4 : 3;
731 t = x1; x1 = x2; x2 = t;
732 t = y1; y1 = y2; y2 = t;
736 t = x2; x2 = x3; x3 = t;
737 t = y2; y2 = y3; y3 = t;
741 t = x1; x1 = x2; x2 = t;
742 t = y1; y1 = y2; y2 = t;
745 slope1 = (gdouble)(y2 - y1);
746 if (slope1) slope1 = (gdouble)(x2 - x1) / slope1;
749 slope2 = (gdouble)(y3 - y1);
750 if (slope2) slope2 = (gdouble)(x3 - x1) / slope2;
752 for (y = fy1; y < fy2; y++)
756 if (!middle && y > y2)
758 slope1 = (gdouble)(y3 - y2);
759 if (slope1) slope1 = (gdouble)(x3 - x2) / slope1;
766 xa = slope1_x + ((gdouble)slope1 * (y - slope1_y) + 0.5);
767 xb = x1 + ((gdouble)slope2 * (y - y1) + 0.5);
771 t = xa; xa = xb; xb = t;
774 xa = CLAMP(xa, fx1, fx2);
775 xb = CLAMP(xb, fx1, fx2);
777 pp = p_pix + y * prs + xa * p_step;
781 *pp = (r * a + *pp * (256-a)) >> 8;
783 *pp = (g * a + *pp * (256-a)) >> 8;
785 *pp = (b * a + *pp * (256-a)) >> 8;
795 *-----------------------------------------------------------------------------
796 * pixbuf drawing (line)
797 *-----------------------------------------------------------------------------
800 static gint util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, gdouble clip_h,
801 gdouble x1, gdouble y1, gdouble x2, gdouble y2,
802 gdouble *rx1, gdouble *ry1, gdouble *rx2, gdouble *ry2)
811 t = x1; x1 = x2; x2 = t;
812 t = y1; y1 = y2; y2 = t;
816 if (x2 < clip_x || x1 > clip_x + clip_w) return FALSE;
820 if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE;
824 if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE;
828 if (x1 >= clip_x && x2 <= clip_x + clip_w)
832 if (y1 >= clip_y && y2 <= clip_y + clip_h) return TRUE;
836 if (y2 >= clip_y && y1 <= clip_y + clip_h) return TRUE;
846 slope = (y2 - y1) / d;
849 y1 = y1 + slope * (clip_x - x1);
852 if (x2 > clip_x + clip_w)
854 y2 = y2 + slope * (clip_x + clip_w - x2);
855 x2 = clip_x + clip_w;
861 if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE;
867 if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE;
869 t = x1; x1 = x2; x2 = t;
870 t = y1; y1 = y2; y2 = t;
879 slope = (x2 - x1) / d;
882 x1 = x1 + slope * (clip_y - y1);
885 if (y2 > clip_y + clip_h)
887 x2 = x2 + slope * (clip_y + clip_h - y2);
888 y2 = clip_y + clip_h;
910 void pixbuf_draw_line(GdkPixbuf *pb,
911 gint clip_x, gint clip_y, gint clip_w, gint clip_h,
912 gint x1, gint y1, gint x2, gint y2,
913 guint8 r, guint8 g, guint8 b, guint8 a)
918 gdouble rx1, ry1, rx2, ry2;
925 gint cx1, cy1, cx2, cy2;
929 pw = gdk_pixbuf_get_width(pb);
930 ph = gdk_pixbuf_get_height(pb);
932 if (!util_clip_region(0, 0, pw, ph,
933 clip_x, clip_y, clip_w, clip_h,
934 &rx, &ry, &rw, &rh)) return;
935 if (!util_clip_line((gdouble)rx, (gdouble)ry, (gdouble)rw, (gdouble)rh,
936 (gdouble)x1, (gdouble)y1, (gdouble)x2, (gdouble)y2,
937 &rx1, &ry1, &rx2, &ry2)) return;
944 p_alpha = gdk_pixbuf_get_has_alpha(pb);
945 prs = gdk_pixbuf_get_rowstride(pb);
946 p_pix = gdk_pixbuf_get_pixels(pb);
948 p_step = (p_alpha) ? 4 : 3;
950 if (fabs(rx2 - rx1) > fabs(ry2 - ry1))
955 t = rx1; rx1 = rx2; rx2 = t;
956 t = ry1; ry1 = ry2; ry2 = t;
960 if (slope != 0.0) slope = (ry2 - ry1) / slope;
961 for (x = rx1; x < rx2; x += 1.0)
963 px = (gint)(x + 0.5);
964 py = (gint)(ry1 + (x - rx1) * slope + 0.5);
966 if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2)
968 pp = p_pix + py * prs + px * p_step;
969 *pp = (r * a + *pp * (256-a)) >> 8;
971 *pp = (g * a + *pp * (256-a)) >> 8;
973 *pp = (b * a + *pp * (256-a)) >> 8;
982 t = rx1; rx1 = rx2; rx2 = t;
983 t = ry1; ry1 = ry2; ry2 = t;
987 if (slope != 0.0) slope = (rx2 - rx1) / slope;
988 for (y = ry1; y < ry2; y += 1.0)
990 px = (gint)(rx1 + (y - ry1) * slope + 0.5);
991 py = (gint)(y + 0.5);
993 if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2)
995 pp = p_pix + py * prs + px * p_step;
996 *pp = (r * a + *pp * (256-a)) >> 8;
998 *pp = (g * a + *pp * (256-a)) >> 8;
1000 *pp = (b * a + *pp * (256-a)) >> 8;
1007 *-----------------------------------------------------------------------------
1008 * pixbuf drawing (fades and shadows)
1009 *-----------------------------------------------------------------------------
1012 static void pixbuf_draw_fade_linear(guchar *p_pix, gint prs, gint p_alpha,
1013 gint s, gint vertical, gint border,
1014 gint x1, gint y1, gint x2, gint y2,
1015 guint8 r, guint8 g, guint8 b, guint8 a)
1022 p_step = (p_alpha) ? 4 : 3;
1023 for (j = y1; j < y2; j++)
1025 pp = p_pix + j * prs + x1 * p_step;
1026 if (!vertical) n = a - a * abs(j - s) / border;
1027 for (i = x1; i < x2; i++)
1029 if (vertical) n = a - a * abs(i - s) / border;
1030 *pp = (r * n + *pp * (256-n)) >> 8;
1032 *pp = (g * n + *pp * (256-n)) >> 8;
1034 *pp = (b * n + *pp * (256-n)) >> 8;
1041 static void pixbuf_draw_fade_radius(guchar *p_pix, gint prs, gint p_alpha,
1042 gint sx, gint sy, gint border,
1043 gint x1, gint y1, gint x2, gint y2,
1044 guint8 r, guint8 g, guint8 b, guint8 a)
1050 p_step = (p_alpha) ? 4 : 3;
1051 for (j = y1; j < y2; j++)
1053 pp = p_pix + j * prs + x1 * p_step;
1054 for (i = x1; i < x2; i++)
1059 r = MIN(border, (gint)sqrt((i-sx)*(i-sx) + (j-sy)*(j-sy)));
1060 n = a - a * r / border;
1061 *pp = (r * n + *pp * (256-n)) >> 8;
1063 *pp = (g * n + *pp * (256-n)) >> 8;
1065 *pp = (b * n + *pp * (256-n)) >> 8;
1072 void pixbuf_draw_shadow(GdkPixbuf *pb,
1073 gint clip_x, gint clip_y, gint clip_w, gint clip_h,
1074 gint x, gint y, gint w, gint h, gint border,
1075 guint8 r, guint8 g, guint8 b, guint8 a)
1079 gint rx, ry, rw, rh;
1080 gint fx, fy, fw, fh;
1085 pw = gdk_pixbuf_get_width(pb);
1086 ph = gdk_pixbuf_get_height(pb);
1088 if (!util_clip_region(0, 0, pw, ph,
1089 clip_x, clip_y, clip_w, clip_h,
1090 &rx, &ry, &rw, &rh)) return;
1092 p_alpha = gdk_pixbuf_get_has_alpha(pb);
1093 prs = gdk_pixbuf_get_rowstride(pb);
1094 p_pix = gdk_pixbuf_get_pixels(pb);
1096 if (util_clip_region(x + border, y + border, w - border * 2, h - border * 2,
1098 &fx, &fy, &fw, &fh))
1100 pixbuf_draw_rect_fill(pb, fx, fy, fw, fh, r, g, b, a);
1103 if (border < 1) return;
1105 if (util_clip_region(x, y + border, border, h - border * 2,
1107 &fx, &fy, &fw, &fh))
1109 pixbuf_draw_fade_linear(p_pix, prs, p_alpha,
1110 x + border, TRUE, border,
1111 fx, fy, fx + fw, fy + fh,
1114 if (util_clip_region(x + w - border, y + border, border, h - border * 2,
1116 &fx, &fy, &fw, &fh))
1118 pixbuf_draw_fade_linear(p_pix, prs, p_alpha,
1119 x + w - border, TRUE, border,
1120 fx, fy, fx + fw, fy + fh,
1123 if (util_clip_region(x + border, y, w - border * 2, border,
1125 &fx, &fy, &fw, &fh))
1127 pixbuf_draw_fade_linear(p_pix, prs, p_alpha,
1128 y + border, FALSE, border,
1129 fx, fy, fx + fw, fy + fh,
1132 if (util_clip_region(x + border, y + h - border, w - border * 2, border,
1134 &fx, &fy, &fw, &fh))
1136 pixbuf_draw_fade_linear(p_pix, prs, p_alpha,
1137 y + h - border, FALSE, border,
1138 fx, fy, fx + fw, fy + fh,
1141 if (util_clip_region(x, y, border, border,
1143 &fx, &fy, &fw, &fh))
1145 pixbuf_draw_fade_radius(p_pix, prs, p_alpha,
1146 x + border, y + border, border,
1147 fx, fy, fx + fw, fy + fh,
1150 if (util_clip_region(x + w - border, y, border, border,
1152 &fx, &fy, &fw, &fh))
1154 pixbuf_draw_fade_radius(p_pix, prs, p_alpha,
1155 x + w - border, y + border, border,
1156 fx, fy, fx + fw, fy + fh,
1159 if (util_clip_region(x, y + h - border, border, border,
1161 &fx, &fy, &fw, &fh))
1163 pixbuf_draw_fade_radius(p_pix, prs, p_alpha,
1164 x + border, y + h - border, border,
1165 fx, fy, fx + fw, fy + fh,
1168 if (util_clip_region(x + w - border, y + h - border, border, border,
1170 &fx, &fy, &fw, &fh))
1172 pixbuf_draw_fade_radius(p_pix, prs, p_alpha,
1173 x + w - border, y + h - border, border,
1174 fx, fy, fx + fw, fy + fh,