Index: app/tools/gimptransformtool.c =================================================================== --- app/tools/gimptransformtool.c (revision 25004) +++ app/tools/gimptransformtool.c (working copy) @@ -280,6 +280,10 @@ gimp_transform_tool_constructor (GType g_signal_connect_object (options, "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 (options, "notify::constrain", @@ -1360,7 +1364,7 @@ gimp_transform_tool_force_expose_preview static gint last_h = 0; GimpDisplayShell *shell; - gdouble dx [4], dy [4]; + gdouble dx[4], dy[4]; gint area_x, area_y, area_w, area_h; gint i; @@ -1388,20 +1392,20 @@ gimp_transform_tool_force_expose_preview dx + 3, dy + 3, FALSE); /* find bounding box around preview */ - area_x = area_w = (gint) dx [0]; - area_y = area_h = (gint) dy [0]; + area_x = area_w = (gint) dx[0]; + area_y = area_h = (gint) dy[0]; for (i = 1; i < 4; i++) { - if (dx [i] < area_x) - area_x = (gint) dx [i]; - else if (dx [i] > area_w) - area_w = (gint) dx [i]; - - if (dy [i] < area_y) - area_y = (gint) dy [i]; - else if (dy [i] > area_h) - area_h = (gint) dy [i]; + if (dx[i] < area_x) + area_x = (gint) dx[i]; + else if (dx[i] > area_w) + area_w = (gint) dx[i]; + + if (dy[i] < area_y) + area_y = (gint) dy[i]; + else if (dy[i] > area_h) + area_h = (gint) dy[i]; } area_w -= area_x; Index: app/tools/gimptransformtool.h =================================================================== --- app/tools/gimptransformtool.h (revision 25004) +++ app/tools/gimptransformtool.h (working copy) @@ -62,7 +62,7 @@ struct _GimpTransformTool gdouble cx, cy; /* center point (for rotation) */ gdouble aspect; /* original aspect ratio */ - gdouble tx1, ty1; /* transformed coords */ + gdouble tx1, ty1; /* transformed handle coords */ gdouble tx2, ty2; gdouble tx3, ty3; gdouble tx4, ty4; Index: app/tools/gimptransformoptions.c =================================================================== --- app/tools/gimptransformoptions.c (revision 25004) +++ app/tools/gimptransformoptions.c (working copy) @@ -50,7 +50,8 @@ enum PROP_PREVIEW_TYPE, PROP_GRID_TYPE, PROP_GRID_SIZE, - PROP_CONSTRAIN + PROP_CONSTRAIN, + PROP_PREVIEW_OPACITY }; @@ -69,6 +70,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) @@ -125,6 +130,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 @@ -167,6 +176,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; @@ -207,6 +219,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; @@ -228,6 +243,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) { @@ -311,7 +332,17 @@ gimp_transform_options_gui (GimpToolOpti gtk_box_pack_start (GTK_BOX (button), table, FALSE, FALSE, 0); gtk_widget_show (table); - gtk_widget_set_sensitive (button, + 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 == @@ -319,7 +350,7 @@ gimp_transform_options_gui (GimpToolOpti g_signal_connect (config, "notify::preview-type", G_CALLBACK (gimp_transform_options_preview_notify), - button); + table); gimp_prop_scale_entry_new (config, "grid-size", GTK_TABLE (table), 0, 0, @@ -327,6 +358,29 @@ gimp_transform_options_gui (GimpToolOpti 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) { constrain = (_("15 degrees (%s)")); @@ -365,3 +419,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 =================================================================== --- app/tools/gimptransformoptions.h (revision 25004) +++ app/tools/gimptransformoptions.h (working copy) @@ -47,6 +47,7 @@ struct _GimpTransformOptions GimpTransformGridType grid_type; gint grid_size; gboolean constrain; + gint preview_opacity; }; Index: app/display/gimpdisplayshell-preview.c =================================================================== --- app/display/gimpdisplayshell-preview.c (revision 25004) +++ app/display/gimpdisplayshell-preview.c (working copy) @@ -28,10 +28,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" @@ -55,29 +57,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, @@ -87,7 +99,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, @@ -96,187 +109,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; - - tool = tool_manager_get_active (shell->display->image->gimp); - - if (! GIMP_IS_TRANSFORM_TOOL (tool) || - ! GIMP_IS_DRAWABLE (tool->drawable)) - return; + GimpTool *tool; + GimpTransformTool *tr_tool; + gdouble z1, z2, z3, z4; + + 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; - tr_tool = GIMP_TRANSFORM_TOOL (tool); + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); - if (! tr_tool->use_grid) - return; + if (! gimp_display_shell_get_show_transform (shell) || ! shell->canvas) + 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)); + tool = tool_manager_get_active (shell->display->image->gimp); - /* only draw convex polygons */ + if (! GIMP_IS_TRANSFORM_TOOL (tool) || + ! GIMP_IS_DRAWABLE (tool->drawable)) + return; - 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); + tr_tool = GIMP_TRANSFORM_TOOL (tool); - gimp_item_offsets (GIMP_ITEM (tool->drawable), - &mask_offx, &mask_offy); - } + if (! tr_tool->use_grid) + return; - 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; - } + 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; + + 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); + + 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; + } - 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 - */ + x[subdest][idest] = x[subsrc][isrc]; \ + y[subdest][idest] = y[subsrc][isrc]; \ + u[subdest][idest] = u[subsrc][isrc]; \ + v[subdest][idest] = v[subsrc][isrc]; - for (j = 0; j < 4; j++) - { - CALC_VERTEX (0, 0, 0, j); - } + /* + * upper left corner subdivision: calculate all vertices + */ - /* - * top row subdivisions: calculate only right side vertices - */ + for (j = 0; j < 4; j++) + { + CALC_VERTEX (0, 0, 0, j); + } - 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); - } + /* + * top row subdivisions: calculate only right side vertices + */ - /* - * left column subdivisions: calculate only bottom 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); + } - 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); - } + /* + * left column subdivisions: calculate only bottom side vertices + */ - /* - * the rest: calculate only the bottom-right vertex - */ + 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); + } - for (j = 1, sub = columns; j < rows; j++) - { - sub++; + /* + * the rest: calculate only the bottom-right vertex + */ - 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); - } - } + 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]); + 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, @@ -286,62 +336,118 @@ 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); - gdk_drawable_get_size (dest, &dwidth, &dheight); - - if (dwidth > 0 && dheight > 0) - row = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - mask ? TRUE : gimp_drawable_has_alpha (texture), - 8, dwidth, 1); - else - return; - - g_return_if_fail (row != NULL); - left = right = NULL; dul = dvl = dur = dvr = 0; u_l = v_l = u_r = v_r = 0; + gdk_drawable_get_size (dest, &dwidth, &dheight); + /* sort vertices in order of y-coordinate */ for (j = 0; j < 3; j++) @@ -383,28 +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]) @@ -417,51 +531,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_free (l_edge); g_free (r_edge); - - g_object_unref (row); } +/** + * 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; @@ -474,16 +607,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; @@ -500,123 +634,244 @@ 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)) + else if (x2 > area_offx + gdk_pixbuf_get_width (area) - 1) { - x2 = gdk_pixbuf_get_width (row); + x2 = area_offx + gdk_pixbuf_get_width (area) - 1; } dx = x2 - x1; + if (! dx) return; - 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); + 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]; - offset = pixel[0] + pixel[0] + pixel[0]; - - *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, @@ -626,11 +881,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; @@ -645,16 +902,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; @@ -671,154 +930,285 @@ 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)) + else if (x2 > area_offx + gdk_pixbuf_get_width (area) - 1) { - x2 = gdk_pixbuf_get_width (row); + x2 = area_offx + gdk_pixbuf_get_width (area) - 1; } dx = x2 - x1; - - if (! dx) + if (! dx) return; mu = u + mask_offx; mv = v + mask_offy; + /* 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,