From adb610d22582f0598f6e5c699c08e7495767de28 Mon Sep 17 00:00:00 2001 From: Marek Kasik Date: Wed, 7 Jan 2015 18:35:16 +0100 Subject: [PATCH] Rotate documents correctly Rotate result of rendering given by ghostscript. https://bugs.freedesktop.org/show_bug.cgi?id=76450 --- libspectre/spectre-device.c | 97 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/libspectre/spectre-device.c b/libspectre/spectre-device.c index a527d86..537f337 100644 --- a/libspectre/spectre-device.c +++ b/libspectre/spectre-device.c @@ -99,7 +99,7 @@ spectre_sync (void *handle, void *device) } static int -spectre_page (void *handle, void * device, int copies, int flush) +spectre_page (void *handle, void *device, int copies, int flush) { SpectreDevice *sd; @@ -162,6 +162,33 @@ spectre_device_new (struct document *doc) return device; } +#define PIXEL_SIZE 4 +#define ROW_ALIGN 32 + +static void +swap_pixels (unsigned char *data, + size_t pixel_a_start, + size_t pixel_b_start) +{ + unsigned char value; + size_t i; + + for (i = 0; i < PIXEL_SIZE; i++) { + value = data[pixel_a_start + i]; + data[pixel_a_start + i] = data[pixel_b_start + i]; + data[pixel_b_start + i] = value; + } +} + +static void +copy_pixel (unsigned char *dest, + unsigned char *src, + size_t dest_pixel_start, + size_t src_pixel_start) +{ + memcpy (dest + dest_pixel_start, src + src_pixel_start, PIXEL_SIZE); +} + SpectreStatus spectre_device_render (SpectreDevice *device, unsigned int page, @@ -185,6 +212,10 @@ spectre_device_render (SpectreDevice *device, char *dsp_format, *dsp_handle; char *width_points = NULL; char *height_points = NULL; + unsigned char *user_image; + size_t stride, padding; + int i, j; + gs = spectre_gs_new (); if (!gs) @@ -277,7 +308,7 @@ spectre_device_render (SpectreDevice *device, } set = _spectre_strdup_printf ("<< /Orientation %d >> setpagedevice .locksafe", - rc->orientation); + SPECTRE_ORIENTATION_PORTRAIT); if (!spectre_gs_send_string (gs, set)) { free (set); spectre_gs_free (gs); @@ -293,6 +324,68 @@ spectre_device_render (SpectreDevice *device, *page_data = device->user_image; *row_length = device->row_length; + switch (rc->orientation) + { + default: + case SPECTRE_ORIENTATION_PORTRAIT: + break; + case SPECTRE_ORIENTATION_REVERSE_PORTRAIT: + for (j = 0; j < height / 2; ++j) { + for (i = 0; i < width; ++i) { + swap_pixels (device->user_image, + device->row_length * j + PIXEL_SIZE * i, + device->row_length * (height - 1 - j) + PIXEL_SIZE * (width - 1 - i)); + } + } + if (height % 2 == 1) { + for (i = 0; i < width / 2; ++i) { + swap_pixels (device->user_image, + device->row_length * (height / 2) + PIXEL_SIZE * i, + device->row_length * (height - 1 - height / 2) + PIXEL_SIZE * (width - 1 - i)); + } + } + break; + case SPECTRE_ORIENTATION_LANDSCAPE: + case SPECTRE_ORIENTATION_REVERSE_LANDSCAPE: + if (height % ROW_ALIGN > 0) { + padding = (ROW_ALIGN - height % ROW_ALIGN) * PIXEL_SIZE; + stride = height * PIXEL_SIZE + padding; + user_image = malloc (width * stride); + + for (j = 0; j < width; ++j) + memset (user_image + j * stride + stride - padding, 0, padding); + } + else { + stride = height * PIXEL_SIZE; + user_image = malloc (width * stride); + } + + if (rc->orientation == SPECTRE_ORIENTATION_LANDSCAPE) { + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + copy_pixel (user_image, + device->user_image, + stride * i + PIXEL_SIZE * (height - 1 - j), + device->row_length * j + PIXEL_SIZE * i); + } + } + } else { + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + copy_pixel (user_image, + device->user_image, + stride * (width - 1 - i) + PIXEL_SIZE * j, + device->row_length * j + PIXEL_SIZE * i); + } + } + } + + free (device->user_image); + *page_data = user_image; + *row_length = stride; + break; + } + spectre_gs_free (gs); return SPECTRE_STATUS_SUCCESS; -- 2.1.0