1 /* flip.c - image flip
2  *
3  * Raster graphics library
4  *
5  * Copyright (c) 2014 Window Maker Team
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
20  *  MA 02110-1301, USA.
21  */
22 
23 #include "config.h"
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include <X11/Xlib.h>
30 
31 #include "wraster.h"
32 #include "rotate.h"
33 
34 
35 static RImage *r_flip_vertically(RImage *source);
36 static RImage *r_flip_horizontally(RImage *source);
37 
38 /* Flip an image in the direction(s) specified */
RFlipImage(RImage * source,int mode)39 RImage *RFlipImage(RImage *source, int mode)
40 {
41 	/* Security */
42 	if (source == NULL)
43 		return NULL;
44 
45 	switch (mode & (RVerticalFlip | RHorizontalFlip)) {
46 	case RHorizontalFlip:
47 		return r_flip_horizontally(source);
48 
49 	case RVerticalFlip:
50 		return r_flip_vertically(source);
51 
52 	case RHorizontalFlip | RVerticalFlip:
53 		return wraster_rotate_image_180(source);
54 
55 	default:
56 		return RRetainImage(source);
57 	}
58 }
59 
r_flip_vertically(RImage * source)60 RImage *r_flip_vertically(RImage *source)
61 {
62 	RImage *target;
63 	int nwidth, nheight;
64 	int x, y;
65 
66 	nwidth = source->width;
67 	nheight = source->height;
68 
69 	target = RCreateImage(nwidth, nheight, (source->format != RRGBFormat));
70 	if (!target)
71 		return NULL;
72 
73 	if (source->format == RRGBFormat) {
74 		unsigned char *optr, *nptr;
75 
76 		optr = source->data;
77 		nptr = target->data + 3 * (nwidth * nheight - nwidth);
78 
79 		for (y = 0; y < nheight; y++) {
80 			for (x = 0; x < nwidth; x++) {
81 				nptr[0] = optr[0];
82 				nptr[1] = optr[1];
83 				nptr[2] = optr[2];
84 
85 				optr += 3;
86 				nptr += 3;
87 			}
88 			nptr -= (nwidth * 3) * 2;
89 		}
90 	} else {
91 		unsigned char *optr, *nptr;
92 
93 		optr = source->data;
94 		nptr = target->data + 4 * (nwidth * nheight - nwidth);
95 
96 		for (y = 0; y < nheight; y++) {
97 			for (x = 0; x < nwidth; x++) {
98 				nptr[0] = optr[0];
99 				nptr[1] = optr[1];
100 				nptr[2] = optr[2];
101 				nptr[3] = optr[3];
102 
103 				optr += 4;
104 				nptr += 4;
105 			}
106 			nptr -= (nwidth * 4) * 2;
107 		}
108 	}
109 	return target;
110 }
111 
r_flip_horizontally(RImage * source)112 RImage *r_flip_horizontally(RImage *source)
113 {
114 	RImage *target;
115 	int nwidth, nheight;
116 	int x, y;
117 
118 	nwidth = source->width;
119 	nheight = source->height;
120 
121 	target = RCreateImage(nwidth, nheight, (source->format != RRGBFormat));
122 	if (!target)
123 		return NULL;
124 
125 	if (source->format == RRGBFormat) {
126 		unsigned char *optr, *nptr;
127 
128 		optr = source->data;
129 		nptr = target->data + 3 * (nwidth - 1);
130 
131 		for (y = nheight; y; y--) {
132 			for (x = 0; x < nwidth; x++) {
133 				nptr[0] = optr[0];
134 				nptr[1] = optr[1];
135 				nptr[2] = optr[2];
136 
137 				optr += 3;
138 				nptr -= 3;
139 			}
140 			nptr += (nwidth * 3) * 2;
141 		}
142 	} else {
143 		unsigned char *optr, *nptr;
144 
145 		optr = source->data;
146 		nptr = target->data + 4 * (nwidth - 1);
147 
148 		for (y = nheight; y; y--) {
149 			for (x = 0; x < nwidth; x++) {
150 				nptr[0] = optr[0];
151 				nptr[1] = optr[1];
152 				nptr[2] = optr[2];
153 				nptr[3] = optr[3];
154 
155 				optr += 4;
156 				nptr -= 4;
157 			}
158 			nptr += (nwidth * 4) * 2;
159 		}
160 	}
161 	return target;
162 }
163