~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/print/print-preview.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mto: This revision was merged to the branch mainline in revision 35.
  • Revision ID: james.westby@ubuntu.com-20081006133041-3panbkcanaymfsmp
Tags: upstream-2.6.0
ImportĀ upstreamĀ versionĀ 2.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "print-preview.h"
25
25
 
26
26
 
27
 
#define DRAWING_AREA_SIZE 200
28
 
 
29
 
 
30
27
enum
31
28
{
32
29
  OFFSETS_CHANGED,
34
31
};
35
32
 
36
33
 
37
 
static void      gimp_print_preview_finalize         (GObject          *object);
38
 
 
39
 
static void      gimp_print_preview_size_allocate    (GtkWidget        *widget,
40
 
                                                      GtkAllocation    *allocation,
41
 
                                                      GimpPrintPreview *preview);
42
 
static void      gimp_print_preview_realize          (GtkWidget        *widget);
43
 
static gboolean  gimp_print_preview_event            (GtkWidget        *widget,
44
 
                                                      GdkEvent         *event,
45
 
                                                      GimpPrintPreview *preview);
46
 
 
47
 
static gboolean  gimp_print_preview_expose_event     (GtkWidget        *widget,
48
 
                                                      GdkEventExpose   *eevent,
49
 
                                                      GimpPrintPreview *preview);
50
 
 
51
 
static gdouble   gimp_print_preview_get_scale        (GimpPrintPreview *preview);
52
 
 
53
 
static void      gimp_print_preview_get_page_margins (GimpPrintPreview *preview,
54
 
                                                      gdouble          *left_margin,
55
 
                                                      gdouble          *right_margin,
56
 
                                                      gdouble          *top_margin,
57
 
                                                      gdouble          *bottom_margin);
58
 
 
59
 
static void      print_preview_queue_draw            (GimpPrintPreview *preview);
60
 
 
61
 
 
62
 
G_DEFINE_TYPE (GimpPrintPreview, gimp_print_preview, GTK_TYPE_ASPECT_FRAME)
63
 
 
64
 
#define parent_class gimp_print_preview_parent_class
65
 
 
66
 
static guint gimp_print_preview_signals[LAST_SIGNAL] = { 0 };
 
34
#define SIZE_REQUEST  200
 
35
 
 
36
 
 
37
struct _PrintPreview
 
38
{
 
39
  GtkEventBox      parent_instance;
 
40
 
 
41
  GdkCursor       *cursor;
 
42
 
 
43
  GtkPageSetup    *page;
 
44
  cairo_surface_t *thumbnail;
 
45
  gboolean         dragging;
 
46
  gboolean         inside;
 
47
 
 
48
  GimpDrawable    *drawable;
 
49
 
 
50
  gdouble          image_offset_x;
 
51
  gdouble          image_offset_y;
 
52
  gdouble          image_offset_x_max;
 
53
  gdouble          image_offset_y_max;
 
54
  gdouble          image_width;
 
55
  gdouble          image_height;
 
56
 
 
57
  gboolean         use_full_page;
 
58
 
 
59
  /* for mouse drags */
 
60
  gdouble          orig_offset_x;
 
61
  gdouble          orig_offset_y;
 
62
  gint             start_x;
 
63
  gint             start_y;
 
64
};
 
65
 
 
66
struct _PrintPreviewClass
 
67
{
 
68
  GtkEventBoxClass  parent_class;
 
69
 
 
70
  void (* offsets_changed)  (PrintPreview *print_preview,
 
71
                             gint          offset_x,
 
72
                             gint          offset_y);
 
73
};
 
74
 
 
75
 
 
76
static void      print_preview_finalize             (GObject          *object);
 
77
 
 
78
static void      print_preview_realize              (GtkWidget        *widget);
 
79
static void      print_preview_unrealize            (GtkWidget        *widget);
 
80
static void      print_preview_size_request         (GtkWidget        *widget,
 
81
                                                     GtkRequisition   *requisition);
 
82
static void      print_preview_size_allocate        (GtkWidget        *widget,
 
83
                                                     GtkAllocation    *allocation);
 
84
static gboolean  print_preview_expose_event         (GtkWidget        *widget,
 
85
                                                     GdkEventExpose   *event);
 
86
static gboolean  print_preview_button_press_event   (GtkWidget        *widget,
 
87
                                                     GdkEventButton   *event);
 
88
static gboolean  print_preview_button_release_event (GtkWidget        *widget,
 
89
                                                     GdkEventButton   *event);
 
90
static gboolean  print_preview_motion_notify_event  (GtkWidget        *widget,
 
91
                                                     GdkEventMotion   *event);
 
92
static gboolean  print_preview_leave_notify_event   (GtkWidget        *widget,
 
93
                                                     GdkEventCrossing *event);
 
94
 
 
95
static gboolean  print_preview_is_inside            (PrintPreview     *preview,
 
96
                                                     gdouble           x,
 
97
                                                     gdouble           y);
 
98
static void      print_preview_set_inside           (PrintPreview     *preview,
 
99
                                                     gboolean          inside);
 
100
 
 
101
static gdouble   print_preview_get_scale            (PrintPreview     *preview);
 
102
 
 
103
static void      print_preview_get_page_size        (PrintPreview     *preview,
 
104
                                                     gdouble          *paper_width,
 
105
                                                     gdouble          *paper_height);
 
106
static void      print_preview_get_page_margins     (PrintPreview     *preview,
 
107
                                                     gdouble          *left_margin,
 
108
                                                     gdouble          *right_margin,
 
109
                                                     gdouble          *top_margin,
 
110
                                                     gdouble          *bottom_margin);
 
111
static cairo_surface_t * print_preview_get_thumbnail (GimpDrawable    *drawable,
 
112
                                                      gint             width,
 
113
                                                      gint             height);
 
114
 
 
115
 
 
116
G_DEFINE_TYPE (PrintPreview, print_preview, GTK_TYPE_EVENT_BOX)
 
117
 
 
118
#define parent_class print_preview_parent_class
 
119
 
 
120
static guint print_preview_signals[LAST_SIGNAL] = { 0 };
67
121
 
68
122
 
69
123
#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
107
161
}
108
162
 
109
163
static void
110
 
gimp_print_preview_class_init (GimpPrintPreviewClass *klass)
 
164
print_preview_class_init (PrintPreviewClass *klass)
111
165
{
112
 
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
166
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
167
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
113
168
 
114
 
  gimp_print_preview_signals[OFFSETS_CHANGED] =
 
169
  print_preview_signals[OFFSETS_CHANGED] =
115
170
    g_signal_new ("offsets-changed",
116
171
                  G_TYPE_FROM_CLASS (klass),
117
172
                  G_SIGNAL_RUN_FIRST,
118
 
                  G_STRUCT_OFFSET (GimpPrintPreviewClass, offsets_changed),
 
173
                  G_STRUCT_OFFSET (PrintPreviewClass, offsets_changed),
119
174
                  NULL, NULL,
120
175
                  marshal_VOID__DOUBLE_DOUBLE,
121
176
                  G_TYPE_NONE, 2,
122
177
                  G_TYPE_DOUBLE,
123
178
                  G_TYPE_DOUBLE);
124
179
 
125
 
  object_class->finalize = gimp_print_preview_finalize;
 
180
  object_class->finalize             = print_preview_finalize;
 
181
 
 
182
  widget_class->realize              = print_preview_realize;
 
183
  widget_class->unrealize            = print_preview_unrealize;
 
184
  widget_class->size_request         = print_preview_size_request;
 
185
  widget_class->size_allocate        = print_preview_size_allocate;
 
186
  widget_class->expose_event         = print_preview_expose_event;
 
187
  widget_class->button_press_event   = print_preview_button_press_event;
 
188
  widget_class->button_release_event = print_preview_button_release_event;
 
189
  widget_class->motion_notify_event  = print_preview_motion_notify_event;
 
190
  widget_class->leave_notify_event   = print_preview_leave_notify_event;
126
191
 
127
192
  klass->offsets_changed = NULL;
128
193
}
129
194
 
130
195
static void
131
 
gimp_print_preview_init (GimpPrintPreview *preview)
 
196
print_preview_init (PrintPreview *preview)
132
197
{
133
 
  preview->page               = NULL;
134
 
  preview->pixbuf             = NULL;
135
 
  preview->dragging           = FALSE;
136
 
  preview->image_offset_x     = 0.0;
137
 
  preview->image_offset_y     = 0.0;
138
 
  preview->image_offset_x_max = 0.0;
139
 
  preview->image_offset_y_max = 0.0;
140
 
  preview->image_xres         = 1.0;
141
 
  preview->image_yres         = 1.0;
142
 
  preview->use_full_page      = FALSE;
143
 
 
144
 
  preview->area = gtk_drawing_area_new();
145
 
  gtk_container_add (GTK_CONTAINER (preview), preview->area);
146
 
  gtk_widget_show (preview->area);
147
 
 
148
 
  gtk_widget_add_events (GTK_WIDGET (preview->area), GDK_BUTTON_PRESS_MASK);
149
 
 
150
 
  g_signal_connect (preview->area, "size-allocate",
151
 
                    G_CALLBACK (gimp_print_preview_size_allocate),
152
 
                    preview);
153
 
  g_signal_connect (preview->area, "realize",
154
 
                    G_CALLBACK (gimp_print_preview_realize),
155
 
                    NULL);
156
 
  g_signal_connect (preview->area, "event",
157
 
                    G_CALLBACK (gimp_print_preview_event),
158
 
                    preview);
159
 
  g_signal_connect (preview->area, "expose-event",
160
 
                    G_CALLBACK (gimp_print_preview_expose_event),
161
 
                    preview);
 
198
  gtk_event_box_set_visible_window (GTK_EVENT_BOX (preview), FALSE);
 
199
 
 
200
  gtk_widget_add_events (GTK_WIDGET (preview),
 
201
                         GDK_BUTTON_PRESS_MASK   |
 
202
                         GDK_BUTTON_RELEASE_MASK |
 
203
                         GDK_POINTER_MOTION_MASK);
162
204
}
163
205
 
164
206
 
165
207
static void
166
 
gimp_print_preview_finalize (GObject *object)
 
208
print_preview_finalize (GObject *object)
167
209
{
168
 
  GimpPrintPreview *preview = GIMP_PRINT_PREVIEW (object);
 
210
  PrintPreview *preview = PRINT_PREVIEW (object);
169
211
 
170
212
  if (preview->drawable)
171
213
    {
173
215
      preview->drawable = NULL;
174
216
    }
175
217
 
176
 
  if (preview->pixbuf)
 
218
  if (preview->thumbnail)
177
219
    {
178
 
      g_object_unref (preview->pixbuf);
179
 
      preview->pixbuf = NULL;
 
220
      cairo_surface_destroy (preview->thumbnail);
 
221
      preview->thumbnail = NULL;
180
222
    }
181
223
 
182
224
  if (preview->page)
185
227
      preview->page = NULL;
186
228
    }
187
229
 
188
 
  G_OBJECT_CLASS (gimp_print_preview_parent_class)->finalize (object);
 
230
  G_OBJECT_CLASS (print_preview_parent_class)->finalize (object);
 
231
}
 
232
 
 
233
static void
 
234
print_preview_realize (GtkWidget *widget)
 
235
{
 
236
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
237
 
 
238
  GTK_WIDGET_CLASS (print_preview_parent_class)->realize (widget);
 
239
 
 
240
  preview->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
 
241
                                                GDK_HAND1);
 
242
}
 
243
 
 
244
static void
 
245
print_preview_unrealize (GtkWidget *widget)
 
246
{
 
247
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
248
 
 
249
  if (preview->cursor)
 
250
    gdk_cursor_unref (preview->cursor);
 
251
 
 
252
  GTK_WIDGET_CLASS (print_preview_parent_class)->unrealize (widget);
 
253
}
 
254
 
 
255
static void
 
256
print_preview_size_request (GtkWidget      *widget,
 
257
                            GtkRequisition *requisition)
 
258
{
 
259
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
260
  gdouble       paper_width;
 
261
  gdouble       paper_height;
 
262
  gint          border  = GTK_CONTAINER (widget)->border_width + 1;
 
263
 
 
264
  print_preview_get_page_size (preview, &paper_width, &paper_height);
 
265
 
 
266
  if (paper_width > paper_height)
 
267
    {
 
268
      requisition->height = SIZE_REQUEST;
 
269
      requisition->width  = paper_width * SIZE_REQUEST / paper_height;
 
270
      requisition->width  = MIN (requisition->width, 2 * SIZE_REQUEST);
 
271
    }
 
272
  else
 
273
    {
 
274
      requisition->width  = SIZE_REQUEST;
 
275
      requisition->height = paper_height * SIZE_REQUEST / paper_width;
 
276
      requisition->height = MIN (requisition->height, 2 * SIZE_REQUEST);
 
277
    }
 
278
 
 
279
  requisition->width  += 2 * border;
 
280
  requisition->height += 2 * border;
 
281
}
 
282
 
 
283
static void
 
284
print_preview_size_allocate (GtkWidget     *widget,
 
285
                             GtkAllocation *allocation)
 
286
{
 
287
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
288
 
 
289
  GTK_WIDGET_CLASS (print_preview_parent_class)->size_allocate (widget,
 
290
                                                                allocation);
 
291
 
 
292
  if (preview->thumbnail)
 
293
    {
 
294
      cairo_surface_destroy (preview->thumbnail);
 
295
      preview->thumbnail = NULL;
 
296
    }
 
297
}
 
298
 
 
299
static gboolean
 
300
print_preview_button_press_event (GtkWidget      *widget,
 
301
                                  GdkEventButton *event)
 
302
{
 
303
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
304
 
 
305
  if (event->type == GDK_BUTTON_PRESS && event->button == 1 && preview->inside)
 
306
    {
 
307
      GdkCursor *cursor;
 
308
 
 
309
      cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
 
310
                                           GDK_FLEUR);
 
311
 
 
312
      if (gdk_pointer_grab (event->window, FALSE,
 
313
                            (GDK_BUTTON1_MOTION_MASK |
 
314
                             GDK_BUTTON_RELEASE_MASK),
 
315
                            NULL, cursor, event->time) == GDK_GRAB_SUCCESS)
 
316
        {
 
317
          preview->orig_offset_x = preview->image_offset_x;
 
318
          preview->orig_offset_y = preview->image_offset_y;
 
319
 
 
320
          preview->start_x = event->x;
 
321
          preview->start_y = event->y;
 
322
 
 
323
          preview->dragging = TRUE;
 
324
        }
 
325
 
 
326
      gdk_cursor_unref (cursor);
 
327
    }
 
328
 
 
329
  return FALSE;
 
330
}
 
331
 
 
332
static gboolean
 
333
print_preview_button_release_event (GtkWidget      *widget,
 
334
                                    GdkEventButton *event)
 
335
{
 
336
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
337
 
 
338
  if (preview->dragging)
 
339
    {
 
340
      gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
 
341
                                  event->time);
 
342
      preview->dragging = FALSE;
 
343
 
 
344
      print_preview_set_inside (preview,
 
345
                                print_preview_is_inside (preview,
 
346
                                                         event->x, event->y));
 
347
    }
 
348
 
 
349
  return FALSE;
 
350
}
 
351
 
 
352
static gboolean
 
353
print_preview_motion_notify_event (GtkWidget      *widget,
 
354
                                   GdkEventMotion *event)
 
355
{
 
356
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
357
 
 
358
  if (preview->dragging)
 
359
    {
 
360
      gdouble scale = print_preview_get_scale (preview);
 
361
      gdouble offset_x;
 
362
      gdouble offset_y;
 
363
 
 
364
      offset_x = (preview->orig_offset_x +
 
365
                  (event->x - preview->start_x) / scale);
 
366
      offset_y = (preview->orig_offset_y +
 
367
                  (event->y - preview->start_y) / scale);
 
368
 
 
369
      offset_x = CLAMP (offset_x, 0, preview->image_offset_x_max);
 
370
      offset_y = CLAMP (offset_y, 0, preview->image_offset_y_max);
 
371
 
 
372
      if (preview->image_offset_x != offset_x ||
 
373
          preview->image_offset_y != offset_y)
 
374
        {
 
375
          print_preview_set_image_offsets (preview,
 
376
                                           offset_x, offset_y);
 
377
 
 
378
          g_signal_emit (preview,
 
379
                         print_preview_signals[OFFSETS_CHANGED], 0,
 
380
                         preview->image_offset_x,
 
381
                         preview->image_offset_y);
 
382
        }
 
383
    }
 
384
  else
 
385
    {
 
386
      print_preview_set_inside (preview,
 
387
                                print_preview_is_inside (preview,
 
388
                                                         event->x, event->y));
 
389
    }
 
390
 
 
391
  return FALSE;
 
392
}
 
393
 
 
394
static gboolean
 
395
print_preview_leave_notify_event (GtkWidget        *widget,
 
396
                                  GdkEventCrossing *event)
 
397
{
 
398
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
399
 
 
400
  print_preview_set_inside (preview, FALSE);
 
401
 
 
402
  return FALSE;
 
403
}
 
404
 
 
405
static gboolean
 
406
print_preview_expose_event (GtkWidget      *widget,
 
407
                            GdkEventExpose *event)
 
408
{
 
409
  PrintPreview *preview = PRINT_PREVIEW (widget);
 
410
  GtkStyle     *style   = gtk_widget_get_style (widget);
 
411
  cairo_t      *cr;
 
412
  gdouble       paper_width;
 
413
  gdouble       paper_height;
 
414
  gdouble       left_margin;
 
415
  gdouble       right_margin;
 
416
  gdouble       top_margin;
 
417
  gdouble       bottom_margin;
 
418
  gdouble       scale;
 
419
  gint          border = GTK_CONTAINER (widget)->border_width + 1;
 
420
 
 
421
  print_preview_get_page_size (preview, &paper_width, &paper_height);
 
422
  print_preview_get_page_margins (preview,
 
423
                                  &left_margin, &right_margin,
 
424
                                  &top_margin,  &bottom_margin);
 
425
 
 
426
  scale = print_preview_get_scale (preview);
 
427
 
 
428
  cr = gdk_cairo_create (widget->window);
 
429
 
 
430
  cairo_translate (cr,
 
431
                   widget->allocation.x + border,
 
432
                   widget->allocation.y + border);
 
433
 
 
434
  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
 
435
    {
 
436
      gint width = widget->allocation.width - 2 * border;
 
437
 
 
438
      cairo_translate (cr, width - scale * paper_width, 0);
 
439
    }
 
440
 
 
441
  cairo_set_line_width (cr, 1.0);
 
442
 
 
443
  /* draw page background */
 
444
  cairo_rectangle (cr, 0, 0, scale * paper_width, scale * paper_height);
 
445
 
 
446
  gdk_cairo_set_source_color (cr, &style->black);
 
447
  cairo_stroke_preserve (cr);
 
448
 
 
449
  gdk_cairo_set_source_color (cr, &style->white);
 
450
  cairo_fill (cr);
 
451
 
 
452
  /* draw page_margins */
 
453
  cairo_rectangle (cr,
 
454
                   scale * left_margin,
 
455
                   scale * top_margin,
 
456
                   scale * (paper_width - left_margin - right_margin),
 
457
                   scale * (paper_height - top_margin - bottom_margin));
 
458
 
 
459
  gdk_cairo_set_source_color (cr, &style->mid[widget->state]);
 
460
  cairo_stroke (cr);
 
461
 
 
462
  cairo_translate (cr,
 
463
                   scale * (left_margin + preview->image_offset_x),
 
464
                   scale * (top_margin  + preview->image_offset_y));
 
465
 
 
466
  if (preview->dragging || preview->inside)
 
467
    {
 
468
      cairo_rectangle (cr,
 
469
                       0, 0,
 
470
                       scale * preview->image_width,
 
471
                       scale * preview->image_height);
 
472
 
 
473
      gdk_cairo_set_source_color (cr, &style->black);
 
474
      cairo_stroke (cr);
 
475
    }
 
476
 
 
477
  if (preview->thumbnail == NULL &&
 
478
      gimp_drawable_is_valid (preview->drawable->drawable_id))
 
479
    {
 
480
      preview->thumbnail =
 
481
        print_preview_get_thumbnail (preview->drawable,
 
482
                                     MIN (widget->allocation.width,  1024),
 
483
                                     MIN (widget->allocation.height, 1024));
 
484
    }
 
485
 
 
486
  if (preview->thumbnail != NULL)
 
487
    {
 
488
      gdouble scale_x;
 
489
      gdouble scale_y;
 
490
 
 
491
      scale_x = (preview->image_width  /
 
492
                 cairo_image_surface_get_width (preview->thumbnail));
 
493
      scale_y = (preview->image_height /
 
494
                 cairo_image_surface_get_height (preview->thumbnail));
 
495
 
 
496
      cairo_rectangle (cr, 0, 0, preview->image_width, preview->image_height);
 
497
 
 
498
      cairo_scale (cr, scale_x * scale, scale_y * scale);
 
499
 
 
500
      cairo_set_source_surface (cr, preview->thumbnail, 0, 0);
 
501
      cairo_fill (cr);
 
502
    }
 
503
 
 
504
  cairo_destroy (cr);
 
505
 
 
506
  return FALSE;
189
507
}
190
508
 
191
509
/**
192
 
 * gimp_print_preview_new:
 
510
 * print_preview_new:
193
511
 * @page: page setup
194
512
 * @drawable_id: the drawable to print
195
513
 *
196
 
 * Creates a new #GimpPrintPreview widget.
 
514
 * Creates a new #PrintPreview widget.
197
515
 *
198
 
 * Return value: the new #GimpPrintPreview widget.
 
516
 * Return value: the new #PrintPreview widget.
199
517
 **/
200
518
GtkWidget *
201
 
gimp_print_preview_new (GtkPageSetup *page,
202
 
                        gint32        drawable_id)
 
519
print_preview_new (GtkPageSetup *page,
 
520
                   gint32        drawable_id)
203
521
{
204
 
  GimpPrintPreview *preview;
205
 
  gfloat            ratio;
206
 
 
207
 
  preview = g_object_new (GIMP_TYPE_PRINT_PREVIEW, NULL);
 
522
  PrintPreview *preview;
 
523
 
 
524
  g_return_val_if_fail (GTK_IS_PAGE_SETUP (page), NULL);
 
525
 
 
526
  preview = g_object_new (PRINT_TYPE_PREVIEW, NULL);
208
527
 
209
528
  preview->drawable = gimp_drawable_get (drawable_id);
210
529
 
211
 
  if (page != NULL)
212
 
    preview->page = gtk_page_setup_copy (page);
213
 
  else
214
 
    preview->page = gtk_page_setup_new ();
215
 
 
216
 
  ratio = (gtk_page_setup_get_paper_width (preview->page, GTK_UNIT_POINTS) /
217
 
           gtk_page_setup_get_paper_height (preview->page, GTK_UNIT_POINTS));
218
 
 
219
 
  gtk_aspect_frame_set (GTK_ASPECT_FRAME (preview), 0.5, 0.5, ratio, FALSE);
220
 
 
221
 
  gtk_widget_set_size_request (preview->area,
222
 
                               DRAWING_AREA_SIZE, DRAWING_AREA_SIZE);
 
530
  print_preview_set_page_setup (preview, page);
223
531
 
224
532
  return GTK_WIDGET (preview);
225
533
}
226
534
 
227
535
/**
228
 
 * gimp_print_preview_set_image_dpi:
229
 
 * @preview: a #GimpPrintPreview.
 
536
 * print_preview_set_image_dpi:
 
537
 * @preview: a #PrintPreview.
230
538
 * @xres: the X resolution
231
539
 * @yres: the Y resolution
232
540
 *
233
541
 * Sets the resolution of the image/drawable displayed by the
234
 
 * #GimpPrintPreview.
 
542
 * #PrintPreview.
235
543
 **/
236
544
void
237
 
gimp_print_preview_set_image_dpi (GimpPrintPreview *preview,
238
 
                                  gdouble           xres,
239
 
                                  gdouble           yres)
 
545
print_preview_set_image_dpi (PrintPreview *preview,
 
546
                             gdouble       xres,
 
547
                             gdouble       yres)
240
548
{
241
 
  g_return_if_fail (GIMP_IS_PRINT_PREVIEW (preview));
242
 
 
243
 
  if (preview->image_xres != xres || preview->image_yres != yres)
 
549
  gdouble width;
 
550
  gdouble height;
 
551
 
 
552
  g_return_if_fail (PRINT_IS_PREVIEW (preview));
 
553
  g_return_if_fail (xres > 0.0 && yres > 0.0);
 
554
 
 
555
  width  = preview->drawable->width  * 72.0 / xres;
 
556
  height = preview->drawable->height * 72.0 / yres;
 
557
 
 
558
  if (width != preview->image_width || height != preview->image_height)
244
559
    {
245
 
      preview->image_xres = xres;
246
 
      preview->image_yres = yres;
 
560
      preview->image_width  = width;
 
561
      preview->image_height = height;
247
562
 
248
 
      print_preview_queue_draw (preview);
 
563
      gtk_widget_queue_draw (GTK_WIDGET (preview));
249
564
    }
250
565
}
251
566
 
252
567
/**
253
 
 * gimp_print_preview_set_page_setup:
254
 
 * @preview: a #GimpPrintPreview.
 
568
 * print_preview_set_page_setup:
 
569
 * @preview: a #PrintPreview.
255
570
 * @page: the page setup to use
256
571
 *
257
 
 * Sets the page setup to use by the #GimpPrintPreview.
 
572
 * Sets the page setup to use by the #PrintPreview.
258
573
 **/
259
574
void
260
 
gimp_print_preview_set_page_setup (GimpPrintPreview *preview,
261
 
                                   GtkPageSetup     *page)
 
575
print_preview_set_page_setup (PrintPreview *preview,
 
576
                              GtkPageSetup *page)
262
577
{
263
 
  gfloat ratio;
 
578
  g_return_if_fail (PRINT_IS_PREVIEW (preview));
 
579
  g_return_if_fail (GTK_IS_PAGE_SETUP (page));
264
580
 
265
581
  if (preview->page)
266
582
    g_object_unref (preview->page);
267
583
 
268
584
  preview->page = gtk_page_setup_copy (page);
269
585
 
270
 
  ratio = (gtk_page_setup_get_paper_width (page, GTK_UNIT_POINTS) /
271
 
           gtk_page_setup_get_paper_height (page, GTK_UNIT_POINTS));
272
 
 
273
 
  gtk_aspect_frame_set (GTK_ASPECT_FRAME (preview), 0.5, 0.5, ratio, FALSE);
274
 
 
275
 
  print_preview_queue_draw (preview);
 
586
  gtk_widget_queue_resize (GTK_WIDGET (preview));
276
587
}
277
588
 
278
589
/**
279
 
 * gimp_print_preview_set_image_offsets:
280
 
 * @preview: a #GimpPrintPreview.
 
590
 * print_preview_set_image_offsets:
 
591
 * @preview: a #PrintPreview.
281
592
 * @offset_x: the X offset
282
593
 * @offset_y: the Y offset
283
594
 *
284
 
 * Sets the offsets of the image/drawable displayed by the #GimpPrintPreview.
 
595
 * Sets the offsets of the image/drawable displayed by the #PrintPreview.
285
596
 * It does not emit the "offsets-changed" signal.
286
597
 **/
287
598
void
288
 
gimp_print_preview_set_image_offsets (GimpPrintPreview *preview,
289
 
                                      gdouble           offset_x,
290
 
                                      gdouble           offset_y)
 
599
print_preview_set_image_offsets (PrintPreview *preview,
 
600
                                 gdouble       offset_x,
 
601
                                 gdouble       offset_y)
291
602
{
292
 
  g_return_if_fail (GIMP_IS_PRINT_PREVIEW (preview));
 
603
  g_return_if_fail (PRINT_IS_PREVIEW (preview));
293
604
 
294
605
  preview->image_offset_x = offset_x;
295
606
  preview->image_offset_y = offset_y;
296
607
 
297
 
  print_preview_queue_draw (preview);
 
608
  gtk_widget_queue_draw (GTK_WIDGET (preview));
298
609
}
299
610
 
300
611
/**
301
 
 * gimp_print_preview_set_image_offsets_max:
302
 
 * @preview: a #GimpPrintPreview.
 
612
 * print_preview_set_image_offsets_max:
 
613
 * @preview: a #PrintPreview.
303
614
 * @offset_x_max: the maximum X offset allowed
304
615
 * @offset_y_max: the maximum Y offset allowed
305
616
 *
306
617
 * Sets the maximum offsets of the image/drawable displayed by the
307
 
 * #GimpPrintPreview.  It does not emit the "offsets-changed" signal.
 
618
 * #PrintPreview.  It does not emit the "offsets-changed" signal.
308
619
 **/
309
620
void
310
 
gimp_print_preview_set_image_offsets_max (GimpPrintPreview *preview,
311
 
                                          gdouble           offset_x_max,
312
 
                                          gdouble           offset_y_max)
 
621
print_preview_set_image_offsets_max (PrintPreview *preview,
 
622
                                     gdouble       offset_x_max,
 
623
                                     gdouble       offset_y_max)
313
624
{
314
 
  g_return_if_fail (GIMP_IS_PRINT_PREVIEW (preview));
 
625
  g_return_if_fail (PRINT_IS_PREVIEW (preview));
315
626
 
316
627
  preview->image_offset_x_max = offset_x_max;
317
628
  preview->image_offset_y_max = offset_y_max;
318
629
 
319
 
  print_preview_queue_draw (preview);
 
630
  gtk_widget_queue_draw (GTK_WIDGET (preview));
320
631
}
321
632
 
322
633
/**
323
 
 * gimp_print_preview_set_use_full_page:
324
 
 * @preview: a #GimpPrintPreview.
 
634
 * print_preview_set_use_full_page:
 
635
 * @preview: a #PrintPreview.
325
636
 * @full_page: TRUE to ignore the page margins
326
637
 *
327
638
 * If @full_page is TRUE, the page margins are ignored and the full page
328
639
 * can be used to setup printing.
329
640
 **/
330
641
void
331
 
gimp_print_preview_set_use_full_page (GimpPrintPreview *preview,
332
 
                                      gboolean          full_page)
 
642
print_preview_set_use_full_page (PrintPreview *preview,
 
643
                                 gboolean      full_page)
333
644
{
334
 
  g_return_if_fail (GIMP_IS_PRINT_PREVIEW (preview));
 
645
  g_return_if_fail (PRINT_IS_PREVIEW (preview));
335
646
 
336
647
  preview->use_full_page = full_page;
337
648
 
338
 
  print_preview_queue_draw (preview);
 
649
  gtk_widget_queue_draw (GTK_WIDGET (preview));
 
650
}
 
651
 
 
652
static gboolean
 
653
print_preview_is_inside (PrintPreview *preview,
 
654
                         gdouble       x,
 
655
                         gdouble       y)
 
656
{
 
657
  GtkWidget *widget = GTK_WIDGET (preview);
 
658
  gdouble    left_margin;
 
659
  gdouble    right_margin;
 
660
  gdouble    top_margin;
 
661
  gdouble    bottom_margin;
 
662
  gdouble    scale;
 
663
  gint       border = GTK_CONTAINER (widget)->border_width + 1;
 
664
 
 
665
  x -= border;
 
666
 
 
667
  scale = print_preview_get_scale (preview);
 
668
 
 
669
  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
 
670
    {
 
671
      gdouble paper_width;
 
672
      gdouble paper_height;
 
673
      gint    width = widget->allocation.width - 2 * border;
 
674
 
 
675
      print_preview_get_page_size (preview, &paper_width, &paper_height);
 
676
 
 
677
      x -= width - scale * paper_width;
 
678
    }
 
679
 
 
680
  print_preview_get_page_margins (preview,
 
681
                                  &left_margin, &right_margin,
 
682
                                  &top_margin,  &bottom_margin);
 
683
 
 
684
  x = x / scale - left_margin;
 
685
  y = y / scale - top_margin;
 
686
 
 
687
  return (x > preview->image_offset_x                        &&
 
688
          x < preview->image_offset_x + preview->image_width &&
 
689
          y > preview->image_offset_y                        &&
 
690
          y < preview->image_offset_y + preview->image_height);
339
691
}
340
692
 
341
693
static void
342
 
gimp_print_preview_realize (GtkWidget *widget)
343
 
{
344
 
  GdkCursor *cursor;
345
 
 
346
 
  cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
347
 
                                       GDK_FLEUR);
348
 
  gdk_window_set_cursor (widget->window, cursor);
349
 
  gdk_cursor_unref (cursor);
350
 
}
351
 
 
352
 
static gboolean
353
 
gimp_print_preview_event (GtkWidget        *widget,
354
 
                          GdkEvent         *event,
355
 
                          GimpPrintPreview *preview)
356
 
{
357
 
  static gdouble orig_offset_x = 0.0;
358
 
  static gdouble orig_offset_y = 0.0;
359
 
  static gint    start_x       = 0;
360
 
  static gint    start_y       = 0;
361
 
 
362
 
  gdouble        offset_x;
363
 
  gdouble        offset_y;
364
 
  gdouble        scale;
365
 
 
366
 
  switch (event->type)
367
 
    {
368
 
    case GDK_BUTTON_PRESS:
369
 
      gdk_pointer_grab (widget->window, FALSE,
370
 
                        (GDK_BUTTON1_MOTION_MASK |
371
 
                         GDK_BUTTON_RELEASE_MASK),
372
 
                        NULL, NULL, event->button.time);
373
 
 
374
 
      orig_offset_x = preview->image_offset_x;
375
 
      orig_offset_y = preview->image_offset_y;
376
 
 
377
 
      start_x = event->button.x;
378
 
      start_y = event->button.y;
379
 
 
380
 
      preview->dragging = TRUE;
381
 
      break;
382
 
 
383
 
    case GDK_MOTION_NOTIFY:
384
 
      scale = gimp_print_preview_get_scale (preview);
385
 
 
386
 
      offset_x = (orig_offset_x + (event->motion.x - start_x) / scale);
387
 
      offset_y = (orig_offset_y + (event->motion.y - start_y) / scale);
388
 
 
389
 
      offset_x = CLAMP (offset_x, 0, preview->image_offset_x_max);
390
 
      offset_y = CLAMP (offset_y, 0, preview->image_offset_y_max);
391
 
 
392
 
      if (preview->image_offset_x != offset_x ||
393
 
          preview->image_offset_y != offset_y)
394
 
        {
395
 
          gimp_print_preview_set_image_offsets (preview, offset_x, offset_y);
396
 
 
397
 
          g_signal_emit (preview,
398
 
                         gimp_print_preview_signals[OFFSETS_CHANGED], 0,
399
 
                         preview->image_offset_x, preview->image_offset_y);
400
 
        }
401
 
      break;
402
 
 
403
 
    case GDK_BUTTON_RELEASE:
404
 
      gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
405
 
                                  event->button.time);
406
 
      start_x = start_y = 0;
407
 
      preview->dragging = FALSE;
408
 
 
409
 
      print_preview_queue_draw (preview);
410
 
      break;
411
 
 
412
 
    default:
413
 
      break;
414
 
    }
415
 
 
416
 
  return FALSE;
417
 
}
418
 
 
419
 
static gboolean
420
 
gimp_print_preview_expose_event (GtkWidget        *widget,
421
 
                                 GdkEventExpose   *eevent,
422
 
                                 GimpPrintPreview *preview)
423
 
{
424
 
  gdouble  paper_width;
425
 
  gdouble  paper_height;
426
 
  gdouble  left_margin;
427
 
  gdouble  right_margin;
428
 
  gdouble  top_margin;
429
 
  gdouble  bottom_margin;
430
 
  gdouble  scale;
431
 
  cairo_t *cr;
432
 
 
433
 
  paper_width = gtk_page_setup_get_paper_width (preview->page,
434
 
                                                GTK_UNIT_POINTS);
435
 
  paper_height = gtk_page_setup_get_paper_height (preview->page,
436
 
                                                  GTK_UNIT_POINTS);
437
 
  gimp_print_preview_get_page_margins (preview,
438
 
                                       &left_margin,
439
 
                                       &right_margin,
440
 
                                       &top_margin,
441
 
                                       &bottom_margin);
442
 
 
443
 
  cr = gdk_cairo_create (widget->window);
444
 
 
445
 
  scale = gimp_print_preview_get_scale (preview);
446
 
 
447
 
  /* draw background */
448
 
  cairo_scale (cr, scale, scale);
449
 
  gdk_cairo_set_source_color (cr, &widget->style->white);
450
 
  cairo_rectangle (cr, 0, 0, paper_width, paper_height);
451
 
  cairo_fill (cr);
452
 
 
453
 
  /* draw page_margins */
454
 
  gdk_cairo_set_source_color (cr, &widget->style->black);
455
 
  cairo_rectangle (cr,
456
 
                   left_margin,
457
 
                   top_margin,
458
 
                   paper_width - left_margin - right_margin,
459
 
                   paper_height - top_margin - bottom_margin);
460
 
  cairo_stroke (cr);
461
 
 
462
 
  if (preview->dragging)
463
 
    {
464
 
      gdouble width  = preview->drawable->width;
465
 
      gdouble height = preview->drawable->height;
466
 
 
467
 
      cairo_rectangle (cr,
468
 
                       left_margin + preview->image_offset_x,
469
 
                       top_margin  + preview->image_offset_y,
470
 
                       width  * 72.0 / preview->image_xres,
471
 
                       height * 72.0 / preview->image_yres);
472
 
      cairo_stroke (cr);
473
 
    }
474
 
  else
475
 
    {
476
 
      gint32 drawable_id = preview->drawable->drawable_id;
477
 
 
478
 
      /* draw image */
479
 
      cairo_translate (cr,
480
 
                       left_margin + preview->image_offset_x,
481
 
                       top_margin  + preview->image_offset_y);
482
 
 
483
 
      if (preview->pixbuf == NULL && gimp_drawable_is_valid (drawable_id))
484
 
        {
485
 
          gint width  = MIN (widget->allocation.width, 1024);
486
 
          gint height = MIN (widget->allocation.height, 1024);
487
 
 
488
 
          preview->pixbuf = gimp_drawable_get_thumbnail (drawable_id,
489
 
                                                         width, height,
490
 
                                                         GIMP_PIXBUF_KEEP_ALPHA);
491
 
        }
492
 
 
493
 
      if (preview->pixbuf != NULL)
494
 
        {
495
 
          gdouble scale_x = ((gdouble) preview->drawable->width /
496
 
                             gdk_pixbuf_get_width (preview->pixbuf));
497
 
          gdouble scale_y = ((gdouble) preview->drawable->height /
498
 
                             gdk_pixbuf_get_height (preview->pixbuf));
499
 
 
500
 
          if (scale_x < scale_y)
501
 
            scale_x = scale_y;
502
 
          else
503
 
            scale_y = scale_x;
504
 
 
505
 
          scale_x = scale_x * 72.0 / preview->image_xres;
506
 
          scale_y = scale_y * 72.0 / preview->image_yres;
507
 
 
508
 
          cairo_scale (cr, scale_x, scale_y);
509
 
 
510
 
          gdk_cairo_set_source_pixbuf (cr, preview->pixbuf, 0, 0);
511
 
 
512
 
          cairo_paint (cr);
513
 
        }
514
 
    }
515
 
 
516
 
  cairo_destroy (cr);
517
 
 
518
 
  return FALSE;
 
694
print_preview_set_inside (PrintPreview *preview,
 
695
                          gboolean      inside)
 
696
{
 
697
  if (inside != preview->inside)
 
698
    {
 
699
      GtkWidget *widget = GTK_WIDGET (preview);
 
700
 
 
701
      preview->inside = inside;
 
702
 
 
703
      if (GTK_WIDGET_DRAWABLE (widget))
 
704
        gdk_window_set_cursor (widget->window,
 
705
                               inside ? preview->cursor : NULL);
 
706
 
 
707
      gtk_widget_queue_draw (widget);
 
708
    }
519
709
}
520
710
 
521
711
static gdouble
522
 
gimp_print_preview_get_scale (GimpPrintPreview* preview)
 
712
print_preview_get_scale (PrintPreview *preview)
523
713
{
524
 
  gdouble scale_x;
525
 
  gdouble scale_y;
526
 
 
527
 
  scale_x = ((gdouble) preview->area->allocation.width /
528
 
             gtk_page_setup_get_paper_width (preview->page, GTK_UNIT_POINTS));
529
 
 
530
 
  scale_y = ((gdouble) preview->area->allocation.height /
531
 
             gtk_page_setup_get_paper_height (preview->page, GTK_UNIT_POINTS));
 
714
  GtkWidget *widget = GTK_WIDGET (preview);
 
715
  gdouble    paper_width;
 
716
  gdouble    paper_height;
 
717
  gdouble    scale_x;
 
718
  gdouble    scale_y;
 
719
  gint       border = GTK_CONTAINER (widget)->border_width + 1;
 
720
 
 
721
  print_preview_get_page_size (preview, &paper_width, &paper_height);
 
722
 
 
723
  scale_x = (gdouble) (widget->allocation.width  - 2 * border) / paper_width;
 
724
  scale_y = (gdouble) (widget->allocation.height - 2 * border) / paper_height;
532
725
 
533
726
  return MIN (scale_x, scale_y);
534
727
}
535
728
 
536
729
static void
537
 
gimp_print_preview_size_allocate (GtkWidget        *widget,
538
 
                                  GtkAllocation    *allocation,
539
 
                                  GimpPrintPreview *preview)
 
730
print_preview_get_page_size (PrintPreview *preview,
 
731
                             gdouble      *paper_width,
 
732
                             gdouble      *paper_height)
540
733
{
541
 
  if (preview->pixbuf != NULL)
542
 
    {
543
 
      g_object_unref (preview->pixbuf);
544
 
      preview->pixbuf = NULL;
545
 
    }
 
734
  *paper_width  = gtk_page_setup_get_paper_width  (preview->page,
 
735
                                                   GTK_UNIT_POINTS);
 
736
  *paper_height = gtk_page_setup_get_paper_height (preview->page,
 
737
                                                   GTK_UNIT_POINTS);
546
738
}
547
739
 
548
740
static void
549
 
gimp_print_preview_get_page_margins (GimpPrintPreview *preview,
550
 
                                     gdouble          *left_margin,
551
 
                                     gdouble          *right_margin,
552
 
                                     gdouble          *top_margin,
553
 
                                     gdouble          *bottom_margin)
 
741
print_preview_get_page_margins (PrintPreview *preview,
 
742
                                gdouble      *left_margin,
 
743
                                gdouble      *right_margin,
 
744
                                gdouble      *top_margin,
 
745
                                gdouble      *bottom_margin)
554
746
{
555
747
  if (preview->use_full_page)
556
748
    {
561
753
    }
562
754
  else
563
755
    {
564
 
      *left_margin   = gtk_page_setup_get_left_margin (preview->page,
565
 
                                                       GTK_UNIT_POINTS);
566
 
      *right_margin  = gtk_page_setup_get_right_margin (preview->page,
567
 
                                                        GTK_UNIT_POINTS);
568
 
      *top_margin    = gtk_page_setup_get_top_margin (preview->page,
569
 
                                                      GTK_UNIT_POINTS);
 
756
      *left_margin   = gtk_page_setup_get_left_margin   (preview->page,
 
757
                                                         GTK_UNIT_POINTS);
 
758
      *right_margin  = gtk_page_setup_get_right_margin  (preview->page,
 
759
                                                         GTK_UNIT_POINTS);
 
760
      *top_margin    = gtk_page_setup_get_top_margin    (preview->page,
 
761
                                                         GTK_UNIT_POINTS);
570
762
      *bottom_margin = gtk_page_setup_get_bottom_margin (preview->page,
571
763
                                                         GTK_UNIT_POINTS);
572
764
    }
573
765
}
574
766
 
575
 
static void
576
 
print_preview_queue_draw (GimpPrintPreview *preview)
 
767
 
 
768
/*  This thumbnail code should eventually end up in libgimpui.  */
 
769
 
 
770
static cairo_surface_t *
 
771
print_preview_get_thumbnail (GimpDrawable *drawable,
 
772
                             gint          width,
 
773
                             gint          height)
577
774
{
578
 
  gtk_widget_queue_draw (GTK_WIDGET (preview->area));
 
775
  cairo_surface_t *surface;
 
776
  cairo_format_t   format;
 
777
  guchar          *data;
 
778
  guchar          *dest;
 
779
  const guchar    *src;
 
780
  gint             src_stride;
 
781
  gint             dest_stride;
 
782
  gint             y;
 
783
  gint             bpp;
 
784
 
 
785
  g_return_val_if_fail (width  > 0 && width  <= 1024, NULL);
 
786
  g_return_val_if_fail (height > 0 && height <= 1024, NULL);
 
787
 
 
788
  data = gimp_drawable_get_thumbnail_data (drawable->drawable_id,
 
789
                                           &width, &height, &bpp);
 
790
 
 
791
  switch (bpp)
 
792
    {
 
793
    case 1:
 
794
    case 3:
 
795
      format = CAIRO_FORMAT_RGB24;
 
796
      break;
 
797
    case 2:
 
798
    case 4:
 
799
      format = CAIRO_FORMAT_ARGB32;
 
800
      break;
 
801
    default:
 
802
      g_assert_not_reached ();
 
803
      break;
 
804
    }
 
805
 
 
806
  surface = cairo_image_surface_create (format, width, height);
 
807
 
 
808
  src         = data;
 
809
  src_stride  = width * bpp;
 
810
 
 
811
  dest        = cairo_image_surface_get_data (surface);
 
812
  dest_stride = cairo_image_surface_get_stride (surface);
 
813
 
 
814
  for (y = 0; y < height; y++)
 
815
    {
 
816
      const guchar *s = src;
 
817
      guchar       *d = dest;
 
818
      gint          w = width;
 
819
 
 
820
      switch (bpp)
 
821
        {
 
822
        case 1:
 
823
          while (w--)
 
824
            {
 
825
              GIMP_CAIRO_RGB24_SET_PIXEL (d, s[0], s[0], s[0]);
 
826
              s += 1;
 
827
              d += 4;
 
828
            }
 
829
          break;
 
830
 
 
831
        case 2:
 
832
          while (w--)
 
833
            {
 
834
              GIMP_CAIRO_ARGB32_SET_PIXEL (d, s[0], s[0], s[0], s[1]);
 
835
              s += 2;
 
836
              d += 4;
 
837
            }
 
838
          break;
 
839
 
 
840
        case 3:
 
841
          while (w--)
 
842
            {
 
843
              GIMP_CAIRO_RGB24_SET_PIXEL (d, s[0], s[1], s[2]);
 
844
              s += 3;
 
845
              d += 4;
 
846
            }
 
847
          break;
 
848
 
 
849
        case 4:
 
850
          while (w--)
 
851
            {
 
852
              GIMP_CAIRO_ARGB32_SET_PIXEL (d, s[0], s[1], s[2], s[3]);
 
853
              s += 4;
 
854
              d += 4;
 
855
            }
 
856
          break;
 
857
        }
 
858
 
 
859
      src  += src_stride;
 
860
      dest += dest_stride;
 
861
    }
 
862
 
 
863
  g_free (data);
 
864
 
 
865
  return surface;
579
866
}