Index: app/display/gimpdisplayshell-preview.c =================================================================== RCS file: /cvs/gnome/gimp/app/display/gimpdisplayshell-preview.c,v retrieving revision 1.14 diff -u -p -r1.14 gimpdisplayshell-preview.c --- app/display/gimpdisplayshell-preview.c 7 Apr 2006 09:30:37 -0000 1.14 +++ app/display/gimpdisplayshell-preview.c 19 Aug 2006 00:32:03 -0000 @@ -26,10 +26,12 @@ #include "core/gimpimage.h" #include "core/gimpdrawable.h" #include "core/gimpchannel.h" +#include "core/gimptoolinfo.h" #include "base/tile-manager.h" #include "tools/gimpperspectivetool.h" +#include "tools/gimptransformoptions.h" #include "tools/gimptransformtool.h" #include "tools/tool_manager.h" @@ -53,29 +55,39 @@ static void gimp_display_shell_draw_q gint *x, gint *y, gfloat *u, - gfloat *v); + gfloat *v, + gint opacity); static void gimp_display_shell_draw_tri (GimpDrawable *texture, GdkDrawable *dest, + GdkPixbuf *area, + gint area_offx, + gint area_offy, GimpChannel *mask, gint mask_offx, gint mask_offy, gint *x, gint *y, gfloat *u, - gfloat *v); + gfloat *v, + gint opacity); static void gimp_display_shell_draw_tri_row (GimpDrawable *texture, GdkDrawable *dest, - GdkPixbuf *row, + GdkPixbuf *area, + gint area_offx, + gint area_offy, gint x1, gfloat u1, gfloat v1, gint x2, gfloat u2, gfloat v2, - gint y); + gint y, + gint opacity); static void gimp_display_shell_draw_tri_row_mask (GimpDrawable *texture, GdkDrawable *dest, - GdkPixbuf *row, + GdkPixbuf *area, + gint area_offx, + gint area_offy, GimpChannel *mask, gint mask_offx, gint mask_offy, @@ -85,7 +97,8 @@ static void gimp_display_shell_draw_t gint x2, gfloat u2, gfloat v2, - gint y); + gint y, + gint opacity); static void gimp_display_shell_trace_tri_edge (gint *dest, gint x1, gint y1, @@ -94,187 +107,224 @@ static void gimp_display_shell_trace_ /* public functions */ +/** + * gimp_display_shell_preview_transform: + * @shell: the #GimpDisplayShell + * + * If the active tool as reported by tool_manager_get_active() is a + * #GimpTransformTool and the tool has a valid drawable, and the tool has + * use_grid true (which, incidentally, is not the same thing as the preview + * type), and the area of the transformed preview is convex, + * then proceed with drawing the preview. + * + * The preview area is divided into 1 or more quadrilaterals, and drawn with + * gimp_display_shell_draw_quad(), which in turn breaks it down into 2 + * triangles, and draws row by row. If the tool is the Perspective tool, then + * more small quadrilaterals are used to compensate for the little rectangles + * not being the same size. In other words, all the transform tools are + * affine transformations except perspective, so approximate it with a + * few subdivisions. + **/ void gimp_display_shell_preview_transform (GimpDisplayShell *shell) { g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); - if (gimp_display_shell_get_show_transform (shell)) - { - GimpTool *tool; - GimpTransformTool *tr_tool; - gdouble z1, z2, z3, z4; + if (! gimp_display_shell_get_show_transform (shell) || ! shell->canvas) + return; - tool = tool_manager_get_active (shell->display->image->gimp); + GimpTool *tool; + GimpTransformTool *tr_tool; + gdouble z1, z2, z3, z4; - if (! GIMP_IS_TRANSFORM_TOOL (tool) || - ! GIMP_IS_DRAWABLE (tool->drawable)) - return; + tool = tool_manager_get_active (shell->display->image->gimp); + + if (! GIMP_IS_TRANSFORM_TOOL (tool) || + ! GIMP_IS_DRAWABLE (tool->drawable)) + return; - tr_tool = GIMP_TRANSFORM_TOOL (tool); + tr_tool = GIMP_TRANSFORM_TOOL (tool); - if (! tr_tool->use_grid) - return; + if (! tr_tool->use_grid) + return; - z1 = ((tr_tool->tx2 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1) - - (tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty2 - tr_tool->ty1)); - z2 = ((tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty3 - tr_tool->ty1) - - (tr_tool->tx3 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1)); - z3 = ((tr_tool->tx4 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2) - - (tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty4 - tr_tool->ty2)); - z4 = ((tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty1 - tr_tool->ty2) - - (tr_tool->tx1 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2)); + z1 = ((tr_tool->tx2 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1) - + (tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty2 - tr_tool->ty1)); + z2 = ((tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty3 - tr_tool->ty1) - + (tr_tool->tx3 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1)); + z3 = ((tr_tool->tx4 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2) - + (tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty4 - tr_tool->ty2)); + z4 = ((tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty1 - tr_tool->ty2) - + (tr_tool->tx1 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2)); + + /* only draw convex polygons */ + + if (! ((z1 * z2 > 0) && (z3 * z4 > 0))) return; + + GimpChannel *mask; + gint mask_x1, mask_y1; + gint mask_x2, mask_y2; + gint mask_offx, mask_offy; + + gint columns, rows; + gint j, k, sub; + + /* x and y get filled with the screen coordinates of each corner of + * each quadrilateral subdivision of the transformed area. u and v + * are the corresponding points in the mask + */ + gfloat du, dv, dx, dy; + gint x [MAX_SUB_COLS * MAX_SUB_ROWS][4], + y [MAX_SUB_COLS * MAX_SUB_ROWS][4]; + gfloat u [MAX_SUB_COLS * MAX_SUB_ROWS][4], + v [MAX_SUB_COLS * MAX_SUB_ROWS][4]; + gint preview_opacity; + + preview_opacity = + GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options) + ->preview_opacity * 255 / 100; + + mask = NULL; + mask_offx = mask_offy = 0; + + if (gimp_drawable_mask_bounds (tool->drawable, + &mask_x1, &mask_y1, + &mask_x2, &mask_y2)) + { + mask = gimp_image_get_mask (shell->display->image); - /* only draw convex polygons */ + gimp_item_offsets (GIMP_ITEM (tool->drawable), + &mask_offx, &mask_offy); + } - if ((z1 * z2 > 0) && (z3 * z4 > 0)) - { - GimpChannel *mask; - gint mask_x1, mask_y1; - gint mask_x2, mask_y2; - gint mask_offx, mask_offy; - - gint columns, rows; - gint j, k, sub; - - gfloat du, dv, dx, dy; - gint x [MAX_SUB_COLS * MAX_SUB_ROWS][4], - y [MAX_SUB_COLS * MAX_SUB_ROWS][4]; - gfloat u [MAX_SUB_COLS * MAX_SUB_ROWS][4], - v [MAX_SUB_COLS * MAX_SUB_ROWS][4]; - - mask = NULL; - mask_offx = mask_offy = 0; - - if (gimp_drawable_mask_bounds (tool->drawable, - &mask_x1, &mask_y1, - &mask_x2, &mask_y2)) - { - mask = gimp_image_get_mask (shell->display->image); - - gimp_item_offsets (GIMP_ITEM (tool->drawable), - &mask_offx, &mask_offy); - } - - if (GIMP_IS_PERSPECTIVE_TOOL (tr_tool)) - { - /* approximate perspective transform by subdivision - * - * increase number of columns/rows to increase precision - */ - columns = MAX_SUB_COLS; - rows = MAX_SUB_ROWS; - } - else - { - /* for affine transforms subdivision has no effect - */ - columns = 1; - rows = 1; - } + if (GIMP_IS_PERSPECTIVE_TOOL (tr_tool)) + { + /* approximate perspective transform by subdivision + * + * increase number of columns/rows to increase precision + */ + columns = MAX_SUB_COLS; + rows = MAX_SUB_ROWS; + } + else + { + /* for affine transforms subdivision has no effect + */ + columns = 1; + rows = 1; + } - dx = (tr_tool->x2 - tr_tool->x1) / ((gfloat) columns); - dy = (tr_tool->y2 - tr_tool->y1) / ((gfloat) rows); + dx = (tr_tool->x2 - tr_tool->x1) / ((gfloat) columns); + dy = (tr_tool->y2 - tr_tool->y1) / ((gfloat) rows); - du = (mask_x2 - mask_x1) / ((gfloat) columns); - dv = (mask_y2 - mask_y1) / ((gfloat) rows); + du = (mask_x2 - mask_x1) / ((gfloat) columns); + dv = (mask_y2 - mask_y1) / ((gfloat) rows); #define CALC_VERTEX(col, row, sub, index) \ - { \ - gdouble tx1, ty1; \ - gdouble tx2, ty2; \ + { \ + gdouble tx1, ty1; \ + gdouble tx2, ty2; \ \ - u [sub][index] = tr_tool->x1 + (dx * (col + (index & 1))); \ - v [sub][index] = tr_tool->y1 + (dy * (row + (index >> 1))); \ + u [sub][index] = tr_tool->x1 + (dx * (col + (index & 1))); \ + v [sub][index] = tr_tool->y1 + (dy * (row + (index >> 1))); \ \ - gimp_matrix3_transform_point (&tr_tool->transform, \ - u[sub][index], v[sub][index], \ - &tx1, &ty1); \ + gimp_matrix3_transform_point (&tr_tool->transform, \ + u[sub][index], v[sub][index], \ + &tx1, &ty1); \ \ - gimp_display_shell_transform_xy_f (shell, \ - tx1, ty1, \ - &tx2, &ty2, \ - FALSE); \ - x [sub][index] = (gint) tx2; \ - y [sub][index] = (gint) ty2; \ + gimp_display_shell_transform_xy_f (shell, \ + tx1, ty1, \ + &tx2, &ty2, \ + FALSE); \ + x [sub][index] = (gint) tx2; \ + y [sub][index] = (gint) ty2; \ \ - u [sub][index] = mask_x1 + (du * (col + (index & 1))); \ - v [sub][index] = mask_y1 + (dv * (row + (index >> 1))); \ - } + u [sub][index] = mask_x1 + (du * (col + (index & 1))); \ + v [sub][index] = mask_y1 + (dv * (row + (index >> 1))); \ + } #define COPY_VERTEX(subdest, idest, subsrc, isrc) \ - x [subdest][idest] = x [subsrc][isrc]; \ - y [subdest][idest] = y [subsrc][isrc]; \ - u [subdest][idest] = u [subsrc][isrc]; \ - v [subdest][idest] = v [subsrc][isrc]; - - /* - * upper left corner subdivision: calculate all vertices - */ - - for (j = 0; j < 4; j++) - { - CALC_VERTEX (0, 0, 0, j); - } - - /* - * top row subdivisions: calculate only right side vertices - */ - - for (j = 1; j < columns; j++) - { - COPY_VERTEX (j, 0, j - 1, 1); - CALC_VERTEX (j, 0, j, 1); - COPY_VERTEX (j, 2, j - 1, 3); - CALC_VERTEX (j, 0, j, 3); - } - - /* - * left column subdivisions: calculate only bottom side vertices - */ - - for (j = 1, sub = columns; j < rows; j++, sub += columns) - { - COPY_VERTEX (sub, 0, sub - columns, 2); - COPY_VERTEX (sub, 1, sub - columns, 3); - CALC_VERTEX (0, j, sub, 2); - CALC_VERTEX (0, j, sub, 3); - } - - /* - * the rest: calculate only the bottom-right vertex - */ - - for (j = 1, sub = columns; j < rows; j++) - { - sub++; - - for (k = 1; k < columns; k++, sub++) - { - COPY_VERTEX (sub, 0, sub - 1, 1); - COPY_VERTEX (sub, 1, sub - columns, 3); - COPY_VERTEX (sub, 2, sub - 1, 3); - CALC_VERTEX (k, j, sub, 3); - } - } + x [subdest][idest] = x [subsrc][isrc]; \ + y [subdest][idest] = y [subsrc][isrc]; \ + u [subdest][idest] = u [subsrc][isrc]; \ + v [subdest][idest] = v [subsrc][isrc]; + + /* + * upper left corner subdivision: calculate all vertices + */ -#undef CALC_VERTEX -#undef COPY_VERTEX + for (j = 0; j < 4; j++) + { + CALC_VERTEX (0, 0, 0, j); + } + + /* + * top row subdivisions: calculate only right side vertices + */ + + for (j = 1; j < columns; j++) + { + COPY_VERTEX (j, 0, j - 1, 1); + CALC_VERTEX (j, 0, j, 1); + COPY_VERTEX (j, 2, j - 1, 3); + CALC_VERTEX (j, 0, j, 3); + } + + /* + * left column subdivisions: calculate only bottom side vertices + */ - k = columns * rows; - for (j = 0; j < k; j++) - gimp_display_shell_draw_quad (tool->drawable, - GDK_DRAWABLE (GTK_WIDGET (shell->canvas)->window), - mask, mask_offx, mask_offy, - x [j], y [j], u [j], v [j]); + for (j = 1, sub = columns; j < rows; j++, sub += columns) + { + COPY_VERTEX (sub, 0, sub - columns, 2); + COPY_VERTEX (sub, 1, sub - columns, 3); + CALC_VERTEX (0, j, sub, 2); + CALC_VERTEX (0, j, sub, 3); + } + /* + * the rest: calculate only the bottom-right vertex + */ + + for (j = 1, sub = columns; j < rows; j++) + { + sub++; + + for (k = 1; k < columns; k++, sub++) + { + COPY_VERTEX (sub, 0, sub - 1, 1); + COPY_VERTEX (sub, 1, sub - columns, 3); + COPY_VERTEX (sub, 2, sub - 1, 3); + CALC_VERTEX (k, j, sub, 3); } } + +#undef CALC_VERTEX +#undef COPY_VERTEX + + k = columns * rows; + for (j = 0; j < k; j++) + gimp_display_shell_draw_quad (tool->drawable, + GDK_DRAWABLE (GTK_WIDGET (shell->canvas)->window), + mask, mask_offx, mask_offy, + x [j], y [j], u [j], v [j], + preview_opacity); + } /* private functions */ +/** + * gimp_display_shell_draw_quad: + * @texture: the #GimpDrawable to be previewed + * @dest: the #GdkDrawable for that @texture lives on + * @mask: a #GimpChannel + * @opacity: the opacity of the preview + * + * Take a quadrilateral, divide it into two triangles, and draw those + * with gimp_display_shell_draw_tri(). + **/ static void gimp_display_shell_draw_quad (GimpDrawable *texture, GdkDrawable *dest, @@ -284,44 +334,109 @@ gimp_display_shell_draw_quad (GimpDrawab gint *x, gint *y, gfloat *u, - gfloat *v) + gfloat *v, + gint opacity) { - gint x2 [3], y2 [3]; - gfloat u2 [3], v2 [3]; + gint x2 [3], y2 [3]; + gfloat u2 [3], v2 [3]; + gint minx, maxx, miny, maxy; /* screen bounds of the quad */ + gint dwidth, dheight; /* dimensions of dest */ + GdkPixbuf *area; /* quad sized area with dest pixels */ + gint c; + g_return_if_fail(GDK_IS_DRAWABLE (dest)); + x2 [0] = x [3]; y2 [0] = y [3]; u2 [0] = u [3]; v2 [0] = v [3]; x2 [1] = x [2]; y2 [1] = y [2]; u2 [1] = u [2]; v2 [1] = v [2]; x2 [2] = x [1]; y2 [2] = y [1]; u2 [2] = u [1]; v2 [2] = v [1]; - gimp_display_shell_draw_tri (texture, dest, mask, mask_offx, mask_offy, - x, y, u, v); - gimp_display_shell_draw_tri (texture, dest, mask, mask_offx, mask_offy, - x2, y2, u2, v2); + /* Allocate a box around the quad to compute preview data into + * and fill it with the original window contents. + */ + + gdk_drawable_get_size (dest, &dwidth, &dheight); + + /* find bounds of quad in order to only grab as much of dest as needed */ + + minx = maxx = x[0]; + miny = maxy = y[0]; + for (c = 1; c < 4; c++) + { + if (x [c] < minx) minx = x [c]; + else if (x [c] > maxx) maxx = x [c]; + + if (y [c] < miny) miny = y [c]; + else if (y [c] > maxy) maxy = y [c]; + } + if (minx < 0) minx = 0; + if (miny < 0) miny = 0; + if (maxx > dwidth - 1) maxx=dwidth - 1; + if (maxy > dheight - 1) maxy=dheight - 1; + + area = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + mask ? TRUE : gimp_drawable_has_alpha (texture), + 8, maxx - minx + 1, maxy - miny + 1); + g_return_if_fail (area != NULL); + + + /* get original data from dest in order to potentially take + * into account opacity + */ + + if (opacity != 255) + gdk_pixbuf_get_from_drawable (area, dest, NULL, minx, miny, + 0, 0, maxx - minx + 1, maxy - miny + 1); + + gimp_display_shell_draw_tri (texture, dest, area, minx, miny, + mask, mask_offx, mask_offy, + x, y, u, v, opacity); + gimp_display_shell_draw_tri (texture, dest, area, minx, miny, + mask, mask_offx, mask_offy, + x2, y2, u2, v2, opacity); + + g_object_unref (area); } +/** + * gimp_display_shell_draw_tri: + * @texture: the thing being transformed + * @dest: the #GdkDrawable for that @texture lives on + * @area: has prefetched pixel data of dest + * @area_offx: x coordinate of area in dest + * @area_offy: y coordinate of area in dest + * @x: Array of the three x coords of triangle + * @y: Array of the three y coords of triangle + * + * This draws a triangle onto dest by breaking it down into pixel rows, and + * then calling gimp_display_shell_draw_tri_row() and + * gimp_display_shell_draw_tri_row_mask() to do the actual pixel changing. + **/ static void gimp_display_shell_draw_tri (GimpDrawable *texture, GdkDrawable *dest, + GdkPixbuf *area, + gint area_offx, + gint area_offy, GimpChannel *mask, gint mask_offx, gint mask_offy, gint *x, gint *y, gfloat *u, /* texture coords */ - gfloat *v) /* 0.0 ... tex width, height */ + gfloat *v, /* 0.0 ... tex width, height */ + gint opacity) { - GdkPixbuf *row; gint dwidth, dheight; /* clip boundary */ gint j, k; gint ry; gint *l_edge, *r_edge; /* arrays holding x-coords of edge pixels */ - gint *left, *right; - gfloat dul, dvl, dur, dvr; /* left and right texture coord deltas */ - gfloat u_l, v_l, u_r, v_r; /* left and right texture coord pairs */ + gint *left, *right; /* temp pointers into l_edge and r_edge */ + gfloat dul, dvl, dur, dvr; /* left and right texture coord deltas */ + gfloat u_l, v_l, u_r, v_r; /* left and right texture coord pairs */ - if (! GIMP_IS_DRAWABLE (texture) || - ! GDK_IS_DRAWABLE (dest)) - return; + g_return_if_fail (GIMP_IS_DRAWABLE (texture)); + g_return_if_fail (GDK_IS_DRAWABLE (dest)); + g_return_if_fail (GDK_IS_PIXBUF (area)); g_return_if_fail (x != NULL && y != NULL && u != NULL && v != NULL); @@ -330,12 +445,7 @@ gimp_display_shell_draw_tri (GimpDrawabl u_l = v_l = u_r = v_r = 0; gdk_drawable_get_size (dest, &dwidth, &dheight); - - row = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - mask ? TRUE : gimp_drawable_has_alpha (texture), - 8, dwidth, 1); - g_return_if_fail (row != NULL); - + /* sort vertices in order of y-coordinate */ for (j = 0; j < 3; j++) @@ -379,27 +489,36 @@ gimp_display_shell_draw_tri (GimpDrawabl u_r = u [0]; v_r = v [0]; - for (ry = y [0]; ry < y [1]; ry++) - { - if (ry >= 0 && ry < dheight) - { - if (mask) - gimp_display_shell_draw_tri_row_mask - (texture, dest, row, + if (mask) + for (ry = y [0]; ry < y [1]; ry++) + { + if (ry >= 0 && ry < dheight) + gimp_display_shell_draw_tri_row_mask + (texture, dest, + area, area_offx, area_offy, mask, mask_offx, mask_offy, *left, u_l, v_l, *right, u_r, v_r, - ry); - else - gimp_display_shell_draw_tri_row (texture, dest, row, - *left, u_l, v_l, - *right, u_r, v_r, - ry); - } - left ++; right ++; - u_l += dul; v_l += dvl; - u_r += dur; v_r += dvr; - } + ry, + opacity); + left ++; right ++; + u_l += dul; v_l += dvl; + u_r += dur; v_r += dvr; + } + else + for (ry = y [0]; ry < y [1]; ry++) + { + if (ry >= 0 && ry < dheight) + gimp_display_shell_draw_tri_row (texture, dest, + area, area_offx, area_offy, + *left, u_l, v_l, + *right, u_r, v_r, + ry, + opacity); + left ++; right ++; + u_l += dul; v_l += dvl; + u_r += dur; v_r += dvr; + } } if (y [1] != y [2]) @@ -413,49 +532,70 @@ gimp_display_shell_draw_tri (GimpDrawabl u_r = u [1]; v_r = v [1]; - for (ry = y [1]; ry < y [2]; ry++) - { - if (ry >= 0 && ry < dheight) - { - if (mask) - gimp_display_shell_draw_tri_row_mask - (texture, dest, row, - mask, mask_offx, mask_offy, - *left, u_l, v_l, - *right, u_r, v_r, - ry); - else - gimp_display_shell_draw_tri_row (texture, dest, row, - *left, u_l, v_l, - *right, u_r, v_r, - ry); - } - left ++; right ++; - u_l += dul; v_l += dvl; - u_r += dur; v_r += dvr; - } + if (mask) + for (ry = y [1]; ry < y [2]; ry++) + { + if (ry >= 0 && ry < dheight) + gimp_display_shell_draw_tri_row_mask + (texture, dest, + area, area_offx, area_offy, + mask, mask_offx, mask_offy, + *left, u_l, v_l, + *right, u_r, v_r, + ry, + opacity); + left ++; right ++; + u_l += dul; v_l += dvl; + u_r += dur; v_r += dvr; + } + else + for (ry = y [1]; ry < y [2]; ry++) + { + if (ry >= 0 && ry < dheight) + gimp_display_shell_draw_tri_row (texture, dest, + area, area_offx, area_offy, + *left, u_l, v_l, + *right, u_r, v_r, + ry, + opacity); + left ++; right ++; + u_l += dul; v_l += dvl; + u_r += dur; v_r += dvr; + } } - g_object_unref (row); g_free (l_edge); g_free (r_edge); } +/** + * gimp_display_shell_draw_tri_row: + * @texture: the thing being transformed + * @dest: the #GdkDrawable for that @texture lives on + * @area: has prefetched pixel data of dest + * + * Called from gimp_display_shell_draw_tri(), this draws a single row of a + * triangle onto dest when there is not a mask. The run (x1,y) to (x2,y) in + * dest corresponds to the run (u1,v1) to (u2,v2) in texture. + **/ static void gimp_display_shell_draw_tri_row (GimpDrawable *texture, GdkDrawable *dest, - GdkPixbuf *row, + GdkPixbuf *area, + gint area_offx, + gint area_offy, gint x1, gfloat u1, gfloat v1, gint x2, gfloat u2, gfloat v2, - gint y) + gint y, + gint opacity) { - TileManager *tiles; - guchar *pptr; - guchar bytes; + TileManager *tiles; /* used to get the source texture colors */ + guchar *pptr; /* points into the pixels of a row of area */ + guchar bytes; /* the number of channels of area */ gfloat u, v; gfloat du, dv; gint dx; @@ -468,16 +608,17 @@ gimp_display_shell_draw_tri_row (GimpDra g_return_if_fail (GIMP_IS_DRAWABLE (texture)); g_return_if_fail (GDK_IS_DRAWABLE (dest)); - g_return_if_fail (GDK_IS_PIXBUF (row)); - g_return_if_fail (gdk_pixbuf_get_bits_per_sample (row) == 8); - g_return_if_fail (gdk_pixbuf_get_colorspace (row) == GDK_COLORSPACE_RGB); - g_return_if_fail (gdk_pixbuf_get_has_alpha (row) == + g_return_if_fail (GDK_IS_PIXBUF (area)); + g_return_if_fail (gdk_pixbuf_get_bits_per_sample (area) == 8); + g_return_if_fail (gdk_pixbuf_get_colorspace (area) == GDK_COLORSPACE_RGB); + g_return_if_fail (gdk_pixbuf_get_has_alpha (area) == gimp_drawable_has_alpha (texture)); - bytes = gdk_pixbuf_get_n_channels (row); - pptr = gdk_pixbuf_get_pixels (row); + bytes = gdk_pixbuf_get_n_channels (area); + pptr = gdk_pixbuf_get_pixels (area); tiles = gimp_drawable_get_tiles (texture); + /* make sure the pixel run goes in the positive direction */ if (x1 > x2) { gint tmp; @@ -494,114 +635,237 @@ gimp_display_shell_draw_tri_row (GimpDra dv = (v2 - v1) / (x2 - x1); /* don't calculate unseen pixels */ - if (x1 < 0) + if (x1 < area_offx) { - u += du * (0 - x1); - v += dv * (0 - x1); - x1 = 0; + u += du * (area_offx - x1); + v += dv * (area_offx - x1); + x1 = area_offx; } - else if (x1 > gdk_pixbuf_get_width (row)) + else if (x1 > area_offx + gdk_pixbuf_get_width (area) - 1) return; - if (x2 < 0) + if (x2 < area_offx) return; - else if (x2 > gdk_pixbuf_get_width (row)) - x2 = gdk_pixbuf_get_width (row); - + else if (x2 > area_offx + gdk_pixbuf_get_width (area) - 1) + x2 = area_offx + gdk_pixbuf_get_width (area) - 1; dx = x2 - x1; + if (! dx) return; + /* set pptr to the proper position in area */ + pptr += (y - area_offy) * gdk_pixbuf_get_rowstride(area) + + (x1 - area_offx)*bytes; + switch (gimp_drawable_type (texture)) { case GIMP_INDEXED_IMAGE: cmap = gimp_drawable_get_colormap (texture); - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - - offset = pixel [0] + pixel [0] + pixel [0]; + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + offset = pixel [0] + pixel [0] + pixel [0]; + + *pptr++ = cmap [offset]; + *pptr++ = cmap [offset + 1]; + *pptr++ = cmap [offset + 2]; - *pptr++ = cmap [offset]; - *pptr++ = cmap [offset + 1]; - *pptr++ = cmap [offset + 2]; + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + offset = pixel [0] + pixel [0] + pixel [0]; + + pptr[0] = (pptr[0] * (255-opacity) + cmap[offset ] * opacity)>>8; + pptr[1] = (pptr[1] * (255-opacity) + cmap[offset+1] * opacity)>>8; + pptr[2] = (pptr[2] * (255-opacity) + cmap[offset+2] * opacity)>>8; + pptr += bytes; - u += du; - v += dv; - } + u += du; + v += dv; + } break; case GIMP_INDEXEDA_IMAGE: cmap = gimp_drawable_get_colormap (texture); - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - - offset = pixel [0] + pixel [0] + pixel [0]; + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + offset = pixel [0] + pixel [0] + pixel [0]; + + *pptr++ = cmap [offset]; + *pptr++ = cmap [offset + 1]; + *pptr++ = cmap [offset + 2]; + *pptr++ = pixel [1]; - *pptr++ = cmap [offset]; - *pptr++ = cmap [offset + 1]; - *pptr++ = cmap [offset + 2]; - *pptr++ = pixel [1]; + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + offset = pixel [0] + pixel [0] + pixel [0]; + + pptr[0] = (pptr[0] * (255-opacity) + cmap[offset ] * opacity)>>8; + pptr[1] = (pptr[1] * (255-opacity) + cmap[offset+1] * opacity)>>8; + pptr[2] = (pptr[2] * (255-opacity) + cmap[offset+2] * opacity)>>8; + pptr[3] = pixel [1]; + pptr += bytes; - u += du; - v += dv; - } + u += du; + v += dv; + } break; case GIMP_GRAY_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = (pptr [0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr [1] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [2] = (pptr [2] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr += bytes; - u += du; - v += dv; - } + u += du; + v += dv; + } break; case GIMP_GRAYA_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [1]; - - u += du; - v += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = pixel [1]; + + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = (pptr [0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr [1] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [2] = (pptr [2] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [3] = pixel [1]; + pptr += bytes; + + u += du; + v += dv; + } break; case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pptr); + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = pixel [0]; + pptr [1] = pixel [1]; + pptr [2] = pixel [2]; + + pptr += bytes; + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = (pptr [0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr [1] * (255-opacity) + pixel [1] * opacity) >> 8; + pptr [2] = (pptr [2] * (255-opacity) + pixel [2] * opacity) >> 8; + + pptr += bytes; + u += du; + v += dv; + } + break; - pptr += bytes; - u += du; - v += dv; - } + case GIMP_RGBA_IMAGE: + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = pixel [0]; + pptr [1] = pixel [1]; + pptr [2] = pixel [2]; + pptr [3] = pixel [3]; + + pptr += bytes; + u += du; + v += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + + pptr [0] = (pptr [0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr [1] * (255-opacity) + pixel [1] * opacity) >> 8; + pptr [2] = (pptr [2] * (255-opacity) + pixel [2] * opacity) >> 8; + pptr [3] = pixel [3]; + + pptr += bytes; + u += du; + v += dv; + } break; default: return; } - gdk_draw_pixbuf (dest, NULL, row, 0, 0, x1, y, x2 - x1, 1, + gdk_draw_pixbuf (dest, NULL, area, x1 - area_offx, y - area_offy, + x1, y, x2 - x1, 1, GDK_RGB_DITHER_NONE, 0, 0); } +/** + * gimp_display_shell_draw_tri_row_mask: + * + * Called from gimp_display_shell_draw_tri(), this draws a single row of a + * triangle onto dest, when there is a mask. + **/ static void gimp_display_shell_draw_tri_row_mask (GimpDrawable *texture, GdkDrawable *dest, - GdkPixbuf *row, + GdkPixbuf *area, + gint area_offx, + gint area_offy, GimpChannel *mask, gint mask_offx, gint mask_offy, @@ -611,11 +875,13 @@ gimp_display_shell_draw_tri_row_mask (Gi gint x2, gfloat u2, gfloat v2, - gint y) + gint y, + gint opacity) { - TileManager *tiles, *masktiles; - guchar *pptr; - guchar bytes, alpha; + + TileManager *tiles, *masktiles; /* used to get the source texture colors */ + guchar *pptr; /* points into the pixels of area */ + guchar bytes, alpha; /* channels in row, channel of alpha */ gfloat u, v; gfloat mu, mv; gfloat du, dv; @@ -630,16 +896,18 @@ gimp_display_shell_draw_tri_row_mask (Gi g_return_if_fail (GIMP_IS_DRAWABLE (texture)); g_return_if_fail (GIMP_IS_CHANNEL (mask)); g_return_if_fail (GDK_IS_DRAWABLE (dest)); - g_return_if_fail (GDK_IS_PIXBUF (row)); - g_return_if_fail (gdk_pixbuf_get_bits_per_sample (row) == 8); - g_return_if_fail (gdk_pixbuf_get_colorspace (row) == GDK_COLORSPACE_RGB); + g_return_if_fail (GDK_IS_PIXBUF (area)); + g_return_if_fail (gdk_pixbuf_get_bits_per_sample (area) == 8); + g_return_if_fail (gdk_pixbuf_get_colorspace (area) == GDK_COLORSPACE_RGB); - bytes = gdk_pixbuf_get_n_channels (row); + bytes = gdk_pixbuf_get_n_channels (area); alpha = bytes - 1; - pptr = gdk_pixbuf_get_pixels (row); + pptr = gdk_pixbuf_get_pixels (area); tiles = gimp_drawable_get_tiles (texture); masktiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)); + + /* make sure the pixel run goes in the positive direction */ if (x1 > x2) { gint tmp; @@ -656,143 +924,277 @@ gimp_display_shell_draw_tri_row_mask (Gi dv = (v2 - v1) / (x2 - x1); /* don't calculate unseen pixels */ - if (x1 < 0) + if (x1 < area_offx) { - u += du * (0 - x1); - v += dv * (0 - x1); - x1 = 0; + u += du * (area_offx - x1); + v += dv * (area_offx - x1); + x1 = area_offx; } - else if (x1 > gdk_pixbuf_get_width (row)) + else if (x1 > area_offx + gdk_pixbuf_get_width (area) - 1) return; - if (x2 < 0) + if (x2 < area_offx) return; - else if (x2 > gdk_pixbuf_get_width (row)) - x2 = gdk_pixbuf_get_width (row); + else if (x2 > area_offx + gdk_pixbuf_get_width (area) - 1) + x2 = area_offx + gdk_pixbuf_get_width (area) - 1; + + dx = x2 - x1; + if (! dx) return; mu = u + mask_offx; mv = v + mask_offy; - dx = x2 - x1; + /* set pptr to the proper position in area */ + pptr += (y - area_offy) * gdk_pixbuf_get_rowstride(area) + + (x1 - area_offx) * bytes; + switch (gimp_drawable_type (texture)) { case GIMP_INDEXED_IMAGE: cmap = gimp_drawable_get_colormap (texture); - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); - - offset = pixel [0] + pixel [0] + pixel [0]; - - *pptr++ = cmap [offset]; - *pptr++ = cmap [offset + 1]; - *pptr++ = cmap [offset + 2]; - - pptr ++; - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); + + offset = pixel [0] + pixel [0] + pixel [0]; + + *pptr++ = cmap [offset]; + *pptr++ = cmap [offset + 1]; + *pptr++ = cmap [offset + 2]; + + pptr ++; + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); + + offset = pixel [0] + pixel [0] + pixel [0]; + + pptr[0] = (pptr[0] * (255-opacity) + cmap[offset] * opacity) >> 8; + pptr[1] = (pptr[1] * (255-opacity) + cmap[offset+1] * opacity)>>8; + pptr[2] = (pptr[2] * (255-opacity) + cmap[offset+2] * opacity)>>8; + pptr += 3; + + pptr ++; + u += du; + v += dv; + mu += du; + mv += dv; + } break; case GIMP_INDEXEDA_IMAGE: cmap = gimp_drawable_get_colormap (texture); - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); - - offset = pixel [0] + pixel [0] + pixel [0]; - - *pptr++ = cmap [offset]; - *pptr++ = cmap [offset + 1]; - *pptr++ = cmap [offset + 2]; - *pptr++ = ((gint) maskval * pixel [1]) >> 8; - - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + offset = pixel [0] + pixel [0] + pixel [0]; + + *pptr++ = cmap [offset]; + *pptr++ = cmap [offset + 1]; + *pptr++ = cmap [offset + 2]; + + *pptr++ = ((gint) maskval * pixel [1]) >> 8; + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + offset = pixel [0] + pixel [0] + pixel [0]; + + pptr[0] = (pptr[0] * (255-opacity) + cmap[offset] * opacity)>>8; + pptr[1] = (pptr[1] * (255-opacity) + cmap[offset+1] * opacity)>>8; + pptr[2] = (pptr[2] * (255-opacity) + cmap[offset+2] * opacity)>>8; + pptr += 3; + + *pptr++ = ((gint) maskval * pixel [1]) >> 8; + u += du; + v += dv; + mu += du; + mv += dv; + } break; case GIMP_GRAY_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); - - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - - pptr ++; - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); + + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + pptr ++; + + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); + + pptr [0] = (pptr[0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr[1] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [2] = (pptr[2] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr += bytes; + + u += du; + v += dv; + mu += du; + mv += dv; + } break; case GIMP_GRAYA_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); - - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = pixel [0]; - *pptr++ = ((gint) maskval * pixel [1]) >> 8; - - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = pixel [0]; + *pptr++ = ((gint) maskval * pixel [1]) >> 8; + + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + pptr [0] = (pptr[0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr[1] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [2] = (pptr[2] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [3] = ((gint) maskval * pixel [1]) >> 8; + pptr += bytes; + + u += du; + v += dv; + mu += du; + mv += dv; + } break; case GIMP_RGB_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pptr); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, pptr + alpha); - - pptr += bytes; - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + pptr [0] = pixel [0]; + pptr [1] = pixel [1]; + pptr [2] = pixel [2]; + pptr [alpha] = maskval; + + pptr += bytes; + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + pptr [0] = (pptr[0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr[1] * (255-opacity) + pixel [1] * opacity) >> 8; + pptr [2] = (pptr[2] * (255-opacity) + pixel [2] * opacity) >> 8; + pptr [alpha] = maskval; + + pptr += bytes; + u += du; + v += dv; + mu += du; + mv += dv; + } break; case GIMP_RGBA_IMAGE: - while (dx --) - { - read_pixel_data_1 (tiles, (gint) u, (gint) v, pptr); - read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); - - pptr [alpha] = ((gint) maskval * pptr [alpha]) >> 8; - - pptr += bytes; - u += du; - v += dv; - mu += du; - mv += dv; - } + if (opacity == 255) + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + pptr [0] = pixel [0]; + pptr [1] = pixel [1]; + pptr [2] = pixel [2]; + pptr [alpha] = ((gint) maskval * pixel [alpha]) >> 8; + + pptr += bytes; + u += du; + v += dv; + mu += du; + mv += dv; + } + else + while (dx --) + { + read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel); + read_pixel_data_1 (masktiles, (gint) mu, (gint) mv, &maskval); + + pptr [0] = (pptr[0] * (255-opacity) + pixel [0] * opacity) >> 8; + pptr [1] = (pptr[1] * (255-opacity) + pixel [1] * opacity) >> 8; + pptr [2] = (pptr[2] * (255-opacity) + pixel [2] * opacity) >> 8; + pptr [alpha] = ((gint) maskval * pixel [alpha]) >> 8; + + pptr += bytes; + u += du; + v += dv; + mu += du; + mv += dv; + } break; default: return; } - gdk_draw_pixbuf (dest, NULL, row, 0, 0, x1, y, x2 - x1, 1, + gdk_draw_pixbuf (dest, NULL, area, x1 - area_offx, y - area_offy, + x1, y, x2 - x1, 1, GDK_RGB_DITHER_NONE, 0, 0); } +/** + * gimp_display_shell_trace_tri_edge: + * @dest: x coordinates are placed in this array + * + * Find the x coordinates for a line that runs from (x1,y1) to (x2,y2), + * corresponding to the y coordinates y1 to y2-1. So + * dest must be large enough to hold y2-y1 values. + **/ static void gimp_display_shell_trace_tri_edge (gint *dest, gint x1, Index: app/tools/gimptransformoptions.c =================================================================== RCS file: /cvs/gnome/gimp/app/tools/gimptransformoptions.c,v retrieving revision 1.59 diff -u -p -r1.59 gimptransformoptions.c --- app/tools/gimptransformoptions.c 19 May 2006 10:56:34 -0000 1.59 +++ app/tools/gimptransformoptions.c 19 Aug 2006 00:32:05 -0000 @@ -53,7 +53,8 @@ enum PROP_PREVIEW_TYPE, PROP_GRID_TYPE, PROP_GRID_SIZE, - PROP_CONSTRAIN + PROP_CONSTRAIN, + PROP_PREVIEW_OPACITY }; @@ -72,6 +73,10 @@ static void gimp_transform_options_pre GParamSpec *pspec, GtkWidget *density_box); +static void gimp_transform_options_preview_opacity_notify (GimpTransformOptions *options, + GParamSpec *pspec, + GtkWidget *density_box); + G_DEFINE_TYPE (GimpTransformOptions, gimp_transform_options, GIMP_TYPE_TOOL_OPTIONS) @@ -146,6 +151,10 @@ gimp_transform_options_class_init (GimpT "constrain", NULL, FALSE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_PREVIEW_OPACITY, + "preview-opacity", NULL, + 0, 100, 100, + GIMP_PARAM_STATIC_STRINGS); } static void @@ -193,6 +202,9 @@ gimp_transform_options_set_property (GOb case PROP_CONSTRAIN: options->constrain = g_value_get_boolean (value); break; + case PROP_PREVIEW_OPACITY: + options->preview_opacity = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -239,6 +251,9 @@ gimp_transform_options_get_property (GOb case PROP_CONSTRAIN: g_value_set_boolean (value, options->constrain); break; + case PROP_PREVIEW_OPACITY: + g_value_set_int (value, options->preview_opacity); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -260,6 +275,12 @@ gimp_transform_options_reset (GimpToolOp GIMP_TOOL_OPTIONS_CLASS (parent_class)->reset (tool_options); } +/** + * gimp_transform_options_gui: + * @tool_options: a #GimpToolOptions + * + * Build the Transform Tool Options dialog. + **/ GtkWidget * gimp_transform_options_gui (GimpToolOptions *tool_options) { @@ -319,49 +340,81 @@ gimp_transform_options_gui (GimpToolOpti gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); - /* the preview type menu */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_frame_set_label_widget (GTK_FRAME (frame), hbox); - gtk_widget_show (hbox); - - label = gtk_label_new (_("Preview:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - combo = gimp_prop_enum_combo_box_new (config, "preview-type", 0, 0); - gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); - gtk_widget_show (combo); - - /* the grid type menu */ - button = gtk_vbox_new (FALSE, 4); - gtk_container_add (GTK_CONTAINER (frame), button); - gtk_widget_show (button); - - combo = gimp_prop_enum_combo_box_new (config, "grid-type", 0, 0); - gtk_box_pack_start (GTK_BOX (button), combo, FALSE, FALSE, 0); - gtk_widget_show (combo); - - /* the grid density scale */ - table = gtk_table_new (1, 3, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2); - gtk_box_pack_start (GTK_BOX (button), table, FALSE, FALSE, 0); - gtk_widget_show (table); - - gtk_widget_set_sensitive (button, - options->preview_type == - GIMP_TRANSFORM_PREVIEW_TYPE_GRID || - options->preview_type == - GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); - - g_signal_connect (config, "notify::preview-type", - G_CALLBACK (gimp_transform_options_preview_notify), - button); - - gimp_prop_scale_entry_new (config, "grid-size", - GTK_TABLE (table), 0, 0, - NULL, - 1.0, 8.0, 0, - FALSE, 0.0, 0.0); + /* the preview type menu */ + hbox = gtk_hbox_new (FALSE, 4); + gtk_frame_set_label_widget (GTK_FRAME (frame), hbox); + gtk_widget_show (hbox); + + label = gtk_label_new (_("Preview:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + combo = gimp_prop_enum_combo_box_new (config, "preview-type", 0, 0); + gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); + gtk_widget_show (combo); + + /* the grid type menu */ + button = gtk_vbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (frame), button); + gtk_widget_show (button); + + combo = gimp_prop_enum_combo_box_new (config, "grid-type", 0, 0); + gtk_box_pack_start (GTK_BOX (button), combo, FALSE, FALSE, 0); + gtk_widget_show (combo); + + /* the grid density scale */ + table = gtk_table_new (1, 3, FALSE); + gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2); + gtk_box_pack_start (GTK_BOX (button), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + gtk_widget_set_sensitive (combo, + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_GRID || + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); + + g_signal_connect (config, "notify::preview-type", + G_CALLBACK (gimp_transform_options_preview_notify), + combo); + + gtk_widget_set_sensitive (table, + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_GRID || + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); + + g_signal_connect (config, "notify::preview-type", + G_CALLBACK (gimp_transform_options_preview_notify), + table); + + gimp_prop_scale_entry_new (config, "grid-size", + GTK_TABLE (table), 0, 0, + NULL, + 1.0, 8.0, 0, + FALSE, 0.0, 0.0); + + /* the preview opacity scale */ + table = gtk_table_new (1, 3, FALSE); + gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2); + gtk_box_pack_start (GTK_BOX (button), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + gtk_widget_set_sensitive (table, + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE || + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); + + g_signal_connect (config, "notify::preview-type", + G_CALLBACK (gimp_transform_options_preview_opacity_notify), + table); + + gimp_prop_scale_entry_new (config, "preview-opacity", + GTK_TABLE (table), 0, 0, + _("Opacity:"), + 1.0, 8.0, 0, + FALSE, 0.0, 0.0); if (tool_options->tool_info->tool_type == GIMP_TYPE_ROTATE_TOOL) { @@ -401,3 +454,16 @@ gimp_transform_options_preview_notify (G options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); } + +static void +gimp_transform_options_preview_opacity_notify (GimpTransformOptions *options, + GParamSpec *pspec, + GtkWidget *density_box) +{ + gtk_widget_set_sensitive (density_box, + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE || + options->preview_type == + GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID); +} + Index: app/tools/gimptransformoptions.h =================================================================== RCS file: /cvs/gnome/gimp/app/tools/gimptransformoptions.h,v retrieving revision 1.22 diff -u -p -r1.22 gimptransformoptions.h --- app/tools/gimptransformoptions.h 19 May 2006 10:56:34 -0000 1.22 +++ app/tools/gimptransformoptions.h 19 Aug 2006 00:32:05 -0000 @@ -48,6 +48,7 @@ struct _GimpTransformOptions GimpTransformGridType grid_type; gint grid_size; gboolean constrain; + gint preview_opacity; }; Index: app/tools/gimptransformtool.c =================================================================== RCS file: /cvs/gnome/gimp/app/tools/gimptransformtool.c,v retrieving revision 1.166 diff -u -p -r1.166 gimptransformtool.c --- app/tools/gimptransformtool.c 27 Jun 2006 20:05:56 -0000 1.166 +++ app/tools/gimptransformtool.c 19 Aug 2006 00:32:06 -0000 @@ -281,6 +281,10 @@ gimp_transform_tool_constructor (GType "notify::grid-size", G_CALLBACK (gimp_transform_tool_notify_preview), tr_tool, 0); + g_signal_connect_object (tool->tool_info->tool_options, + "notify::preview-opacity", + G_CALLBACK (gimp_transform_tool_notify_preview), + tr_tool, 0); } g_signal_connect_object (tool->tool_info->tool_options, Index: app/tools/gimptransformtool.h =================================================================== RCS file: /cvs/gnome/gimp/app/tools/gimptransformtool.h,v retrieving revision 1.42 diff -u -p -r1.42 gimptransformtool.h --- app/tools/gimptransformtool.h 27 Jun 2006 20:05:56 -0000 1.42 +++ app/tools/gimptransformtool.h 19 Aug 2006 00:32:06 -0000 @@ -60,7 +60,7 @@ struct _GimpTransformTool gint x2, y2; /* lower right hand coords */ gdouble cx, cy; /* center point (for rotation) */ - gdouble tx1, ty1; /* transformed coords */ + gdouble tx1, ty1; /* transformed handle coords */ gdouble tx2, ty2; gdouble tx3, ty3; gdouble tx4, ty4;