app: s/sprintf/g_snprintf/ in xcf_save_image()
[gimp.git] / libgimp / gimpzoompreview.c
blob2fd199a981e26a1959d0331de125c4de094c97f4
1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
4 * gimpzoompreview.c
5 * Copyright (C) 2005 David Odin <dindinx@gimp.org>
7 * This library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <https://www.gnu.org/licenses/>.
22 #include "config.h"
24 #include <gegl.h>
25 #include <gtk/gtk.h>
27 #include "libgimpwidgets/gimpwidgets.h"
29 #include "gimpuitypes.h"
31 #include "gimp.h"
33 #include "gimpdrawablepreview.h"
34 #include "gimpzoompreview.h"
37 /**
38 * SECTION: gimpzoompreview
39 * @title: GimpZoomPreview
40 * @short_description: A drawable preview with zooming capabilities.
42 * A drawable preview with zooming capabilities.
43 **/
46 enum
48 PROP_0,
49 PROP_DRAWABLE_ID,
50 PROP_MODEL
53 typedef struct
55 gboolean update;
56 } PreviewSettings;
59 struct _GimpZoomPreviewPrivate
61 gint32 drawable_ID;
62 GimpZoomModel *model;
63 GdkRectangle extents;
66 #define GET_PRIVATE(obj) (((GimpZoomPreview *) (obj))->priv)
69 static void gimp_zoom_preview_constructed (GObject *object);
70 static void gimp_zoom_preview_finalize (GObject *object);
71 static void gimp_zoom_preview_dispose (GObject *object);
72 static void gimp_zoom_preview_get_property (GObject *object,
73 guint property_id,
74 GValue *value,
75 GParamSpec *pspec);
76 static void gimp_zoom_preview_set_property (GObject *object,
77 guint property_id,
78 const GValue *value,
79 GParamSpec *pspec);
81 static void gimp_zoom_preview_set_adjustments (GimpZoomPreview *preview,
82 gdouble old_factor,
83 gdouble new_factor);
84 static void gimp_zoom_preview_size_allocate (GtkWidget *widget,
85 GtkAllocation *allocation,
86 GimpZoomPreview *preview);
87 static void gimp_zoom_preview_style_updated (GtkWidget *widget);
88 static gboolean gimp_zoom_preview_scroll_event (GtkWidget *widget,
89 GdkEventScroll *event,
90 GimpZoomPreview *preview);
91 static void gimp_zoom_preview_draw (GimpPreview *preview);
92 static void gimp_zoom_preview_draw_buffer (GimpPreview *preview,
93 const guchar *buffer,
94 gint rowstride);
95 static void gimp_zoom_preview_draw_thumb (GimpPreview *preview,
96 GimpPreviewArea *area,
97 gint width,
98 gint height);
99 static void gimp_zoom_preview_set_cursor (GimpPreview *preview);
100 static void gimp_zoom_preview_transform (GimpPreview *preview,
101 gint src_x,
102 gint src_y,
103 gint *dest_x,
104 gint *dest_y);
105 static void gimp_zoom_preview_untransform (GimpPreview *preview,
106 gint src_x,
107 gint src_y,
108 gint *dest_x,
109 gint *dest_y);
111 static void gimp_zoom_preview_set_drawable_id (GimpZoomPreview *preview,
112 gint32 drawable_ID);
113 static void gimp_zoom_preview_set_model (GimpZoomPreview *preview,
114 GimpZoomModel *model);
116 static void gimp_zoom_preview_get_source_area (GimpPreview *preview,
117 gint *x,
118 gint *y,
119 gint *w,
120 gint *h);
123 G_DEFINE_TYPE (GimpZoomPreview, gimp_zoom_preview, GIMP_TYPE_SCROLLED_PREVIEW)
125 #define parent_class gimp_zoom_preview_parent_class
127 static gint gimp_zoom_preview_counter = 0;
130 static void
131 gimp_zoom_preview_class_init (GimpZoomPreviewClass *klass)
133 GObjectClass *object_class = G_OBJECT_CLASS (klass);
134 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
135 GimpPreviewClass *preview_class = GIMP_PREVIEW_CLASS (klass);
137 object_class->constructed = gimp_zoom_preview_constructed;
138 object_class->finalize = gimp_zoom_preview_finalize;
139 object_class->dispose = gimp_zoom_preview_dispose;
140 object_class->get_property = gimp_zoom_preview_get_property;
141 object_class->set_property = gimp_zoom_preview_set_property;
143 widget_class->style_updated = gimp_zoom_preview_style_updated;
145 preview_class->draw = gimp_zoom_preview_draw;
146 preview_class->draw_buffer = gimp_zoom_preview_draw_buffer;
147 preview_class->draw_thumb = gimp_zoom_preview_draw_thumb;
148 preview_class->set_cursor = gimp_zoom_preview_set_cursor;
149 preview_class->transform = gimp_zoom_preview_transform;
150 preview_class->untransform = gimp_zoom_preview_untransform;
152 g_type_class_add_private (object_class, sizeof (GimpZoomPreviewPrivate));
155 * GimpZoomPreview:drawable-id:
157 * The drawable the #GimpZoomPreview is attached to.
159 * Since: 2.10
161 g_object_class_install_property (object_class, PROP_DRAWABLE_ID,
162 g_param_spec_int ("drawable-id",
163 "Drawable ID",
164 "The drawable this preview is attached to",
165 -1, G_MAXINT, -1,
166 GIMP_PARAM_READWRITE |
167 G_PARAM_CONSTRUCT_ONLY));
170 * GimpZoomPreview:model:
172 * The #GimpZoomModel used by this #GimpZoomPreview.
174 * Since: 2.4
176 g_object_class_install_property (object_class, PROP_MODEL,
177 g_param_spec_object ("model",
178 "Model",
179 "The zoom preview's GimpZoomModel",
180 GIMP_TYPE_ZOOM_MODEL,
181 GIMP_PARAM_READWRITE |
182 G_PARAM_CONSTRUCT_ONLY));
185 static void
186 gimp_zoom_preview_init (GimpZoomPreview *preview)
188 GtkWidget *area = gimp_preview_get_area (GIMP_PREVIEW (preview));
190 preview->priv = G_TYPE_INSTANCE_GET_PRIVATE (preview,
191 GIMP_TYPE_ZOOM_PREVIEW,
192 GimpZoomPreviewPrivate);
194 g_signal_connect (area, "size-allocate",
195 G_CALLBACK (gimp_zoom_preview_size_allocate),
196 preview);
197 g_signal_connect (area, "scroll-event",
198 G_CALLBACK (gimp_zoom_preview_scroll_event),
199 preview);
201 g_object_set (area,
202 "check-size", gimp_check_size (),
203 "check-type", gimp_check_type (),
204 NULL);
206 gimp_scrolled_preview_set_policy (GIMP_SCROLLED_PREVIEW (preview),
207 GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
210 static void
211 gimp_zoom_preview_constructed (GObject *object)
213 GimpZoomPreviewPrivate *priv = GET_PRIVATE (object);
214 gchar *data_name;
215 PreviewSettings settings;
217 G_OBJECT_CLASS (parent_class)->constructed (object);
219 data_name = g_strdup_printf ("%s-zoom-preview-%d",
220 g_get_prgname (),
221 gimp_zoom_preview_counter++);
223 if (gimp_get_data (data_name, &settings))
225 gimp_preview_set_update (GIMP_PREVIEW (object), settings.update);
228 g_object_set_data_full (object, "gimp-zoom-preview-data-name",
229 data_name, (GDestroyNotify) g_free);
231 if (! priv->model)
233 GimpZoomModel *model = gimp_zoom_model_new ();
235 gimp_zoom_model_set_range (model, 1.0, 256.0);
236 gimp_zoom_preview_set_model (GIMP_ZOOM_PREVIEW (object), model);
238 g_object_unref (model);
241 gimp_zoom_preview_set_adjustments (GIMP_ZOOM_PREVIEW (object), 1.0, 1.0);
244 static void
245 gimp_zoom_preview_finalize (GObject *object)
247 GimpZoomPreviewPrivate *priv = GET_PRIVATE (object);
249 g_clear_object (&priv->model);
251 G_OBJECT_CLASS (parent_class)->finalize (object);
254 static void
255 gimp_zoom_preview_dispose (GObject *object)
257 const gchar *data_name = g_object_get_data (G_OBJECT (object),
258 "gimp-zoom-preview-data-name");
260 if (data_name)
262 GimpPreview *preview = GIMP_PREVIEW (object);
263 PreviewSettings settings;
265 settings.update = gimp_preview_get_update (preview);
267 gimp_set_data (data_name, &settings, sizeof (PreviewSettings));
270 G_OBJECT_CLASS (parent_class)->dispose (object);
273 static void
274 gimp_zoom_preview_get_property (GObject *object,
275 guint property_id,
276 GValue *value,
277 GParamSpec *pspec)
279 GimpZoomPreview *preview = GIMP_ZOOM_PREVIEW (object);
281 switch (property_id)
283 case PROP_DRAWABLE_ID:
284 g_value_set_int (value, gimp_zoom_preview_get_drawable_id (preview));
285 break;
287 case PROP_MODEL:
288 g_value_set_object (value, gimp_zoom_preview_get_model (preview));
289 break;
291 default:
292 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
293 break;
297 static void
298 gimp_zoom_preview_set_property (GObject *object,
299 guint property_id,
300 const GValue *value,
301 GParamSpec *pspec)
303 GimpZoomPreview *preview = GIMP_ZOOM_PREVIEW (object);
305 switch (property_id)
307 case PROP_DRAWABLE_ID:
308 gimp_zoom_preview_set_drawable_id (preview, g_value_get_int (value));
309 break;
311 case PROP_MODEL:
312 gimp_zoom_preview_set_model (preview, g_value_get_object (value));
313 break;
315 default:
316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
317 break;
321 static void
322 gimp_zoom_preview_set_adjustments (GimpZoomPreview *preview,
323 gdouble old_factor,
324 gdouble new_factor)
326 GimpScrolledPreview *scrolled_preview = GIMP_SCROLLED_PREVIEW (preview);
327 GtkAdjustment *hadj;
328 GtkAdjustment *vadj;
329 gint width;
330 gint height;
331 gdouble ratio;
333 gimp_scrolled_preview_freeze (scrolled_preview);
335 gimp_preview_get_size (GIMP_PREVIEW (preview), &width, &height);
337 ratio = new_factor / old_factor;
339 gimp_scrolled_preview_get_adjustments (scrolled_preview, &hadj, &vadj);
341 gtk_adjustment_configure (hadj,
342 (gtk_adjustment_get_value (vadj) + width / 2.0) * ratio
343 - width / 2.0,
345 width * new_factor,
346 new_factor,
347 MAX (width / 2.0, new_factor),
348 width);
350 gtk_adjustment_configure (vadj,
351 (gtk_adjustment_get_value (vadj) + height / 2.0) * ratio
352 - height / 2.0,
354 height * new_factor,
355 new_factor,
356 MAX (height / 2.0, new_factor),
357 height);
359 gimp_scrolled_preview_thaw (scrolled_preview);
362 static void
363 gimp_zoom_preview_size_allocate (GtkWidget *widget,
364 GtkAllocation *allocation,
365 GimpZoomPreview *preview)
367 gdouble zoom;
369 #if 0
370 gint width = GIMP_PREVIEW (preview)->xmax - GIMP_PREVIEW (preview)->xmin;
371 gint height = GIMP_PREVIEW (preview)->ymax - GIMP_PREVIEW (preview)->ymin;
373 GIMP_PREVIEW (preview)->width = MIN (width, allocation->width);
374 GIMP_PREVIEW (preview)->height = MIN (height, allocation->height);
375 #endif
377 zoom = gimp_zoom_model_get_factor (preview->priv->model);
379 gimp_zoom_preview_set_adjustments (preview, zoom, zoom);
382 static void
383 gimp_zoom_preview_style_updated (GtkWidget *widget)
385 GimpPreview *preview = GIMP_PREVIEW (widget);
386 GtkWidget *area = gimp_preview_get_area (preview);
388 GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
390 if (area)
392 GimpZoomPreviewPrivate *priv = GET_PRIVATE (preview);
393 gint size;
394 gint width;
395 gint height;
396 gint preview_width;
397 gint preview_height;
398 gint x1, y1;
399 gint x2, y2;
401 gtk_widget_style_get (widget, "size", &size, NULL);
403 if (_gimp_drawable_preview_get_bounds (priv->drawable_ID,
404 &x1, &y1, &x2, &y2))
406 width = x2 - x1;
407 height = y2 - y1;
409 else
411 width = gimp_drawable_width (priv->drawable_ID);
412 height = gimp_drawable_height (priv->drawable_ID);
415 if (width > height)
417 preview_width = MIN (width, size);
418 preview_height = (height * preview_width) / width;
420 else
422 preview_height = MIN (height, size);
423 preview_width = (width * preview_height) / height;
426 gimp_preview_set_size (preview, preview_width, preview_height);
430 static gboolean
431 gimp_zoom_preview_scroll_event (GtkWidget *widget,
432 GdkEventScroll *event,
433 GimpZoomPreview *preview)
435 if (event->state & GDK_CONTROL_MASK)
437 GimpZoomPreviewPrivate *priv = GET_PRIVATE (preview);
438 gdouble delta;
440 gimp_scrolled_preview_freeze (GIMP_SCROLLED_PREVIEW (preview));
442 switch (event->direction)
444 case GDK_SCROLL_UP:
445 gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_IN, 0.0);
446 break;
448 case GDK_SCROLL_DOWN:
449 gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_OUT, 0.0);
450 break;
452 case GDK_SCROLL_SMOOTH:
453 gdk_event_get_scroll_deltas ((GdkEvent *) event, NULL, &delta);
454 gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_SMOOTH, delta);
455 break;
457 default:
458 break;
461 gimp_scrolled_preview_thaw (GIMP_SCROLLED_PREVIEW (preview));
464 return FALSE;
467 static void
468 gimp_zoom_preview_draw (GimpPreview *preview)
470 GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW (preview)->priv;
471 guchar *data;
472 gint width;
473 gint height;
474 gint bpp;
476 if (! priv->model)
477 return;
479 if (priv->drawable_ID < 1)
480 return;
482 data = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
483 &width, &height, &bpp);
485 if (data)
487 GtkWidget *area = gimp_preview_get_area (preview);
489 gimp_preview_area_draw (GIMP_PREVIEW_AREA (area),
490 0, 0, width, height,
491 gimp_drawable_type (priv->drawable_ID),
492 data, width * bpp);
493 g_free (data);
497 static void
498 gimp_zoom_preview_draw_buffer (GimpPreview *preview,
499 const guchar *buffer,
500 gint rowstride)
502 GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW (preview)->priv;
503 GtkWidget *area = gimp_preview_get_area (preview);
504 gint width;
505 gint height;
506 gint32 image_ID;
508 gimp_preview_get_size (preview, &width, &height);
509 image_ID = gimp_item_get_image (priv->drawable_ID);
511 if (gimp_selection_is_empty (image_ID))
513 gimp_preview_area_draw (GIMP_PREVIEW_AREA (area),
514 0, 0,
515 width, height,
516 gimp_drawable_type (priv->drawable_ID),
517 buffer,
518 rowstride);
520 else
522 guchar *sel;
523 guchar *src;
524 gint selection_ID;
525 gint w, h;
526 gint bpp;
527 gint src_x;
528 gint src_y;
529 gint src_width;
530 gint src_height;
531 gint offsx = 0;
532 gint offsy = 0;
534 selection_ID = gimp_image_get_selection (image_ID);
536 w = width;
537 h = height;
539 gimp_zoom_preview_get_source_area (preview,
540 &src_x, &src_y,
541 &src_width, &src_height);
543 src = gimp_drawable_get_sub_thumbnail_data (priv->drawable_ID,
544 src_x, src_y,
545 src_width, src_height,
546 &w, &h, &bpp);
547 gimp_drawable_offsets (priv->drawable_ID, &offsx, &offsy);
548 sel = gimp_drawable_get_sub_thumbnail_data (selection_ID,
549 src_x + offsx, src_y + offsy,
550 src_width, src_height,
551 &width, &height, &bpp);
553 gimp_preview_area_mask (GIMP_PREVIEW_AREA (area),
554 0, 0, width, height,
555 gimp_drawable_type (priv->drawable_ID),
556 src, width * gimp_drawable_bpp (priv->drawable_ID),
557 buffer, rowstride,
558 sel, width);
560 g_free (sel);
561 g_free (src);
566 static void
567 gimp_zoom_preview_draw_thumb (GimpPreview *preview,
568 GimpPreviewArea *area,
569 gint width,
570 gint height)
572 GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW (preview)->priv;
574 if (priv->drawable_ID > 0)
575 _gimp_drawable_preview_area_draw_thumb (area, priv->drawable_ID,
576 width, height);
579 static void
580 gimp_zoom_preview_set_cursor (GimpPreview *preview)
582 GtkWidget *area = gimp_preview_get_area (preview);
584 if (! gtk_widget_get_realized (area))
585 return;
587 if (gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview)) > 1.0)
589 GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (preview));
590 GdkCursor *cursor;
592 cursor = gdk_cursor_new_for_display (display, GDK_HAND1);
593 gdk_window_set_cursor (gtk_widget_get_window (area),
594 cursor);
595 g_object_unref (cursor);
597 else
599 gdk_window_set_cursor (gtk_widget_get_window (area),
600 gimp_preview_get_default_cursor (preview));
604 static void
605 gimp_zoom_preview_transform (GimpPreview *preview,
606 gint src_x,
607 gint src_y,
608 gint *dest_x,
609 gint *dest_y)
611 GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW (preview)->priv;
612 gint width;
613 gint height;
614 gint xoff;
615 gint yoff;
616 gdouble zoom;
618 gimp_preview_get_size (preview, &width, &height);
619 gimp_preview_get_offsets (preview, &xoff, &yoff);
621 zoom = gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview));
623 *dest_x = ((gdouble) (src_x - priv->extents.x) *
624 width / priv->extents.width * zoom) - xoff;
626 *dest_y = ((gdouble) (src_y - priv->extents.y) *
627 height / priv->extents.height * zoom) - yoff;
630 static void
631 gimp_zoom_preview_untransform (GimpPreview *preview,
632 gint src_x,
633 gint src_y,
634 gint *dest_x,
635 gint *dest_y)
637 GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW (preview)->priv;
638 gint width;
639 gint height;
640 gint xoff;
641 gint yoff;
642 gdouble zoom;
644 gimp_preview_get_size (preview, &width, &height);
645 gimp_preview_get_offsets (preview, &xoff, &yoff);
647 zoom = gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview));
649 *dest_x = (priv->extents.x +
650 ((gdouble) (src_x + xoff) *
651 priv->extents.width / width / zoom));
653 *dest_y = (priv->extents.y +
654 ((gdouble) (src_y + yoff) *
655 priv->extents.height / height / zoom));
658 static void
659 gimp_zoom_preview_set_drawable_id (GimpZoomPreview *preview,
660 gint32 drawable_ID)
662 GimpZoomPreviewPrivate *priv = preview->priv;
663 gint x, y;
664 gint width, height;
665 gint max_width, max_height;
667 g_return_if_fail (preview->priv->drawable_ID < 1);
669 priv->drawable_ID = drawable_ID;
671 if (gimp_drawable_mask_intersect (drawable_ID, &x, &y, &width, &height))
673 priv->extents.x = x;
674 priv->extents.y = y;
676 else
678 width = gimp_drawable_width (drawable_ID);
679 height = gimp_drawable_height (drawable_ID);
681 priv->extents.x = 0;
682 priv->extents.y = 0;
685 priv->extents.width = width;
686 priv->extents.height = height;
688 if (width > height)
690 max_width = MIN (width, 512);
691 max_height = (height * max_width) / width;
693 else
695 max_height = MIN (height, 512);
696 max_width = (width * max_height) / height;
699 gimp_preview_set_bounds (GIMP_PREVIEW (preview),
700 0, 0, max_width, max_height);
702 g_object_set (gimp_preview_get_frame (GIMP_PREVIEW (preview)),
703 "ratio", (gdouble) width / (gdouble) height,
704 NULL);
707 static void
708 gimp_zoom_preview_set_model (GimpZoomPreview *preview,
709 GimpZoomModel *model)
711 GimpZoomPreviewPrivate *priv = GET_PRIVATE (preview);
712 GtkWidget *button_bar;
713 GtkWidget *button;
714 GtkWidget *box;
716 g_return_if_fail (priv->model == NULL);
718 if (! model)
719 return;
721 priv->model = g_object_ref (model);
723 g_signal_connect_swapped (priv->model, "zoomed",
724 G_CALLBACK (gimp_zoom_preview_set_adjustments),
725 preview);
727 box = gimp_preview_get_controls (GIMP_PREVIEW (preview));
728 g_return_if_fail (GTK_IS_BOX (box));
730 button_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
731 gtk_box_pack_end (GTK_BOX (box), button_bar, FALSE, FALSE, 0);
732 gtk_widget_show (button_bar);
734 /* zoom out */
735 button = gimp_zoom_button_new (priv->model,
736 GIMP_ZOOM_OUT, GTK_ICON_SIZE_SMALL_TOOLBAR);
737 gtk_box_pack_start (GTK_BOX (button_bar), button, FALSE, FALSE, 0);
738 gtk_widget_show (button);
740 /* zoom in */
741 button = gimp_zoom_button_new (priv->model,
742 GIMP_ZOOM_IN, GTK_ICON_SIZE_SMALL_TOOLBAR);
743 gtk_box_pack_start (GTK_BOX (button_bar), button, FALSE, FALSE, 0);
744 gtk_widget_show (button);
747 static void
748 gimp_zoom_preview_get_source_area (GimpPreview *preview,
749 gint *x,
750 gint *y,
751 gint *w,
752 gint *h)
754 GimpZoomPreviewPrivate *priv = GET_PRIVATE (preview);
755 gdouble zoom = gimp_zoom_model_get_factor (priv->model);
757 gimp_zoom_preview_untransform (preview, 0, 0, x, y);
759 *w = priv->extents.width / zoom;
760 *h = priv->extents.height / zoom;
765 * gimp_zoom_preview_new_from_drawable_id:
766 * @drawable_ID: a drawable ID
768 * Creates a new #GimpZoomPreview widget for @drawable_ID.
770 * Since: 2.10
772 * Returns: a new #GimpZoomPreview.
774 GtkWidget *
775 gimp_zoom_preview_new_from_drawable_id (gint32 drawable_ID)
777 g_return_val_if_fail (gimp_item_is_valid (drawable_ID), NULL);
778 g_return_val_if_fail (gimp_item_is_drawable (drawable_ID), NULL);
780 return g_object_new (GIMP_TYPE_ZOOM_PREVIEW,
781 "drawable-id", drawable_ID,
782 NULL);
786 * gimp_zoom_preview_new_with_model_from_drawable_id:
787 * @drawable_ID: a drawable ID
788 * @model: a #GimpZoomModel
790 * Creates a new #GimpZoomPreview widget for @drawable_ID using the
791 * given @model.
793 * This variant of gimp_zoom_preview_new_from_drawable_id() allows you
794 * to create a preview using an existing zoom model. This may be
795 * useful if for example you want to have two zoom previews that keep
796 * their zoom factor in sync.
798 * Since: 2.10
800 * Returns: a new #GimpZoomPreview.
802 GtkWidget *
803 gimp_zoom_preview_new_with_model_from_drawable_id (gint32 drawable_ID,
804 GimpZoomModel *model)
807 g_return_val_if_fail (gimp_item_is_valid (drawable_ID), NULL);
808 g_return_val_if_fail (gimp_item_is_drawable (drawable_ID), NULL);
809 g_return_val_if_fail (GIMP_IS_ZOOM_MODEL (model), NULL);
811 return g_object_new (GIMP_TYPE_ZOOM_PREVIEW,
812 "drawable-id", drawable_ID,
813 "model", model,
814 NULL);
818 * gimp_zoom_preview_get_drawable_id:
819 * @preview: a #GimpZoomPreview widget
821 * Returns the drawable_ID the #GimpZoomPreview is attached to.
823 * Return Value: the drawable_ID that was passed to
824 * gimp_zoom_preview_new_from_drawable_id().
826 * Since: 2.10
828 gint32
829 gimp_zoom_preview_get_drawable_id (GimpZoomPreview *preview)
831 g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), -1);
833 return GET_PRIVATE (preview)->drawable_ID;
837 * gimp_zoom_preview_get_model:
838 * @preview: a #GimpZoomPreview widget
840 * Returns the #GimpZoomModel the preview is using.
842 * Return Value: a pointer to the #GimpZoomModel owned by the @preview
844 * Since: 2.4
846 GimpZoomModel *
847 gimp_zoom_preview_get_model (GimpZoomPreview *preview)
849 g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), NULL);
851 return GET_PRIVATE (preview)->model;
855 * gimp_zoom_preview_get_factor:
856 * @preview: a #GimpZoomPreview widget
858 * Returns the zoom factor the preview is currently using.
860 * Return Value: the current zoom factor
862 * Since: 2.4
864 gdouble
865 gimp_zoom_preview_get_factor (GimpZoomPreview *preview)
867 GimpZoomPreviewPrivate *priv;
869 g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), 1.0);
871 priv = GET_PRIVATE (preview);
873 return priv->model ? gimp_zoom_model_get_factor (priv->model) : 1.0;
877 * gimp_zoom_preview_get_source:
878 * @preview: a #GimpZoomPreview widget
879 * @width: a pointer to an int where the current width of the zoom widget
880 * will be put.
881 * @height: a pointer to an int where the current width of the zoom widget
882 * will be put.
883 * @bpp: return location for the number of bytes per pixel
885 * Returns the scaled image data of the part of the drawable the
886 * #GimpZoomPreview is currently showing, as a newly allocated array of guchar.
887 * This function also allow to get the current width, height and bpp of the
888 * #GimpZoomPreview.
890 * Return Value: newly allocated data that should be released using g_free()
891 * when it is not any longer needed
893 * Since: 2.4
895 guchar *
896 gimp_zoom_preview_get_source (GimpZoomPreview *preview,
897 gint *width,
898 gint *height,
899 gint *bpp)
901 gint32 drawable_ID;
903 g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), NULL);
904 g_return_val_if_fail (width != NULL && height != NULL && bpp != NULL, NULL);
906 drawable_ID = gimp_zoom_preview_get_drawable_id (preview);
908 if (drawable_ID > 0)
910 GimpPreview *gimp_preview = GIMP_PREVIEW (preview);
911 gint src_x;
912 gint src_y;
913 gint src_width;
914 gint src_height;
916 gimp_preview_get_size (gimp_preview, width, height);
918 gimp_zoom_preview_get_source_area (gimp_preview,
919 &src_x, &src_y,
920 &src_width, &src_height);
922 return gimp_drawable_get_sub_thumbnail_data (drawable_ID,
923 src_x, src_y,
924 src_width, src_height,
925 width, height, bpp);
927 else
929 *width = 0;
930 *height = 0;
931 *bpp = 0;
933 return NULL;