1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <cairo.h>
21 #include <gdk-pixbuf/gdk-pixbuf.h>
22 #include <gegl.h>
23
24 #include "core-types.h"
25
26 #include "gimpbezierdesc.h"
27 #include "gimpboundary.h"
28 #include "gimpbrush.h"
29 #include "gimpbrush-boundary.h"
30 #include "gimptempbuf.h"
31
32
33 static GimpBezierDesc *
gimp_brush_transform_boundary_exact(GimpBrush * brush,gdouble scale,gdouble aspect_ratio,gdouble angle,gboolean reflect,gdouble hardness)34 gimp_brush_transform_boundary_exact (GimpBrush *brush,
35 gdouble scale,
36 gdouble aspect_ratio,
37 gdouble angle,
38 gboolean reflect,
39 gdouble hardness)
40 {
41 const GimpTempBuf *mask;
42
43 mask = gimp_brush_transform_mask (brush,
44 scale, aspect_ratio,
45 angle, reflect, hardness);
46
47 if (mask)
48 {
49 GeglBuffer *buffer;
50 GimpBoundSeg *bound_segs;
51 gint n_bound_segs;
52
53 buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) mask);
54
55 bound_segs = gimp_boundary_find (buffer, NULL,
56 babl_format ("Y float"),
57 GIMP_BOUNDARY_WITHIN_BOUNDS,
58 0, 0,
59 gegl_buffer_get_width (buffer),
60 gegl_buffer_get_height (buffer),
61 0.0,
62 &n_bound_segs);
63
64 g_object_unref (buffer);
65
66 if (bound_segs)
67 {
68 GimpBoundSeg *stroke_segs;
69 gint n_stroke_groups;
70
71 stroke_segs = gimp_boundary_sort (bound_segs, n_bound_segs,
72 &n_stroke_groups);
73
74 g_free (bound_segs);
75
76 if (stroke_segs)
77 {
78 GimpBezierDesc *path;
79
80 path = gimp_bezier_desc_new_from_bound_segs (stroke_segs,
81 n_bound_segs,
82 n_stroke_groups);
83
84 g_free (stroke_segs);
85
86 return path;
87 }
88 }
89 }
90
91 return NULL;
92 }
93
94 static GimpBezierDesc *
gimp_brush_transform_boundary_approx(GimpBrush * brush,gdouble scale,gdouble aspect_ratio,gdouble angle,gboolean reflect,gdouble hardness)95 gimp_brush_transform_boundary_approx (GimpBrush *brush,
96 gdouble scale,
97 gdouble aspect_ratio,
98 gdouble angle,
99 gboolean reflect,
100 gdouble hardness)
101 {
102 return gimp_brush_transform_boundary_exact (brush,
103 scale, aspect_ratio,
104 angle, reflect, hardness);
105 }
106
107 GimpBezierDesc *
gimp_brush_real_transform_boundary(GimpBrush * brush,gdouble scale,gdouble aspect_ratio,gdouble angle,gboolean reflect,gdouble hardness,gint * width,gint * height)108 gimp_brush_real_transform_boundary (GimpBrush *brush,
109 gdouble scale,
110 gdouble aspect_ratio,
111 gdouble angle,
112 gboolean reflect,
113 gdouble hardness,
114 gint *width,
115 gint *height)
116 {
117 gimp_brush_transform_size (brush, scale, aspect_ratio, angle, reflect,
118 width, height);
119
120 if (*width < 256 && *height < 256)
121 {
122 return gimp_brush_transform_boundary_exact (brush,
123 scale, aspect_ratio,
124 angle, reflect, hardness);
125 }
126
127 return gimp_brush_transform_boundary_approx (brush,
128 scale, aspect_ratio,
129 angle, reflect, hardness);
130 }
131