1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#include "SDL_video.h"
25#include "SDL_blit.h"
26
27/* Functions to blit from bitmaps to other surfaces */
28
29static void BlitBto1(SDL_BlitInfo *info)
30{
31	int c;
32	int width, height;
33	Uint8 *src, *map, *dst;
34	int srcskip, dstskip;
35
36	/* Set up some basic variables */
37	width = info->d_width;
38	height = info->d_height;
39	src = info->s_pixels;
40	srcskip = info->s_skip;
41	dst = info->d_pixels;
42	dstskip = info->d_skip;
43	map = info->table;
44	srcskip += width-(width+7)/8;
45
46	if ( map ) {
47		while ( height-- ) {
48		        Uint8 byte = 0, bit;
49	    		for ( c=0; c<width; ++c ) {
50				if ( (c&7) == 0 ) {
51					byte = *src++;
52				}
53				bit = (byte&0x80)>>7;
54				if ( 1 ) {
55				  *dst = map[bit];
56				}
57				dst++;
58				byte <<= 1;
59			}
60			src += srcskip;
61			dst += dstskip;
62		}
63	} else {
64		while ( height-- ) {
65		        Uint8 byte = 0, bit;
66	    		for ( c=0; c<width; ++c ) {
67				if ( (c&7) == 0 ) {
68					byte = *src++;
69				}
70				bit = (byte&0x80)>>7;
71				if ( 1 ) {
72				  *dst = bit;
73				}
74				dst++;
75				byte <<= 1;
76			}
77			src += srcskip;
78			dst += dstskip;
79		}
80	}
81}
82static void BlitBto2(SDL_BlitInfo *info)
83{
84	int c;
85	int width, height;
86	Uint8 *src;
87	Uint16 *map, *dst;
88	int srcskip, dstskip;
89
90	/* Set up some basic variables */
91	width = info->d_width;
92	height = info->d_height;
93	src = info->s_pixels;
94	srcskip = info->s_skip;
95	dst = (Uint16 *)info->d_pixels;
96	dstskip = info->d_skip/2;
97	map = (Uint16 *)info->table;
98	srcskip += width-(width+7)/8;
99
100	while ( height-- ) {
101	        Uint8 byte = 0, bit;
102	    	for ( c=0; c<width; ++c ) {
103			if ( (c&7) == 0 ) {
104				byte = *src++;
105			}
106			bit = (byte&0x80)>>7;
107			if ( 1 ) {
108				*dst = map[bit];
109			}
110			byte <<= 1;
111			dst++;
112		}
113		src += srcskip;
114		dst += dstskip;
115	}
116}
117static void BlitBto3(SDL_BlitInfo *info)
118{
119	int c, o;
120	int width, height;
121	Uint8 *src, *map, *dst;
122	int srcskip, dstskip;
123
124	/* Set up some basic variables */
125	width = info->d_width;
126	height = info->d_height;
127	src = info->s_pixels;
128	srcskip = info->s_skip;
129	dst = info->d_pixels;
130	dstskip = info->d_skip;
131	map = info->table;
132	srcskip += width-(width+7)/8;
133
134	while ( height-- ) {
135	        Uint8 byte = 0, bit;
136	    	for ( c=0; c<width; ++c ) {
137			if ( (c&7) == 0 ) {
138				byte = *src++;
139			}
140			bit = (byte&0x80)>>7;
141			if ( 1 ) {
142				o = bit * 4;
143				dst[0] = map[o++];
144				dst[1] = map[o++];
145				dst[2] = map[o++];
146			}
147			byte <<= 1;
148			dst += 3;
149		}
150		src += srcskip;
151		dst += dstskip;
152	}
153}
154static void BlitBto4(SDL_BlitInfo *info)
155{
156	int width, height;
157	Uint8 *src;
158	Uint32 *map, *dst;
159	int srcskip, dstskip;
160	int c;
161
162	/* Set up some basic variables */
163	width = info->d_width;
164	height = info->d_height;
165	src = info->s_pixels;
166	srcskip = info->s_skip;
167	dst = (Uint32 *)info->d_pixels;
168	dstskip = info->d_skip/4;
169	map = (Uint32 *)info->table;
170	srcskip += width-(width+7)/8;
171
172	while ( height-- ) {
173	        Uint8 byte = 0, bit;
174	    	for ( c=0; c<width; ++c ) {
175			if ( (c&7) == 0 ) {
176				byte = *src++;
177			}
178			bit = (byte&0x80)>>7;
179			if ( 1 ) {
180				*dst = map[bit];
181			}
182			byte <<= 1;
183			dst++;
184		}
185		src += srcskip;
186		dst += dstskip;
187	}
188}
189
190static void BlitBto1Key(SDL_BlitInfo *info)
191{
192        int width = info->d_width;
193	int height = info->d_height;
194	Uint8 *src = info->s_pixels;
195	Uint8 *dst = info->d_pixels;
196	int srcskip = info->s_skip;
197	int dstskip = info->d_skip;
198	Uint32 ckey = info->src->colorkey;
199	Uint8 *palmap = info->table;
200	int c;
201
202	/* Set up some basic variables */
203	srcskip += width-(width+7)/8;
204
205	if ( palmap ) {
206		while ( height-- ) {
207		        Uint8  byte = 0, bit;
208	    		for ( c=0; c<width; ++c ) {
209				if ( (c&7) == 0 ) {
210					byte = *src++;
211				}
212				bit = (byte&0x80)>>7;
213				if ( bit != ckey ) {
214				  *dst = palmap[bit];
215				}
216				dst++;
217				byte <<= 1;
218			}
219			src += srcskip;
220			dst += dstskip;
221		}
222	} else {
223		while ( height-- ) {
224		        Uint8  byte = 0, bit;
225	    		for ( c=0; c<width; ++c ) {
226				if ( (c&7) == 0 ) {
227					byte = *src++;
228				}
229				bit = (byte&0x80)>>7;
230				if ( bit != ckey ) {
231				  *dst = bit;
232				}
233				dst++;
234				byte <<= 1;
235			}
236			src += srcskip;
237			dst += dstskip;
238		}
239	}
240}
241
242static void BlitBto2Key(SDL_BlitInfo *info)
243{
244        int width = info->d_width;
245	int height = info->d_height;
246	Uint8 *src = info->s_pixels;
247	Uint16 *dstp = (Uint16 *)info->d_pixels;
248	int srcskip = info->s_skip;
249	int dstskip = info->d_skip;
250	Uint32 ckey = info->src->colorkey;
251	Uint8 *palmap = info->table;
252	int c;
253
254	/* Set up some basic variables */
255	srcskip += width-(width+7)/8;
256	dstskip /= 2;
257
258	while ( height-- ) {
259	        Uint8 byte = 0, bit;
260	    	for ( c=0; c<width; ++c ) {
261			if ( (c&7) == 0 ) {
262				byte = *src++;
263			}
264			bit = (byte&0x80)>>7;
265			if ( bit != ckey ) {
266				*dstp=((Uint16 *)palmap)[bit];
267			}
268			byte <<= 1;
269			dstp++;
270		}
271		src += srcskip;
272		dstp += dstskip;
273	}
274}
275
276static void BlitBto3Key(SDL_BlitInfo *info)
277{
278        int width = info->d_width;
279	int height = info->d_height;
280	Uint8 *src = info->s_pixels;
281	Uint8 *dst = info->d_pixels;
282	int srcskip = info->s_skip;
283	int dstskip = info->d_skip;
284	Uint32 ckey = info->src->colorkey;
285	Uint8 *palmap = info->table;
286	int c;
287
288	/* Set up some basic variables */
289	srcskip += width-(width+7)/8;
290
291	while ( height-- ) {
292	        Uint8  byte = 0, bit;
293	    	for ( c=0; c<width; ++c ) {
294			if ( (c&7) == 0 ) {
295				byte = *src++;
296			}
297			bit = (byte&0x80)>>7;
298			if ( bit != ckey ) {
299				SDL_memcpy(dst, &palmap[bit*4], 3);
300			}
301			byte <<= 1;
302			dst += 3;
303		}
304		src += srcskip;
305		dst += dstskip;
306	}
307}
308
309static void BlitBto4Key(SDL_BlitInfo *info)
310{
311        int width = info->d_width;
312	int height = info->d_height;
313	Uint8 *src = info->s_pixels;
314	Uint32 *dstp = (Uint32 *)info->d_pixels;
315	int srcskip = info->s_skip;
316	int dstskip = info->d_skip;
317	Uint32 ckey = info->src->colorkey;
318	Uint8 *palmap = info->table;
319	int c;
320
321	/* Set up some basic variables */
322	srcskip += width-(width+7)/8;
323	dstskip /= 4;
324
325	while ( height-- ) {
326	        Uint8 byte = 0, bit;
327	    	for ( c=0; c<width; ++c ) {
328			if ( (c&7) == 0 ) {
329				byte = *src++;
330			}
331			bit = (byte&0x80)>>7;
332			if ( bit != ckey ) {
333				*dstp=((Uint32 *)palmap)[bit];
334			}
335			byte <<= 1;
336			dstp++;
337		}
338		src += srcskip;
339		dstp += dstskip;
340	}
341}
342
343static void BlitBtoNAlpha(SDL_BlitInfo *info)
344{
345        int width = info->d_width;
346	int height = info->d_height;
347	Uint8 *src = info->s_pixels;
348	Uint8 *dst = info->d_pixels;
349	int srcskip = info->s_skip;
350	int dstskip = info->d_skip;
351	const SDL_Color *srcpal	= info->src->palette->colors;
352	SDL_PixelFormat *dstfmt = info->dst;
353	int  dstbpp;
354	int c;
355	const int A = info->src->alpha;
356
357	/* Set up some basic variables */
358	dstbpp = dstfmt->BytesPerPixel;
359	srcskip += width-(width+7)/8;
360
361	while ( height-- ) {
362	        Uint8 byte = 0, bit;
363	    	for ( c=0; c<width; ++c ) {
364			if ( (c&7) == 0 ) {
365				byte = *src++;
366			}
367			bit = (byte&0x80)>>7;
368			if ( 1 ) {
369			        Uint32 pixel;
370			        unsigned sR, sG, sB;
371				unsigned dR, dG, dB;
372				sR = srcpal[bit].r;
373				sG = srcpal[bit].g;
374				sB = srcpal[bit].b;
375				DISEMBLE_RGB(dst, dstbpp, dstfmt,
376							pixel, dR, dG, dB);
377				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
378			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
379			}
380			byte <<= 1;
381			dst += dstbpp;
382		}
383		src += srcskip;
384		dst += dstskip;
385	}
386}
387
388static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
389{
390        int width = info->d_width;
391	int height = info->d_height;
392	Uint8 *src = info->s_pixels;
393	Uint8 *dst = info->d_pixels;
394	int srcskip = info->s_skip;
395	int dstskip = info->d_skip;
396	SDL_PixelFormat *srcfmt = info->src;
397	SDL_PixelFormat *dstfmt = info->dst;
398	const SDL_Color *srcpal	= srcfmt->palette->colors;
399	int dstbpp;
400	int c;
401	const int A = srcfmt->alpha;
402	Uint32 ckey = srcfmt->colorkey;
403
404	/* Set up some basic variables */
405	dstbpp = dstfmt->BytesPerPixel;
406	srcskip += width-(width+7)/8;
407
408	while ( height-- ) {
409	        Uint8  byte = 0, bit;
410	    	for ( c=0; c<width; ++c ) {
411			if ( (c&7) == 0 ) {
412				byte = *src++;
413			}
414			bit = (byte&0x80)>>7;
415			if ( bit != ckey ) {
416			        int sR, sG, sB;
417				int dR, dG, dB;
418				Uint32 pixel;
419				sR = srcpal[bit].r;
420				sG = srcpal[bit].g;
421				sB = srcpal[bit].b;
422				DISEMBLE_RGB(dst, dstbpp, dstfmt,
423							pixel, dR, dG, dB);
424				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
425			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
426			}
427			byte <<= 1;
428			dst += dstbpp;
429		}
430		src += srcskip;
431		dst += dstskip;
432	}
433}
434
435static SDL_loblit bitmap_blit[] = {
436	NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4
437};
438
439static SDL_loblit colorkey_blit[] = {
440    NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key
441};
442
443SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index)
444{
445	int which;
446
447	if ( surface->format->BitsPerPixel != 1 ) {
448		/* We don't support sub 8-bit packed pixel modes */
449		return NULL;
450	}
451	if ( surface->map->dst->format->BitsPerPixel < 8 ) {
452		which = 0;
453	} else {
454		which = surface->map->dst->format->BytesPerPixel;
455	}
456	switch(blit_index) {
457	case 0:			/* copy */
458	    return bitmap_blit[which];
459
460	case 1:			/* colorkey */
461	    return colorkey_blit[which];
462
463	case 2:			/* alpha */
464	    return which >= 2 ? BlitBtoNAlpha : NULL;
465
466	case 4:			/* alpha + colorkey */
467	    return which >= 2 ? BlitBtoNAlphaKey : NULL;
468	}
469	return NULL;
470}
471
472