Initial checkin of Pika from heckimp
This commit is contained in:
37
plug-ins/print/meson.build
Normal file
37
plug-ins/print/meson.build
Normal file
@ -0,0 +1,37 @@
|
||||
if have_print
|
||||
|
||||
|
||||
plugin_name = 'print'
|
||||
|
||||
plugin_sources = [
|
||||
'print-draw-page.c',
|
||||
'print-page-layout.c',
|
||||
'print-page-setup.c',
|
||||
'print-preview.c',
|
||||
'print-settings.c',
|
||||
'print-utils.c',
|
||||
'print.c',
|
||||
]
|
||||
|
||||
if platform_windows
|
||||
plugin_sources += windows.compile_resources(
|
||||
pika_plugins_rc,
|
||||
args: [
|
||||
'--define', 'ORIGINALFILENAME_STR="@0@"'.format(plugin_name+'.exe'),
|
||||
'--define', 'INTERNALNAME_STR="@0@"' .format(plugin_name),
|
||||
'--define', 'TOP_SRCDIR="@0@"' .format(meson.project_source_root()),
|
||||
],
|
||||
include_directories: [
|
||||
rootInclude, appInclude,
|
||||
],
|
||||
)
|
||||
endif
|
||||
|
||||
executable(plugin_name,
|
||||
plugin_sources,
|
||||
dependencies: libpikaui_dep,
|
||||
install: true,
|
||||
install_dir: pikaplugindir / 'plug-ins' / plugin_name,
|
||||
)
|
||||
|
||||
endif
|
226
plug-ins/print/print-draw-page.c
Normal file
226
plug-ins/print/print-draw-page.c
Normal file
@ -0,0 +1,226 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print.h"
|
||||
#include "print-draw-page.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
|
||||
static cairo_surface_t * print_surface_from_drawable (PikaDrawable *drawable,
|
||||
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, 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 (PikaDrawable *drawable,
|
||||
GError **error)
|
||||
{
|
||||
GeglBuffer *buffer = pika_drawable_get_buffer (drawable);
|
||||
const Babl *format;
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
const gint width = pika_drawable_get_width (drawable);
|
||||
const gint height = pika_drawable_get_height (drawable);
|
||||
GeglBufferIterator *iter;
|
||||
guchar *pixels;
|
||||
gint stride;
|
||||
guint count = 0;
|
||||
guint64 done = 0;
|
||||
|
||||
if (pika_drawable_has_alpha (drawable))
|
||||
format = babl_format ("cairo-ARGB32");
|
||||
else
|
||||
format = babl_format ("cairo-RGB24");
|
||||
|
||||
surface = cairo_image_surface_create (pika_drawable_has_alpha (drawable) ?
|
||||
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,
|
||||
PIKA_PLUGIN_PRINT_ERROR,
|
||||
PIKA_PLUGIN_PRINT_ERROR_FAILED,
|
||||
_("Cannot handle the size (either width or height) of the image."));
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
PIKA_PLUGIN_PRINT_ERROR,
|
||||
PIKA_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)
|
||||
pika_progress_update ((gdouble) done / ((gdouble) width * height));
|
||||
}
|
||||
|
||||
g_object_unref (buffer);
|
||||
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
pika_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);
|
||||
}
|
24
plug-ins/print/print-draw-page.h
Normal file
24
plug-ins/print/print-draw-page.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
gboolean print_draw_page (GtkPrintContext *context,
|
||||
PrintData *data,
|
||||
GError **error);
|
949
plug-ins/print/print-page-layout.c
Normal file
949
plug-ins/print/print-page-layout.c
Normal file
@ -0,0 +1,949 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print.h"
|
||||
#include "print-page-layout.h"
|
||||
#include "print-preview.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PrintData *data;
|
||||
gint image_width;
|
||||
gint image_height;
|
||||
PikaSizeEntry *size_entry;
|
||||
PikaSizeEntry *resolution_entry;
|
||||
PikaChainButton *chain;
|
||||
GtkWidget *center_combo;
|
||||
GtkWidget *area_label;
|
||||
GtkWidget *preview;
|
||||
GtkAdjustment *left_adj;
|
||||
GtkAdjustment *right_adj;
|
||||
GtkAdjustment *top_adj;
|
||||
GtkAdjustment *bottom_adj;
|
||||
} PrintSizeInfo;
|
||||
|
||||
enum
|
||||
{
|
||||
BOTTOM,
|
||||
TOP,
|
||||
RIGHT,
|
||||
LEFT,
|
||||
WIDTH,
|
||||
HEIGHT
|
||||
};
|
||||
|
||||
|
||||
static void print_page_setup_notify (GtkPrintOperation *operation);
|
||||
static void update_custom_widget (GtkPrintOperation *operation,
|
||||
GtkWidget *custom_widget,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintSettings *print_settings);
|
||||
|
||||
static GtkWidget * print_size_frame (PrintData *data,
|
||||
GtkSizeGroup *label_group,
|
||||
GtkSizeGroup *entry_group);
|
||||
static GtkWidget * print_offset_frame (PrintData *data,
|
||||
GtkSizeGroup *label_group,
|
||||
GtkSizeGroup *entry_group);
|
||||
|
||||
static void print_size_info_update_offsets (void);
|
||||
static void print_size_info_size_changed (GtkWidget *widget);
|
||||
static void print_size_info_offset_max_changed (GtkAdjustment *adj,
|
||||
gpointer data);
|
||||
static void print_size_info_resolution_changed (GtkWidget *widget);
|
||||
static void print_size_info_unit_changed (GtkWidget *widget);
|
||||
static void print_size_info_preview_offset_changed
|
||||
(GtkWidget *widget,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y);
|
||||
static void print_size_info_center_changed (GtkWidget *widget);
|
||||
static void print_size_info_center_none (void);
|
||||
static void print_size_info_use_full_page_toggled
|
||||
(GtkWidget *widget);
|
||||
|
||||
static void print_size_info_set_resolution (PrintSizeInfo *info,
|
||||
gdouble xres,
|
||||
gdouble yres);
|
||||
|
||||
|
||||
static void print_size_info_set_page_setup (PrintSizeInfo *info);
|
||||
|
||||
static void print_draw_crop_marks_toggled (GtkWidget *widget);
|
||||
|
||||
static void print_resolution_load_defaults (PrintSizeInfo *info);
|
||||
|
||||
static PrintSizeInfo info;
|
||||
|
||||
|
||||
GtkWidget *
|
||||
print_page_layout_gui (PrintData *data,
|
||||
const gchar *help)
|
||||
{
|
||||
GtkWidget *main_hbox;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *button;
|
||||
GtkWidget *frame;
|
||||
GtkPageSetup *setup;
|
||||
GtkSizeGroup *label_group;
|
||||
GtkSizeGroup *entry_group;
|
||||
|
||||
memset (&info, 0, sizeof (PrintSizeInfo));
|
||||
|
||||
info.data = data;
|
||||
info.image_width = pika_drawable_get_width (data->drawable);
|
||||
info.image_height = pika_drawable_get_height (data->drawable);
|
||||
|
||||
setup = gtk_print_operation_get_default_page_setup (data->operation);
|
||||
if (! setup)
|
||||
{
|
||||
setup = gtk_page_setup_new ();
|
||||
gtk_print_operation_set_default_page_setup (data->operation, setup);
|
||||
}
|
||||
|
||||
/* main hbox */
|
||||
main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
|
||||
|
||||
/* main vbox */
|
||||
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (main_vbox);
|
||||
|
||||
label_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
entry_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
|
||||
/* size entry area for the image's print size */
|
||||
|
||||
frame = print_size_frame (data, label_group, entry_group);
|
||||
gtk_widget_set_vexpand (frame, FALSE);
|
||||
gtk_widget_set_valign (frame, GTK_ALIGN_START);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* offset entry area for the image's offset position */
|
||||
|
||||
frame = print_offset_frame (data, label_group, entry_group);
|
||||
gtk_widget_set_vexpand (frame, FALSE);
|
||||
gtk_widget_set_valign (frame, GTK_ALIGN_START);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
g_object_unref (label_group);
|
||||
g_object_unref (entry_group);
|
||||
|
||||
button = gtk_check_button_new_with_mnemonic (_("Ignore Page _Margins"));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
||||
data->use_full_page);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
|
||||
g_signal_connect (button, "toggled",
|
||||
G_CALLBACK (print_size_info_use_full_page_toggled),
|
||||
NULL);
|
||||
gtk_widget_show (button);
|
||||
|
||||
/* crop marks toggle */
|
||||
button = gtk_check_button_new_with_mnemonic (_("_Draw Crop Marks"));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
||||
data->draw_crop_marks);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
|
||||
g_signal_connect (button, "toggled",
|
||||
G_CALLBACK (print_draw_crop_marks_toggled),
|
||||
NULL);
|
||||
gtk_widget_show (button);
|
||||
|
||||
/* preview */
|
||||
frame = pika_frame_new (_("Preview"));
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
info.preview = print_preview_new (setup, data->drawable);
|
||||
print_preview_set_use_full_page (PRINT_PREVIEW (info.preview),
|
||||
data->use_full_page);
|
||||
gtk_container_add (GTK_CONTAINER (frame), info.preview);
|
||||
gtk_widget_show (info.preview);
|
||||
|
||||
g_signal_connect (info.preview, "offsets-changed",
|
||||
G_CALLBACK (print_size_info_preview_offset_changed),
|
||||
NULL);
|
||||
|
||||
print_size_info_set_page_setup (&info);
|
||||
|
||||
g_signal_connect_object (data->operation, "notify::default-page-setup",
|
||||
G_CALLBACK (print_page_setup_notify),
|
||||
main_hbox, 0);
|
||||
g_signal_connect_object (data->operation, "update-custom-widget",
|
||||
G_CALLBACK (update_custom_widget),
|
||||
main_hbox, 0);
|
||||
|
||||
pika_help_connect (main_hbox, pika_standard_help_func, help, NULL, NULL);
|
||||
|
||||
return main_hbox;
|
||||
}
|
||||
|
||||
static void
|
||||
print_page_setup_notify (GtkPrintOperation *operation)
|
||||
{
|
||||
GtkPageSetup *setup;
|
||||
|
||||
setup = gtk_print_operation_get_default_page_setup (operation);
|
||||
|
||||
print_size_info_set_page_setup (&info);
|
||||
print_preview_set_page_setup (PRINT_PREVIEW (info.preview), setup);
|
||||
}
|
||||
|
||||
static void
|
||||
update_custom_widget (GtkPrintOperation *operation,
|
||||
GtkWidget *custom_widget,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintSettings *print_settings)
|
||||
{
|
||||
gtk_print_operation_set_default_page_setup (operation, page_setup);
|
||||
}
|
||||
|
||||
|
||||
#define SB_WIDTH 8
|
||||
|
||||
static GtkWidget *
|
||||
print_size_frame (PrintData *data,
|
||||
GtkSizeGroup *label_group,
|
||||
GtkSizeGroup *entry_group)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
GtkWidget *height;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *chain;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
GtkWidget *button;
|
||||
GtkAdjustment *adj;
|
||||
gdouble image_width;
|
||||
gdouble image_height;
|
||||
|
||||
image_width = (info.image_width *
|
||||
pika_unit_get_factor (data->unit) / data->xres);
|
||||
image_height = (info.image_height *
|
||||
pika_unit_get_factor (data->unit) / data->yres);
|
||||
|
||||
frame = pika_frame_new (_("Size"));
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
/* the print size entry */
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
entry = pika_size_entry_new (1, data->unit, "%p",
|
||||
FALSE, FALSE, FALSE, SB_WIDTH,
|
||||
PIKA_SIZE_ENTRY_UPDATE_SIZE);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||
gtk_widget_show (entry);
|
||||
|
||||
info.size_entry = PIKA_SIZE_ENTRY (entry);
|
||||
|
||||
gtk_grid_set_row_spacing (GTK_GRID (entry), 2);
|
||||
|
||||
adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
height = pika_spin_button_new (adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (height), NULL);
|
||||
gtk_grid_attach (GTK_GRID (entry), height, 1, 0, 1, 1);
|
||||
gtk_widget_show (height);
|
||||
|
||||
gtk_size_group_add_widget (entry_group, height);
|
||||
|
||||
pika_size_entry_attach_label (PIKA_SIZE_ENTRY (entry),
|
||||
_("_Width:"), 0, 0, 0.0);
|
||||
label = pika_size_entry_attach_label (PIKA_SIZE_ENTRY (entry),
|
||||
_("_Height:"), 1, 0, 0.0);
|
||||
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), 0,
|
||||
data->xres, FALSE);
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), 1,
|
||||
data->yres, FALSE);
|
||||
|
||||
pika_size_entry_set_value (PIKA_SIZE_ENTRY (entry), 0, image_width);
|
||||
pika_size_entry_set_value (PIKA_SIZE_ENTRY (entry), 1, image_height);
|
||||
|
||||
/* the resolution entry */
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
entry = pika_size_entry_new (1, data->image_unit,
|
||||
_("pixels/%a"),
|
||||
FALSE, FALSE, FALSE, SB_WIDTH,
|
||||
PIKA_SIZE_ENTRY_UPDATE_RESOLUTION);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||
gtk_widget_show (entry);
|
||||
|
||||
info.resolution_entry = PIKA_SIZE_ENTRY (entry);
|
||||
|
||||
gtk_grid_set_row_spacing (GTK_GRID (entry), 2);
|
||||
|
||||
adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
height = pika_spin_button_new (adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (height), NULL);
|
||||
gtk_grid_attach (GTK_GRID (entry), height, 1, 0, 1, 1);
|
||||
gtk_widget_show (height);
|
||||
|
||||
gtk_size_group_add_widget (entry_group, height);
|
||||
|
||||
label = pika_size_entry_attach_label (PIKA_SIZE_ENTRY (entry),
|
||||
_("_X resolution:"), 0, 0, 0.0);
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
|
||||
label = pika_size_entry_attach_label (PIKA_SIZE_ENTRY (entry),
|
||||
_("_Y resolution:"), 1, 0, 0.0);
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
|
||||
button = gtk_button_new_with_mnemonic (_("_Load Defaults"));
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (print_resolution_load_defaults),
|
||||
&info);
|
||||
gtk_widget_show (button);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
pika_size_entry_set_refval_boundaries (PIKA_SIZE_ENTRY (entry), 0,
|
||||
PIKA_MIN_RESOLUTION,
|
||||
PIKA_MAX_RESOLUTION);
|
||||
pika_size_entry_set_refval_boundaries (PIKA_SIZE_ENTRY (entry), 1,
|
||||
PIKA_MIN_RESOLUTION,
|
||||
PIKA_MAX_RESOLUTION);
|
||||
|
||||
pika_size_entry_set_refval (PIKA_SIZE_ENTRY (entry), 0, data->xres);
|
||||
pika_size_entry_set_refval (PIKA_SIZE_ENTRY (entry), 1, data->yres);
|
||||
|
||||
chain = pika_chain_button_new (PIKA_CHAIN_RIGHT);
|
||||
if (ABS (data->xres - data->yres) < PIKA_MIN_RESOLUTION)
|
||||
pika_chain_button_set_active (PIKA_CHAIN_BUTTON (chain), TRUE);
|
||||
gtk_grid_attach (GTK_GRID (entry), chain, 2, 0, 1, 2);
|
||||
gtk_widget_show (chain);
|
||||
|
||||
info.chain = PIKA_CHAIN_BUTTON (chain);
|
||||
|
||||
g_signal_connect (info.resolution_entry, "value-changed",
|
||||
G_CALLBACK (print_size_info_resolution_changed),
|
||||
NULL);
|
||||
g_signal_connect (info.size_entry, "unit-changed",
|
||||
G_CALLBACK (print_size_info_unit_changed),
|
||||
NULL);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
print_offset_frame (PrintData *data,
|
||||
GtkSizeGroup *label_group,
|
||||
GtkSizeGroup *entry_group)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
GtkWidget *spinner;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
GtkWidget *combo;
|
||||
|
||||
frame = pika_frame_new (_("Position"));
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
/* the offset entry */
|
||||
|
||||
entry = GTK_WIDGET (info.size_entry);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
||||
gtk_widget_show (grid);
|
||||
|
||||
/* left */
|
||||
info.left_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
spinner = pika_spin_button_new (info.left_adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
||||
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (spinner), NULL);
|
||||
gtk_grid_attach (GTK_GRID (grid), spinner, 1, 0, 1, 1);
|
||||
gtk_widget_show (spinner);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("_Left:"));
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* right */
|
||||
info.right_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
spinner = pika_spin_button_new (info.right_adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
||||
|
||||
g_signal_connect (info.right_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_offset_max_changed),
|
||||
GINT_TO_POINTER (LEFT));
|
||||
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (spinner), NULL);
|
||||
gtk_grid_attach (GTK_GRID (grid), spinner, 3, 0, 1, 1);
|
||||
gtk_widget_show (spinner);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("_Right:"));
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* top */
|
||||
info.top_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
spinner = pika_spin_button_new (info.top_adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
||||
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (spinner), NULL);
|
||||
gtk_grid_attach (GTK_GRID (grid), spinner, 1, 1, 1, 1);
|
||||
gtk_widget_show (spinner);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("_Top:"));
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* bottom */
|
||||
info.bottom_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
|
||||
spinner = pika_spin_button_new (info.bottom_adj, 1, 2);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
||||
|
||||
g_signal_connect (info.bottom_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_offset_max_changed),
|
||||
GINT_TO_POINTER (TOP));
|
||||
|
||||
pika_size_entry_add_field (PIKA_SIZE_ENTRY (entry),
|
||||
GTK_SPIN_BUTTON (spinner), NULL);
|
||||
gtk_grid_attach (GTK_GRID (grid), spinner, 3, 1, 1, 1);
|
||||
gtk_widget_show (spinner);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("_Bottom:"));
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 2, 1, 1, 1);
|
||||
gtk_widget_show (label);
|
||||
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), LEFT, 72.0, FALSE);
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), RIGHT, 72.0, FALSE);
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), TOP, 72.0, FALSE);
|
||||
pika_size_entry_set_resolution (PIKA_SIZE_ENTRY (entry), BOTTOM, 72.0, FALSE);
|
||||
|
||||
print_size_info_update_offsets ();
|
||||
|
||||
g_signal_connect (info.size_entry, "value-changed",
|
||||
G_CALLBACK (print_size_info_size_changed),
|
||||
NULL);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("C_enter:"));
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_size_group_add_widget (label_group, label);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* if and how to center the image on the page */
|
||||
combo = pika_int_combo_box_new (C_("center-mode", "None"), CENTER_NONE,
|
||||
_("Horizontally"), CENTER_HORIZONTALLY,
|
||||
_("Vertically"), CENTER_VERTICALLY,
|
||||
_("Both"), CENTER_BOTH,
|
||||
NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
|
||||
gtk_widget_show (combo);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
|
||||
|
||||
pika_int_combo_box_connect (PIKA_INT_COMBO_BOX (combo),
|
||||
data->center,
|
||||
G_CALLBACK (print_size_info_center_changed),
|
||||
NULL, NULL);
|
||||
|
||||
info.center_combo = combo;
|
||||
|
||||
g_signal_connect (info.left_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_center_none),
|
||||
NULL);
|
||||
g_signal_connect (info.right_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_center_none),
|
||||
NULL);
|
||||
g_signal_connect (info.top_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_center_none),
|
||||
NULL);
|
||||
g_signal_connect (info.bottom_adj, "value-changed",
|
||||
G_CALLBACK (print_size_info_center_none),
|
||||
NULL);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_get_page_dimensions (PrintSizeInfo *info,
|
||||
gdouble *page_width,
|
||||
gdouble *page_height,
|
||||
GtkUnit unit)
|
||||
{
|
||||
GtkPageSetup *setup;
|
||||
|
||||
setup = gtk_print_operation_get_default_page_setup (info->data->operation);
|
||||
|
||||
if (info->data->use_full_page)
|
||||
{
|
||||
*page_width = gtk_page_setup_get_paper_width (setup, unit);
|
||||
*page_height = gtk_page_setup_get_paper_height (setup, unit);
|
||||
}
|
||||
else
|
||||
{
|
||||
*page_width = gtk_page_setup_get_page_width (setup, unit);
|
||||
*page_height = gtk_page_setup_get_page_height (setup, unit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
pika_size_info_get_max_offsets (gdouble *offset_x_max,
|
||||
gdouble *offset_y_max)
|
||||
{
|
||||
gdouble width;
|
||||
gdouble height;
|
||||
|
||||
print_size_info_get_page_dimensions (&info, &width, &height, GTK_UNIT_POINTS);
|
||||
|
||||
*offset_x_max = width - 72.0 * info.image_width / info.data->xres;
|
||||
*offset_x_max = MAX (0, *offset_x_max);
|
||||
|
||||
*offset_y_max = height - 72.0 * info.image_height / info.data->yres;
|
||||
*offset_y_max = MAX (0, *offset_y_max);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_center_none_block (void)
|
||||
{
|
||||
g_signal_handlers_block_by_func (info.left_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_block_by_func (info.right_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_block_by_func (info.top_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_block_by_func (info.bottom_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_center_none_unblock (void)
|
||||
{
|
||||
g_signal_handlers_unblock_by_func (info.left_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_unblock_by_func (info.right_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_unblock_by_func (info.top_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
g_signal_handlers_unblock_by_func (info.bottom_adj,
|
||||
print_size_info_center_none, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_update_offsets (void)
|
||||
{
|
||||
PrintData *data = info.data;
|
||||
gdouble offset_x_max;
|
||||
gdouble offset_y_max;
|
||||
|
||||
pika_size_info_get_max_offsets (&offset_x_max, &offset_y_max);
|
||||
|
||||
g_signal_handlers_block_by_func (info.size_entry,
|
||||
print_size_info_size_changed, NULL);
|
||||
|
||||
print_size_info_center_none_block ();
|
||||
|
||||
pika_size_entry_set_refval_boundaries (info.size_entry, LEFT,
|
||||
0, offset_x_max);
|
||||
pika_size_entry_set_refval_boundaries (info.size_entry, RIGHT,
|
||||
0, offset_x_max);
|
||||
pika_size_entry_set_refval_boundaries (info.size_entry, TOP,
|
||||
0, offset_y_max);
|
||||
pika_size_entry_set_refval_boundaries (info.size_entry, BOTTOM,
|
||||
0, offset_y_max);
|
||||
|
||||
switch (data->center)
|
||||
{
|
||||
case CENTER_NONE:
|
||||
break;
|
||||
|
||||
case CENTER_HORIZONTALLY:
|
||||
data->offset_x = offset_x_max / 2.0;
|
||||
break;
|
||||
|
||||
case CENTER_VERTICALLY:
|
||||
data->offset_y = offset_y_max / 2.0;
|
||||
break;
|
||||
|
||||
case CENTER_BOTH:
|
||||
data->offset_x = offset_x_max / 2.0;
|
||||
data->offset_y = offset_y_max / 2.0;
|
||||
break;
|
||||
}
|
||||
|
||||
pika_size_entry_set_refval (info.size_entry, LEFT,
|
||||
data->offset_x);
|
||||
pika_size_entry_set_refval (info.size_entry, RIGHT,
|
||||
offset_x_max - data->offset_x);
|
||||
pika_size_entry_set_refval (info.size_entry, TOP,
|
||||
info.data->offset_y);
|
||||
pika_size_entry_set_refval (info.size_entry, BOTTOM,
|
||||
offset_y_max - data->offset_y);
|
||||
|
||||
print_size_info_center_none_unblock ();
|
||||
|
||||
g_signal_handlers_unblock_by_func (info.size_entry,
|
||||
print_size_info_size_changed, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_center_changed (GtkWidget *combo)
|
||||
{
|
||||
gint value;
|
||||
|
||||
if (pika_int_combo_box_get_active (PIKA_INT_COMBO_BOX (combo), &value))
|
||||
{
|
||||
info.data->center = value;
|
||||
|
||||
print_size_info_update_offsets ();
|
||||
|
||||
if (info.preview)
|
||||
print_preview_set_image_offsets (PRINT_PREVIEW (info.preview),
|
||||
info.data->offset_x,
|
||||
info.data->offset_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_center_none (void)
|
||||
{
|
||||
/* return early if we are called from a unit change */
|
||||
if (pika_size_entry_get_unit (info.size_entry) != info.data->unit)
|
||||
return;
|
||||
|
||||
info.data->center = CENTER_NONE;
|
||||
|
||||
if (info.center_combo)
|
||||
{
|
||||
g_signal_handlers_block_by_func (info.center_combo,
|
||||
print_size_info_center_changed, NULL);
|
||||
|
||||
info.data->center = CENTER_NONE;
|
||||
|
||||
pika_int_combo_box_set_active (PIKA_INT_COMBO_BOX (info.center_combo),
|
||||
info.data->center);
|
||||
|
||||
g_signal_handlers_unblock_by_func (info.center_combo,
|
||||
print_size_info_center_changed, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_preview_offset_changed (GtkWidget *widget,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y)
|
||||
{
|
||||
print_size_info_center_none ();
|
||||
|
||||
info.data->offset_x = offset_x;
|
||||
info.data->offset_y = offset_y;
|
||||
|
||||
print_size_info_update_offsets ();
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_size_changed (GtkWidget *widget)
|
||||
{
|
||||
gdouble width;
|
||||
gdouble height;
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
gdouble scale;
|
||||
|
||||
scale = pika_unit_get_factor (pika_size_entry_get_unit (info.size_entry));
|
||||
|
||||
width = pika_size_entry_get_value (info.size_entry, WIDTH);
|
||||
height = pika_size_entry_get_value (info.size_entry, HEIGHT);
|
||||
|
||||
xres = scale * info.image_width / MAX (0.0001, width);
|
||||
yres = scale * info.image_height / MAX (0.0001, height);
|
||||
|
||||
print_size_info_set_resolution (&info, xres, yres);
|
||||
|
||||
info.data->offset_x = pika_size_entry_get_refval (info.size_entry, LEFT);
|
||||
info.data->offset_y = pika_size_entry_get_refval (info.size_entry, TOP);
|
||||
|
||||
print_preview_set_image_offsets (PRINT_PREVIEW (info.preview),
|
||||
info.data->offset_x,
|
||||
info.data->offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_offset_max_changed (GtkAdjustment *adj,
|
||||
gpointer data)
|
||||
{
|
||||
guint index = GPOINTER_TO_INT (data);
|
||||
|
||||
/* return early if we are called from a unit change */
|
||||
if (pika_size_entry_get_unit (info.size_entry) != info.data->unit)
|
||||
return;
|
||||
|
||||
g_signal_handlers_block_by_func (info.size_entry,
|
||||
print_size_info_size_changed, NULL);
|
||||
|
||||
pika_size_entry_set_value (info.size_entry, index,
|
||||
gtk_adjustment_get_upper (adj) -
|
||||
gtk_adjustment_get_value (adj));
|
||||
|
||||
g_signal_handlers_unblock_by_func (info.size_entry,
|
||||
print_size_info_size_changed, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_resolution_changed (GtkWidget *widget)
|
||||
{
|
||||
PikaSizeEntry *entry = info.resolution_entry;
|
||||
gdouble xres = pika_size_entry_get_refval (entry, 0);
|
||||
gdouble yres = pika_size_entry_get_refval (entry, 1);
|
||||
|
||||
print_size_info_set_resolution (&info, xres, yres);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_use_full_page_toggled (GtkWidget *widget)
|
||||
{
|
||||
gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
|
||||
|
||||
info.data->use_full_page = active;
|
||||
|
||||
print_size_info_set_page_setup (&info);
|
||||
|
||||
print_preview_set_use_full_page (PRINT_PREVIEW(info.preview), active);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_unit_changed (GtkWidget *widget)
|
||||
{
|
||||
info.data->unit = pika_size_entry_get_unit (PIKA_SIZE_ENTRY (widget));
|
||||
|
||||
print_size_info_set_page_setup (&info);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_set_resolution (PrintSizeInfo *info,
|
||||
gdouble xres,
|
||||
gdouble yres)
|
||||
{
|
||||
PrintData *data = info->data;
|
||||
gdouble offset_x;
|
||||
gdouble offset_y;
|
||||
gdouble offset_x_max;
|
||||
gdouble offset_y_max;
|
||||
|
||||
if (info->chain && pika_chain_button_get_active (info->chain))
|
||||
{
|
||||
if (xres != data->xres)
|
||||
yres = xres;
|
||||
else
|
||||
xres = yres;
|
||||
}
|
||||
|
||||
data->xres = xres;
|
||||
data->yres = yres;
|
||||
|
||||
g_signal_handlers_block_by_func (info->resolution_entry,
|
||||
print_size_info_resolution_changed,
|
||||
NULL);
|
||||
|
||||
pika_size_entry_set_refval (info->resolution_entry, 0, xres);
|
||||
pika_size_entry_set_refval (info->resolution_entry, 1, yres);
|
||||
|
||||
g_signal_handlers_unblock_by_func (info->resolution_entry,
|
||||
print_size_info_resolution_changed,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_block_by_func (info->size_entry,
|
||||
print_size_info_size_changed,
|
||||
NULL);
|
||||
|
||||
pika_size_entry_set_value (info->size_entry, WIDTH,
|
||||
info->image_width *
|
||||
pika_unit_get_factor (data->unit) / xres);
|
||||
pika_size_entry_set_value (info->size_entry, HEIGHT,
|
||||
info->image_height *
|
||||
pika_unit_get_factor (data->unit) / yres);
|
||||
|
||||
g_signal_handlers_unblock_by_func (info->size_entry,
|
||||
print_size_info_size_changed,
|
||||
NULL);
|
||||
|
||||
pika_size_info_get_max_offsets (&offset_x_max, &offset_y_max);
|
||||
|
||||
offset_x = pika_size_entry_get_refval (info->size_entry, LEFT);
|
||||
offset_y = pika_size_entry_get_refval (info->size_entry, TOP);
|
||||
|
||||
offset_x = CLAMP (offset_x, 0, offset_x_max);
|
||||
offset_y = CLAMP (offset_y, 0, offset_y_max);
|
||||
|
||||
data->offset_x = offset_x;
|
||||
data->offset_y = offset_y;
|
||||
|
||||
print_size_info_update_offsets ();
|
||||
|
||||
print_preview_set_image_dpi (PRINT_PREVIEW (info->preview),
|
||||
data->xres, data->yres);
|
||||
print_preview_set_image_offsets (PRINT_PREVIEW (info->preview),
|
||||
data->offset_x, data->offset_y);
|
||||
print_preview_set_image_offsets_max (PRINT_PREVIEW (info->preview),
|
||||
offset_x_max, offset_y_max);
|
||||
}
|
||||
|
||||
static void
|
||||
print_size_info_set_page_setup (PrintSizeInfo *info)
|
||||
{
|
||||
PrintData *data = info->data;
|
||||
gdouble page_width;
|
||||
gdouble page_height;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
|
||||
print_size_info_get_page_dimensions (info,
|
||||
&page_width, &page_height,
|
||||
GTK_UNIT_INCH);
|
||||
|
||||
page_width *= pika_unit_get_factor (data->unit);
|
||||
page_height *= pika_unit_get_factor (data->unit);
|
||||
|
||||
if (info->area_label)
|
||||
{
|
||||
gchar *format;
|
||||
gchar *text;
|
||||
|
||||
format = g_strdup_printf ("%%.%df x %%.%df %s",
|
||||
pika_unit_get_digits (data->unit),
|
||||
pika_unit_get_digits (data->unit),
|
||||
pika_unit_get_plural (data->unit));
|
||||
text = g_strdup_printf (format, page_width, page_height);
|
||||
g_free (format);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (info->area_label), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
x = page_width;
|
||||
y = page_height;
|
||||
|
||||
if (info->chain && pika_chain_button_get_active (info->chain))
|
||||
{
|
||||
gdouble ratio_x = page_width / (gdouble) info->image_width;
|
||||
gdouble ratio_y = page_height / (gdouble) info->image_height;
|
||||
|
||||
if (ratio_x < ratio_y)
|
||||
y = (gdouble) info->image_height * ratio_x;
|
||||
else
|
||||
x = (gdouble) info->image_width * ratio_y;
|
||||
}
|
||||
|
||||
pika_size_entry_set_value_boundaries (info->size_entry, WIDTH,
|
||||
page_width / 100.0, x);
|
||||
pika_size_entry_set_value_boundaries (info->size_entry, HEIGHT,
|
||||
page_height / 100.0, y);
|
||||
|
||||
print_size_info_get_page_dimensions (info,
|
||||
&page_width, &page_height,
|
||||
GTK_UNIT_POINTS);
|
||||
|
||||
x = (gdouble) info->image_width / page_width * 72.0;
|
||||
y = (gdouble) info->image_height / page_height * 72.0;
|
||||
|
||||
if (info->chain && pika_chain_button_get_active (info->chain))
|
||||
{
|
||||
gdouble max = MAX (x, y);
|
||||
|
||||
x = y = max;
|
||||
}
|
||||
|
||||
data->min_xres = x;
|
||||
data->min_yres = y;
|
||||
pika_size_entry_set_refval_boundaries (info->resolution_entry, 0,
|
||||
x, PIKA_MAX_RESOLUTION);
|
||||
pika_size_entry_set_refval_boundaries (info->resolution_entry, 1,
|
||||
y, PIKA_MAX_RESOLUTION);
|
||||
}
|
||||
|
||||
static void
|
||||
print_draw_crop_marks_toggled (GtkWidget *widget)
|
||||
{
|
||||
gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
|
||||
|
||||
info.data->draw_crop_marks = active;
|
||||
}
|
||||
|
||||
static void
|
||||
print_resolution_load_defaults (PrintSizeInfo *info)
|
||||
{
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
|
||||
pika_image_get_resolution (info->data->image, &xres, &yres);
|
||||
|
||||
pika_size_entry_set_refval (info->resolution_entry, 0, xres);
|
||||
pika_size_entry_set_refval (info->resolution_entry, 1, yres);
|
||||
print_size_info_resolution_changed (GTK_WIDGET (info->resolution_entry));
|
||||
}
|
24
plug-ins/print/print-page-layout.h
Normal file
24
plug-ins/print/print-page-layout.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
GtkWidget * print_page_layout_gui (PrintData *data,
|
||||
const gchar *help_id);
|
||||
|
105
plug-ins/print/print-page-setup.c
Normal file
105
plug-ins/print/print-page-setup.c
Normal file
@ -0,0 +1,105 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print.h"
|
||||
#include "print-page-setup.h"
|
||||
#include "print-utils.h"
|
||||
|
||||
#define PRINT_PAGE_SETUP_NAME "print-page-setup"
|
||||
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
void
|
||||
print_page_setup_dialog (GtkPrintOperation *operation)
|
||||
{
|
||||
GtkPrintSettings *settings;
|
||||
GtkPageSetup *setup;
|
||||
|
||||
g_return_if_fail (GTK_IS_PRINT_OPERATION (operation));
|
||||
|
||||
setup = gtk_print_operation_get_default_page_setup (operation);
|
||||
|
||||
settings = gtk_print_settings_new ();
|
||||
setup = gtk_print_run_page_setup_dialog (NULL, setup, settings);
|
||||
g_object_unref (settings);
|
||||
|
||||
gtk_print_operation_set_default_page_setup (operation, setup);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
print_page_setup_load (GtkPrintOperation *operation,
|
||||
PikaImage *image)
|
||||
{
|
||||
GKeyFile *key_file;
|
||||
|
||||
g_return_if_fail (GTK_IS_PRINT_OPERATION (operation));
|
||||
|
||||
key_file = print_utils_key_file_load_from_parasite (image,
|
||||
PRINT_PAGE_SETUP_NAME);
|
||||
|
||||
if (! key_file)
|
||||
key_file = print_utils_key_file_load_from_rcfile (PRINT_PAGE_SETUP_NAME);
|
||||
|
||||
if (key_file)
|
||||
{
|
||||
GtkPageSetup *setup;
|
||||
|
||||
setup = gtk_page_setup_new_from_key_file (key_file,
|
||||
PRINT_PAGE_SETUP_NAME, NULL);
|
||||
|
||||
if (setup)
|
||||
{
|
||||
gtk_print_operation_set_default_page_setup (operation, setup);
|
||||
g_object_unref (setup);
|
||||
}
|
||||
|
||||
g_key_file_free (key_file);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_page_setup_save (GtkPrintOperation *operation,
|
||||
PikaImage *image)
|
||||
{
|
||||
GtkPageSetup *setup;
|
||||
GKeyFile *key_file;
|
||||
|
||||
g_return_if_fail (GTK_IS_PRINT_OPERATION (operation));
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
|
||||
setup = gtk_print_operation_get_default_page_setup (operation);
|
||||
|
||||
gtk_page_setup_to_key_file (setup, key_file, PRINT_PAGE_SETUP_NAME);
|
||||
|
||||
print_utils_key_file_save_as_parasite (key_file,
|
||||
image, PRINT_PAGE_SETUP_NAME);
|
||||
print_utils_key_file_save_as_rcfile (key_file,
|
||||
PRINT_PAGE_SETUP_NAME);
|
||||
|
||||
g_key_file_free (key_file);
|
||||
}
|
31
plug-ins/print/print-page-setup.h
Normal file
31
plug-ins/print/print-page-setup.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
void print_page_setup_dialog (GtkPrintOperation *operation);
|
||||
#endif
|
||||
void print_page_setup_load (GtkPrintOperation *operation,
|
||||
PikaImage *image);
|
||||
void print_page_setup_save (GtkPrintOperation *operation,
|
||||
PikaImage *image);
|
||||
|
||||
|
917
plug-ins/print/print-preview.c
Normal file
917
plug-ins/print/print-preview.c
Normal file
@ -0,0 +1,917 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print-preview.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
OFFSETS_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
#define SIZE_REQUEST 200
|
||||
|
||||
|
||||
struct _PrintPreview
|
||||
{
|
||||
GtkEventBox parent_instance;
|
||||
|
||||
GdkCursor *cursor;
|
||||
|
||||
GtkPageSetup *page;
|
||||
cairo_surface_t *thumbnail;
|
||||
gboolean dragging;
|
||||
gboolean inside;
|
||||
|
||||
PikaDrawable *drawable;
|
||||
|
||||
gdouble image_offset_x;
|
||||
gdouble image_offset_y;
|
||||
gdouble image_offset_x_max;
|
||||
gdouble image_offset_y_max;
|
||||
gdouble image_width;
|
||||
gdouble image_height;
|
||||
|
||||
gboolean use_full_page;
|
||||
|
||||
/* for mouse drags */
|
||||
gdouble orig_offset_x;
|
||||
gdouble orig_offset_y;
|
||||
gint start_x;
|
||||
gint start_y;
|
||||
};
|
||||
|
||||
struct _PrintPreviewClass
|
||||
{
|
||||
GtkEventBoxClass parent_class;
|
||||
|
||||
void (* offsets_changed) (PrintPreview *print_preview,
|
||||
gint offset_x,
|
||||
gint offset_y);
|
||||
};
|
||||
|
||||
|
||||
static void print_preview_finalize (GObject *object);
|
||||
|
||||
static void print_preview_realize (GtkWidget *widget);
|
||||
static void print_preview_unrealize (GtkWidget *widget);
|
||||
static void print_preview_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum_width,
|
||||
gint *natural_width);
|
||||
static void print_preview_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum_height,
|
||||
gint *natural_height);
|
||||
static void print_preview_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static gboolean print_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
static gboolean print_preview_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gboolean print_preview_button_release_event (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gboolean print_preview_motion_notify_event (GtkWidget *widget,
|
||||
GdkEventMotion *event);
|
||||
static gboolean print_preview_leave_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event);
|
||||
|
||||
static gboolean print_preview_is_inside (PrintPreview *preview,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
static void print_preview_set_inside (PrintPreview *preview,
|
||||
gboolean inside);
|
||||
|
||||
static gdouble print_preview_get_scale (PrintPreview *preview);
|
||||
|
||||
static void print_preview_get_page_size (PrintPreview *preview,
|
||||
gdouble *paper_width,
|
||||
gdouble *paper_height);
|
||||
static void print_preview_get_page_margins (PrintPreview *preview,
|
||||
gdouble *left_margin,
|
||||
gdouble *right_margin,
|
||||
gdouble *top_margin,
|
||||
gdouble *bottom_margin);
|
||||
static cairo_surface_t * print_preview_get_thumbnail (PikaDrawable *drawable,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PrintPreview, print_preview, GTK_TYPE_EVENT_BOX)
|
||||
|
||||
#define parent_class print_preview_parent_class
|
||||
|
||||
static guint print_preview_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
|
||||
|
||||
static void
|
||||
marshal_VOID__DOUBLE_DOUBLE (GClosure *closure,
|
||||
GValue *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data)
|
||||
{
|
||||
typedef void (*GMarshalFunc_VOID__DOUBLE_DOUBLE) (gpointer data1,
|
||||
gdouble arg_1,
|
||||
gdouble arg_2,
|
||||
gpointer data2);
|
||||
register GMarshalFunc_VOID__DOUBLE_DOUBLE callback;
|
||||
register GCClosure *cc = (GCClosure*) closure;
|
||||
register gpointer data1, data2;
|
||||
|
||||
g_return_if_fail (n_param_values == 3);
|
||||
|
||||
if (G_CCLOSURE_SWAP_DATA (closure))
|
||||
{
|
||||
data1 = closure->data;
|
||||
data2 = g_value_peek_pointer (param_values + 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data1 = g_value_peek_pointer (param_values + 0);
|
||||
data2 = closure->data;
|
||||
}
|
||||
|
||||
callback = (GMarshalFunc_VOID__DOUBLE_DOUBLE) (marshal_data ?
|
||||
marshal_data : cc->callback);
|
||||
|
||||
callback (data1,
|
||||
g_marshal_value_peek_double (param_values + 1),
|
||||
g_marshal_value_peek_double (param_values + 2),
|
||||
data2);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_class_init (PrintPreviewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
print_preview_signals[OFFSETS_CHANGED] =
|
||||
g_signal_new ("offsets-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PrintPreviewClass, offsets_changed),
|
||||
NULL, NULL,
|
||||
marshal_VOID__DOUBLE_DOUBLE,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_DOUBLE,
|
||||
G_TYPE_DOUBLE);
|
||||
|
||||
object_class->finalize = print_preview_finalize;
|
||||
|
||||
widget_class->realize = print_preview_realize;
|
||||
widget_class->unrealize = print_preview_unrealize;
|
||||
widget_class->get_preferred_width = print_preview_get_preferred_width;
|
||||
widget_class->get_preferred_height = print_preview_get_preferred_height;
|
||||
widget_class->size_allocate = print_preview_size_allocate;
|
||||
widget_class->draw = print_preview_draw;
|
||||
widget_class->button_press_event = print_preview_button_press_event;
|
||||
widget_class->button_release_event = print_preview_button_release_event;
|
||||
widget_class->motion_notify_event = print_preview_motion_notify_event;
|
||||
widget_class->leave_notify_event = print_preview_leave_notify_event;
|
||||
|
||||
klass->offsets_changed = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_init (PrintPreview *preview)
|
||||
{
|
||||
gtk_event_box_set_visible_window (GTK_EVENT_BOX (preview), FALSE);
|
||||
|
||||
gtk_widget_add_events (GTK_WIDGET (preview),
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_preview_finalize (GObject *object)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (object);
|
||||
|
||||
if (preview->thumbnail)
|
||||
{
|
||||
cairo_surface_destroy (preview->thumbnail);
|
||||
preview->thumbnail = NULL;
|
||||
}
|
||||
|
||||
if (preview->page)
|
||||
{
|
||||
g_object_unref (preview->page);
|
||||
preview->page = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (print_preview_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_realize (GtkWidget *widget)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (print_preview_parent_class)->realize (widget);
|
||||
|
||||
preview->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
|
||||
GDK_HAND1);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_unrealize (GtkWidget *widget)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
if (preview->cursor)
|
||||
g_object_unref (preview->cursor);
|
||||
|
||||
GTK_WIDGET_CLASS (print_preview_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
gdouble paper_width;
|
||||
gdouble paper_height;
|
||||
gint border;
|
||||
|
||||
border = gtk_container_get_border_width (GTK_CONTAINER (widget)) + 1;
|
||||
|
||||
print_preview_get_page_size (preview, &paper_width, &paper_height);
|
||||
|
||||
if (paper_width > paper_height)
|
||||
{
|
||||
requisition->height = SIZE_REQUEST;
|
||||
requisition->width = paper_width * SIZE_REQUEST / paper_height;
|
||||
requisition->width = MIN (requisition->width, 2 * SIZE_REQUEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
requisition->width = SIZE_REQUEST;
|
||||
requisition->height = paper_height * SIZE_REQUEST / paper_width;
|
||||
requisition->height = MIN (requisition->height, 2 * SIZE_REQUEST);
|
||||
}
|
||||
|
||||
requisition->width += 2 * border;
|
||||
requisition->height += 2 * border;
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum_width,
|
||||
gint *natural_width)
|
||||
{
|
||||
GtkRequisition requisition;
|
||||
|
||||
print_preview_size_request (widget, &requisition);
|
||||
|
||||
*minimum_width = *natural_width = requisition.width;
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum_height,
|
||||
gint *natural_height)
|
||||
{
|
||||
GtkRequisition requisition;
|
||||
|
||||
print_preview_size_request (widget, &requisition);
|
||||
|
||||
*minimum_height = *natural_height = requisition.height;
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (print_preview_parent_class)->size_allocate (widget,
|
||||
allocation);
|
||||
|
||||
if (preview->thumbnail)
|
||||
{
|
||||
cairo_surface_destroy (preview->thumbnail);
|
||||
preview->thumbnail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == 1 && preview->inside)
|
||||
{
|
||||
GdkDisplay *display = gtk_widget_get_display (widget);
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
GdkCursor *cursor;
|
||||
|
||||
cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
|
||||
GDK_FLEUR);
|
||||
|
||||
if (gdk_seat_grab (seat, gdk_event_get_window ((GdkEvent *) event),
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING, FALSE,
|
||||
cursor,
|
||||
(GdkEvent *) event,
|
||||
NULL, NULL) == GDK_GRAB_SUCCESS)
|
||||
{
|
||||
preview->orig_offset_x = preview->image_offset_x;
|
||||
preview->orig_offset_y = preview->image_offset_y;
|
||||
|
||||
preview->start_x = event->x;
|
||||
preview->start_y = event->y;
|
||||
|
||||
preview->dragging = TRUE;
|
||||
}
|
||||
|
||||
g_object_unref (cursor);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_button_release_event (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
if (preview->dragging)
|
||||
{
|
||||
GdkDisplay *display = gtk_widget_get_display (widget);
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
|
||||
gdk_seat_ungrab (seat);
|
||||
|
||||
preview->dragging = FALSE;
|
||||
|
||||
print_preview_set_inside (preview,
|
||||
print_preview_is_inside (preview,
|
||||
event->x, event->y));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_motion_notify_event (GtkWidget *widget,
|
||||
GdkEventMotion *event)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
if (preview->dragging)
|
||||
{
|
||||
gdouble scale = print_preview_get_scale (preview);
|
||||
gdouble offset_x;
|
||||
gdouble offset_y;
|
||||
|
||||
offset_x = (preview->orig_offset_x +
|
||||
(event->x - preview->start_x) / scale);
|
||||
offset_y = (preview->orig_offset_y +
|
||||
(event->y - preview->start_y) / scale);
|
||||
|
||||
offset_x = CLAMP (offset_x, 0, preview->image_offset_x_max);
|
||||
offset_y = CLAMP (offset_y, 0, preview->image_offset_y_max);
|
||||
|
||||
if (preview->image_offset_x != offset_x ||
|
||||
preview->image_offset_y != offset_y)
|
||||
{
|
||||
print_preview_set_image_offsets (preview, offset_x, offset_y);
|
||||
|
||||
g_signal_emit (preview,
|
||||
print_preview_signals[OFFSETS_CHANGED], 0,
|
||||
preview->image_offset_x,
|
||||
preview->image_offset_y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_preview_set_inside (preview,
|
||||
print_preview_is_inside (preview,
|
||||
event->x, event->y));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_leave_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
|
||||
if (event->mode == GDK_CROSSING_NORMAL)
|
||||
print_preview_set_inside (preview, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
PrintPreview *preview = PRINT_PREVIEW (widget);
|
||||
GtkAllocation allocation;
|
||||
GdkRGBA color;
|
||||
gdouble paper_width;
|
||||
gdouble paper_height;
|
||||
gdouble left_margin;
|
||||
gdouble right_margin;
|
||||
gdouble top_margin;
|
||||
gdouble bottom_margin;
|
||||
gdouble scale;
|
||||
gint border;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
border = gtk_container_get_border_width (GTK_CONTAINER (widget)) + 1;
|
||||
|
||||
print_preview_get_page_size (preview, &paper_width, &paper_height);
|
||||
print_preview_get_page_margins (preview,
|
||||
&left_margin, &right_margin,
|
||||
&top_margin, &bottom_margin);
|
||||
|
||||
scale = print_preview_get_scale (preview);
|
||||
|
||||
cairo_translate (cr, border, border);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
{
|
||||
gint width = allocation.width - 2 * border;
|
||||
|
||||
cairo_translate (cr, width - scale * paper_width, 0);
|
||||
}
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
/* draw page background */
|
||||
cairo_rectangle (cr, 0, 0, scale * paper_width, scale * paper_height);
|
||||
|
||||
color = (GdkRGBA) { 0.0, 0.0, 0.0, 1.0 };
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
color = (GdkRGBA) { 1.0, 1.0, 1.0, 1.0 };
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_fill (cr);
|
||||
|
||||
/* draw page_margins */
|
||||
cairo_rectangle (cr,
|
||||
scale * left_margin,
|
||||
scale * top_margin,
|
||||
scale * (paper_width - left_margin - right_margin),
|
||||
scale * (paper_height - top_margin - bottom_margin));
|
||||
|
||||
color = (GdkRGBA) { 0.0, 0.0, 0.0, 0.3 };
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_translate (cr,
|
||||
scale * (left_margin + preview->image_offset_x),
|
||||
scale * (top_margin + preview->image_offset_y));
|
||||
|
||||
if (preview->dragging || preview->inside)
|
||||
{
|
||||
cairo_rectangle (cr,
|
||||
0, 0,
|
||||
scale * preview->image_width,
|
||||
scale * preview->image_height);
|
||||
|
||||
color = (GdkRGBA) { 0.0, 0.0, 0.0, 1.0 };
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
if (preview->thumbnail == NULL &&
|
||||
pika_item_is_valid (PIKA_ITEM (preview->drawable)))
|
||||
{
|
||||
preview->thumbnail =
|
||||
print_preview_get_thumbnail (preview->drawable,
|
||||
MIN (allocation.width, 1024),
|
||||
MIN (allocation.height, 1024));
|
||||
}
|
||||
|
||||
if (preview->thumbnail != NULL)
|
||||
{
|
||||
gdouble scale_x;
|
||||
gdouble scale_y;
|
||||
|
||||
scale_x = (preview->image_width /
|
||||
cairo_image_surface_get_width (preview->thumbnail));
|
||||
scale_y = (preview->image_height /
|
||||
cairo_image_surface_get_height (preview->thumbnail));
|
||||
|
||||
cairo_rectangle (cr, 0, 0, preview->image_width, preview->image_height);
|
||||
|
||||
cairo_scale (cr, scale_x * scale, scale_y * scale);
|
||||
|
||||
cairo_set_source_surface (cr, preview->thumbnail, 0, 0);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_new:
|
||||
* @page: page setup
|
||||
* @drawable: the drawable to print
|
||||
*
|
||||
* Creates a new #PrintPreview widget.
|
||||
*
|
||||
* Returns: the new #PrintPreview widget.
|
||||
**/
|
||||
GtkWidget *
|
||||
print_preview_new (GtkPageSetup *page,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PrintPreview *preview;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_PAGE_SETUP (page), NULL);
|
||||
|
||||
preview = g_object_new (PRINT_TYPE_PREVIEW, NULL);
|
||||
|
||||
preview->drawable = drawable;
|
||||
|
||||
print_preview_set_page_setup (preview, page);
|
||||
|
||||
return GTK_WIDGET (preview);
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_set_image_dpi:
|
||||
* @preview: a #PrintPreview.
|
||||
* @xres: the X resolution
|
||||
* @yres: the Y resolution
|
||||
*
|
||||
* Sets the resolution of the image/drawable displayed by the
|
||||
* #PrintPreview.
|
||||
**/
|
||||
void
|
||||
print_preview_set_image_dpi (PrintPreview *preview,
|
||||
gdouble xres,
|
||||
gdouble yres)
|
||||
{
|
||||
gdouble width;
|
||||
gdouble height;
|
||||
|
||||
g_return_if_fail (PRINT_IS_PREVIEW (preview));
|
||||
g_return_if_fail (xres > 0.0 && yres > 0.0);
|
||||
|
||||
width = pika_drawable_get_width (preview->drawable) * 72.0 / xres;
|
||||
height = pika_drawable_get_height (preview->drawable) * 72.0 / yres;
|
||||
|
||||
if (width != preview->image_width || height != preview->image_height)
|
||||
{
|
||||
preview->image_width = width;
|
||||
preview->image_height = height;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (preview));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_set_page_setup:
|
||||
* @preview: a #PrintPreview.
|
||||
* @page: the page setup to use
|
||||
*
|
||||
* Sets the page setup to use by the #PrintPreview.
|
||||
**/
|
||||
void
|
||||
print_preview_set_page_setup (PrintPreview *preview,
|
||||
GtkPageSetup *page)
|
||||
{
|
||||
g_return_if_fail (PRINT_IS_PREVIEW (preview));
|
||||
g_return_if_fail (GTK_IS_PAGE_SETUP (page));
|
||||
|
||||
if (preview->page)
|
||||
g_object_unref (preview->page);
|
||||
|
||||
preview->page = gtk_page_setup_copy (page);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_set_image_offsets:
|
||||
* @preview: a #PrintPreview.
|
||||
* @offset_x: the X offset
|
||||
* @offset_y: the Y offset
|
||||
*
|
||||
* Sets the offsets of the image/drawable displayed by the #PrintPreview.
|
||||
* It does not emit the "offsets-changed" signal.
|
||||
**/
|
||||
void
|
||||
print_preview_set_image_offsets (PrintPreview *preview,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y)
|
||||
{
|
||||
g_return_if_fail (PRINT_IS_PREVIEW (preview));
|
||||
|
||||
preview->image_offset_x = offset_x;
|
||||
preview->image_offset_y = offset_y;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_set_image_offsets_max:
|
||||
* @preview: a #PrintPreview.
|
||||
* @offset_x_max: the maximum X offset allowed
|
||||
* @offset_y_max: the maximum Y offset allowed
|
||||
*
|
||||
* Sets the maximum offsets of the image/drawable displayed by the
|
||||
* #PrintPreview. It does not emit the "offsets-changed" signal.
|
||||
**/
|
||||
void
|
||||
print_preview_set_image_offsets_max (PrintPreview *preview,
|
||||
gdouble offset_x_max,
|
||||
gdouble offset_y_max)
|
||||
{
|
||||
g_return_if_fail (PRINT_IS_PREVIEW (preview));
|
||||
|
||||
preview->image_offset_x_max = offset_x_max;
|
||||
preview->image_offset_y_max = offset_y_max;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
/**
|
||||
* print_preview_set_use_full_page:
|
||||
* @preview: a #PrintPreview.
|
||||
* @full_page: TRUE to ignore the page margins
|
||||
*
|
||||
* If @full_page is TRUE, the page margins are ignored and the full page
|
||||
* can be used to setup printing.
|
||||
**/
|
||||
void
|
||||
print_preview_set_use_full_page (PrintPreview *preview,
|
||||
gboolean full_page)
|
||||
{
|
||||
g_return_if_fail (PRINT_IS_PREVIEW (preview));
|
||||
|
||||
preview->use_full_page = full_page;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_preview_is_inside (PrintPreview *preview,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (preview);
|
||||
GtkAllocation allocation;
|
||||
gdouble left_margin;
|
||||
gdouble right_margin;
|
||||
gdouble top_margin;
|
||||
gdouble bottom_margin;
|
||||
gdouble scale;
|
||||
gint border;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
border = gtk_container_get_border_width (GTK_CONTAINER (widget)) + 1;
|
||||
|
||||
x -= border;
|
||||
|
||||
scale = print_preview_get_scale (preview);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
{
|
||||
gdouble paper_width;
|
||||
gdouble paper_height;
|
||||
gint width = allocation.width - 2 * border;
|
||||
|
||||
print_preview_get_page_size (preview, &paper_width, &paper_height);
|
||||
|
||||
x -= width - scale * paper_width;
|
||||
}
|
||||
|
||||
print_preview_get_page_margins (preview,
|
||||
&left_margin, &right_margin,
|
||||
&top_margin, &bottom_margin);
|
||||
|
||||
x = x / scale - left_margin;
|
||||
y = y / scale - top_margin;
|
||||
|
||||
return (x > preview->image_offset_x &&
|
||||
x < preview->image_offset_x + preview->image_width &&
|
||||
y > preview->image_offset_y &&
|
||||
y < preview->image_offset_y + preview->image_height);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_set_inside (PrintPreview *preview,
|
||||
gboolean inside)
|
||||
{
|
||||
if (inside != preview->inside)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (preview);
|
||||
|
||||
preview->inside = inside;
|
||||
|
||||
if (gtk_widget_is_drawable (widget))
|
||||
gdk_window_set_cursor (gtk_widget_get_window (widget),
|
||||
inside ? preview->cursor : NULL);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
print_preview_get_scale (PrintPreview *preview)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (preview);
|
||||
GtkAllocation allocation;
|
||||
gdouble paper_width;
|
||||
gdouble paper_height;
|
||||
gdouble scale_x;
|
||||
gdouble scale_y;
|
||||
gint border;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
border = gtk_container_get_border_width (GTK_CONTAINER (widget)) + 1;
|
||||
|
||||
print_preview_get_page_size (preview, &paper_width, &paper_height);
|
||||
|
||||
scale_x = (gdouble) (allocation.width - 2 * border) / paper_width;
|
||||
scale_y = (gdouble) (allocation.height - 2 * border) / paper_height;
|
||||
|
||||
return MIN (scale_x, scale_y);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_get_page_size (PrintPreview *preview,
|
||||
gdouble *paper_width,
|
||||
gdouble *paper_height)
|
||||
{
|
||||
*paper_width = gtk_page_setup_get_paper_width (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
*paper_height = gtk_page_setup_get_paper_height (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
}
|
||||
|
||||
static void
|
||||
print_preview_get_page_margins (PrintPreview *preview,
|
||||
gdouble *left_margin,
|
||||
gdouble *right_margin,
|
||||
gdouble *top_margin,
|
||||
gdouble *bottom_margin)
|
||||
{
|
||||
if (preview->use_full_page)
|
||||
{
|
||||
*left_margin = 0.0;
|
||||
*right_margin = 0.0;
|
||||
*top_margin = 0.0;
|
||||
*bottom_margin = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*left_margin = gtk_page_setup_get_left_margin (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
*right_margin = gtk_page_setup_get_right_margin (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
*top_margin = gtk_page_setup_get_top_margin (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
*bottom_margin = gtk_page_setup_get_bottom_margin (preview->page,
|
||||
GTK_UNIT_POINTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This thumbnail code should eventually end up in libpikaui. */
|
||||
|
||||
static cairo_surface_t *
|
||||
print_preview_get_thumbnail (PikaDrawable *drawable,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
GBytes *data;
|
||||
guchar *dest;
|
||||
const guchar *src;
|
||||
gint src_stride;
|
||||
gint dest_stride;
|
||||
gint y;
|
||||
gint bpp;
|
||||
|
||||
g_return_val_if_fail (width > 0 && width <= 1024, NULL);
|
||||
g_return_val_if_fail (height > 0 && height <= 1024, NULL);
|
||||
|
||||
data = pika_drawable_get_thumbnail_data (drawable,
|
||||
width, height,
|
||||
&width, &height, &bpp);
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 4:
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create (format, width, height);
|
||||
|
||||
src = g_bytes_get_data (data, NULL);
|
||||
src_stride = width * bpp;
|
||||
|
||||
dest = cairo_image_surface_get_data (surface);
|
||||
dest_stride = cairo_image_surface_get_stride (surface);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
const guchar *s = src;
|
||||
guchar *d = dest;
|
||||
gint w = width;
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 1:
|
||||
while (w--)
|
||||
{
|
||||
PIKA_CAIRO_RGB24_SET_PIXEL (d, s[0], s[0], s[0]);
|
||||
s += 1;
|
||||
d += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
while (w--)
|
||||
{
|
||||
PIKA_CAIRO_ARGB32_SET_PIXEL (d, s[0], s[0], s[0], s[1]);
|
||||
s += 2;
|
||||
d += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
while (w--)
|
||||
{
|
||||
PIKA_CAIRO_RGB24_SET_PIXEL (d, s[0], s[1], s[2]);
|
||||
s += 3;
|
||||
d += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
while (w--)
|
||||
{
|
||||
PIKA_CAIRO_ARGB32_SET_PIXEL (d, s[0], s[1], s[2], s[3]);
|
||||
s += 4;
|
||||
d += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
src += src_stride;
|
||||
dest += dest_stride;
|
||||
}
|
||||
|
||||
g_bytes_unref (data);
|
||||
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
}
|
64
plug-ins/print/print-preview.h
Normal file
64
plug-ins/print/print-preview.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __PRINT_PREVIEW_H__
|
||||
#define __PRINT_PREVIEW_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define PRINT_TYPE_PREVIEW (print_preview_get_type ())
|
||||
#define PRINT_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PRINT_TYPE_PREVIEW, PrintPreview))
|
||||
#define PRINT_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PRINT_TYPE_PREVIEW, PrintPreviewClass))
|
||||
#define PRINT_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PRINT_TYPE_PREVIEW))
|
||||
#define PRINT_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PRINT_TYPE_PREVIEW))
|
||||
#define PRINT_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PRINT_TYPE_PREVIEW, PrintPreviewClass))
|
||||
|
||||
typedef struct _PrintPreview PrintPreview;
|
||||
typedef struct _PrintPreviewClass PrintPreviewClass;
|
||||
|
||||
|
||||
GType print_preview_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * print_preview_new (GtkPageSetup *page,
|
||||
PikaDrawable *drawable);
|
||||
|
||||
void print_preview_set_image_dpi (PrintPreview *preview,
|
||||
gdouble xres,
|
||||
gdouble yres);
|
||||
|
||||
void print_preview_set_page_setup (PrintPreview *preview,
|
||||
GtkPageSetup *page);
|
||||
|
||||
void print_preview_set_image_offsets (PrintPreview *preview,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y);
|
||||
|
||||
void print_preview_set_image_offsets_max (PrintPreview *preview,
|
||||
gdouble offset_x_max,
|
||||
gdouble offset_y_max);
|
||||
|
||||
void print_preview_set_use_full_page (PrintPreview *preview,
|
||||
gboolean full_page);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PRINT_PREVIEW_H__ */
|
324
plug-ins/print/print-settings.c
Normal file
324
plug-ins/print/print-settings.c
Normal file
@ -0,0 +1,324 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print.h"
|
||||
#include "print-settings.h"
|
||||
#include "print-utils.h"
|
||||
|
||||
|
||||
#define PRINT_SETTINGS_MAJOR_VERSION 0
|
||||
#define PRINT_SETTINGS_MINOR_VERSION 4
|
||||
|
||||
#define PRINT_SETTINGS_NAME "print-settings"
|
||||
|
||||
|
||||
static GKeyFile * print_settings_key_file_from_settings (PrintData *data);
|
||||
|
||||
static void print_settings_add_to_key_file (const gchar *key,
|
||||
const gchar *value,
|
||||
gpointer data);
|
||||
|
||||
static GKeyFile * print_settings_key_file_from_resource_file (void);
|
||||
|
||||
static GKeyFile * print_settings_key_file_from_parasite (PikaImage *image);
|
||||
|
||||
static gboolean print_settings_load_from_key_file (PrintData *data,
|
||||
GKeyFile *key_file);
|
||||
|
||||
static gboolean print_settings_check_version (GKeyFile *key_file);
|
||||
|
||||
/*
|
||||
* set GtkPrintSettings from the contents of a "print-settings"
|
||||
* image parasite, or, if none exists, from a resource
|
||||
* file of the same name
|
||||
*/
|
||||
gboolean
|
||||
print_settings_load (PrintData *data)
|
||||
{
|
||||
GKeyFile *key_file = print_settings_key_file_from_parasite (data->image);
|
||||
|
||||
if (! key_file)
|
||||
key_file = print_settings_key_file_from_resource_file ();
|
||||
|
||||
if (key_file)
|
||||
{
|
||||
print_settings_load_from_key_file (data, key_file);
|
||||
g_key_file_free (key_file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* save all settings as a resource file "print-settings"
|
||||
* and as an image parasite
|
||||
*/
|
||||
void
|
||||
print_settings_save (PrintData *data)
|
||||
{
|
||||
GKeyFile *key_file = print_settings_key_file_from_settings (data);
|
||||
|
||||
/* image setup */
|
||||
if (pika_image_is_valid (data->image))
|
||||
{
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
|
||||
pika_image_get_resolution (data->image, &xres, &yres);
|
||||
|
||||
g_key_file_set_integer (key_file, "image-setup",
|
||||
"unit", data->unit);
|
||||
/* Do not save the print resolution when it is the expected image
|
||||
* resolution so that changing it (i.e. in "print size" dialog)
|
||||
* is not overridden by any previous prints.
|
||||
*/
|
||||
if ((data->min_xres <= xres && ABS (xres - data->xres) > 0.1) ||
|
||||
(data->min_yres <= yres && ABS (yres - data->yres) > 0.1) ||
|
||||
(data->min_xres > xres && ABS (data->min_xres - data->xres) > 0.1) ||
|
||||
(data->min_yres > yres && ABS (data->min_yres - data->yres) > 0.1))
|
||||
{
|
||||
g_key_file_set_double (key_file, "image-setup",
|
||||
"x-resolution", data->xres);
|
||||
g_key_file_set_double (key_file, "image-setup",
|
||||
"y-resolution", data->yres);
|
||||
}
|
||||
g_key_file_set_double (key_file, "image-setup",
|
||||
"x-offset", data->offset_x);
|
||||
g_key_file_set_double (key_file, "image-setup",
|
||||
"y-offset", data->offset_y);
|
||||
g_key_file_set_integer (key_file, "image-setup",
|
||||
"center-mode", data->center);
|
||||
g_key_file_set_boolean (key_file, "image-setup",
|
||||
"use-full-page", data->use_full_page);
|
||||
g_key_file_set_boolean (key_file, "image-setup",
|
||||
"crop-marks", data->draw_crop_marks);
|
||||
|
||||
print_utils_key_file_save_as_parasite (key_file,
|
||||
data->image,
|
||||
PRINT_SETTINGS_NAME);
|
||||
}
|
||||
|
||||
/* some settings shouldn't be made persistent on a global level,
|
||||
* so they are only stored in the image, not in the rcfile
|
||||
*/
|
||||
|
||||
g_key_file_remove_key (key_file, "image-setup", "x-resolution", NULL);
|
||||
g_key_file_remove_key (key_file, "image-setup", "y-resolution", NULL);
|
||||
g_key_file_remove_key (key_file, "image-setup", "x-offset", NULL);
|
||||
g_key_file_remove_key (key_file, "image-setup", "y-offset", NULL);
|
||||
|
||||
g_key_file_remove_key (key_file, PRINT_SETTINGS_NAME, "n-copies", NULL);
|
||||
|
||||
print_utils_key_file_save_as_rcfile (key_file, PRINT_SETTINGS_NAME);
|
||||
|
||||
g_key_file_free (key_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* serialize print settings into a GKeyFile
|
||||
*/
|
||||
static GKeyFile *
|
||||
print_settings_key_file_from_settings (PrintData *data)
|
||||
{
|
||||
GtkPrintOperation *operation = data->operation;
|
||||
GtkPrintSettings *settings;
|
||||
GKeyFile *key_file = g_key_file_new ();
|
||||
|
||||
/* put version information into the file */
|
||||
g_key_file_set_integer (key_file, "meta", "major-version",
|
||||
PRINT_SETTINGS_MAJOR_VERSION);
|
||||
g_key_file_set_integer (key_file, "meta", "minor-version",
|
||||
PRINT_SETTINGS_MINOR_VERSION);
|
||||
|
||||
/* save the contents of the GtkPrintSettings for the operation */
|
||||
settings = gtk_print_operation_get_print_settings (operation);
|
||||
|
||||
if (settings)
|
||||
gtk_print_settings_foreach (settings,
|
||||
print_settings_add_to_key_file, key_file);
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback used in gtk_print_settings_foreach loop
|
||||
*/
|
||||
static void
|
||||
print_settings_add_to_key_file (const gchar *key,
|
||||
const gchar *value,
|
||||
gpointer data)
|
||||
{
|
||||
GKeyFile *key_file = data;
|
||||
|
||||
g_key_file_set_value (key_file, PRINT_SETTINGS_NAME, key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* deserialize a "print-settings" resource file into a GKeyFile
|
||||
*/
|
||||
static GKeyFile *
|
||||
print_settings_key_file_from_resource_file (void)
|
||||
{
|
||||
GKeyFile *key_file;
|
||||
|
||||
key_file = print_utils_key_file_load_from_rcfile (PRINT_SETTINGS_NAME);
|
||||
|
||||
if (key_file && ! print_settings_check_version (key_file))
|
||||
{
|
||||
g_key_file_free (key_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
/* load information from an image parasite called "print-settings"
|
||||
* return a GKeyFile containing the information if a valid parasite is found,
|
||||
* NULL otherwise
|
||||
*/
|
||||
static GKeyFile *
|
||||
print_settings_key_file_from_parasite (PikaImage *image)
|
||||
{
|
||||
GKeyFile *key_file;
|
||||
|
||||
key_file = print_utils_key_file_load_from_parasite (image,
|
||||
PRINT_SETTINGS_NAME);
|
||||
|
||||
if (key_file && ! print_settings_check_version (key_file))
|
||||
{
|
||||
g_key_file_free (key_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_settings_load_from_key_file (PrintData *data,
|
||||
GKeyFile *key_file)
|
||||
{
|
||||
GtkPrintOperation *operation = data->operation;
|
||||
GtkPrintSettings *settings;
|
||||
gchar **keys;
|
||||
gsize n_keys;
|
||||
gint i;
|
||||
|
||||
settings = gtk_print_operation_get_print_settings (operation);
|
||||
if (! settings)
|
||||
settings = gtk_print_settings_new ();
|
||||
|
||||
keys = g_key_file_get_keys (key_file, PRINT_SETTINGS_NAME, &n_keys, NULL);
|
||||
|
||||
if (! keys)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_keys; i++)
|
||||
{
|
||||
gchar *value;
|
||||
|
||||
value = g_key_file_get_value (key_file,
|
||||
PRINT_SETTINGS_NAME, keys[i], NULL);
|
||||
|
||||
if (value)
|
||||
{
|
||||
gtk_print_settings_set (settings, keys[i], value);
|
||||
g_free (value);
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (keys);
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "unit", NULL))
|
||||
{
|
||||
data->unit = g_key_file_get_integer (key_file, "image-setup",
|
||||
"unit", NULL);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "x-resolution", NULL) &&
|
||||
g_key_file_has_key (key_file, "image-setup", "y-resolution", NULL))
|
||||
{
|
||||
data->xres = g_key_file_get_double (key_file, "image-setup",
|
||||
"x-resolution", NULL);
|
||||
data->yres = g_key_file_get_double (key_file, "image-setup",
|
||||
"y-resolution", NULL);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "x-offset", NULL) &&
|
||||
g_key_file_has_key (key_file, "image-setup", "y-offset", NULL))
|
||||
{
|
||||
data->offset_x = g_key_file_get_double (key_file, "image-setup",
|
||||
"x-offset", NULL);
|
||||
data->offset_y = g_key_file_get_double (key_file, "image-setup",
|
||||
"y-offset", NULL);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "center-mode", NULL))
|
||||
{
|
||||
data->center = g_key_file_get_integer (key_file, "image-setup",
|
||||
"center-mode", NULL);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "use-full-page", NULL))
|
||||
{
|
||||
data->use_full_page = g_key_file_get_boolean (key_file, "image-setup",
|
||||
"use-full-page", NULL);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key (key_file, "image-setup", "crop-marks", NULL))
|
||||
{
|
||||
data->draw_crop_marks = g_key_file_get_boolean (key_file, "image-setup",
|
||||
"crop-marks", NULL);
|
||||
}
|
||||
|
||||
gtk_print_operation_set_print_settings (operation, settings);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_settings_check_version (GKeyFile *key_file)
|
||||
{
|
||||
gint major_version;
|
||||
gint minor_version;
|
||||
|
||||
if (! g_key_file_has_group (key_file, "meta"))
|
||||
return FALSE;
|
||||
|
||||
major_version = g_key_file_get_integer (key_file,
|
||||
"meta", "major-version", NULL);
|
||||
|
||||
if (major_version != PRINT_SETTINGS_MAJOR_VERSION)
|
||||
return FALSE;
|
||||
|
||||
minor_version = g_key_file_get_integer (key_file,
|
||||
"meta", "minor-version", NULL);
|
||||
|
||||
if (minor_version != PRINT_SETTINGS_MINOR_VERSION)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
23
plug-ins/print/print-settings.h
Normal file
23
plug-ins/print/print-settings.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
gboolean print_settings_load (PrintData *data);
|
||||
void print_settings_save (PrintData *data);
|
151
plug-ins/print/print-utils.c
Normal file
151
plug-ins/print/print-utils.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
|
||||
#include "print-utils.h"
|
||||
|
||||
|
||||
GKeyFile *
|
||||
print_utils_key_file_load_from_rcfile (const gchar *basename)
|
||||
{
|
||||
GKeyFile *key_file;
|
||||
gchar *filename;
|
||||
|
||||
g_return_val_if_fail (basename != NULL, NULL);
|
||||
|
||||
filename = g_build_filename (pika_directory (), basename, NULL);
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
|
||||
if (! g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, NULL))
|
||||
{
|
||||
g_key_file_free (key_file);
|
||||
key_file = NULL;
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
print_utils_key_file_load_from_parasite (PikaImage *image,
|
||||
const gchar *parasite_name)
|
||||
{
|
||||
PikaParasite *parasite;
|
||||
GKeyFile *key_file;
|
||||
GError *error = NULL;
|
||||
const gchar *parasite_data;
|
||||
guint32 parasite_size;
|
||||
|
||||
|
||||
g_return_val_if_fail (parasite_name != NULL, NULL);
|
||||
|
||||
parasite = pika_image_get_parasite (image, parasite_name);
|
||||
|
||||
if (! parasite)
|
||||
return NULL;
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
|
||||
parasite_data = pika_parasite_get_data (parasite, ¶site_size);
|
||||
if (! g_key_file_load_from_data (key_file, parasite_data, parasite_size,
|
||||
G_KEY_FILE_NONE, &error))
|
||||
{
|
||||
g_key_file_free (key_file);
|
||||
pika_parasite_free (parasite);
|
||||
|
||||
g_warning ("Unable to create key file from image parasite '%s': %s",
|
||||
parasite_name, error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pika_parasite_free (parasite);
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
void
|
||||
print_utils_key_file_save_as_rcfile (GKeyFile *key_file,
|
||||
const gchar *basename)
|
||||
{
|
||||
gchar *filename;
|
||||
gchar *contents;
|
||||
gsize length;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (basename != NULL);
|
||||
|
||||
contents = g_key_file_to_data (key_file, &length, &error);
|
||||
|
||||
if (! contents)
|
||||
{
|
||||
g_warning ("Unable to get contents of key file for '%s': %s",
|
||||
basename, error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
filename = g_build_filename (pika_directory (), basename, NULL);
|
||||
|
||||
if (! g_file_set_contents (filename, contents, length, &error))
|
||||
{
|
||||
g_warning ("Unable to write settings to '%s': %s",
|
||||
pika_filename_to_utf8 (filename), error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
void
|
||||
print_utils_key_file_save_as_parasite (GKeyFile *key_file,
|
||||
PikaImage *image,
|
||||
const gchar *parasite_name)
|
||||
{
|
||||
PikaParasite *parasite;
|
||||
gchar *contents;
|
||||
gsize length;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (parasite_name != NULL);
|
||||
|
||||
contents = g_key_file_to_data (key_file, &length, &error);
|
||||
|
||||
if (! contents)
|
||||
{
|
||||
g_warning ("Unable to get contents of key file for parasite '%s': %s",
|
||||
parasite_name, error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
parasite = pika_parasite_new (parasite_name, 0, length, contents);
|
||||
g_free (contents);
|
||||
|
||||
pika_image_attach_parasite (image, parasite);
|
||||
pika_parasite_free (parasite);
|
||||
}
|
30
plug-ins/print/print-utils.h
Normal file
30
plug-ins/print/print-utils.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
GKeyFile * print_utils_key_file_load_from_rcfile (const gchar *basename);
|
||||
GKeyFile * print_utils_key_file_load_from_parasite (PikaImage *image,
|
||||
const gchar *parasite_name);
|
||||
|
||||
void print_utils_key_file_save_as_rcfile (GKeyFile *key_file,
|
||||
const gchar *basename);
|
||||
void print_utils_key_file_save_as_parasite (GKeyFile *key_file,
|
||||
PikaImage *image,
|
||||
const gchar *parasite_name);
|
562
plug-ins/print/print.c
Normal file
562
plug-ins/print/print.c
Normal file
@ -0,0 +1,562 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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 <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "print.h"
|
||||
#include "print-settings.h"
|
||||
#include "print-page-layout.h"
|
||||
#include "print-page-setup.h"
|
||||
#include "print-draw-page.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
|
||||
#define PLUG_IN_BINARY "print"
|
||||
#define PLUG_IN_ROLE "pika-print"
|
||||
#define PRINT_PROC_NAME "file-print-gtk"
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
#define PAGE_SETUP_PROC_NAME "file-print-gtk-page-setup"
|
||||
#define PRINT_TEMP_PROC_NAME "file-print-gtk-page-setup-notify-temp"
|
||||
#endif
|
||||
|
||||
|
||||
G_DEFINE_QUARK (pika-plugin-print-error-quark, pika_plugin_print_error)
|
||||
|
||||
|
||||
typedef struct _Print Print;
|
||||
typedef struct _PrintClass PrintClass;
|
||||
|
||||
struct _Print
|
||||
{
|
||||
PikaPlugIn parent_instance;
|
||||
};
|
||||
|
||||
struct _PrintClass
|
||||
{
|
||||
PikaPlugInClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#define PRINT_TYPE (print_get_type ())
|
||||
#define PRINT (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PRINT_TYPE, Print))
|
||||
|
||||
GType print_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GList * print_query_procedures (PikaPlugIn *plug_in);
|
||||
static PikaProcedure * print_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static PikaValueArray * print_run (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
|
||||
static PikaPDBStatusType print_image (PikaImage *image,
|
||||
gboolean interactive,
|
||||
GError **error);
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
static PikaPDBStatusType page_setup (PikaImage *image);
|
||||
#endif
|
||||
|
||||
static void print_show_error (const gchar *message);
|
||||
static void print_operation_set_name (GtkPrintOperation *operation,
|
||||
PikaImage *image);
|
||||
|
||||
static void begin_print (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
PrintData *data);
|
||||
static void end_print (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
PikaLayer **layer);
|
||||
static void draw_page (GtkPrintOperation *print,
|
||||
GtkPrintContext *context,
|
||||
gint page_nr,
|
||||
PrintData *data);
|
||||
|
||||
static GtkWidget * create_custom_widget (GtkPrintOperation *operation,
|
||||
PrintData *data);
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
static gchar * print_temp_proc_name (PikaImage *image);
|
||||
static gchar * print_temp_proc_install (PikaImage *image);
|
||||
|
||||
/* Keep a reference to the current GtkPrintOperation
|
||||
* for access by the temporary procedure.
|
||||
*/
|
||||
static GtkPrintOperation *print_operation = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
G_DEFINE_TYPE (Print, print, PIKA_TYPE_PLUG_IN)
|
||||
|
||||
PIKA_MAIN (PRINT_TYPE)
|
||||
DEFINE_STD_SET_I18N
|
||||
|
||||
|
||||
static void
|
||||
print_class_init (PrintClass *klass)
|
||||
{
|
||||
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
|
||||
|
||||
plug_in_class->query_procedures = print_query_procedures;
|
||||
plug_in_class->create_procedure = print_create_procedure;
|
||||
plug_in_class->set_i18n = STD_SET_I18N;
|
||||
}
|
||||
|
||||
static void
|
||||
print_init (Print *print)
|
||||
{
|
||||
}
|
||||
|
||||
static GList *
|
||||
print_query_procedures (PikaPlugIn *plug_in)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
||||
list = g_list_append (list, g_strdup (PRINT_PROC_NAME));
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
list = g_list_append (list, g_strdup (PAGE_SETUP_PROC_NAME));
|
||||
#endif
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static PikaProcedure *
|
||||
print_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name)
|
||||
{
|
||||
PikaProcedure *procedure = NULL;
|
||||
|
||||
if (! strcmp (name, PRINT_PROC_NAME))
|
||||
{
|
||||
procedure = pika_image_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
print_run, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
pika_procedure_set_sensitivity_mask (procedure,
|
||||
PIKA_PROCEDURE_SENSITIVE_DRAWABLE |
|
||||
PIKA_PROCEDURE_SENSITIVE_DRAWABLES |
|
||||
PIKA_PROCEDURE_SENSITIVE_NO_DRAWABLES);
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("_Print..."));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_DOCUMENT_PRINT);
|
||||
pika_procedure_add_menu_path (procedure, "<Image>/File/[Send]");
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
_("Print the image"),
|
||||
"Print the image using the "
|
||||
"GTK+ Print API.",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Bill Skaggs, Sven Neumann, Stefan Röllin",
|
||||
"Bill Skaggs <weskaggs@primate.ucdavis.edu>",
|
||||
"2006 - 2008");
|
||||
|
||||
}
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
else if (! strcmp (name, PAGE_SETUP_PROC_NAME))
|
||||
{
|
||||
procedure = pika_image_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
print_run, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Page Set_up..."));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_DOCUMENT_PAGE_SETUP);
|
||||
pika_procedure_add_menu_path (procedure, "<Image>/File/[Send]");
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
_("Adjust page size and orientation "
|
||||
"for printing"),
|
||||
"Adjust page size and orientation "
|
||||
"for printing the image using the "
|
||||
"GTK+ Print API.",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Bill Skaggs, Sven Neumann, Stefan Röllin",
|
||||
"Sven Neumann <sven@gimp.org>",
|
||||
"2008");
|
||||
}
|
||||
#endif
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
print_run (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaPDBStatusType status;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
if (strcmp (pika_procedure_get_name (procedure),
|
||||
PRINT_PROC_NAME) == 0)
|
||||
{
|
||||
status = print_image (image, run_mode == PIKA_RUN_INTERACTIVE, &error);
|
||||
|
||||
if (error && run_mode == PIKA_RUN_INTERACTIVE)
|
||||
{
|
||||
print_show_error (error->message);
|
||||
}
|
||||
}
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
else if (strcmp (pika_procedure_get_name (procedure),
|
||||
PAGE_SETUP_PROC_NAME) == 0)
|
||||
{
|
||||
if (run_mode == PIKA_RUN_INTERACTIVE)
|
||||
{
|
||||
status = page_setup (image);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = PIKA_PDB_CALLING_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
status = PIKA_PDB_CALLING_ERROR;
|
||||
}
|
||||
|
||||
return pika_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
|
||||
static PikaPDBStatusType
|
||||
print_image (PikaImage *image,
|
||||
gboolean interactive,
|
||||
GError **error)
|
||||
{
|
||||
GtkPrintOperation *operation;
|
||||
GtkPrintOperationResult result;
|
||||
PikaLayer *layer;
|
||||
PrintData data;
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
gchar *temp_proc;
|
||||
#endif
|
||||
|
||||
/* create a print layer from the projection */
|
||||
layer = pika_layer_new_from_visible (image, image, PRINT_PROC_NAME);
|
||||
|
||||
operation = gtk_print_operation_new ();
|
||||
|
||||
gtk_print_operation_set_n_pages (operation, 1);
|
||||
print_operation_set_name (operation, image);
|
||||
|
||||
print_page_setup_load (operation, image);
|
||||
|
||||
/* fill in the PrintData struct */
|
||||
data.image = image;
|
||||
data.drawable = PIKA_DRAWABLE (layer);
|
||||
data.unit = pika_get_default_unit ();
|
||||
data.image_unit = pika_image_get_unit (image);
|
||||
data.offset_x = 0;
|
||||
data.offset_y = 0;
|
||||
data.center = CENTER_BOTH;
|
||||
data.use_full_page = FALSE;
|
||||
data.draw_crop_marks = FALSE;
|
||||
data.operation = operation;
|
||||
|
||||
pika_image_get_resolution (image, &data.xres, &data.yres);
|
||||
|
||||
print_settings_load (&data);
|
||||
|
||||
gtk_print_operation_set_unit (operation, GTK_UNIT_PIXEL);
|
||||
|
||||
g_signal_connect (operation, "begin-print",
|
||||
G_CALLBACK (begin_print),
|
||||
&data);
|
||||
g_signal_connect (operation, "draw-page",
|
||||
G_CALLBACK (draw_page),
|
||||
&data);
|
||||
g_signal_connect (operation, "end-print",
|
||||
G_CALLBACK (end_print),
|
||||
&layer);
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
print_operation = operation;
|
||||
temp_proc = print_temp_proc_install (image);
|
||||
pika_plug_in_extension_enable (pika_get_plug_in ());
|
||||
#endif
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
pika_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
g_signal_connect_swapped (operation, "end-print",
|
||||
G_CALLBACK (print_settings_save),
|
||||
&data);
|
||||
|
||||
g_signal_connect (operation, "create-custom-widget",
|
||||
G_CALLBACK (create_custom_widget),
|
||||
&data);
|
||||
|
||||
gtk_print_operation_set_custom_tab_label (operation, _("Image Settings"));
|
||||
|
||||
#ifdef EMBED_PAGE_SETUP
|
||||
gtk_print_operation_set_embed_page_setup (operation, TRUE);
|
||||
#endif
|
||||
|
||||
result = gtk_print_operation_run (operation,
|
||||
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
|
||||
NULL, error);
|
||||
|
||||
if (result == GTK_PRINT_OPERATION_RESULT_APPLY ||
|
||||
result == GTK_PRINT_OPERATION_RESULT_IN_PROGRESS)
|
||||
{
|
||||
print_page_setup_save (operation, image);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gtk_print_operation_run (operation,
|
||||
GTK_PRINT_OPERATION_ACTION_PRINT,
|
||||
NULL, error);
|
||||
}
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
pika_plug_in_remove_temp_procedure (pika_get_plug_in (), temp_proc);
|
||||
g_free (temp_proc);
|
||||
print_operation = NULL;
|
||||
#endif
|
||||
|
||||
g_object_unref (operation);
|
||||
|
||||
if (pika_item_is_valid (PIKA_ITEM (layer)))
|
||||
pika_item_delete (PIKA_ITEM (layer));
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case GTK_PRINT_OPERATION_RESULT_APPLY:
|
||||
case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS:
|
||||
return PIKA_PDB_SUCCESS;
|
||||
|
||||
case GTK_PRINT_OPERATION_RESULT_CANCEL:
|
||||
return PIKA_PDB_CANCEL;
|
||||
|
||||
case GTK_PRINT_OPERATION_RESULT_ERROR:
|
||||
return PIKA_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
||||
return PIKA_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
static PikaPDBStatusType
|
||||
page_setup (PikaImage *image)
|
||||
{
|
||||
GtkPrintOperation *operation;
|
||||
PikaValueArray *return_vals;
|
||||
gchar *name;
|
||||
|
||||
pika_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
operation = gtk_print_operation_new ();
|
||||
|
||||
print_page_setup_load (operation, image);
|
||||
print_page_setup_dialog (operation);
|
||||
print_page_setup_save (operation, image);
|
||||
|
||||
g_object_unref (operation);
|
||||
|
||||
/* now notify a running print procedure about this change */
|
||||
name = print_temp_proc_name (image);
|
||||
|
||||
/* we don't want the core to show an error message if the
|
||||
* temporary procedure does not exist
|
||||
*/
|
||||
pika_plug_in_set_pdb_error_handler (pika_get_plug_in (),
|
||||
PIKA_PDB_ERROR_HANDLER_PLUGIN);
|
||||
|
||||
return_vals = pika_pdb_run_procedure (pika_get_pdb (),
|
||||
name,
|
||||
PIKA_TYPE_IMAGE, image,
|
||||
G_TYPE_NONE);
|
||||
pika_value_array_unref (return_vals);
|
||||
|
||||
g_free (name);
|
||||
|
||||
return PIKA_PDB_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_show_error (const gchar *message)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (NULL, 0,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s",
|
||||
_("An error occurred while trying to print:"));
|
||||
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||
"%s", message);
|
||||
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
print_operation_set_name (GtkPrintOperation *operation,
|
||||
PikaImage *image)
|
||||
{
|
||||
gchar *name = pika_image_get_name (image);
|
||||
|
||||
gtk_print_operation_set_job_name (operation, name);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
begin_print (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
PrintData *data)
|
||||
{
|
||||
gtk_print_operation_set_use_full_page (operation, data->use_full_page);
|
||||
|
||||
pika_progress_init (_("Printing"));
|
||||
}
|
||||
|
||||
static void
|
||||
end_print (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
PikaLayer **layer)
|
||||
{
|
||||
/* we don't need the print layer any longer, delete it */
|
||||
if (pika_item_is_valid (PIKA_ITEM (*layer)))
|
||||
{
|
||||
pika_item_delete (PIKA_ITEM (*layer));
|
||||
*layer = NULL;
|
||||
}
|
||||
|
||||
pika_progress_end ();
|
||||
|
||||
/* generate events to solve the problems described in bug #466928 */
|
||||
g_timeout_add_seconds (1, (GSourceFunc) gtk_true, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_page (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
gint page_nr,
|
||||
PrintData *data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (print_draw_page (context, data, &error))
|
||||
{
|
||||
pika_progress_update (1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_show_error (error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This callback creates a "custom" widget that gets inserted into the
|
||||
* print operation dialog.
|
||||
*/
|
||||
static GtkWidget *
|
||||
create_custom_widget (GtkPrintOperation *operation,
|
||||
PrintData *data)
|
||||
{
|
||||
return print_page_layout_gui (data, PRINT_PROC_NAME);
|
||||
}
|
||||
|
||||
#ifndef EMBED_PAGE_SETUP
|
||||
static PikaValueArray *
|
||||
print_temp_proc_run (PikaProcedure *procedure,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaImage *image = PIKA_VALUES_GET_IMAGE (args, 0);
|
||||
|
||||
if (print_operation)
|
||||
print_page_setup_load (print_operation, image);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
print_temp_proc_name (PikaImage *image)
|
||||
{
|
||||
return g_strdup_printf (PRINT_TEMP_PROC_NAME "-%d",
|
||||
pika_image_get_id (image));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
print_temp_proc_install (PikaImage *image)
|
||||
{
|
||||
PikaPlugIn *plug_in = pika_get_plug_in ();
|
||||
gchar *name = print_temp_proc_name (image);
|
||||
PikaProcedure *procedure;
|
||||
|
||||
procedure = pika_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_TEMPORARY,
|
||||
print_temp_proc_run, NULL, NULL);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"DON'T USE THIS ONE",
|
||||
"Temporary procedure to notify the "
|
||||
"Print plug-in about changes to the "
|
||||
"Page Setup.",
|
||||
NULL);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Sven Neumann",
|
||||
"Sven Neumann",
|
||||
"2008");
|
||||
|
||||
PIKA_PROC_ARG_IMAGE (procedure, "image",
|
||||
"Image",
|
||||
"The image to notify about",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
pika_plug_in_add_temp_procedure (plug_in, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
return name;
|
||||
}
|
||||
#endif
|
60
plug-ins/print/print.h
Normal file
60
plug-ins/print/print.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
#define EMBED_PAGE_SETUP 1
|
||||
#endif
|
||||
|
||||
#define PIKA_PLUGIN_PRINT_ERROR pika_plugin_print_error_quark ()
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_PLUGIN_PRINT_ERROR_FAILED
|
||||
} PikaPluginPrintError;
|
||||
|
||||
GQuark pika_plugin_print_error_quark (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CENTER_NONE = 0,
|
||||
CENTER_HORIZONTALLY = 1,
|
||||
CENTER_VERTICALLY = 2,
|
||||
CENTER_BOTH = 3
|
||||
} PrintCenterMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PikaImage *image;
|
||||
PikaDrawable *drawable;
|
||||
PikaUnit unit;
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
gdouble min_xres;
|
||||
gdouble min_yres;
|
||||
PikaUnit image_unit;
|
||||
gdouble offset_x;
|
||||
gdouble offset_y;
|
||||
PrintCenterMode center;
|
||||
gboolean use_full_page;
|
||||
gboolean draw_crop_marks;
|
||||
GtkPrintOperation *operation;
|
||||
} PrintData;
|
Reference in New Issue
Block a user