2004-06-13 09:37:29 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include "display-types.h"
|
|
|
|
#include "tools/tools-types.h"
|
|
|
|
|
|
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "core/gimpdrawable.h"
|
2004-06-14 13:13:21 +08:00
|
|
|
#include "core/gimpchannel.h"
|
2004-06-13 09:37:29 +08:00
|
|
|
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
|
2004-10-28 14:06:58 +08:00
|
|
|
#include "tools/gimpperspectivetool.h"
|
2004-06-13 09:37:29 +08:00
|
|
|
#include "tools/gimptransformtool.h"
|
|
|
|
#include "tools/tool_manager.h"
|
|
|
|
|
|
|
|
#include "gimpdisplay.h"
|
|
|
|
#include "gimpdisplayshell.h"
|
|
|
|
#include "gimpdisplayshell-appearance.h"
|
|
|
|
#include "gimpdisplayshell-preview.h"
|
|
|
|
#include "gimpdisplayshell-transform.h"
|
|
|
|
|
2004-11-15 23:22:45 +08:00
|
|
|
|
|
|
|
#define MAX_SUB_COLS 6 /* number of columns and */
|
|
|
|
#define MAX_SUB_ROWS 6 /* rows to use in perspective preview subdivision */
|
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
/* local function prototypes */
|
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
static void gimp_display_shell_draw_quad (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gfloat *u,
|
|
|
|
gfloat *v);
|
2004-10-28 10:32:58 +08:00
|
|
|
static void gimp_display_shell_draw_tri (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gfloat *u,
|
|
|
|
gfloat *v);
|
|
|
|
static void gimp_display_shell_draw_tri_row (GimpDrawable *texture,
|
2004-06-14 13:13:21 +08:00
|
|
|
GdkDrawable *dest,
|
|
|
|
GdkPixbuf *row,
|
|
|
|
gint x1,
|
|
|
|
gfloat u1,
|
|
|
|
gfloat v1,
|
|
|
|
gint x2,
|
|
|
|
gfloat u2,
|
|
|
|
gfloat v2,
|
|
|
|
gint y);
|
2004-10-28 10:32:58 +08:00
|
|
|
static void gimp_display_shell_draw_tri_row_mask (GimpDrawable *texture,
|
2004-06-14 13:13:21 +08:00
|
|
|
GdkDrawable *dest,
|
|
|
|
GdkPixbuf *row,
|
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
|
|
|
gint x1,
|
|
|
|
gfloat u1,
|
|
|
|
gfloat v1,
|
|
|
|
gint x2,
|
|
|
|
gfloat u2,
|
|
|
|
gfloat v2,
|
|
|
|
gint y);
|
2004-10-28 10:32:58 +08:00
|
|
|
static void gimp_display_shell_trace_tri_edge (gint *dest,
|
2004-06-14 13:13:21 +08:00
|
|
|
gint x1,
|
|
|
|
gint y1,
|
|
|
|
gint x2,
|
|
|
|
gint y2);
|
2004-06-13 09:37:29 +08:00
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_display_shell_preview_transform (GimpDisplayShell *shell)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
if (gimp_display_shell_get_show_transform (shell))
|
|
|
|
{
|
|
|
|
GimpTool *tool;
|
|
|
|
GimpTransformTool *tr_tool;
|
|
|
|
gdouble z1, z2, z3, z4;
|
|
|
|
|
|
|
|
tool = tool_manager_get_active (shell->gdisp->gimage->gimp);
|
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
if (! GIMP_IS_TRANSFORM_TOOL (tool) ||
|
|
|
|
! GIMP_IS_DRAWABLE (tool->drawable))
|
2004-06-13 09:37:29 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
|
|
|
|
if (! tr_tool->use_grid)
|
|
|
|
return;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
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))
|
2004-10-25 20:42:23 +08:00
|
|
|
{
|
2004-06-14 13:13:21 +08:00
|
|
|
GimpChannel *mask;
|
2004-10-25 20:42:23 +08:00
|
|
|
gint mask_x1, mask_y1;
|
|
|
|
gint mask_x2, mask_y2;
|
2004-06-14 13:13:21 +08:00
|
|
|
gint mask_offx, mask_offy;
|
2004-11-15 23:22:45 +08:00
|
|
|
|
2004-10-28 14:06:58 +08:00
|
|
|
gint columns, rows;
|
2004-11-15 23:22:45 +08:00
|
|
|
gint j, k, sub;
|
|
|
|
|
2004-11-14 17:27:34 +08:00
|
|
|
gfloat du, dv, dx, dy;
|
2004-11-15 23:22:45 +08:00
|
|
|
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];
|
2004-11-11 17:36:45 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
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->gdisp->gimage);
|
|
|
|
|
|
|
|
gimp_item_offsets (GIMP_ITEM (tool->drawable),
|
|
|
|
&mask_offx, &mask_offy);
|
|
|
|
}
|
|
|
|
|
2004-10-28 14:06:58 +08:00
|
|
|
if (GIMP_IS_PERSPECTIVE_TOOL (tr_tool))
|
|
|
|
{
|
|
|
|
/* approximate perspective transform by subdivision
|
|
|
|
*
|
|
|
|
* increase number of columns/rows to increase precision
|
|
|
|
*/
|
2004-11-15 23:22:45 +08:00
|
|
|
columns = MAX_SUB_COLS;
|
|
|
|
rows = MAX_SUB_ROWS;
|
2004-10-28 14:06:58 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* for affine transforms subdivision has no effect
|
|
|
|
*/
|
|
|
|
columns = 1;
|
|
|
|
rows = 1;
|
|
|
|
}
|
2004-06-14 13:13:21 +08:00
|
|
|
|
2004-11-14 17:27:34 +08:00
|
|
|
dx = (tr_tool->x2 - tr_tool->x1) / ((gfloat) columns);
|
|
|
|
dy = (tr_tool->y2 - tr_tool->y1) / ((gfloat) rows);
|
2004-11-15 23:22:45 +08:00
|
|
|
|
2004-11-14 17:27:34 +08:00
|
|
|
du = (mask_x2 - mask_x1) / ((gfloat) columns);
|
|
|
|
dv = (mask_y2 - mask_y1) / ((gfloat) rows);
|
|
|
|
|
2004-11-15 23:22:45 +08:00
|
|
|
#define CALC_VERTEX(col, row, sub, index) \
|
|
|
|
{ \
|
|
|
|
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))); \
|
|
|
|
\
|
|
|
|
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; \
|
|
|
|
\
|
|
|
|
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++)
|
2004-10-28 14:06:58 +08:00
|
|
|
{
|
2004-11-15 23:22:45 +08:00
|
|
|
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++)
|
2004-10-28 14:06:58 +08:00
|
|
|
{
|
2004-11-15 23:22:45 +08:00
|
|
|
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);
|
2004-10-28 14:06:58 +08:00
|
|
|
}
|
|
|
|
}
|
2004-11-15 23:22:45 +08:00
|
|
|
|
|
|
|
#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]);
|
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_display_shell_draw_quad (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
2004-06-14 13:13:21 +08:00
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
2004-06-13 09:37:29 +08:00
|
|
|
gint *x,
|
|
|
|
gint *y,
|
2004-10-28 10:32:58 +08:00
|
|
|
gfloat *u,
|
|
|
|
gfloat *v)
|
|
|
|
{
|
|
|
|
gint x2 [3], y2 [3];
|
|
|
|
gfloat u2 [3], v2 [3];
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_display_shell_draw_tri (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gfloat *u, /* texture coords */
|
|
|
|
gfloat *v) /* 0.0 ... tex width, height */
|
2004-06-13 09:37:29 +08:00
|
|
|
{
|
|
|
|
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 */
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
if (! GIMP_IS_DRAWABLE (texture) ||
|
|
|
|
! GDK_IS_DRAWABLE (dest))
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_return_if_fail (x != NULL && y != NULL && u != NULL && v != 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);
|
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
row = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
|
|
|
mask ? TRUE : gimp_drawable_has_alpha (texture),
|
2004-06-13 09:37:29 +08:00
|
|
|
8, dwidth, 1);
|
2004-06-13 23:22:51 +08:00
|
|
|
g_return_if_fail (row != NULL);
|
2004-06-13 09:37:29 +08:00
|
|
|
|
|
|
|
/* sort vertices in order of y-coordinate */
|
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
for (j = 0; j < 3; j++)
|
|
|
|
for (k = j + 1; k < 3; k++)
|
2004-06-13 09:37:29 +08:00
|
|
|
if (y [k] < y [j])
|
|
|
|
{
|
|
|
|
gint tmp;
|
|
|
|
gfloat ftmp;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
tmp = y [k]; y [k] = y [j]; y [j] = tmp;
|
|
|
|
tmp = x [k]; x [k] = x [j]; x [j] = tmp;
|
|
|
|
ftmp = u [k]; u [k] = u [j]; u [j] = ftmp;
|
|
|
|
ftmp = v [k]; v [k] = v [j]; v [j] = ftmp;
|
|
|
|
}
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
if (y [2] == y [0])
|
2004-06-13 09:37:29 +08:00
|
|
|
return;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
l_edge = g_malloc ((y [2] - y [0]) * sizeof (gint));
|
|
|
|
r_edge = g_malloc ((y [2] - y [0]) * sizeof (gint));
|
2004-06-13 09:37:29 +08:00
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
/* draw the triangle */
|
|
|
|
|
|
|
|
gimp_display_shell_trace_tri_edge (l_edge,
|
|
|
|
x [0], y [0],
|
|
|
|
x [2], y [2]);
|
|
|
|
left = l_edge;
|
|
|
|
dul = (u [2] - u [0]) / (y [2] - y [0]);
|
|
|
|
dvl = (v [2] - v [0]) / (y [2] - y [0]);
|
|
|
|
u_l = u [0];
|
|
|
|
v_l = v [0];
|
2004-06-13 09:37:29 +08:00
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
if (y [0] != y [1])
|
2004-06-13 09:37:29 +08:00
|
|
|
{
|
2004-10-28 10:32:58 +08:00
|
|
|
gimp_display_shell_trace_tri_edge (r_edge,
|
|
|
|
x [0], y [0],
|
|
|
|
x [1], y [1]);
|
|
|
|
right = r_edge;
|
|
|
|
dur = (u [1] - u [0]) / (y [1] - y [0]);
|
|
|
|
dvr = (v [1] - v [0]) / (y [1] - y [0]);
|
|
|
|
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,
|
|
|
|
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;
|
|
|
|
}
|
2004-06-13 09:37:29 +08:00
|
|
|
}
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-10-28 10:32:58 +08:00
|
|
|
if (y [1] != y [2])
|
|
|
|
{
|
|
|
|
gimp_display_shell_trace_tri_edge (r_edge,
|
|
|
|
x [1], y [1],
|
|
|
|
x [2], y [2]);
|
|
|
|
right = r_edge;
|
|
|
|
dur = (u [2] - u [1]) / (y [2] - y [1]);
|
|
|
|
dvr = (v [2] - v [1]) / (y [2] - y [1]);
|
|
|
|
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;
|
|
|
|
}
|
2004-06-13 09:37:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (row);
|
|
|
|
g_free (l_edge);
|
|
|
|
g_free (r_edge);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-10-28 10:32:58 +08:00
|
|
|
gimp_display_shell_draw_tri_row (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
|
|
|
GdkPixbuf *row,
|
|
|
|
gint x1,
|
|
|
|
gfloat u1,
|
|
|
|
gfloat v1,
|
|
|
|
gint x2,
|
|
|
|
gfloat u2,
|
|
|
|
gfloat v2,
|
|
|
|
gint y)
|
2004-06-13 09:37:29 +08:00
|
|
|
{
|
|
|
|
TileManager *tiles;
|
|
|
|
guchar *pptr;
|
2004-06-14 13:13:21 +08:00
|
|
|
guchar bytes;
|
2004-06-13 09:37:29 +08:00
|
|
|
gfloat u, v;
|
|
|
|
gfloat du, dv;
|
|
|
|
gint dx;
|
|
|
|
guchar pixel [4];
|
|
|
|
guchar *cmap;
|
|
|
|
gint offset;
|
|
|
|
|
|
|
|
if (! (x2 - x1))
|
|
|
|
return;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
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) ==
|
|
|
|
gimp_drawable_has_alpha (texture));
|
|
|
|
|
|
|
|
bytes = gdk_pixbuf_get_n_channels (row);
|
|
|
|
pptr = gdk_pixbuf_get_pixels (row);
|
|
|
|
tiles = gimp_drawable_data (texture);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
if (x1 > x2)
|
|
|
|
{
|
|
|
|
gint tmp;
|
|
|
|
gfloat ftmp;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
tmp = x2; x2 = x1; x1 = tmp;
|
|
|
|
ftmp = u2; u2 = u1; u1 = ftmp;
|
|
|
|
ftmp = v2; v2 = v1; v1 = ftmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = u1;
|
|
|
|
v = v1;
|
|
|
|
du = (u2 - u1) / (x2 - x1);
|
|
|
|
dv = (v2 - v1) / (x2 - x1);
|
|
|
|
|
|
|
|
/* don't calculate unseen pixels */
|
|
|
|
if (x1 < 0)
|
|
|
|
{
|
|
|
|
u += du * (0 - x1);
|
|
|
|
v += dv * (0 - x1);
|
|
|
|
x1 = 0;
|
|
|
|
}
|
|
|
|
else if (x1 > gdk_pixbuf_get_width (row))
|
|
|
|
return;
|
|
|
|
if (x2 < 0)
|
|
|
|
return;
|
|
|
|
else if (x2 > gdk_pixbuf_get_width (row))
|
|
|
|
x2 = gdk_pixbuf_get_width (row);
|
|
|
|
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
dx = x2 - x1;
|
|
|
|
|
|
|
|
switch (gimp_drawable_type (texture))
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
cmap = gimp_drawable_cmap (texture);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
while (dx --)
|
|
|
|
{
|
|
|
|
read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel);
|
|
|
|
|
|
|
|
offset = pixel [0] + pixel [0] + pixel [0];
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
*pptr++ = cmap [offset];
|
|
|
|
*pptr++ = cmap [offset + 1];
|
|
|
|
*pptr++ = cmap [offset + 2];
|
|
|
|
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXEDA_IMAGE:
|
|
|
|
cmap = gimp_drawable_cmap (texture);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
while (dx --)
|
|
|
|
{
|
|
|
|
read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel);
|
|
|
|
|
|
|
|
offset = pixel [0] + pixel [0] + pixel [0];
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
*pptr++ = cmap [offset];
|
|
|
|
*pptr++ = cmap [offset + 1];
|
|
|
|
*pptr++ = cmap [offset + 2];
|
|
|
|
*pptr++ = pixel [1];
|
|
|
|
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
while (dx --)
|
|
|
|
{
|
|
|
|
read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel);
|
|
|
|
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GRAYA_IMAGE:
|
|
|
|
while (dx --)
|
|
|
|
{
|
|
|
|
read_pixel_data_1 (tiles, (gint) u, (gint) v, pixel);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [1];
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RGB_IMAGE:
|
2004-10-25 20:42:23 +08:00
|
|
|
case GIMP_RGBA_IMAGE:
|
2004-06-13 09:37:29 +08:00
|
|
|
while (dx --)
|
|
|
|
{
|
|
|
|
read_pixel_data_1 (tiles, (gint) u, (gint) v, pptr);
|
|
|
|
|
|
|
|
pptr += bytes;
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gdk_draw_pixbuf (dest, NULL, row, 0, 0, x1, y, x2 - x1, 1,
|
|
|
|
GDK_RGB_DITHER_NONE, 0, 0);
|
|
|
|
}
|
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
static void
|
2004-10-28 10:32:58 +08:00
|
|
|
gimp_display_shell_draw_tri_row_mask (GimpDrawable *texture,
|
|
|
|
GdkDrawable *dest,
|
|
|
|
GdkPixbuf *row,
|
|
|
|
GimpChannel *mask,
|
|
|
|
gint mask_offx,
|
|
|
|
gint mask_offy,
|
|
|
|
gint x1,
|
|
|
|
gfloat u1,
|
|
|
|
gfloat v1,
|
|
|
|
gint x2,
|
|
|
|
gfloat u2,
|
|
|
|
gfloat v2,
|
|
|
|
gint y)
|
2004-06-14 13:13:21 +08:00
|
|
|
{
|
|
|
|
TileManager *tiles, *masktiles;
|
|
|
|
guchar *pptr;
|
|
|
|
guchar bytes, alpha;
|
|
|
|
gfloat u, v;
|
|
|
|
gfloat mu, mv;
|
|
|
|
gfloat du, dv;
|
|
|
|
gint dx;
|
|
|
|
guchar pixel [4], maskval;
|
|
|
|
guchar *cmap;
|
|
|
|
gint offset;
|
|
|
|
|
|
|
|
if (! (x2 - x1))
|
|
|
|
return;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
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);
|
|
|
|
|
|
|
|
bytes = gdk_pixbuf_get_n_channels (row);
|
|
|
|
alpha = bytes - 1;
|
|
|
|
pptr = gdk_pixbuf_get_pixels (row);
|
|
|
|
tiles = gimp_drawable_data (texture);
|
|
|
|
masktiles = gimp_drawable_data (GIMP_DRAWABLE (mask));
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
if (x1 > x2)
|
|
|
|
{
|
|
|
|
gint tmp;
|
|
|
|
gfloat ftmp;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
tmp = x2; x2 = x1; x1 = tmp;
|
|
|
|
ftmp = u2; u2 = u1; u1 = ftmp;
|
|
|
|
ftmp = v2; v2 = v1; v1 = ftmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = u1;
|
|
|
|
v = v1;
|
|
|
|
du = (u2 - u1) / (x2 - x1);
|
|
|
|
dv = (v2 - v1) / (x2 - x1);
|
|
|
|
|
|
|
|
/* don't calculate unseen pixels */
|
|
|
|
if (x1 < 0)
|
|
|
|
{
|
|
|
|
u += du * (0 - x1);
|
|
|
|
v += dv * (0 - x1);
|
|
|
|
x1 = 0;
|
|
|
|
}
|
|
|
|
else if (x1 > gdk_pixbuf_get_width (row))
|
|
|
|
return;
|
|
|
|
if (x2 < 0)
|
|
|
|
return;
|
|
|
|
else if (x2 > gdk_pixbuf_get_width (row))
|
|
|
|
x2 = gdk_pixbuf_get_width (row);
|
|
|
|
|
|
|
|
mu = u + mask_offx;
|
|
|
|
mv = v + mask_offy;
|
|
|
|
dx = x2 - x1;
|
|
|
|
|
|
|
|
switch (gimp_drawable_type (texture))
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
cmap = gimp_drawable_cmap (texture);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
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];
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
*pptr++ = cmap [offset];
|
|
|
|
*pptr++ = cmap [offset + 1];
|
|
|
|
*pptr++ = cmap [offset + 2];
|
|
|
|
|
|
|
|
pptr ++;
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
mu += du;
|
|
|
|
mv += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXEDA_IMAGE:
|
|
|
|
cmap = gimp_drawable_cmap (texture);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
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];
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
*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;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
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);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = pixel [0];
|
|
|
|
*pptr++ = ((gint) maskval * pixel [1]) >> 8;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
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);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-14 13:13:21 +08:00
|
|
|
pptr += bytes;
|
|
|
|
u += du;
|
|
|
|
v += dv;
|
|
|
|
mu += du;
|
|
|
|
mv += dv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-10-25 20:42:23 +08:00
|
|
|
case GIMP_RGBA_IMAGE:
|
2004-06-14 13:13:21 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gdk_draw_pixbuf (dest, NULL, row, 0, 0, x1, y, x2 - x1, 1,
|
|
|
|
GDK_RGB_DITHER_NONE, 0, 0);
|
|
|
|
}
|
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
static void
|
2004-10-28 10:32:58 +08:00
|
|
|
gimp_display_shell_trace_tri_edge (gint *dest,
|
|
|
|
gint x1,
|
|
|
|
gint y1,
|
|
|
|
gint x2,
|
|
|
|
gint y2)
|
2004-06-13 09:37:29 +08:00
|
|
|
{
|
|
|
|
const gint dy = y2 - y1;
|
|
|
|
gint dx;
|
|
|
|
gchar xdir;
|
|
|
|
gint errorterm;
|
|
|
|
gint b;
|
|
|
|
gint *dptr;
|
|
|
|
|
2004-10-25 20:42:23 +08:00
|
|
|
if (dy == 0)
|
2004-06-13 09:37:29 +08:00
|
|
|
return;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
g_return_if_fail (dest != NULL);
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
b = 0;
|
|
|
|
errorterm = 0;
|
|
|
|
dptr = dest;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
if (x2 < x1)
|
|
|
|
{
|
|
|
|
dx = x1 - x2;
|
|
|
|
xdir = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dx = x2 - x1;
|
|
|
|
xdir = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dx >= dy)
|
|
|
|
{
|
|
|
|
b = dy;
|
|
|
|
while (b --)
|
|
|
|
{
|
|
|
|
*dptr = x1;
|
|
|
|
errorterm += dx;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
while (errorterm > dy)
|
|
|
|
{
|
|
|
|
x1 += xdir;
|
|
|
|
errorterm -= dy;
|
|
|
|
}
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
dptr ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dy >= dx)
|
|
|
|
{
|
|
|
|
b = dy;
|
|
|
|
while (b --)
|
|
|
|
{
|
|
|
|
*dptr = x1;
|
|
|
|
errorterm += dx;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
if (errorterm > dy)
|
|
|
|
{
|
|
|
|
x1 += xdir;
|
|
|
|
errorterm -= dy;
|
|
|
|
}
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
dptr ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dx == 0)
|
|
|
|
{
|
|
|
|
b = dy;
|
|
|
|
while (b --)
|
|
|
|
{
|
|
|
|
*dptr = x1;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
dptr ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* dy == dx */
|
|
|
|
{
|
|
|
|
b = dy;
|
|
|
|
while (b --)
|
|
|
|
{
|
|
|
|
*dptr = x1;
|
|
|
|
x1 += xdir;
|
2004-10-25 20:42:23 +08:00
|
|
|
|
2004-06-13 09:37:29 +08:00
|
|
|
dptr ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|