From: John Ellis Date: Wed, 6 Apr 2005 10:45:36 +0000 (+0000) Subject: Wed Apr 6 06:41:25 2005 John Ellis X-Git-Tag: v1.0.0~1770 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=52225b73916c2054e74c8f730b0922cb271199fc Wed Apr 6 06:41:25 2005 John Ellis * pan-view.c: Move pixbuf drawing into pixbuf_util.c. * pixbuf-renderer.c: Rename util_clip_region to pr_clip_region to fix namespace conflict with util in pixbuf_util.h. * pixbuf_util.[ch]: Moved pixbuf drawing utils here from pan-view.c ##### Note: GQview CVS on sourceforge is not always up to date, please use ##### ##### an offical release when making enhancements and translation updates. ##### --- diff --git a/ChangeLog b/ChangeLog index 2f8361f3..3cbea8ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Apr 6 06:41:25 2005 John Ellis + + * pan-view.c: Move pixbuf drawing into pixbuf_util.c. + * pixbuf-renderer.c: Rename util_clip_region to pr_clip_region to fix + namespace conflict with util in pixbuf_util.h. + * pixbuf_util.[ch]: Moved pixbuf drawing utils here from pan-view.c + Wed Apr 6 02:43:40 2005 John Ellis * pan-view.c: Reimplement pixbuf_draw_triangle for efficiency. diff --git a/TODO b/TODO index 633cb8b1..492c5fce 100644 --- a/TODO +++ b/TODO @@ -37,7 +37,7 @@ Major: d> optimize pixbuf_draw_line (line endpoints should clip to draw region before draw loop) d> optimize pixbuf_draw_triangle > does new pixbuf_draw_triangle contain line edge rounding error? - > move pixbuf_draw_* stuff into pixbuf_util.c + d> move pixbuf_draw_* stuff into pixbuf_util.c > time line view: > allow use of file date or EXIF (embedded) date. diff --git a/src/pan-view.c b/src/pan-view.c index 2284def8..2d6e0745 100644 --- a/src/pan-view.c +++ b/src/pan-view.c @@ -249,37 +249,6 @@ static void pan_window_close(PanWindow *pw); static void pan_window_dnd_init(PanWindow *pw); -static gint util_clip_region(gint x, gint y, gint w, gint h, - gint clip_x, gint clip_y, gint clip_w, gint clip_h, - gint *rx, gint *ry, gint *rw, gint *rh) -{ - if (clip_x + clip_w <= x || - clip_x >= x + w || - clip_y + clip_h <= y || - clip_y >= y + h) - { - return FALSE; - } - - *rx = MAX(x, clip_x); - *rw = MIN((x + w), (clip_x + clip_w)) - *rx; - - *ry = MAX(y, clip_y); - *rh = MIN((y + h), (clip_y + clip_h)) - *ry; - - return TRUE; -} - -static gint util_clip_region_test(gint x, gint y, gint w, gint h, - gint clip_x, gint clip_y, gint clip_w, gint clip_h) -{ - gint rx, ry, rw, rh; - - return util_clip_region(x, y, w, h, - clip_x, clip_y, clip_w, clip_h, - &rx, &ry, &rw, &rh); -} - typedef enum { DATE_LENGTH_EXACT, DATE_LENGTH_HOUR, @@ -394,516 +363,6 @@ static time_t date_to_time(gint year, gint month, gint day) return mktime(<); } -/* - *----------------------------------------------------------------------------- - * drawing utils - *----------------------------------------------------------------------------- - */ - -static void triangle_rect_region(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, - gint *rx, gint *ry, gint *rw, gint *rh) -{ - gint tx, ty, tw, th; - - tx = MIN(x1, x2); - tx = MIN(tx, x3); - ty = MIN(y1, y2); - ty = MIN(ty, y3); - tw = MAX(abs(x1 - x2), abs(x2 - x3)); - tw = MAX(tw, abs(x3 - x1)); - th = MAX(abs(y1 - y2), abs(y2 - y3)); - th = MAX(th, abs(y3 - y1)); - - *rx = tx; - *ry = ty; - *rw = tw; - *rh = th; -} - -static void pixbuf_draw_triangle(GdkPixbuf *pb, - gint clip_x, gint clip_y, gint clip_w, gint clip_h, - gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, - guint8 r, guint8 g, guint8 b, guint8 a) -{ - gint p_alpha; - gint pw, ph, prs; - gint rx, ry, rw, rh; - gint tx, ty, tw, th; - gint fx1, fy1; - gint fx2, fy2; - gint fw, fh; - guchar *p_pix; - guchar *pp; - gint p_step; - gdouble slope1, slope2; - gint slope1_x, slope1_y; - gint y; - gint t; - gint middle = FALSE; - - if (!pb) return; - - pw = gdk_pixbuf_get_width(pb); - ph = gdk_pixbuf_get_height(pb); - - if (!util_clip_region(0, 0, pw, ph, - clip_x, clip_y, clip_w, clip_h, - &rx, &ry, &rw, &rh)) return; - - triangle_rect_region(x1, y1, x2, y2, x3, y3, - &tx, &ty, &tw, &th); - - if (!util_clip_region(rx, ry, rw, rh, - tx, ty, tw, th, - &fx1, &fy1, &fw, &fh)) return; - fx2 = fx1 + fw; - fy2 = fy1 + fh; - - p_alpha = gdk_pixbuf_get_has_alpha(pb); - prs = gdk_pixbuf_get_rowstride(pb); - p_pix = gdk_pixbuf_get_pixels(pb); - - p_step = (p_alpha) ? 4 : 3; - - if (y1 > y2) - { - t = x1; x1 = x2; x2 = t; - t = y1; y1 = y2; y2 = t; - } - if (y2 > y3) - { - t = x2; x2 = x3; x3 = t; - t = y2; y2 = y3; y3 = t; - } - if (y1 > y2) - { - t = x1; x1 = x2; x2 = t; - t = y1; y1 = y2; y2 = t; - } - - slope1 = (gdouble)(y2 - y1); - if (slope1) slope1 = (gdouble)(x2 - x1) / slope1; - slope1_x = x1; - slope1_y = y1; - slope2 = (gdouble)(y3 - y1); - if (slope2) slope2 = (gdouble)(x3 - x1) / slope2; - - for (y = fy1; y < fy2; y++) - { - gint xa, xb; - - if (!middle && y > y2) - { - slope1 = (gdouble)(y3 - y2); - if (slope1) slope1 = (gdouble)(x3 - x2) / slope1; - slope1_x = x2; - slope1_y = y2; - - middle = TRUE; - } - - xa = slope1_x + ((gdouble)slope1 * (y - slope1_y) + 0.5); - xb = x1 + ((gdouble)slope2 * (y - y1) + 0.5); - - if (xa > xb) - { - t = xa; xa = xb; xb = t; - } - - xa = CLAMP(xa, fx1, fx2); - xb = CLAMP(xb, fx1, fx2); - - pp = p_pix + y * prs + xa * p_step; - - while (xa < xb) - { - *pp = (r * a + *pp * (256-a)) >> 8; - pp++; - *pp = (g * a + *pp * (256-a)) >> 8; - pp++; - *pp = (b * a + *pp * (256-a)) >> 8; - pp++; - if (p_alpha) pp++; - - xa++; - } - } -} - -static gint util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, gdouble clip_h, - gdouble x1, gdouble y1, gdouble x2, gdouble y2, - gdouble *rx1, gdouble *ry1, gdouble *rx2, gdouble *ry2) -{ - gint flip = FALSE; - gdouble d; - - if (x1 > x2) - { - gdouble t; - - t = x1; x1 = x2; x2 = t; - t = y1; y1 = y2; y2 = t; - flip = TRUE; - } - - if (x2 < clip_x || x1 > clip_x + clip_w) return FALSE; - - if (y1 < y2) - { - if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE; - } - else - { - if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE; - } - -#if 0 - if (x1 >= clip_x && x2 <= clip_x + clip_w) - { - if (y1 < y2) - { - if (y1 >= clip_y && y2 <= clip_y + clip_h) return TRUE; - } - else - { - if (y2 >= clip_y && y1 <= clip_y + clip_h) return TRUE; - } - } -#endif - - d = x2 - x1; - if (d > 0.0) - { - gdouble slope; - - slope = (y2 - y1) / d; - if (x1 < clip_x) - { - y1 = y1 + slope * (clip_x - x1); - x1 = clip_x; - } - if (x2 > clip_x + clip_w) - { - y2 = y2 + slope * (clip_x + clip_w - x2); - x2 = clip_x + clip_w; - } - } - - if (y1 < y2) - { - if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE; - } - else - { - gdouble t; - - if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE; - - t = x1; x1 = x2; x2 = t; - t = y1; y1 = y2; y2 = t; - flip = !flip; - } - - d = y2 - y1; - if (d > 0.0) - { - gdouble slope; - - slope = (x2 - x1) / d; - if (y1 < clip_y) - { - x1 = x1 + slope * (clip_y - y1); - y1 = clip_y; - } - if (y2 > clip_y + clip_h) - { - x2 = x2 + slope * (clip_y + clip_h - y2); - y2 = clip_y + clip_h; - } - } - - if (flip) - { - *rx1 = x2; - *ry1 = y2; - *rx2 = x1; - *ry2 = y1; - } - else - { - *rx1 = x1; - *ry1 = y1; - *rx2 = x2; - *ry2 = y2; - } - - return TRUE; -} - -static void pixbuf_draw_line(GdkPixbuf *pb, - gint clip_x, gint clip_y, gint clip_w, gint clip_h, - gint x1, gint y1, gint x2, gint y2, - guint8 r, guint8 g, guint8 b, guint8 a) -{ - gint p_alpha; - gint pw, ph, prs; - gint rx, ry, rw, rh; - gdouble rx1, ry1, rx2, ry2; - guchar *p_pix; - guchar *pp; - gint p_step; - gdouble slope; - gdouble x, y; - gint px, py; - gint cx1, cy1, cx2, cy2; - - if (!pb) return; - - pw = gdk_pixbuf_get_width(pb); - ph = gdk_pixbuf_get_height(pb); - - if (!util_clip_region(0, 0, pw, ph, - clip_x, clip_y, clip_w, clip_h, - &rx, &ry, &rw, &rh)) return; - if (!util_clip_line((gdouble)rx, (gdouble)ry, (gdouble)rw, (gdouble)rh, - (gdouble)x1, (gdouble)y1, (gdouble)x2, (gdouble)y2, - &rx1, &ry1, &rx2, &ry2)) return; - - cx1 = rx; - cy1 = ry; - cx2 = rx + rw; - cy2 = ry + rh; - - p_alpha = gdk_pixbuf_get_has_alpha(pb); - prs = gdk_pixbuf_get_rowstride(pb); - p_pix = gdk_pixbuf_get_pixels(pb); - - p_step = (p_alpha) ? 4 : 3; - - if (fabs(rx2 - rx1) > fabs(ry2 - ry1)) - { - if (rx1 > rx2) - { - gdouble t; - t = rx1; rx1 = rx2; rx2 = t; - t = ry1; ry1 = ry2; ry2 = t; - } - - slope = rx2 - rx1; - if (slope != 0.0) slope = (ry2 - ry1) / slope; - for (x = rx1; x < rx2; x += 1.0) - { - px = (gint)(x + 0.5); - py = (gint)(ry1 + (x - rx1) * slope + 0.5); - - if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2) - { - pp = p_pix + py * prs + px * p_step; - *pp = (r * a + *pp * (256-a)) >> 8; - pp++; - *pp = (g * a + *pp * (256-a)) >> 8; - pp++; - *pp = (b * a + *pp * (256-a)) >> 8; - } - } - } - else - { - if (ry1 > ry2) - { - gdouble t; - t = rx1; rx1 = rx2; rx2 = t; - t = ry1; ry1 = ry2; ry2 = t; - } - - slope = ry2 - ry1; - if (slope != 0.0) slope = (rx2 - rx1) / slope; - for (y = ry1; y < ry2; y += 1.0) - { - px = (gint)(rx1 + (y - ry1) * slope + 0.5); - py = (gint)(y + 0.5); - - if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2) - { - pp = p_pix + py * prs + px * p_step; - *pp = (r * a + *pp * (256-a)) >> 8; - pp++; - *pp = (g * a + *pp * (256-a)) >> 8; - pp++; - *pp = (b * a + *pp * (256-a)) >> 8; - } - } - } -} - -static void pixbuf_draw_fade_linear(guchar *p_pix, gint prs, gint p_alpha, - gint s, gint vertical, gint border, - gint x1, gint y1, gint x2, gint y2, - guint8 r, guint8 g, guint8 b, guint8 a) -{ - guchar *pp; - gint p_step; - guint8 n = a; - gint i, j; - - p_step = (p_alpha) ? 4 : 3; - for (j = y1; j < y2; j++) - { - pp = p_pix + j * prs + x1 * p_step; - if (!vertical) n = a - a * abs(j - s) / border; - for (i = x1; i < x2; i++) - { - if (vertical) n = a - a * abs(i - s) / border; - *pp = (r * n + *pp * (256-n)) >> 8; - pp++; - *pp = (g * n + *pp * (256-n)) >> 8; - pp++; - *pp = (b * n + *pp * (256-n)) >> 8; - pp++; - if (p_alpha) pp++; - } - } -} - -static void pixbuf_draw_fade_radius(guchar *p_pix, gint prs, gint p_alpha, - gint sx, gint sy, gint border, - gint x1, gint y1, gint x2, gint y2, - guint8 r, guint8 g, guint8 b, guint8 a) -{ - guchar *pp; - gint p_step; - gint i, j; - - p_step = (p_alpha) ? 4 : 3; - for (j = y1; j < y2; j++) - { - pp = p_pix + j * prs + x1 * p_step; - for (i = x1; i < x2; i++) - { - guint8 n; - gint r; - - r = MIN(border, (gint)sqrt((i-sx)*(i-sx) + (j-sy)*(j-sy))); - n = a - a * r / border; - *pp = (r * n + *pp * (256-n)) >> 8; - pp++; - *pp = (g * n + *pp * (256-n)) >> 8; - pp++; - *pp = (b * n + *pp * (256-n)) >> 8; - pp++; - if (p_alpha) pp++; - } - } -} - -static void pixbuf_draw_shadow(GdkPixbuf *pb, - gint clip_x, gint clip_y, gint clip_w, gint clip_h, - gint x, gint y, gint w, gint h, gint border, - guint8 r, guint8 g, guint8 b, guint8 a) -{ - gint p_alpha; - gint pw, ph, prs; - gint rx, ry, rw, rh; - gint fx, fy, fw, fh; - guchar *p_pix; - - if (!pb) return; - - pw = gdk_pixbuf_get_width(pb); - ph = gdk_pixbuf_get_height(pb); - - if (!util_clip_region(0, 0, pw, ph, - clip_x, clip_y, clip_w, clip_h, - &rx, &ry, &rw, &rh)) return; - - p_alpha = gdk_pixbuf_get_has_alpha(pb); - prs = gdk_pixbuf_get_rowstride(pb); - p_pix = gdk_pixbuf_get_pixels(pb); - - if (util_clip_region(x + border, y + border, w - border * 2, h - border * 2, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_rect_fill(pb, fx, fy, fw, fh, r, g, b, a); - } - - if (border < 1) return; - - if (util_clip_region(x, y + border, border, h - border * 2, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_linear(p_pix, prs, p_alpha, - x + border, TRUE, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x + w - border, y + border, border, h - border * 2, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_linear(p_pix, prs, p_alpha, - x + w - border, TRUE, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x + border, y, w - border * 2, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_linear(p_pix, prs, p_alpha, - y + border, FALSE, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x + border, y + h - border, w - border * 2, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_linear(p_pix, prs, p_alpha, - y + h - border, FALSE, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x, y, border, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_radius(p_pix, prs, p_alpha, - x + border, y + border, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x + w - border, y, border, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_radius(p_pix, prs, p_alpha, - x + w - border, y + border, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x, y + h - border, border, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_radius(p_pix, prs, p_alpha, - x + border, y + h - border, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } - if (util_clip_region(x + w - border, y + h - border, border, border, - rx, ry, rw, rh, - &fx, &fy, &fw, &fh)) - { - pixbuf_draw_fade_radius(p_pix, prs, p_alpha, - x + w - border, y + h - border, border, - fx, fy, fx + fw, fy + fh, - r, g, b, a); - } -} - - /* *----------------------------------------------------------------------------- * cache @@ -2141,8 +1600,8 @@ static void pan_calendar_update(PanWindow *pw, PanItem *pi_day) y2 = pbox->y + MIN(42, pbox->height); x3 = pbox->x + 1; y3 = MAX(pbox->y, y2 - 30); - triangle_rect_region(x1, y1, x2, y2, x3, y3, - &x, &y, &w, &h); + util_clip_triangle(x1, y1, x2, y2, x3, y3, + &x, &y, &w, &h); pi = pan_item_new_tri(pw, NULL, x, y, w, h, x1, y1, x2, y2, x3, y3, @@ -2618,12 +2077,14 @@ static GList *pan_layout_intersect(PanWindow *pw, gint x, gint y, gint width, gi while (work) { PanItem *pi; + gint rx, ry, rw, rh; pi = work->data; work = work->next; - if (util_clip_region_test(x, y, width, height, - pi->x, pi->y, pi->width, pi->height)) + if (util_clip_region(x, y, width, height, + pi->x, pi->y, pi->width, pi->height, + &rx, &ry, &rw, &rh)) { list = g_list_prepend(list, pi); } @@ -2632,8 +2093,6 @@ static GList *pan_layout_intersect(PanWindow *pw, gint x, gint y, gint width, gi return list; } - - /* *----------------------------------------------------------------------------- * tile generation @@ -3683,8 +3142,8 @@ static void pan_info_update(PanWindow *pw, PanItem *pi) y2 = pbox->y + 36; x3 = pbox->x + 1; y3 = pbox->y + 12; - triangle_rect_region(x1, y1, x2, y2, x3, y3, - &x, &y, &w, &h); + util_clip_triangle(x1, y1, x2, y2, x3, y3, + &x, &y, &w, &h); p = pan_item_new_tri(pw, NULL, x, y, w, h, x1, y1, x2, y2, x3, y3, diff --git a/src/pixbuf-renderer.c b/src/pixbuf-renderer.c index 6701fdbc..78ed7699 100644 --- a/src/pixbuf-renderer.c +++ b/src/pixbuf-renderer.c @@ -653,9 +653,9 @@ static gint pixmap_calc_size(GdkPixmap *pixmap) return w * h * (d / 8); } -static gint util_clip_region(gint x, gint y, gint w, gint h, - gint clip_x, gint clip_y, gint clip_w, gint clip_h, - gint *rx, gint *ry, gint *rw, gint *rh) +static gint pr_clip_region(gint x, gint y, gint w, gint h, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint *rx, gint *ry, gint *rw, gint *rh) { if (clip_x + clip_w <= x || clip_x >= x + w || @@ -772,7 +772,7 @@ static void pr_overlay_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h) if (py < 0) py = pr->window_height - ph + py; } - if (util_clip_region(x, y, w, h, px, py, pw, ph, &rx, &ry, &rw, &rh)) + if (pr_clip_region(x, y, w, h, px, py, pw, ph, &rx, &ry, &rw, &rh)) { gdk_draw_pixbuf(box->window, box->style->fg_gc[GTK_WIDGET_STATE(box)], @@ -1103,10 +1103,10 @@ static void pr_border_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h) if (!pr->pixbuf && !pr->source_tiles_enabled) { - if (util_clip_region(x, y, w, h, - 0, 0, - pr->window_width, pr->window_height, - &rx, &ry, &rw, &rh)) + if (pr_clip_region(x, y, w, h, + 0, 0, + pr->window_width, pr->window_height, + &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); @@ -1117,19 +1117,19 @@ static void pr_border_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h) if (pr->vis_width < pr->window_width) { if (pr->x_offset > 0 && - util_clip_region(x, y, w, h, - 0, 0, - pr->x_offset, pr->window_height, - &rx, &ry, &rw, &rh)) + pr_clip_region(x, y, w, h, + 0, 0, + pr->x_offset, pr->window_height, + &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } if (pr->window_width - pr->vis_width - pr->x_offset > 0 && - util_clip_region(x, y, w, h, - pr->x_offset + pr->vis_width, 0, - pr->window_width - pr->vis_width - pr->x_offset, pr->window_height, - &rx, &ry, &rw, &rh)) + pr_clip_region(x, y, w, h, + pr->x_offset + pr->vis_width, 0, + pr->window_width - pr->vis_width - pr->x_offset, pr->window_height, + &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); @@ -1138,19 +1138,19 @@ static void pr_border_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h) if (pr->vis_height < pr->window_height) { if (pr->y_offset > 0 && - util_clip_region(x, y, w, h, - pr->x_offset, 0, - pr->vis_width, pr->y_offset, - &rx, &ry, &rw, &rh)) + pr_clip_region(x, y, w, h, + pr->x_offset, 0, + pr->vis_width, pr->y_offset, + &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } if (pr->window_height - pr->vis_height - pr->y_offset > 0 && - util_clip_region(x, y, w, h, - pr->x_offset, pr->y_offset + pr->vis_height, - pr->vis_width, pr->window_height - pr->vis_height - pr->y_offset, - &rx, &ry, &rw, &rh)) + pr_clip_region(x, y, w, h, + pr->x_offset, pr->y_offset + pr->vis_height, + pr->vis_width, pr->window_height - pr->vis_height - pr->y_offset, + &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); @@ -1408,9 +1408,9 @@ static void pr_source_tile_changed(PixbufRenderer *pr, gint x, gint y, gint widt st = work->data; work = work->next; - if (util_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height, - x, y, width, height, - &rx, &ry, &rw, &rh)) + if (pr_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height, + x, y, width, height, + &rx, &ry, &rw, &rh)) { GdkPixbuf *pixbuf; @@ -1449,9 +1449,9 @@ static gint pr_source_tile_render(PixbufRenderer *pr, ImageTile *it, st = work->data; work = work->next; - if (util_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height, - it->x + x, it->y + y, w, h, - &rx, &ry, &rw, &rh)) + if (pr_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height, + it->x + x, it->y + y, w, h, + &rx, &ry, &rw, &rh)) { if (st->blank) { @@ -1508,9 +1508,9 @@ static gint pr_source_tile_render(PixbufRenderer *pr, ImageTile *it, stw = ceil ((double)(st->x + pr->source_tile_width) * scale_x) - stx; sth = ceil ((double)(st->y + pr->source_tile_height) * scale_y) - sty; - if (util_clip_region(stx, sty, stw, sth, - it->x + x, it->y + y, w, h, - &rx, &ry, &rw, &rh)) + if (pr_clip_region(stx, sty, stw, sth, + it->x + x, it->y + y, w, h, + &rx, &ry, &rw, &rh)) { if (st->blank) { diff --git a/src/pixbuf_util.c b/src/pixbuf_util.c index 2690515d..59347473 100644 --- a/src/pixbuf_util.c +++ b/src/pixbuf_util.c @@ -15,6 +15,8 @@ #include "icons/icons_inline.h" +#include + /* *----------------------------------------------------------------------------- @@ -120,6 +122,33 @@ GdkPixbuf *pixbuf_inline(const gchar *key) return NULL; } +/* + *----------------------------------------------------------------------------- + * misc utils + *----------------------------------------------------------------------------- + */ + +gint util_clip_region(gint x, gint y, gint w, gint h, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint *rx, gint *ry, gint *rw, gint *rh) +{ + if (clip_x + clip_w <= x || + clip_x >= x + w || + clip_y + clip_h <= y || + clip_y >= y + h) + { + return FALSE; + } + + *rx = MAX(x, clip_x); + *rw = MIN((x + w), (clip_x + clip_w)) - *rx; + + *ry = MAX(y, clip_y); + *rh = MIN((y + h), (clip_y + clip_h)) - *ry; + + return TRUE; +} + /* *----------------------------------------------------------------------------- * pixbuf rotation @@ -348,7 +377,7 @@ GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gint mirror, gint flip) /* *----------------------------------------------------------------------------- - * pixbuf drawing + * pixbuf drawing (rectangles) *----------------------------------------------------------------------------- */ @@ -624,3 +653,525 @@ void pixbuf_draw_layout(GdkPixbuf *pixbuf, PangoLayout *layout, GtkWidget *widge g_object_unref(buffer); } +/* + *----------------------------------------------------------------------------- + * pixbuf drawing (triangle) + *----------------------------------------------------------------------------- + */ + +void util_clip_triangle(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, + gint *rx, gint *ry, gint *rw, gint *rh) +{ + gint tx, ty, tw, th; + + tx = MIN(x1, x2); + tx = MIN(tx, x3); + ty = MIN(y1, y2); + ty = MIN(ty, y3); + tw = MAX(abs(x1 - x2), abs(x2 - x3)); + tw = MAX(tw, abs(x3 - x1)); + th = MAX(abs(y1 - y2), abs(y2 - y3)); + th = MAX(th, abs(y3 - y1)); + + *rx = tx; + *ry = ty; + *rw = tw; + *rh = th; +} + +void pixbuf_draw_triangle(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, + guint8 r, guint8 g, guint8 b, guint8 a) +{ + gint p_alpha; + gint pw, ph, prs; + gint rx, ry, rw, rh; + gint tx, ty, tw, th; + gint fx1, fy1; + gint fx2, fy2; + gint fw, fh; + guchar *p_pix; + guchar *pp; + gint p_step; + gdouble slope1, slope2; + gint slope1_x, slope1_y; + gint y; + gint t; + gint middle = FALSE; + + if (!pb) return; + + pw = gdk_pixbuf_get_width(pb); + ph = gdk_pixbuf_get_height(pb); + + if (!util_clip_region(0, 0, pw, ph, + clip_x, clip_y, clip_w, clip_h, + &rx, &ry, &rw, &rh)) return; + + util_clip_triangle(x1, y1, x2, y2, x3, y3, + &tx, &ty, &tw, &th); + + if (!util_clip_region(rx, ry, rw, rh, + tx, ty, tw, th, + &fx1, &fy1, &fw, &fh)) return; + fx2 = fx1 + fw; + fy2 = fy1 + fh; + + p_alpha = gdk_pixbuf_get_has_alpha(pb); + prs = gdk_pixbuf_get_rowstride(pb); + p_pix = gdk_pixbuf_get_pixels(pb); + + p_step = (p_alpha) ? 4 : 3; + + if (y1 > y2) + { + t = x1; x1 = x2; x2 = t; + t = y1; y1 = y2; y2 = t; + } + if (y2 > y3) + { + t = x2; x2 = x3; x3 = t; + t = y2; y2 = y3; y3 = t; + } + if (y1 > y2) + { + t = x1; x1 = x2; x2 = t; + t = y1; y1 = y2; y2 = t; + } + + slope1 = (gdouble)(y2 - y1); + if (slope1) slope1 = (gdouble)(x2 - x1) / slope1; + slope1_x = x1; + slope1_y = y1; + slope2 = (gdouble)(y3 - y1); + if (slope2) slope2 = (gdouble)(x3 - x1) / slope2; + + for (y = fy1; y < fy2; y++) + { + gint xa, xb; + + if (!middle && y > y2) + { + slope1 = (gdouble)(y3 - y2); + if (slope1) slope1 = (gdouble)(x3 - x2) / slope1; + slope1_x = x2; + slope1_y = y2; + + middle = TRUE; + } + + xa = slope1_x + ((gdouble)slope1 * (y - slope1_y) + 0.5); + xb = x1 + ((gdouble)slope2 * (y - y1) + 0.5); + + if (xa > xb) + { + t = xa; xa = xb; xb = t; + } + + xa = CLAMP(xa, fx1, fx2); + xb = CLAMP(xb, fx1, fx2); + + pp = p_pix + y * prs + xa * p_step; + + while (xa < xb) + { + *pp = (r * a + *pp * (256-a)) >> 8; + pp++; + *pp = (g * a + *pp * (256-a)) >> 8; + pp++; + *pp = (b * a + *pp * (256-a)) >> 8; + pp++; + if (p_alpha) pp++; + + xa++; + } + } +} + +/* + *----------------------------------------------------------------------------- + * pixbuf drawing (line) + *----------------------------------------------------------------------------- + */ + +static gint util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, gdouble clip_h, + gdouble x1, gdouble y1, gdouble x2, gdouble y2, + gdouble *rx1, gdouble *ry1, gdouble *rx2, gdouble *ry2) +{ + gint flip = FALSE; + gdouble d; + + if (x1 > x2) + { + gdouble t; + + t = x1; x1 = x2; x2 = t; + t = y1; y1 = y2; y2 = t; + flip = TRUE; + } + + if (x2 < clip_x || x1 > clip_x + clip_w) return FALSE; + + if (y1 < y2) + { + if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE; + } + else + { + if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE; + } + +#if 0 + if (x1 >= clip_x && x2 <= clip_x + clip_w) + { + if (y1 < y2) + { + if (y1 >= clip_y && y2 <= clip_y + clip_h) return TRUE; + } + else + { + if (y2 >= clip_y && y1 <= clip_y + clip_h) return TRUE; + } + } +#endif + + d = x2 - x1; + if (d > 0.0) + { + gdouble slope; + + slope = (y2 - y1) / d; + if (x1 < clip_x) + { + y1 = y1 + slope * (clip_x - x1); + x1 = clip_x; + } + if (x2 > clip_x + clip_w) + { + y2 = y2 + slope * (clip_x + clip_w - x2); + x2 = clip_x + clip_w; + } + } + + if (y1 < y2) + { + if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE; + } + else + { + gdouble t; + + if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE; + + t = x1; x1 = x2; x2 = t; + t = y1; y1 = y2; y2 = t; + flip = !flip; + } + + d = y2 - y1; + if (d > 0.0) + { + gdouble slope; + + slope = (x2 - x1) / d; + if (y1 < clip_y) + { + x1 = x1 + slope * (clip_y - y1); + y1 = clip_y; + } + if (y2 > clip_y + clip_h) + { + x2 = x2 + slope * (clip_y + clip_h - y2); + y2 = clip_y + clip_h; + } + } + + if (flip) + { + *rx1 = x2; + *ry1 = y2; + *rx2 = x1; + *ry2 = y1; + } + else + { + *rx1 = x1; + *ry1 = y1; + *rx2 = x2; + *ry2 = y2; + } + + return TRUE; +} + +void pixbuf_draw_line(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x1, gint y1, gint x2, gint y2, + guint8 r, guint8 g, guint8 b, guint8 a) +{ + gint p_alpha; + gint pw, ph, prs; + gint rx, ry, rw, rh; + gdouble rx1, ry1, rx2, ry2; + guchar *p_pix; + guchar *pp; + gint p_step; + gdouble slope; + gdouble x, y; + gint px, py; + gint cx1, cy1, cx2, cy2; + + if (!pb) return; + + pw = gdk_pixbuf_get_width(pb); + ph = gdk_pixbuf_get_height(pb); + + if (!util_clip_region(0, 0, pw, ph, + clip_x, clip_y, clip_w, clip_h, + &rx, &ry, &rw, &rh)) return; + if (!util_clip_line((gdouble)rx, (gdouble)ry, (gdouble)rw, (gdouble)rh, + (gdouble)x1, (gdouble)y1, (gdouble)x2, (gdouble)y2, + &rx1, &ry1, &rx2, &ry2)) return; + + cx1 = rx; + cy1 = ry; + cx2 = rx + rw; + cy2 = ry + rh; + + p_alpha = gdk_pixbuf_get_has_alpha(pb); + prs = gdk_pixbuf_get_rowstride(pb); + p_pix = gdk_pixbuf_get_pixels(pb); + + p_step = (p_alpha) ? 4 : 3; + + if (fabs(rx2 - rx1) > fabs(ry2 - ry1)) + { + if (rx1 > rx2) + { + gdouble t; + t = rx1; rx1 = rx2; rx2 = t; + t = ry1; ry1 = ry2; ry2 = t; + } + + slope = rx2 - rx1; + if (slope != 0.0) slope = (ry2 - ry1) / slope; + for (x = rx1; x < rx2; x += 1.0) + { + px = (gint)(x + 0.5); + py = (gint)(ry1 + (x - rx1) * slope + 0.5); + + if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2) + { + pp = p_pix + py * prs + px * p_step; + *pp = (r * a + *pp * (256-a)) >> 8; + pp++; + *pp = (g * a + *pp * (256-a)) >> 8; + pp++; + *pp = (b * a + *pp * (256-a)) >> 8; + } + } + } + else + { + if (ry1 > ry2) + { + gdouble t; + t = rx1; rx1 = rx2; rx2 = t; + t = ry1; ry1 = ry2; ry2 = t; + } + + slope = ry2 - ry1; + if (slope != 0.0) slope = (rx2 - rx1) / slope; + for (y = ry1; y < ry2; y += 1.0) + { + px = (gint)(rx1 + (y - ry1) * slope + 0.5); + py = (gint)(y + 0.5); + + if (px >= cx1 && px < cx2 && py >= cy1 && py < cy2) + { + pp = p_pix + py * prs + px * p_step; + *pp = (r * a + *pp * (256-a)) >> 8; + pp++; + *pp = (g * a + *pp * (256-a)) >> 8; + pp++; + *pp = (b * a + *pp * (256-a)) >> 8; + } + } + } +} + +/* + *----------------------------------------------------------------------------- + * pixbuf drawing (fades and shadows) + *----------------------------------------------------------------------------- + */ + +static void pixbuf_draw_fade_linear(guchar *p_pix, gint prs, gint p_alpha, + gint s, gint vertical, gint border, + gint x1, gint y1, gint x2, gint y2, + guint8 r, guint8 g, guint8 b, guint8 a) +{ + guchar *pp; + gint p_step; + guint8 n = a; + gint i, j; + + p_step = (p_alpha) ? 4 : 3; + for (j = y1; j < y2; j++) + { + pp = p_pix + j * prs + x1 * p_step; + if (!vertical) n = a - a * abs(j - s) / border; + for (i = x1; i < x2; i++) + { + if (vertical) n = a - a * abs(i - s) / border; + *pp = (r * n + *pp * (256-n)) >> 8; + pp++; + *pp = (g * n + *pp * (256-n)) >> 8; + pp++; + *pp = (b * n + *pp * (256-n)) >> 8; + pp++; + if (p_alpha) pp++; + } + } +} + +static void pixbuf_draw_fade_radius(guchar *p_pix, gint prs, gint p_alpha, + gint sx, gint sy, gint border, + gint x1, gint y1, gint x2, gint y2, + guint8 r, guint8 g, guint8 b, guint8 a) +{ + guchar *pp; + gint p_step; + gint i, j; + + p_step = (p_alpha) ? 4 : 3; + for (j = y1; j < y2; j++) + { + pp = p_pix + j * prs + x1 * p_step; + for (i = x1; i < x2; i++) + { + guint8 n; + gint r; + + r = MIN(border, (gint)sqrt((i-sx)*(i-sx) + (j-sy)*(j-sy))); + n = a - a * r / border; + *pp = (r * n + *pp * (256-n)) >> 8; + pp++; + *pp = (g * n + *pp * (256-n)) >> 8; + pp++; + *pp = (b * n + *pp * (256-n)) >> 8; + pp++; + if (p_alpha) pp++; + } + } +} + +void pixbuf_draw_shadow(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x, gint y, gint w, gint h, gint border, + guint8 r, guint8 g, guint8 b, guint8 a) +{ + gint p_alpha; + gint pw, ph, prs; + gint rx, ry, rw, rh; + gint fx, fy, fw, fh; + guchar *p_pix; + + if (!pb) return; + + pw = gdk_pixbuf_get_width(pb); + ph = gdk_pixbuf_get_height(pb); + + if (!util_clip_region(0, 0, pw, ph, + clip_x, clip_y, clip_w, clip_h, + &rx, &ry, &rw, &rh)) return; + + p_alpha = gdk_pixbuf_get_has_alpha(pb); + prs = gdk_pixbuf_get_rowstride(pb); + p_pix = gdk_pixbuf_get_pixels(pb); + + if (util_clip_region(x + border, y + border, w - border * 2, h - border * 2, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_rect_fill(pb, fx, fy, fw, fh, r, g, b, a); + } + + if (border < 1) return; + + if (util_clip_region(x, y + border, border, h - border * 2, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_linear(p_pix, prs, p_alpha, + x + border, TRUE, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x + w - border, y + border, border, h - border * 2, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_linear(p_pix, prs, p_alpha, + x + w - border, TRUE, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x + border, y, w - border * 2, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_linear(p_pix, prs, p_alpha, + y + border, FALSE, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x + border, y + h - border, w - border * 2, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_linear(p_pix, prs, p_alpha, + y + h - border, FALSE, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x, y, border, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_radius(p_pix, prs, p_alpha, + x + border, y + border, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x + w - border, y, border, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_radius(p_pix, prs, p_alpha, + x + w - border, y + border, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x, y + h - border, border, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_radius(p_pix, prs, p_alpha, + x + border, y + h - border, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } + if (util_clip_region(x + w - border, y + h - border, border, border, + rx, ry, rw, rh, + &fx, &fy, &fw, &fh)) + { + pixbuf_draw_fade_radius(p_pix, prs, p_alpha, + x + w - border, y + h - border, border, + fx, fy, fx + fw, fy + fh, + r, g, b, a); + } +} + + diff --git a/src/pixbuf_util.h b/src/pixbuf_util.h index 87cae568..dcdf9f32 100644 --- a/src/pixbuf_util.h +++ b/src/pixbuf_util.h @@ -59,6 +59,30 @@ void pixbuf_draw_layout(GdkPixbuf *pixbuf, PangoLayout *layout, GtkWidget *widge guint8 r, guint8 g, guint8 b, guint8 a); +void pixbuf_draw_triangle(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, + guint8 r, guint8 g, guint8 b, guint8 a); + +void pixbuf_draw_line(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x1, gint y1, gint x2, gint y2, + guint8 r, guint8 g, guint8 b, guint8 a); + +void pixbuf_draw_shadow(GdkPixbuf *pb, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint x, gint y, gint w, gint h, gint border, + guint8 r, guint8 g, guint8 b, guint8 a); + +/* clipping utils */ + +gint util_clip_region(gint x, gint y, gint w, gint h, + gint clip_x, gint clip_y, gint clip_w, gint clip_h, + gint *rx, gint *ry, gint *rw, gint *rh); +void util_clip_triangle(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, + gint *rx, gint *ry, gint *rw, gint *rh); + + #endif