mirror of https://github.com/GNOME/gimp.git
app: implement gimp_brush_transform_boundary()
There is infinite room for optimization, but the API and pixel-perfect functionality is there, which is step one.
This commit is contained in:
parent
99e0e73fc6
commit
cf52b10e9b
|
@ -55,6 +55,8 @@ libappcore_a_sources = \
|
|||
gimpbezierdesc.c \
|
||||
gimpbrush.c \
|
||||
gimpbrush.h \
|
||||
gimpbrush-boundary.c \
|
||||
gimpbrush-boundary.h \
|
||||
gimpbrush-header.h \
|
||||
gimpbrush-load.c \
|
||||
gimpbrush-load.h \
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/* GIMP - The GNU 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "base/boundary.h"
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/temp-buf.h"
|
||||
|
||||
#include "gimpbezierdesc.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrush-boundary.h"
|
||||
|
||||
|
||||
static void
|
||||
add_polyline (GArray *path_data,
|
||||
const GimpVector2 *points,
|
||||
guint n_points)
|
||||
{
|
||||
GimpVector2 prev = { 0.0, 0.0, };
|
||||
cairo_path_data_t pd;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_points; i++)
|
||||
{
|
||||
/* compress multiple identical coordinates */
|
||||
if (i == 0 ||
|
||||
prev.x != points[i].x ||
|
||||
prev.y != points[i].y)
|
||||
{
|
||||
pd.header.type = (i == 0) ? CAIRO_PATH_MOVE_TO : CAIRO_PATH_LINE_TO;
|
||||
pd.header.length = 2;
|
||||
|
||||
g_array_append_val (path_data, pd);
|
||||
|
||||
pd.point.x = points[i].x;
|
||||
pd.point.y = points[i].y;
|
||||
|
||||
g_array_append_val (path_data, pd);
|
||||
|
||||
prev = points[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* close the polyline */
|
||||
pd.header.type = CAIRO_PATH_CLOSE_PATH;
|
||||
pd.header.length = 1;
|
||||
|
||||
g_array_append_val (path_data, pd);
|
||||
}
|
||||
|
||||
static GimpBezierDesc *
|
||||
gimp_brush_transform_boundary_exact (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness)
|
||||
{
|
||||
TempBuf *mask;
|
||||
|
||||
mask = gimp_brush_transform_mask (brush,
|
||||
scale, aspect_ratio, angle, hardness);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
PixelRegion maskPR;
|
||||
BoundSeg *bound_segs;
|
||||
gint n_bound_segs;
|
||||
BoundSeg *stroke_segs;
|
||||
gint n_stroke_segs;
|
||||
GArray *path_data;
|
||||
|
||||
pixel_region_init_temp_buf (&maskPR, mask,
|
||||
0, 0, mask->width, mask->height);
|
||||
|
||||
bound_segs = boundary_find (&maskPR, BOUNDARY_WITHIN_BOUNDS,
|
||||
0, 0, maskPR.w, maskPR.h,
|
||||
0,
|
||||
&n_bound_segs);
|
||||
|
||||
temp_buf_free (mask);
|
||||
|
||||
if (! bound_segs)
|
||||
return NULL;
|
||||
|
||||
stroke_segs = boundary_sort (bound_segs, n_bound_segs, &n_stroke_segs);
|
||||
|
||||
g_free (bound_segs);
|
||||
|
||||
if (! stroke_segs)
|
||||
return NULL;
|
||||
|
||||
path_data = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t));
|
||||
|
||||
{
|
||||
GimpVector2 *points;
|
||||
gint n_points;
|
||||
gint seg;
|
||||
gint i;
|
||||
|
||||
points = g_new0 (GimpVector2, n_bound_segs + 4);
|
||||
|
||||
seg = 0;
|
||||
n_points = 0;
|
||||
|
||||
points[n_points].x = (gdouble) (stroke_segs[0].x1);
|
||||
points[n_points].y = (gdouble) (stroke_segs[0].y1);
|
||||
|
||||
n_points++;
|
||||
|
||||
for (i = 0; i < n_stroke_segs; i++)
|
||||
{
|
||||
while (stroke_segs[seg].x1 != -1 ||
|
||||
stroke_segs[seg].x2 != -1 ||
|
||||
stroke_segs[seg].y1 != -1 ||
|
||||
stroke_segs[seg].y2 != -1)
|
||||
{
|
||||
points[n_points].x = (gdouble) (stroke_segs[seg].x1);
|
||||
points[n_points].y = (gdouble) (stroke_segs[seg].y1);
|
||||
|
||||
n_points++;
|
||||
seg++;
|
||||
}
|
||||
|
||||
/* Close the stroke points up */
|
||||
points[n_points] = points[0];
|
||||
|
||||
n_points++;
|
||||
|
||||
add_polyline (path_data, points, n_points);
|
||||
|
||||
n_points = 0;
|
||||
seg++;
|
||||
|
||||
points[n_points].x = (gdouble) (stroke_segs[seg].x1);
|
||||
points[n_points].y = (gdouble) (stroke_segs[seg].y1);
|
||||
|
||||
n_points++;
|
||||
}
|
||||
|
||||
g_free (points);
|
||||
}
|
||||
|
||||
g_free (stroke_segs);
|
||||
|
||||
return gimp_bezier_desc_new ((cairo_path_data_t *) g_array_free (path_data, FALSE),
|
||||
path_data->len);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GimpBezierDesc *
|
||||
gimp_brush_transform_boundary_approx (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GimpBezierDesc *
|
||||
gimp_brush_real_transform_boundary (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
gimp_brush_transform_size (brush, scale, aspect_ratio, angle,
|
||||
width, height);
|
||||
|
||||
if (TRUE /* width < foo && height < bar */)
|
||||
{
|
||||
return gimp_brush_transform_boundary_exact (brush,
|
||||
scale, aspect_ratio,
|
||||
angle, hardness);
|
||||
}
|
||||
|
||||
return gimp_brush_transform_boundary_approx (brush,
|
||||
scale, aspect_ratio,
|
||||
angle, hardness);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* GIMP - The GNU 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GIMP_BRUSH_BOUNDARY_H__
|
||||
#define __GIMP_BRUSH_BOUNDARY_H__
|
||||
|
||||
|
||||
GimpBezierDesc * gimp_brush_real_transform_boundary (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
|
||||
#endif /* __GIMP_BRUSH_BOUNDARY_H__ */
|
|
@ -27,6 +27,7 @@
|
|||
#include "base/temp-buf.h"
|
||||
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrush-boundary.h"
|
||||
#include "gimpbrush-load.h"
|
||||
#include "gimpbrush-transform.h"
|
||||
#include "gimpbrushgenerated.h"
|
||||
|
@ -129,6 +130,7 @@ gimp_brush_class_init (GimpBrushClass *klass)
|
|||
klass->transform_size = gimp_brush_real_transform_size;
|
||||
klass->transform_mask = gimp_brush_real_transform_mask;
|
||||
klass->transform_pixmap = gimp_brush_real_transform_pixmap;
|
||||
klass->transform_boundary = gimp_brush_real_transform_boundary;
|
||||
klass->spacing_changed = NULL;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SPACING,
|
||||
|
@ -536,11 +538,19 @@ gimp_brush_transform_boundary (GimpBrush *brush,
|
|||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness)
|
||||
gdouble hardness,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
|
||||
g_return_val_if_fail (scale > 0.0, NULL);
|
||||
g_return_val_if_fail (width != NULL, NULL);
|
||||
g_return_val_if_fail (height != NULL, NULL);
|
||||
|
||||
return NULL;
|
||||
return GIMP_BRUSH_GET_CLASS (brush)->transform_boundary (brush,
|
||||
scale, aspect_ratio,
|
||||
angle, hardness,
|
||||
width, height);
|
||||
}
|
||||
|
||||
gdouble
|
||||
|
|
|
@ -76,7 +76,9 @@ struct _GimpBrushClass
|
|||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness);
|
||||
gdouble hardness,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
/* signals */
|
||||
void (* spacing_changed) (GimpBrush *brush);
|
||||
|
@ -119,7 +121,9 @@ GimpBezierDesc * gimp_brush_transform_boundary (GimpBrush *brush,
|
|||
gdouble scale,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble hardness);
|
||||
gdouble hardness,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
gdouble gimp_brush_clamp_scale (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
|
|
Loading…
Reference in New Issue