summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/eom-image.c17
-rw-r--r--src/eom-image.h6
-rw-r--r--src/eom-print.c138
3 files changed, 160 insertions, 1 deletions
diff --git a/src/eom-image.c b/src/eom-image.c
index 8fb9311..1627f2a 100644
--- a/src/eom-image.c
+++ b/src/eom-image.c
@@ -2350,6 +2350,14 @@ eom_image_get_transform (EomImage *img)
return img->priv->trans;
}
+EomTransform*
+eom_image_get_autorotate_transform (EomImage *img)
+{
+ g_return_val_if_fail (EOM_IS_IMAGE (img), NULL);
+
+ return img->priv->trans_autorotate;
+}
+
/**
* eom_image_file_changed:
* @img: a #EomImage
@@ -2373,3 +2381,12 @@ eom_image_is_file_changed (EomImage *img)
return img->priv->file_is_changed;
}
+
+gboolean
+eom_image_is_jpeg (EomImage *img)
+{
+ g_return_val_if_fail (EOM_IS_IMAGE (img), FALSE);
+
+ return ((img->priv->file_type != NULL) && (g_ascii_strcasecmp (img->priv->file_type, EOM_FILE_FORMAT_JPEG) == 0));
+}
+
diff --git a/src/eom-image.h b/src/eom-image.h
index 3e503db..74abdc5 100644
--- a/src/eom-image.h
+++ b/src/eom-image.h
@@ -211,9 +211,13 @@ gboolean eom_image_start_animation (EomImage *img);
#ifdef HAVE_RSVG
gboolean eom_image_is_svg (EomImage *img);
RsvgHandle *eom_image_get_svg (EomImage *img);
-EomTransform *eom_image_get_transform (EomImage *img);
#endif
+EomTransform *eom_image_get_transform (EomImage *img);
+EomTransform *eom_image_get_autorotate_transform (EomImage *img);
+
+gboolean eom_image_is_jpeg (EomImage *img);
+
void eom_image_file_changed (EomImage *img);
gboolean eom_image_is_file_changed (EomImage *img);
diff --git a/src/eom-print.c b/src/eom-print.c
index f0329ec..54db68e 100644
--- a/src/eom-print.c
+++ b/src/eom-print.c
@@ -45,6 +45,29 @@ typedef struct {
GtkUnit unit;
} EomPrintData;
+/* art_affine_flip modified to work with cairo_matrix_t */
+static void
+_eom_cairo_matrix_flip (cairo_matrix_t *dst, const cairo_matrix_t *src, gboolean horiz, gboolean vert)
+{
+ dst->xx = horiz ? -src->xx : src->xx;
+ dst->yx = horiz ? -src->yx : src->yx;
+ dst->xy = vert ? -src->xy : src->xy;
+ dst->yy = vert ? -src->yy : src->yy;
+ dst->x0 = horiz ? -src->x0 : src->x0;
+ dst->y0 = vert ? -src->y0 : src->y0;
+}
+
+static gboolean
+_cairo_ctx_supports_jpg_metadata (cairo_t *cr)
+{
+ cairo_surface_t *surface = cairo_get_target (cr);
+ cairo_surface_type_t type = cairo_surface_get_type (surface);
+
+ /* Based on cairo-1.10 */
+ return (type == CAIRO_SURFACE_TYPE_PDF || type == CAIRO_SURFACE_TYPE_PS ||
+ type == CAIRO_SURFACE_TYPE_SVG || type == CAIRO_SURFACE_TYPE_WIN32_PRINTING);
+}
+
static void
eom_print_draw_page (GtkPrintOperation *operation,
GtkPrintContext *context,
@@ -105,8 +128,123 @@ eom_print_draw_page (GtkPrintOperation *operation,
RsvgHandle *svg = eom_image_get_svg (data->image);
rsvg_handle_render_cairo (svg, cr);
+ return;
} else
#endif
+ /* JPEGs can be attached to the cairo surface which simply embeds the JPEG file into the
+ * destination PDF skipping (PNG-)recompression. This should reduce PDF sizes enormously. */
+ if (eom_image_is_jpeg (data->image) && _cairo_ctx_supports_jpg_metadata (cr))
+ {
+ GFile *file;
+ char *img_data;
+ gsize data_len;
+ cairo_surface_t *surface = NULL;
+
+ eom_debug_message (DEBUG_PRINTING, "Attaching image to cairo surface");
+
+ file = eom_image_get_file (data->image);
+ if (g_file_load_contents (file, NULL, &img_data, &data_len, NULL, NULL))
+ {
+ EomTransform *tf = eom_image_get_transform (data->image);
+ EomTransform *auto_tf = eom_image_get_autorotate_transform (data->image);
+ cairo_matrix_t mx, mx2;
+
+ if (!tf && auto_tf) {
+ /* If only autorotation data present,
+ * make it the normal rotation. */
+ tf = auto_tf;
+ auto_tf = NULL;
+ }
+
+ /* Care must be taken with height and width values. They are not the original
+ * values but were affected by the transformation. As the surface needs to be
+ * generated using the original dimensions they might need to be flipped. */
+ if (tf) {
+ if (auto_tf) {
+ /* If we have an autorotation apply
+ * it before the others */
+ tf = eom_transform_compose (auto_tf, tf);
+ }
+
+ switch (eom_transform_get_transform_type (tf)) {
+ case EOM_TRANSFORM_ROT_90:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, height, width);
+ cairo_rotate (cr, 90.0 * (G_PI/180.0));
+ cairo_translate (cr, 0.0, -width);
+ break;
+ case EOM_TRANSFORM_ROT_180:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, width, height);
+ cairo_rotate (cr, 180.0 * (G_PI/180.0));
+ cairo_translate (cr, -width, -height);
+ break;
+ case EOM_TRANSFORM_ROT_270:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, height, width);
+ cairo_rotate (cr, 270.0 * (G_PI/180.0));
+ cairo_translate (cr, -height, 0.0);
+ break;
+ case EOM_TRANSFORM_FLIP_HORIZONTAL:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, width, height);
+ cairo_matrix_init_identity (&mx);
+ _eom_cairo_matrix_flip (&mx2, &mx, TRUE, FALSE);
+ cairo_transform (cr, &mx2);
+ cairo_translate (cr, -width, 0.0);
+ break;
+ case EOM_TRANSFORM_FLIP_VERTICAL:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, width, height);
+ cairo_matrix_init_identity (&mx);
+ _eom_cairo_matrix_flip (&mx2, &mx, FALSE, TRUE);
+ cairo_transform (cr, &mx2);
+ cairo_translate (cr, 0.0, -height);
+ break;
+ case EOM_TRANSFORM_TRANSPOSE:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, height, width);
+ cairo_matrix_init_rotate (&mx, 90.0 * (G_PI/180.0));
+ cairo_matrix_init_identity (&mx2);
+ _eom_cairo_matrix_flip (&mx2, &mx2, TRUE, FALSE);
+ cairo_matrix_multiply (&mx2, &mx, &mx2);
+ cairo_transform (cr, &mx2);
+ break;
+ case EOM_TRANSFORM_TRANSVERSE:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, height, width);
+ cairo_matrix_init_rotate (&mx, 90.0 * (G_PI/180.0));
+ cairo_matrix_init_identity (&mx2);
+ _eom_cairo_matrix_flip (&mx2, &mx2, FALSE, TRUE);
+ cairo_matrix_multiply (&mx2, &mx, &mx2);
+ cairo_transform (cr, &mx2);
+ cairo_translate (cr, -height , -width);
+ break;
+ case EOM_TRANSFORM_NONE:
+ default:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_RGB24, width, height);
+ break;
+ }
+ }
+
+ if (!surface)
+ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+ width, height);
+ cairo_surface_set_mime_data (surface,
+ CAIRO_MIME_TYPE_JPEG,
+ (unsigned char*)img_data, data_len,
+ g_free, img_data);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_surface_destroy (surface);
+ g_object_unref (file);
+ return;
+ }
+ g_object_unref (file);
+
+ }
+
{
GdkPixbuf *pixbuf;