1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /**
3 * A simple gradient preview
4 *
5 * Author:
6 * Lauris Kaplinski <lauris@kaplinski.com>
7 *
8 * Copyright (C) 2001-2002 Lauris Kaplinski
9 * Copyright (C) 2001 Ximian, Inc.
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14 #include <sigc++/sigc++.h>
15
16 #include <glibmm/refptr.h>
17 #include <gdkmm/pixbuf.h>
18
19 #include <cairomm/surface.h>
20
21 #include "gradient-image.h"
22
23 #include "display/cairo-utils.h"
24
25 #include "object/sp-gradient.h"
26 #include "object/sp-stop.h"
27
28 namespace Inkscape {
29 namespace UI {
30 namespace Widget {
GradientImage(SPGradient * gradient)31 GradientImage::GradientImage(SPGradient *gradient)
32 : _gradient(nullptr)
33 {
34 set_has_window(false);
35 set_gradient(gradient);
36 }
37
~GradientImage()38 GradientImage::~GradientImage()
39 {
40 if (_gradient) {
41 _release_connection.disconnect();
42 _modified_connection.disconnect();
43 _gradient = nullptr;
44 }
45 }
46
47 void
size_request(GtkRequisition * requisition) const48 GradientImage::size_request(GtkRequisition *requisition) const
49 {
50 requisition->width = 54;
51 requisition->height = 12;
52 }
53
54 void
get_preferred_width_vfunc(int & minimal_width,int & natural_width) const55 GradientImage::get_preferred_width_vfunc(int &minimal_width, int &natural_width) const
56 {
57 GtkRequisition requisition;
58 size_request(&requisition);
59 minimal_width = natural_width = requisition.width;
60 }
61
62 void
get_preferred_height_vfunc(int & minimal_height,int & natural_height) const63 GradientImage::get_preferred_height_vfunc(int &minimal_height, int &natural_height) const
64 {
65 GtkRequisition requisition;
66 size_request(&requisition);
67 minimal_height = natural_height = requisition.height;
68 }
69
70 bool
on_draw(const Cairo::RefPtr<Cairo::Context> & cr)71 GradientImage::on_draw(const Cairo::RefPtr<Cairo::Context> &cr)
72 {
73 auto allocation = get_allocation();
74
75 cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
76 auto ct = cr->cobj();
77
78 cairo_set_source(ct, check);
79 cairo_paint(ct);
80 cairo_pattern_destroy(check);
81
82 if (_gradient) {
83 auto p = _gradient->create_preview_pattern(allocation.get_width());
84 cairo_set_source(ct, p);
85 cairo_paint(ct);
86 cairo_pattern_destroy(p);
87 }
88
89 return true;
90 }
91
92 void
set_gradient(SPGradient * gradient)93 GradientImage::set_gradient(SPGradient *gradient)
94 {
95 if (_gradient) {
96 _release_connection.disconnect();
97 _modified_connection.disconnect();
98 }
99
100 _gradient = gradient;
101
102 if (gradient) {
103 _release_connection = gradient->connectRelease(sigc::mem_fun(this, &GradientImage::gradient_release));
104 _modified_connection = gradient->connectModified(sigc::mem_fun(this, &GradientImage::gradient_modified));
105 }
106
107 update();
108 }
109
110 void
gradient_release(SPObject *)111 GradientImage::gradient_release(SPObject *)
112 {
113 if (_gradient) {
114 _release_connection.disconnect();
115 _modified_connection.disconnect();
116 }
117
118 _gradient = nullptr;
119
120 update();
121 }
122
123 void
gradient_modified(SPObject *,guint)124 GradientImage::gradient_modified(SPObject *, guint /*flags*/)
125 {
126 update();
127 }
128
129 void
update()130 GradientImage::update()
131 {
132 if (get_is_drawable()) {
133 queue_draw();
134 }
135 }
136
137 } // namespace Widget
138 } // namespace UI
139 } // namespace Inkscape
140
141 GdkPixbuf*
sp_gradient_to_pixbuf(SPGradient * gr,int width,int height)142 sp_gradient_to_pixbuf (SPGradient *gr, int width, int height)
143 {
144 cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
145 cairo_t *ct = cairo_create(s);
146
147 cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
148 cairo_set_source(ct, check);
149 cairo_paint(ct);
150 cairo_pattern_destroy(check);
151
152 if (gr) {
153 cairo_pattern_t *p = gr->create_preview_pattern(width);
154 cairo_set_source(ct, p);
155 cairo_paint(ct);
156 cairo_pattern_destroy(p);
157 }
158
159 cairo_destroy(ct);
160 cairo_surface_flush(s);
161
162 // no need to free s - the call below takes ownership
163 GdkPixbuf *pixbuf = ink_pixbuf_create_from_cairo_surface(s);
164 return pixbuf;
165 }
166
167
168 Glib::RefPtr<Gdk::Pixbuf>
sp_gradient_to_pixbuf_ref(SPGradient * gr,int width,int height)169 sp_gradient_to_pixbuf_ref (SPGradient *gr, int width, int height)
170 {
171 cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
172 cairo_t *ct = cairo_create(s);
173
174 cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
175 cairo_set_source(ct, check);
176 cairo_paint(ct);
177 cairo_pattern_destroy(check);
178
179 if (gr) {
180 cairo_pattern_t *p = gr->create_preview_pattern(width);
181 cairo_set_source(ct, p);
182 cairo_paint(ct);
183 cairo_pattern_destroy(p);
184 }
185
186 cairo_destroy(ct);
187 cairo_surface_flush(s);
188
189 Cairo::RefPtr<Cairo::Surface> sref = Cairo::RefPtr<Cairo::Surface>(new Cairo::Surface(s));
190 Glib::RefPtr<Gdk::Pixbuf> pixbuf =
191 Gdk::Pixbuf::create(sref, 0, 0, width, height);
192
193 cairo_surface_destroy(s);
194
195 return pixbuf;
196 }
197
198
199 Glib::RefPtr<Gdk::Pixbuf>
sp_gradstop_to_pixbuf_ref(SPStop * stop,int width,int height)200 sp_gradstop_to_pixbuf_ref (SPStop *stop, int width, int height)
201 {
202 cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
203 cairo_t *ct = cairo_create(s);
204
205 /* Checkerboard background */
206 cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
207 cairo_rectangle(ct, 0, 0, width, height);
208 cairo_set_source(ct, check);
209 cairo_fill_preserve(ct);
210 cairo_pattern_destroy(check);
211
212 if (stop) {
213 /* Alpha area */
214 cairo_rectangle(ct, 0, 0, width/2, height);
215 ink_cairo_set_source_rgba32(ct, stop->get_rgba32());
216 cairo_fill(ct);
217
218 /* Solid area */
219 cairo_rectangle(ct, width/2, 0, width, height);
220 ink_cairo_set_source_rgba32(ct, stop->get_rgba32() | 0xff);
221 cairo_fill(ct);
222 }
223
224 cairo_destroy(ct);
225 cairo_surface_flush(s);
226
227 Cairo::RefPtr<Cairo::Surface> sref = Cairo::RefPtr<Cairo::Surface>(new Cairo::Surface(s));
228 Glib::RefPtr<Gdk::Pixbuf> pixbuf =
229 Gdk::Pixbuf::create(sref, 0, 0, width, height);
230
231 cairo_surface_destroy(s);
232
233 return pixbuf;
234 }
235
236
237
238 /*
239 Local Variables:
240 mode:c++
241 c-file-style:"stroustrup"
242 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
243 indent-tabs-mode:nil
244 fill-column:99
245 End:
246 */
247 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
248