1 /*
2  * This file is part of the Scale2x project.
3  *
4  * Copyright (C) 2003, 2004 Andrea Mazzoleni
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 /*
22  * This file contains an example implementation of the Scale effect
23  * applyed to a generic bitmap.
24  *
25  * You can find an high level description of the effect at :
26  *
27  * http://scale2x.sourceforge.net/
28  *
29  * Alternatively at the previous license terms, you are allowed to use this
30  * code in your program with these conditions:
31  * - the program is not used in commercial activities.
32  * - the whole source code of the program is released with the binary.
33  * - derivative works of the program are allowed.
34  */
35 
36 #if HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 
40 #include "scale2x.h"
41 #include "scale3x.h"
42 
43 #if HAVE_ALLOCA_H
44 #include <alloca.h>
45 #endif
46 
47 #include <assert.h>
48 #include <stdlib.h>
49 
50 #define SSDST(bits, num) (scale2x_uint##bits *)dst##num
51 #define SSSRC(bits, num) (const scale2x_uint##bits *)src##num
52 
53 /**
54  * Apply the Scale2x effect on a group of rows. Used internally.
55  */
stage_scale2x(void * dst0,void * dst1,const void * src0,const void * src1,const void * src2,unsigned pixel,unsigned pixel_per_row)56 static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
57 {
58 	switch (pixel) {
59 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
60 		case 1 : scale2x_8_mmx(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
61 		case 2 : scale2x_16_mmx(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
62 		case 4 : scale2x_32_mmx(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
63 #else
64 		case 1 : scale2x_8_def(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
65 		case 2 : scale2x_16_def(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
66 		case 4 : scale2x_32_def(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
67 #endif
68 	}
69 }
70 
71 /**
72  * Apply the Scale2x3 effect on a group of rows. Used internally.
73  */
stage_scale2x3(void * dst0,void * dst1,void * dst2,const void * src0,const void * src1,const void * src2,unsigned pixel,unsigned pixel_per_row)74 static inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
75 {
76 	switch (pixel) {
77 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
78 		case 1 : scale2x3_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
79 		case 2 : scale2x3_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
80 		case 4 : scale2x3_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
81 #else
82 		case 1 : scale2x3_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
83 		case 2 : scale2x3_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
84 		case 4 : scale2x3_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
85 #endif
86 	}
87 }
88 
89 /**
90  * Apply the Scale2x4 effect on a group of rows. Used internally.
91  */
stage_scale2x4(void * dst0,void * dst1,void * dst2,void * dst3,const void * src0,const void * src1,const void * src2,unsigned pixel,unsigned pixel_per_row)92 static inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
93 {
94 	switch (pixel) {
95 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
96 		case 1 : scale2x4_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
97 		case 2 : scale2x4_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
98 		case 4 : scale2x4_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
99 #else
100 		case 1 : scale2x4_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
101 		case 2 : scale2x4_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
102 		case 4 : scale2x4_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
103 #endif
104 	}
105 }
106 
107 /**
108  * Apply the Scale3x effect on a group of rows. Used internally.
109  */
stage_scale3x(void * dst0,void * dst1,void * dst2,const void * src0,const void * src1,const void * src2,unsigned pixel,unsigned pixel_per_row)110 static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
111 {
112 	switch (pixel) {
113 		case 1 : scale3x_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
114 		case 2 : scale3x_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
115 		case 4 : scale3x_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
116 	}
117 }
118 
119 /**
120  * Apply the Scale4x effect on a group of rows. Used internally.
121  */
stage_scale4x(void * dst0,void * dst1,void * dst2,void * dst3,const void * src0,const void * src1,const void * src2,const void * src3,unsigned pixel,unsigned pixel_per_row)122 static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)
123 {
124 	stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
125 	stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
126 }
127 
128 #define SCDST(i) (dst+(i)*dst_slice)
129 #define SCSRC(i) (src+(i)*src_slice)
130 #define SCMID(i) (mid[(i)])
131 
132 /**
133  * Apply the Scale2x effect on a bitmap.
134  * The destination bitmap is filled with the scaled version of the source bitmap.
135  * The source bitmap isn't modified.
136  * The destination bitmap must be manually allocated before calling the function,
137  * note that the resulting size is exactly 2x2 times the size of the source bitmap.
138  * \param void_dst Pointer at the first pixel of the destination bitmap.
139  * \param dst_slice Size in bytes of a destination bitmap row.
140  * \param void_src Pointer at the first pixel of the source bitmap.
141  * \param src_slice Size in bytes of a source bitmap row.
142  * \param pixel Bytes per pixel of the source and destination bitmap.
143  * \param width Horizontal size in pixels of the source bitmap.
144  * \param height Vertical size in pixels of the source bitmap.
145  */
scale2x(void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)146 static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
147 {
148 	unsigned char* dst = (unsigned char*)void_dst;
149 	const unsigned char* src = (const unsigned char*)void_src;
150 	unsigned count;
151 
152 	assert(height >= 2);
153 
154 	count = height;
155 
156 	stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
157 
158 	dst = SCDST(2);
159 
160 	count -= 2;
161 	while (count) {
162 		stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
163 
164 		dst = SCDST(2);
165 		src = SCSRC(1);
166 
167 		--count;
168 	}
169 
170 	stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
171 
172 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
173 	scale2x_mmx_emms();
174 #endif
175 }
176 
177 /**
178  * Apply the Scale2x3 effect on a bitmap.
179  * The destination bitmap is filled with the scaled version of the source bitmap.
180  * The source bitmap isn't modified.
181  * The destination bitmap must be manually allocated before calling the function,
182  * note that the resulting size is exactly 2x3 times the size of the source bitmap.
183  * \param void_dst Pointer at the first pixel of the destination bitmap.
184  * \param dst_slice Size in bytes of a destination bitmap row.
185  * \param void_src Pointer at the first pixel of the source bitmap.
186  * \param src_slice Size in bytes of a source bitmap row.
187  * \param pixel Bytes per pixel of the source and destination bitmap.
188  * \param width Horizontal size in pixels of the source bitmap.
189  * \param height Vertical size in pixels of the source bitmap.
190  */
scale2x3(void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)191 static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
192 {
193 	unsigned char* dst = (unsigned char*)void_dst;
194 	const unsigned char* src = (const unsigned char*)void_src;
195 	unsigned count;
196 
197 	assert(height >= 2);
198 
199 	count = height;
200 
201 	stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
202 
203 	dst = SCDST(3);
204 
205 	count -= 2;
206 	while (count) {
207 		stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
208 
209 		dst = SCDST(3);
210 		src = SCSRC(1);
211 
212 		--count;
213 	}
214 
215 	stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
216 
217 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
218 	scale2x_mmx_emms();
219 #endif
220 }
221 
222 /**
223  * Apply the Scale2x4 effect on a bitmap.
224  * The destination bitmap is filled with the scaled version of the source bitmap.
225  * The source bitmap isn't modified.
226  * The destination bitmap must be manually allocated before calling the function,
227  * note that the resulting size is exactly 2x4 times the size of the source bitmap.
228  * \param void_dst Pointer at the first pixel of the destination bitmap.
229  * \param dst_slice Size in bytes of a destination bitmap row.
230  * \param void_src Pointer at the first pixel of the source bitmap.
231  * \param src_slice Size in bytes of a source bitmap row.
232  * \param pixel Bytes per pixel of the source and destination bitmap.
233  * \param width Horizontal size in pixels of the source bitmap.
234  * \param height Vertical size in pixels of the source bitmap.
235  */
scale2x4(void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)236 static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
237 {
238 	unsigned char* dst = (unsigned char*)void_dst;
239 	const unsigned char* src = (const unsigned char*)void_src;
240 	unsigned count;
241 
242 	assert(height >= 2);
243 
244 	count = height;
245 
246 	stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
247 
248 	dst = SCDST(4);
249 
250 	count -= 2;
251 	while (count) {
252 		stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
253 
254 		dst = SCDST(4);
255 		src = SCSRC(1);
256 
257 		--count;
258 	}
259 
260 	stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
261 
262 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
263 	scale2x_mmx_emms();
264 #endif
265 }
266 
267 /**
268  * Apply the Scale3x effect on a bitmap.
269  * The destination bitmap is filled with the scaled version of the source bitmap.
270  * The source bitmap isn't modified.
271  * The destination bitmap must be manually allocated before calling the function,
272  * note that the resulting size is exactly 3x3 times the size of the source bitmap.
273  * \param void_dst Pointer at the first pixel of the destination bitmap.
274  * \param dst_slice Size in bytes of a destination bitmap row.
275  * \param void_src Pointer at the first pixel of the source bitmap.
276  * \param src_slice Size in bytes of a source bitmap row.
277  * \param pixel Bytes per pixel of the source and destination bitmap.
278  * \param width Horizontal size in pixels of the source bitmap.
279  * \param height Vertical size in pixels of the source bitmap.
280  */
scale3x(void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)281 static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
282 {
283 	unsigned char* dst = (unsigned char*)void_dst;
284 	const unsigned char* src = (const unsigned char*)void_src;
285 	unsigned count;
286 
287 	assert(height >= 2);
288 
289 	count = height;
290 
291 	stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
292 
293 	dst = SCDST(3);
294 
295 	count -= 2;
296 	while (count) {
297 		stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
298 
299 		dst = SCDST(3);
300 		src = SCSRC(1);
301 
302 		--count;
303 	}
304 
305 	stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
306 }
307 
308 /**
309  * Apply the Scale4x effect on a bitmap.
310  * The destination bitmap is filled with the scaled version of the source bitmap.
311  * The source bitmap isn't modified.
312  * The destination bitmap must be manually allocated before calling the function,
313  * note that the resulting size is exactly 4x4 times the size of the source bitmap.
314  * \note This function requires also a small buffer bitmap used internally to store
315  * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
316  * and a vertical size of 6 rows. The memory of this buffer must not be allocated
317  * in video memory because it's also read and not only written. Generally
318  * a heap (malloc) or a stack (alloca) buffer is the best choice.
319  * \param void_dst Pointer at the first pixel of the destination bitmap.
320  * \param dst_slice Size in bytes of a destination bitmap row.
321  * \param void_mid Pointer at the first pixel of the buffer bitmap.
322  * \param mid_slice Size in bytes of a buffer bitmap row.
323  * \param void_src Pointer at the first pixel of the source bitmap.
324  * \param src_slice Size in bytes of a source bitmap row.
325  * \param pixel Bytes per pixel of the source and destination bitmap.
326  * \param width Horizontal size in pixels of the source bitmap.
327  * \param height Vertical size in pixels of the source bitmap.
328  */
scale4x_buf(void * void_dst,unsigned dst_slice,void * void_mid,unsigned mid_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)329 static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
330 {
331 	unsigned char* dst = (unsigned char*)void_dst;
332 	const unsigned char* src = (const unsigned char*)void_src;
333 	unsigned count;
334 	unsigned char* mid[6];
335 
336 	assert(height >= 4);
337 
338 	count = height;
339 
340 	/* set the 6 buffer pointers */
341 	mid[0] = (unsigned char*)void_mid;
342 	mid[1] = mid[0] + mid_slice;
343 	mid[2] = mid[1] + mid_slice;
344 	mid[3] = mid[2] + mid_slice;
345 	mid[4] = mid[3] + mid_slice;
346 	mid[5] = mid[4] + mid_slice;
347 
348 	stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
349 	stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
350 	stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
351 	stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
352 
353 	dst = SCDST(4);
354 
355 	stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
356 
357 	dst = SCDST(4);
358 
359 	count -= 4;
360 	while (count) {
361 		unsigned char* tmp;
362 
363 		stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
364 		stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
365 
366 		dst = SCDST(4);
367 		src = SCSRC(1);
368 
369 		tmp = SCMID(0); /* shift by 2 position */
370 		SCMID(0) = SCMID(2);
371 		SCMID(2) = SCMID(4);
372 		SCMID(4) = tmp;
373 		tmp = SCMID(1);
374 		SCMID(1) = SCMID(3);
375 		SCMID(3) = SCMID(5);
376 		SCMID(5) = tmp;
377 
378 		--count;
379 	}
380 
381 	stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
382 	stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
383 
384 	dst = SCDST(4);
385 
386 	stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
387 
388 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
389 	scale2x_mmx_emms();
390 #endif
391 }
392 
393 /**
394  * Apply the Scale4x effect on a bitmap.
395  * The destination bitmap is filled with the scaled version of the source bitmap.
396  * The source bitmap isn't modified.
397  * The destination bitmap must be manually allocated before calling the function,
398  * note that the resulting size is exactly 4x4 times the size of the source bitmap.
399  * \note This function operates like ::scale4x_buf() but the intermediate buffer is
400  * automatically allocated in the stack.
401  * \param void_dst Pointer at the first pixel of the destination bitmap.
402  * \param dst_slice Size in bytes of a destination bitmap row.
403  * \param void_src Pointer at the first pixel of the source bitmap.
404  * \param src_slice Size in bytes of a source bitmap row.
405  * \param pixel Bytes per pixel of the source and destination bitmap.
406  * \param width Horizontal size in pixels of the source bitmap.
407  * \param height Vertical size in pixels of the source bitmap.
408  */
scale4x(void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)409 static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
410 {
411 	unsigned mid_slice;
412 	void* mid;
413 
414 	mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
415 
416 	mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
417 
418 #if HAVE_ALLOCA
419 	mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
420 
421 	assert(mid != 0); /* alloca should never fails */
422 #else
423 	mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
424 
425 	if (!mid)
426 		return;
427 #endif
428 
429 	scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
430 
431 #if !HAVE_ALLOCA
432 	free(mid);
433 #endif
434 }
435 
436 /**
437  * Check if the scale implementation is applicable at the given arguments.
438  * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.
439  * \param pixel Bytes per pixel of the source and destination bitmap.
440  * \param width Horizontal size in pixels of the source bitmap.
441  * \param height Vertical size in pixels of the source bitmap.
442  * \return
443  *   - -1 on precondition violated.
444  *   - 0 on success.
445  */
scale_precondition(unsigned scale,unsigned pixel,unsigned width,unsigned height)446 int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
447 {
448 	if (pixel != 1 && pixel != 2 && pixel != 4)
449 		return -1;
450 
451 	switch (scale) {
452 	case 202 :
453 	case 203 :
454 	case 204 :
455 	case 2 :
456 	case 303 :
457 	case 3 :
458 		if (height < 2)
459 			return -1;
460 		break;
461 	case 404 :
462 	case 4 :
463 		if (height < 4)
464 			return -1;
465 		break;
466 	default:
467 		return -1;
468 	}
469 
470 	if (width < 2)
471 		return -1;
472 
473 	return 0;
474 }
475 
476 /**
477  * Apply the Scale effect on a bitmap.
478  * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
479  * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.
480  * \param void_dst Pointer at the first pixel of the destination bitmap.
481  * \param dst_slice Size in bytes of a destination bitmap row.
482  * \param void_src Pointer at the first pixel of the source bitmap.
483  * \param src_slice Size in bytes of a source bitmap row.
484  * \param pixel Bytes per pixel of the source and destination bitmap.
485  * \param width Horizontal size in pixels of the source bitmap.
486  * \param height Vertical size in pixels of the source bitmap.
487  */
scale(unsigned scale,void * void_dst,unsigned dst_slice,const void * void_src,unsigned src_slice,unsigned pixel,unsigned width,unsigned height)488 void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
489 {
490 	switch (scale) {
491 	case 202 :
492 	case 2 :
493 		scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
494 		break;
495 	case 203 :
496 		scale2x3(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
497 		break;
498 	case 204 :
499 		scale2x4(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
500 		break;
501 	case 303 :
502 	case 3 :
503 		scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
504 		break;
505 	case 404 :
506 	case 4 :
507 		scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
508 		break;
509 	}
510 }
511 
512