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