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