Update Portuguese translation
[gegl.git] / bin / mrg-gegl.c
blobdd0e5568693c8576448675151a982f6bac688ee9
1 /* This file is part of GEGL editor -- an mrg frontend for GEGL
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, see <https://www.gnu.org/licenses/>.
16 * Copyright (C) 2015 Øyvind Kolås pippin@gimp.org
19 /* The code in this file is an image viewer/editor written using microraptor
20 * gui and GEGL. It renders the UI directly from GEGLs data structures.
23 #define _BSD_SOURCE
24 #define _DEFAULT_SOURCE
26 #include "config.h"
28 #ifdef HAVE_MRG
30 #include <ctype.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <dirent.h>
38 #include <math.h>
39 #include <mrg.h>
40 #include <gegl.h>
41 #include <gexiv2/gexiv2.h>
42 #include <gegl-paramspecs.h>
43 #include <gegl-audio-fragment.h>
44 #include "mrg-gegl.h"
46 static unsigned char *copy_buf = NULL;
47 static int copy_buf_len = 0;
49 static float cached_x0 = 0;
50 static float cached_y0 = 0;
51 static float cached_width = 0;
52 static float cached_height = 0;
53 static float cached_u = 0;
54 static float cached_v = 0;
55 static float cached_scale = 0;
56 static float cached_prev_mul = 0;
57 static int cached_nearest = 0;
58 static int cached_dirty = 0;
59 static cairo_surface_t *cached_surface = NULL;
61 void mrg_gegl_dirty (Mrg *mrg)
63 cached_dirty++;
66 int mrg_gegl_got_nearest (void)
68 return cached_nearest;
71 void mrg_gegl_buffer_blit (Mrg *mrg,
72 float x0, float y0,
73 float width, float height,
74 GeglBuffer *buffer,
75 float u, float v,
76 float scale,
77 float preview_multiplier,
78 int nearest_neighbor,
79 int color_manage_display)
81 float fake_factor = preview_multiplier;
82 GeglRectangle bounds;
84 cairo_t *cr = mrg_cr (mrg);
85 cairo_surface_t *surface = NULL;
87 if (!buffer)
88 return;
90 bounds = *gegl_buffer_get_extent (buffer);
92 if (width == -1 && height == -1)
94 width = bounds.width;
95 height = bounds.height;
98 if (width == -1)
99 width = bounds.width * height / bounds.height;
100 if (height == -1)
101 height = bounds.height * width / bounds.width;
103 if (cached_x0 == x0 &&
104 cached_y0 == y0 &&
105 cached_width == width &&
106 cached_height == height &&
107 cached_u == u &&
108 cached_v == v &&
109 cached_scale == scale &&
110 cached_prev_mul == preview_multiplier &&
111 cached_dirty == 0)
113 width /= fake_factor;
114 height /= fake_factor;
115 u /= fake_factor;
116 v /= fake_factor;
118 surface = cached_surface;
120 else
122 cached_x0 = x0;
123 cached_y0 = y0;
124 cached_width = width;
125 cached_height = height;
126 cached_u = u;
127 cached_v = v;
128 cached_scale = scale;
129 cached_nearest = nearest_neighbor;
130 cached_prev_mul = preview_multiplier;
131 cached_dirty = 0;
133 width /= fake_factor;
134 height /= fake_factor;
135 u /= fake_factor;
136 v /= fake_factor;
138 if (copy_buf_len < width * height * 4)
140 if (copy_buf)
141 free (copy_buf);
143 /* we over-allocate ones scanline, otherwise we sometimes get
144 crashes.
146 copy_buf_len = width * (height+1) * 4;
147 copy_buf = malloc (copy_buf_len);
150 unsigned char *buf = copy_buf;
151 GeglRectangle roi = {u, v, width, height};
152 const Babl *fmt = NULL;
153 static const Babl *fmt_icc = NULL;
154 static const Babl *fmt_srgb = NULL;
156 if (color_manage_display)
158 if (!fmt_icc)
160 int icc_length = 0;
161 unsigned const char *icc_data = mrg_get_profile (mrg, &icc_length);
162 const Babl *space = NULL;
163 if (icc_data)
164 space = babl_space_from_icc ((char*)icc_data, icc_length, BABL_ICC_INTENT_RELATIVE_COLORIMETRIC, NULL);
165 fmt_icc = babl_format_with_space ("cairo-RGB24", space);
167 fmt = fmt_icc;
169 else
171 if (!fmt_srgb)
172 fmt_srgb = babl_format_with_space ("cairo-RGB24", NULL);
173 fmt = fmt_srgb;
175 gegl_buffer_get (buffer, &roi, scale / fake_factor, fmt, buf, width * 4,
176 GEGL_ABYSS_NONE | (nearest_neighbor?GEGL_BUFFER_FILTER_NEAREST:0));
177 surface = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_RGB24, width, height, width * 4);
180 cairo_surface_set_device_scale (surface, 1.0/fake_factor, 1.0/fake_factor);
181 if (cached_surface)
182 cairo_surface_destroy (cached_surface);
183 cached_surface = surface;
185 cairo_save (cr);
187 width *= fake_factor;
188 height *= fake_factor;
189 u *= fake_factor;
190 v *= fake_factor;
192 cairo_rectangle (cr, x0, y0, width, height);
194 cairo_clip (cr);
195 cairo_translate (cr, floorf (x0 * fake_factor), floorf (y0 * fake_factor));
196 cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
197 cairo_set_source_surface (cr, surface, 0, 0);
199 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
200 cairo_paint (cr);
202 //cairo_surface_destroy (surface);
203 cairo_restore (cr);
208 void mrg_gegl_blit (Mrg *mrg,
209 float x0, float y0,
210 float width, float height,
211 GeglNode *node,
212 float u, float v,
213 float scale,
214 float preview_multiplier,
215 int nearest_neighbor,
216 int color_manage_display)
218 float fake_factor = preview_multiplier;
219 GeglRectangle bounds;
221 cairo_t *cr = mrg_cr (mrg);
222 cairo_surface_t *surface = NULL;
224 if (!node)
225 return;
227 bounds = gegl_node_get_bounding_box (node);
229 if (width == -1 && height == -1)
231 width = bounds.width;
232 height = bounds.height;
235 if (width == -1)
236 width = bounds.width * height / bounds.height;
237 if (height == -1)
238 height = bounds.height * width / bounds.width;
240 width /= fake_factor;
241 height /= fake_factor;
242 u /= fake_factor;
243 v /= fake_factor;
245 if (copy_buf_len < width * height * 4)
247 if (copy_buf)
248 free (copy_buf);
250 /* XXX: same overallocation as in other code-path, overallocating a fixed
251 amount might also be a sufficient workaround until the underlying
252 issue is resolved.
254 copy_buf_len = width * (height+1) * 4;
255 copy_buf = malloc (copy_buf_len);
258 unsigned char *buf = copy_buf;
259 GeglRectangle roi = {u, v, width, height};
260 const Babl *fmt = NULL;
261 static const Babl *fmt_icc = NULL;
262 static const Babl *fmt_srgb = NULL;
264 if (color_manage_display)
266 if (!fmt_icc)
268 int icc_length = 0;
269 unsigned const char *icc_data = mrg_get_profile (mrg, &icc_length);
270 const Babl *space = NULL;
271 if (icc_data)
272 space = babl_space_from_icc ((char*)icc_data, icc_length, BABL_ICC_INTENT_RELATIVE_COLORIMETRIC, NULL);
273 fmt_icc = babl_format_with_space ("cairo-RGB24", space);
275 fmt = fmt_icc;
277 else
279 if (!fmt_srgb)
280 fmt_srgb = babl_format_with_space ("cairo-RGB24", NULL);
281 fmt = fmt_srgb;
284 gegl_node_blit (node, scale / fake_factor, &roi, fmt, buf, width * 4,
285 GEGL_BLIT_DEFAULT | (nearest_neighbor?GEGL_BUFFER_FILTER_NEAREST:0));
286 surface = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_RGB24, width, height, width * 4);
289 cairo_save (cr);
290 cairo_surface_set_device_scale (surface, 1.0/fake_factor, 1.0/fake_factor);
292 width *= fake_factor;
293 height *= fake_factor;
294 u *= fake_factor;
295 v *= fake_factor;
297 cairo_rectangle (cr, x0, y0, width, height);
299 cairo_clip (cr);
300 cairo_translate (cr, floorf (x0 * fake_factor), floorf (y0 * fake_factor));
301 cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
302 cairo_set_source_surface (cr, surface, 0, 0);
304 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
305 cairo_paint (cr);
306 cairo_surface_destroy (surface);
307 cairo_restore (cr);
311 #endif