summaryrefslogtreecommitdiffstats
path: root/plug-ins/print/print-draw-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/print/print-draw-page.c')
-rw-r--r--plug-ins/print/print-draw-page.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/plug-ins/print/print-draw-page.c b/plug-ins/print/print-draw-page.c
new file mode 100644
index 0000000..588cbde
--- /dev/null
+++ b/plug-ins/print/print-draw-page.c
@@ -0,0 +1,222 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "print.h"
+#include "print-draw-page.h"
+
+#include "libgimp/stdplugins-intl.h"
+
+
+static cairo_surface_t * print_surface_from_drawable (gint32 drawable_ID,
+ GError **error);
+
+static void print_draw_crop_marks (GtkPrintContext *context,
+ gdouble x,
+ gdouble y,
+ gdouble w,
+ gdouble h);
+
+gboolean
+print_draw_page (GtkPrintContext *context,
+ PrintData *data,
+ GError **error)
+{
+ cairo_t *cr = gtk_print_context_get_cairo_context (context);
+ cairo_surface_t *surface;
+
+ surface = print_surface_from_drawable (data->drawable_id, error);
+
+ if (surface)
+ {
+ gint width;
+ gint height;
+ gdouble scale_x;
+ gdouble scale_y;
+
+ /* create a white rectangle covering the entire page, just
+ * to be safe; see bug #777233.
+ */
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+
+ scale_x = gtk_print_context_get_dpi_x (context) / data->xres;
+ scale_y = gtk_print_context_get_dpi_y (context) / data->yres;
+
+ cairo_translate (cr,
+ data->offset_x / 72.0 * gtk_print_context_get_dpi_x (context),
+ data->offset_y / 72.0 * gtk_print_context_get_dpi_y (context));
+
+ if (data->draw_crop_marks)
+ print_draw_crop_marks (context,
+ 0, 0, width * scale_x, height * scale_y);
+
+ cairo_scale (cr, scale_x, scale_y);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_fill (cr);
+
+ cairo_surface_destroy (surface);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static cairo_surface_t *
+print_surface_from_drawable (gint32 drawable_ID,
+ GError **error)
+{
+ GeglBuffer *buffer = gimp_drawable_get_buffer (drawable_ID);
+ const Babl *format;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ const gint width = gimp_drawable_width (drawable_ID);
+ const gint height = gimp_drawable_height (drawable_ID);
+ GeglBufferIterator *iter;
+ guchar *pixels;
+ gint stride;
+ guint count = 0;
+ guint64 done = 0;
+
+ if (gimp_drawable_has_alpha (drawable_ID))
+ format = babl_format ("cairo-ARGB32");
+ else
+ format = babl_format ("cairo-RGB24");
+
+ surface = cairo_image_surface_create (gimp_drawable_has_alpha (drawable_ID) ?
+ CAIRO_FORMAT_ARGB32 :
+ CAIRO_FORMAT_RGB24,
+ width, height);
+
+ status = cairo_surface_status (surface);
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ switch (status)
+ {
+ case CAIRO_STATUS_INVALID_SIZE:
+ g_set_error_literal (error,
+ GIMP_PLUGIN_PRINT_ERROR,
+ GIMP_PLUGIN_PRINT_ERROR_FAILED,
+ _("Cannot handle the size (either width or height) of the image."));
+ break;
+ default:
+ g_set_error (error,
+ GIMP_PLUGIN_PRINT_ERROR,
+ GIMP_PLUGIN_PRINT_ERROR_FAILED,
+ "Cairo error: %s",
+ cairo_status_to_string (status));
+ break;
+ }
+
+ return NULL;
+ }
+
+ pixels = cairo_image_surface_get_data (surface);
+ stride = cairo_image_surface_get_stride (surface);
+
+ iter = gegl_buffer_iterator_new (buffer,
+ GEGL_RECTANGLE (0, 0, width, height), 0,
+ format,
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ const guchar *src = iter->items[0].data;
+ guchar *dest = pixels + (guint64) iter->items[0].roi.y * stride + iter->items[0].roi.x * 4;
+ gint y;
+
+ for (y = 0; y < iter->items[0].roi.height; y++)
+ {
+ memcpy (dest, src, iter->items[0].roi.width * 4);
+
+ src += iter->items[0].roi.width * 4;
+ dest += stride;
+ }
+
+ done += (guint64) iter->items[0].roi.height * iter->items[0].roi.width;
+
+ if (count++ % 16 == 0)
+ gimp_progress_update ((gdouble) done / ((gdouble) width * height));
+ }
+
+ g_object_unref (buffer);
+
+ cairo_surface_mark_dirty (surface);
+
+ gimp_progress_update (1.0);
+
+ return surface;
+}
+
+static void
+print_draw_crop_marks (GtkPrintContext *context,
+ gdouble x,
+ gdouble y,
+ gdouble w,
+ gdouble h)
+{
+ cairo_t *cr = gtk_print_context_get_cairo_context (context);
+ gdouble len = MIN (gtk_print_context_get_width (context),
+ gtk_print_context_get_height (context)) / 20.0;
+
+ /* upper left */
+
+ cairo_move_to (cr, x - len, y);
+ cairo_line_to (cr, x - len / 5, y);
+
+ cairo_move_to (cr, x, y - len);
+ cairo_line_to (cr, x, y - len / 5);
+
+ /* upper right */
+
+ cairo_move_to (cr, x + w + len / 5, y);
+ cairo_line_to (cr, x + w + len, y);
+
+ cairo_move_to (cr, x + w, y - len);
+ cairo_line_to (cr, x + w, y - len / 5);
+
+ /* lower left */
+
+ cairo_move_to (cr, x - len, y + h);
+ cairo_line_to (cr, x - len / 5, y + h);
+
+ cairo_move_to (cr, x, y + h + len);
+ cairo_line_to (cr, x, y + h + len / 5);
+
+ /* lower right */
+
+ cairo_move_to (cr, x + w + len / 5, y + h);
+ cairo_line_to (cr, x + w + len, y + h);
+
+ cairo_move_to (cr, x + w, y + h + len);
+ cairo_line_to (cr, x + w, y + h + len / 5);
+
+ cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+}