gimpbuffer.c 10.1 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
Michael Natterer's avatar
Michael Natterer committed
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
Michael Natterer's avatar
Michael Natterer committed
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
Michael Natterer's avatar
Michael Natterer committed
7 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Michael Natterer's avatar
Michael Natterer committed
16 17 18 19
 */

#include "config.h"

20
#include <cairo.h>
21
#include <gegl.h>
22 23 24
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "libgimpcolor/gimpcolor.h"
Michael Natterer's avatar
Michael Natterer committed
25 26 27

#include "core-types.h"

28
#include "gegl/gimp-babl.h"
29

30
#include "gimp-utils.h"
Michael Natterer's avatar
Michael Natterer committed
31
#include "gimpbuffer.h"
32
#include "gimpimage.h"
33
#include "gimptempbuf.h"
Michael Natterer's avatar
Michael Natterer committed
34 35


36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
static void          gimp_buffer_finalize         (GObject       *object);

static gint64        gimp_buffer_get_memsize      (GimpObject    *object,
                                                   gint64        *gui_size);

static gboolean      gimp_buffer_get_size         (GimpViewable  *viewable,
                                                   gint          *width,
                                                   gint          *height);
static void          gimp_buffer_get_preview_size (GimpViewable  *viewable,
                                                   gint           size,
                                                   gboolean       is_popup,
                                                   gboolean       dot_for_dot,
                                                   gint          *popup_width,
                                                   gint          *popup_height);
static gboolean      gimp_buffer_get_popup_size   (GimpViewable  *viewable,
                                                   gint           width,
                                                   gint           height,
                                                   gboolean       dot_for_dot,
                                                   gint          *popup_width,
                                                   gint          *popup_height);
static GimpTempBuf * gimp_buffer_get_new_preview  (GimpViewable  *viewable,
                                                   GimpContext   *context,
                                                   gint           width,
                                                   gint           height);
static gchar       * gimp_buffer_get_description  (GimpViewable  *viewable,
                                                   gchar        **tooltip);
62 63


64
G_DEFINE_TYPE (GimpBuffer, gimp_buffer, GIMP_TYPE_VIEWABLE)
65 66

#define parent_class gimp_buffer_parent_class
Michael Natterer's avatar
Michael Natterer committed
67 68 69 70 71


static void
gimp_buffer_class_init (GimpBufferClass *klass)
{
72 73 74
  GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
  GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
Michael Natterer's avatar
Michael Natterer committed
75

76
  object_class->finalize           = gimp_buffer_finalize;
Michael Natterer's avatar
Michael Natterer committed
77

78
  gimp_object_class->get_memsize   = gimp_buffer_get_memsize;
79

80
  viewable_class->default_stock_id = "gtk-paste";
81
  viewable_class->get_size         = gimp_buffer_get_size;
82
  viewable_class->get_preview_size = gimp_buffer_get_preview_size;
83
  viewable_class->get_popup_size   = gimp_buffer_get_popup_size;
84
  viewable_class->get_new_preview  = gimp_buffer_get_new_preview;
85
  viewable_class->get_description  = gimp_buffer_get_description;
Michael Natterer's avatar
Michael Natterer committed
86 87 88 89 90 91 92 93
}

static void
gimp_buffer_init (GimpBuffer *buffer)
{
}

static void
94
gimp_buffer_finalize (GObject *object)
Michael Natterer's avatar
Michael Natterer committed
95
{
96
  GimpBuffer *buffer = GIMP_BUFFER (object);
Michael Natterer's avatar
Michael Natterer committed
97

98
  if (buffer->buffer)
Michael Natterer's avatar
Michael Natterer committed
99
    {
100 101
      g_object_unref (buffer->buffer);
      buffer->buffer = NULL;
Michael Natterer's avatar
Michael Natterer committed
102 103
    }

104
  G_OBJECT_CLASS (parent_class)->finalize (object);
Michael Natterer's avatar
Michael Natterer committed
105 106
}

107
static gint64
108
gimp_buffer_get_memsize (GimpObject *object,
109
                         gint64     *gui_size)
110
{
111
  GimpBuffer *buffer  = GIMP_BUFFER (object);
112
  gint64      memsize = 0;
113

114
  memsize += gimp_gegl_buffer_get_memsize (buffer->buffer);
115

116 117
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
                                                                  gui_size);
118 119
}

120 121 122 123 124 125 126 127 128 129 130 131 132
static gboolean
gimp_buffer_get_size (GimpViewable *viewable,
                      gint         *width,
                      gint         *height)
{
  GimpBuffer *buffer = GIMP_BUFFER (viewable);

  *width  = gimp_buffer_get_width (buffer);
  *height = gimp_buffer_get_height (buffer);

  return TRUE;
}

133 134
static void
gimp_buffer_get_preview_size (GimpViewable *viewable,
135
                              gint          size,
136 137
                              gboolean      is_popup,
                              gboolean      dot_for_dot,
138 139
                              gint         *width,
                              gint         *height)
140
{
141
  GimpBuffer *buffer = GIMP_BUFFER (viewable);
142

143
  gimp_viewable_calc_preview_size (gimp_buffer_get_width (buffer),
144 145 146 147 148 149 150 151 152
                                   gimp_buffer_get_height (buffer),
                                   size,
                                   size,
                                   dot_for_dot, 1.0, 1.0,
                                   width,
                                   height,
                                   NULL);
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
static gboolean
gimp_buffer_get_popup_size (GimpViewable *viewable,
                            gint          width,
                            gint          height,
                            gboolean      dot_for_dot,
                            gint         *popup_width,
                            gint         *popup_height)
{
  GimpBuffer *buffer;
  gint        buffer_width;
  gint        buffer_height;

  buffer        = GIMP_BUFFER (viewable);
  buffer_width  = gimp_buffer_get_width (buffer);
  buffer_height = gimp_buffer_get_height (buffer);

  if (buffer_width > width || buffer_height > height)
    {
      gboolean scaling_up;

173
      gimp_viewable_calc_preview_size (buffer_width,
174
                                       buffer_height,
175 176
                                       width  * 2,
                                       height * 2,
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
                                       dot_for_dot, 1.0, 1.0,
                                       popup_width,
                                       popup_height,
                                       &scaling_up);

      if (scaling_up)
        {
          *popup_width  = buffer_width;
          *popup_height = buffer_height;
        }

      return TRUE;
    }

  return FALSE;
}

194
static GimpTempBuf *
Michael Natterer's avatar
Michael Natterer committed
195
gimp_buffer_get_new_preview (GimpViewable *viewable,
196
                             GimpContext  *context,
197 198
                             gint          width,
                             gint          height)
Michael Natterer's avatar
Michael Natterer committed
199
{
200
  GimpBuffer  *buffer = GIMP_BUFFER (viewable);
201
  const Babl  *format = gimp_buffer_get_format (buffer);
202
  GimpTempBuf *preview;
203

204
  if (babl_format_is_palette (format))
205
    format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA,
206 207 208
                               babl_format_has_alpha (format));
  else
    format = gimp_babl_format (gimp_babl_format_get_base_type (format),
209
                               GIMP_PRECISION_U8_GAMMA,
210
                               babl_format_has_alpha (format));
211

212 213 214
  preview = gimp_temp_buf_new (width, height, format);

  gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height),
215
                   MIN ((gdouble) width  / (gdouble) gimp_buffer_get_width (buffer),
216
                        (gdouble) height / (gdouble) gimp_buffer_get_height (buffer)),
217
                   format,
218
                   gimp_temp_buf_get_data (preview),
219
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
220 221

  return preview;
Michael Natterer's avatar
Michael Natterer committed
222 223
}

224 225 226 227
static gchar *
gimp_buffer_get_description (GimpViewable  *viewable,
                             gchar        **tooltip)
{
228
  GimpBuffer *buffer = GIMP_BUFFER (viewable);
229

230
  return g_strdup_printf ("%s (%d × %d)",
231
                          gimp_object_get_name (buffer),
232 233 234 235
                          gimp_buffer_get_width (buffer),
                          gimp_buffer_get_height (buffer));
}

Michael Natterer's avatar
Michael Natterer committed
236
GimpBuffer *
237 238 239 240 241
gimp_buffer_new (GeglBuffer    *buffer,
                 const gchar   *name,
                 gint           offset_x,
                 gint           offset_y,
                 gboolean       copy_pixels)
Michael Natterer's avatar
Michael Natterer committed
242
{
243
  GimpBuffer *gimp_buffer;
Michael Natterer's avatar
Michael Natterer committed
244

245
  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
Michael Natterer's avatar
Michael Natterer committed
246 247
  g_return_val_if_fail (name != NULL, NULL);

248 249 250
  gimp_buffer = g_object_new (GIMP_TYPE_BUFFER,
                              "name", name,
                              NULL);
Michael Natterer's avatar
Michael Natterer committed
251

252
  if (copy_pixels)
253
    gimp_buffer->buffer = gegl_buffer_dup (buffer);
254
  else
255
    gimp_buffer->buffer = g_object_ref (buffer);
Michael Natterer's avatar
Michael Natterer committed
256

257 258
  gimp_buffer->offset_x = offset_x;
  gimp_buffer->offset_y = offset_y;
259

260
  return gimp_buffer;
Michael Natterer's avatar
Michael Natterer committed
261
}
262

263 264
GimpBuffer *
gimp_buffer_new_from_pixbuf (GdkPixbuf   *pixbuf,
265 266 267
                             const gchar *name,
                             gint         offset_x,
                             gint         offset_y)
268
{
269 270
  GimpBuffer *gimp_buffer;
  GeglBuffer *buffer;
271 272 273 274

  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
  g_return_val_if_fail (name != NULL, NULL);

275
  buffer = gimp_pixbuf_create_buffer (pixbuf);
276

277 278
  gimp_buffer = gimp_buffer_new (buffer, name,
                                 offset_x, offset_y, FALSE);
279

280
  g_object_unref (buffer);
281

282
  return gimp_buffer;
283 284
}

285
gint
286
gimp_buffer_get_width (const GimpBuffer *buffer)
287 288 289
{
  g_return_val_if_fail (GIMP_IS_BUFFER (buffer), 0);

290
  return gegl_buffer_get_width (buffer->buffer);
291 292 293
}

gint
294
gimp_buffer_get_height (const GimpBuffer *buffer)
295 296 297
{
  g_return_val_if_fail (GIMP_IS_BUFFER (buffer), 0);

298
  return gegl_buffer_get_height (buffer->buffer);
299
}
300

301 302
const Babl *
gimp_buffer_get_format (const GimpBuffer *buffer)
303
{
304
  g_return_val_if_fail (GIMP_IS_BUFFER (buffer), NULL);
305

306
  return gegl_buffer_get_format (buffer->buffer);
307 308
}

309 310
GeglBuffer *
gimp_buffer_get_buffer (const GimpBuffer *buffer)
Sven Neumann's avatar
Sven Neumann committed
311 312 313
{
  g_return_val_if_fail (GIMP_IS_BUFFER (buffer), NULL);

314
  return buffer->buffer;
Sven Neumann's avatar
Sven Neumann committed
315
}