Blob Blame Raw
From adb610d22582f0598f6e5c699c08e7495767de28 Mon Sep 17 00:00:00 2001
From: Marek Kasik <mkasik@redhat.com>
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