mirror of https://github.com/GNOME/gimp.git
added more properties.
2005-05-26 Sven Neumann <sven@gimp.org> * app/core/gimpdata.c: added more properties.
This commit is contained in:
parent
59cb5d75ba
commit
bbc1c947ad
|
@ -1,3 +1,7 @@
|
|||
2005-05-26 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/gimpdata.c: added more properties.
|
||||
|
||||
2005-05-26 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/gimpdata.[ch]: added MIME type as a construct property
|
||||
|
|
|
@ -0,0 +1,363 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* 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 <glib-object.h>
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimp-transform-resize.h"
|
||||
|
||||
|
||||
#if defined (HAVE_FINITE)
|
||||
#define FINITE(x) finite(x)
|
||||
#elif defined (HAVE_ISFINITE)
|
||||
#define FINITE(x) isfinite(x)
|
||||
#elif defined (G_OS_WIN32)
|
||||
#define FINITE(x) _finite(x)
|
||||
#else
|
||||
#error "no FINITE() implementation available?!"
|
||||
#endif
|
||||
|
||||
#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
|
||||
#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gdouble x, y;
|
||||
} Point;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint xmin, xmax;
|
||||
gint ymin, ymax;
|
||||
gdouble m, b; /* y = mx + b */
|
||||
gboolean top, right;
|
||||
} Edge;
|
||||
|
||||
|
||||
|
||||
static void gimp_transform_resize_adjust (gdouble dx1,
|
||||
gdouble dy1,
|
||||
gdouble dx2,
|
||||
gdouble dy2,
|
||||
gdouble dx3,
|
||||
gdouble dy3,
|
||||
gdouble dx4,
|
||||
gdouble dy4,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2);
|
||||
static void gimp_transform_resize_crop (gdouble dx1,
|
||||
gdouble dy1,
|
||||
gdouble dx2,
|
||||
gdouble dy2,
|
||||
gdouble dx3,
|
||||
gdouble dy3,
|
||||
gdouble dx4,
|
||||
gdouble dy4,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2);
|
||||
|
||||
|
||||
/*
|
||||
* This function wants to be passed the inverse transformation matrix!!
|
||||
*/
|
||||
void
|
||||
gimp_transform_resize_boundary (const GimpMatrix3 *inv,
|
||||
GimpTransformResize resize,
|
||||
gint u1,
|
||||
gint v1,
|
||||
gint u2,
|
||||
gint v2,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2)
|
||||
{
|
||||
gdouble dx1, dx2, dx3, dx4;
|
||||
gdouble dy1, dy2, dy3, dy4;
|
||||
|
||||
g_return_if_fail (inv != NULL);
|
||||
|
||||
/* initialize with the original boundary */
|
||||
*x1 = u1;
|
||||
*y1 = v1;
|
||||
*x2 = u2;
|
||||
*y2 = v2;
|
||||
|
||||
if (resize == GIMP_TRANSFORM_SIZE_CLIP)
|
||||
return;
|
||||
|
||||
gimp_matrix3_transform_point (inv, u1, v1, &dx1, &dy1);
|
||||
gimp_matrix3_transform_point (inv, u2, v1, &dx2, &dy2);
|
||||
gimp_matrix3_transform_point (inv, u1, v2, &dx3, &dy3);
|
||||
gimp_matrix3_transform_point (inv, u2, v2, &dx4, &dy4);
|
||||
|
||||
/* check if the transformation matrix is valid at all */
|
||||
if (! FINITE (dx1) || ! FINITE (dy1) ||
|
||||
! FINITE (dx2) || ! FINITE (dy2) ||
|
||||
! FINITE (dx3) || ! FINITE (dy3) ||
|
||||
! FINITE (dx4) || ! FINITE (dy4))
|
||||
{
|
||||
g_warning ("invalid transform matrix");
|
||||
resize = GIMP_TRANSFORM_SIZE_CLIP;
|
||||
}
|
||||
|
||||
switch (resize)
|
||||
{
|
||||
case GIMP_TRANSFORM_SIZE_ADJUST:
|
||||
gimp_transform_resize_adjust (dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4,
|
||||
x1, y1, x2, y2);
|
||||
break;
|
||||
|
||||
case GIMP_TRANSFORM_SIZE_CLIP:
|
||||
/* we are all done already */
|
||||
break;
|
||||
|
||||
case GIMP_TRANSFORM_SIZE_CROP:
|
||||
gimp_transform_resize_crop (dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4,
|
||||
x1, y1, x2, y2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*x1 == *x2)
|
||||
(*x2)++;
|
||||
|
||||
if (*y1 == *y2)
|
||||
(*y2)++;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_resize_adjust (gdouble dx1,
|
||||
gdouble dy1,
|
||||
gdouble dx2,
|
||||
gdouble dy2,
|
||||
gdouble dx3,
|
||||
gdouble dy3,
|
||||
gdouble dx4,
|
||||
gdouble dy4,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2)
|
||||
{
|
||||
*x1 = (gint) floor (MIN4 (dx1, dx2, dx3, dx4));
|
||||
*y1 = (gint) floor (MIN4 (dy1, dy2, dy3, dy4));
|
||||
|
||||
*x2 = (gint) ceil (MAX4 (dx1, dx2, dx3, dx4));
|
||||
*y2 = (gint) ceil (MAX4 (dy1, dy2, dy3, dy4));
|
||||
}
|
||||
|
||||
static void
|
||||
edge_init (Edge *edge,
|
||||
const Point *p,
|
||||
const Point *q)
|
||||
{
|
||||
edge->xmin = MIN (ceil (p->x), ceil (q->x));
|
||||
edge->xmax = MAX (floor (p->x), floor (q->x));
|
||||
edge->ymin = MIN (ceil (p->y), ceil (q->y));
|
||||
edge->ymax = MAX (floor (p->y), floor (q->y));
|
||||
|
||||
edge->top = p->x > q->x;
|
||||
edge->right = p->y > q->y;
|
||||
|
||||
edge->m = (q->y - p->y) / (q->x - p->x);
|
||||
edge->b = p->y - edge->m * p->x;
|
||||
}
|
||||
|
||||
static const Edge *
|
||||
find_edge (const Edge *edges,
|
||||
gint x,
|
||||
gboolean top)
|
||||
{
|
||||
const Edge *emax = edges;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
const Edge *e = edges + i;
|
||||
|
||||
if (e->xmin == x && e->xmax != e->xmin &&
|
||||
((e->top && top) || (!e->top && !top)))
|
||||
emax = e;
|
||||
}
|
||||
|
||||
return emax;
|
||||
}
|
||||
|
||||
/* find largest pixel completely inside;
|
||||
* look through all edges for intersection
|
||||
*/
|
||||
static gint
|
||||
intersect_x (const Edge *edges,
|
||||
gint y)
|
||||
{
|
||||
gdouble x0 = 0;
|
||||
gdouble x1 = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (edges[i].right && edges[i].ymin <= y && edges[i].ymax >= y)
|
||||
{
|
||||
x0 = (double) (y + 0.5 - edges[i].b) / edges[i].m;
|
||||
x1 = (double) (y - 0.5 - edges[i].b) / edges[i].m;
|
||||
}
|
||||
|
||||
return (gint) floor (MIN (x0, x1));
|
||||
}
|
||||
|
||||
static gint
|
||||
intersect_y (const Edge *edge,
|
||||
gint xi)
|
||||
{
|
||||
gdouble yfirst = edge->m * (xi - 0.5) + edge->b;
|
||||
gdouble ylast = edge->m * (xi + 0.5) + edge->b;
|
||||
|
||||
return (gint) floor (edge->top ? MAX (yfirst, ylast) : MIN (yfirst, ylast));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_resize_crop (gdouble dx1,
|
||||
gdouble dy1,
|
||||
gdouble dx2,
|
||||
gdouble dy2,
|
||||
gdouble dx3,
|
||||
gdouble dy3,
|
||||
gdouble dx4,
|
||||
gdouble dy4,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2)
|
||||
{
|
||||
Point points[4];
|
||||
Edge edges[4];
|
||||
const Point *a;
|
||||
const Point *b;
|
||||
const Edge *top;
|
||||
const Edge *bottom;
|
||||
gint *px;
|
||||
gint xmin, ymin;
|
||||
gint xmax, ymax;
|
||||
gint maxarea = 0;
|
||||
gint xi, y;
|
||||
gint i;
|
||||
|
||||
/* fill in the points array */
|
||||
points[0].x = dx1;
|
||||
points[0].y = dy1;
|
||||
points[1].x = dx2;
|
||||
points[1].y = dy2;
|
||||
points[2].x = dx3;
|
||||
points[2].y = dy3;
|
||||
points[3].x = dx4;
|
||||
points[3].y = dy4;
|
||||
|
||||
/* create an array of edges */
|
||||
for (i = 0, a = points + 3, b = points; i < 4; i++, a = b, b++)
|
||||
edge_init (edges + i, a, b);
|
||||
|
||||
/* determine the bounding box */
|
||||
xmin = edges[0].xmin;
|
||||
xmax = edges[0].xmax;
|
||||
ymin = edges[0].ymin;
|
||||
ymax = edges[0].ymax;
|
||||
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
const Edge *edge = edges + i;
|
||||
|
||||
if (edge->xmin < xmin)
|
||||
xmin = edge->xmin;
|
||||
|
||||
if (edge->xmax > xmax)
|
||||
xmax = edge->xmax;
|
||||
|
||||
if (edge->ymin < ymin)
|
||||
ymin = edge->ymin;
|
||||
|
||||
if (edge->ymax > ymax)
|
||||
ymax = edge->ymax;
|
||||
}
|
||||
|
||||
g_printerr ("%d, %d -> %d, %d\n", xmin, ymin, xmax, ymax);
|
||||
|
||||
px = g_new (gint, ymax - ymin + 1);
|
||||
|
||||
for (y = ymin, i = 0; y <= ymax; y++, i++)
|
||||
px[i] = intersect_x (edges, y);
|
||||
|
||||
top = find_edge (edges, xmin, TRUE);
|
||||
bottom = find_edge (edges, xmax, FALSE);
|
||||
|
||||
g_printerr ("top: %d, %d -> %d, %d\n",
|
||||
top->xmin, top->ymin, top->xmax, top->ymax);
|
||||
g_printerr ("bottom: %d, %d -> %d, %d\n",
|
||||
bottom->xmin, bottom->ymin, bottom->xmax, bottom->ymax);
|
||||
|
||||
for (xi = xmin; xi < xmax; xi++)
|
||||
{
|
||||
gint ylo, yhi;
|
||||
|
||||
ymin = intersect_y (top, xi);
|
||||
ymax = intersect_y (bottom, xi);
|
||||
|
||||
for (ylo = ymax; ylo >= ymin; ylo--)
|
||||
{
|
||||
for (yhi = ymin; yhi <= ymax; yhi++)
|
||||
{
|
||||
if (yhi > ylo)
|
||||
{
|
||||
gint xlo = px[ylo - ymin];
|
||||
gint xhi = px[yhi - ymin];
|
||||
gint width = MIN (xlo, xhi) - xi;
|
||||
gint height = yhi - ylo;
|
||||
gint area = width * height;
|
||||
|
||||
if (area > maxarea)
|
||||
{
|
||||
maxarea = area;
|
||||
|
||||
*x1 = xi;
|
||||
*y1 = ylo;
|
||||
*x2 = xi + width;
|
||||
*y2 = ylo + height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xi == top->xmax)
|
||||
top = find_edge (edges, xi, TRUE);
|
||||
|
||||
if (xi == bottom->xmax)
|
||||
bottom = find_edge (edges, xi, FALSE);
|
||||
}
|
||||
|
||||
g_printerr ("%d, %d -> %d, %d\n", *x1, *y1, *x2, *y2);
|
||||
|
||||
g_free (px);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __GIMP_TRANSFORM_RESIZE_H__
|
||||
#define __GIMP_TRANSFORM_RESIZE_H__
|
||||
|
||||
|
||||
void gimp_transform_resize_boundary (const GimpMatrix3 *inv,
|
||||
GimpTransformResize resize,
|
||||
gint u1,
|
||||
gint v1,
|
||||
gint u2,
|
||||
gint v2,
|
||||
gint *x1,
|
||||
gint *y1,
|
||||
gint *x2,
|
||||
gint *y2);
|
||||
|
||||
|
||||
#endif /* __GIMP_TRANSFORM_RESIZE_H__ */
|
|
@ -54,6 +54,9 @@ enum
|
|||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FILENAME,
|
||||
PROP_WRITABLE,
|
||||
PROP_DELETABLE,
|
||||
PROP_MIME_TYPE
|
||||
};
|
||||
|
||||
|
@ -141,9 +144,23 @@ gimp_data_class_init (GimpDataClass *klass)
|
|||
klass->get_extension = NULL;
|
||||
klass->duplicate = NULL;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FILENAME,
|
||||
g_param_spec_string ("filename", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_WRITABLE,
|
||||
g_param_spec_boolean ("writable", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_WRITABLE,
|
||||
g_param_spec_boolean ("deletable", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_MIME_TYPE,
|
||||
g_param_spec_string ("mime-type",
|
||||
NULL, NULL,
|
||||
g_param_spec_string ("mime-type", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
@ -192,6 +209,21 @@ gimp_data_set_property (GObject *object,
|
|||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILENAME:
|
||||
gimp_data_set_filename (data,
|
||||
g_value_get_string (value),
|
||||
data->writable,
|
||||
data->deletable);
|
||||
break;
|
||||
|
||||
case PROP_WRITABLE:
|
||||
data->writable = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_DELETABLE:
|
||||
data->deletable = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_MIME_TYPE:
|
||||
if (g_value_get_string (value))
|
||||
data->mime_type = g_quark_from_string (g_value_get_string (value));
|
||||
|
@ -215,6 +247,18 @@ gimp_data_get_property (GObject *object,
|
|||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILENAME:
|
||||
g_value_set_string (value, data->filename);
|
||||
break;
|
||||
|
||||
case PROP_WRITABLE:
|
||||
g_value_set_boolean (value, data->writable);
|
||||
break;
|
||||
|
||||
case PROP_DELETABLE:
|
||||
g_value_set_boolean (value, data->deletable);
|
||||
break;
|
||||
|
||||
case PROP_MIME_TYPE:
|
||||
g_value_set_string (value, g_quark_to_string (data->mime_type));
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue