1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 #if SDL_HAVE_BLIT_0
24 
25 #include "SDL_video.h"
26 #include "SDL_blit.h"
27 
28 /* Functions to blit from bitmaps to other surfaces */
29 
30 static void
BlitBto1(SDL_BlitInfo * info)31 BlitBto1(SDL_BlitInfo * info)
32 {
33     int c;
34     int width, height;
35     Uint8 *src, *map, *dst;
36     int srcskip, dstskip;
37 
38     /* Set up some basic variables */
39     width = info->dst_w;
40     height = info->dst_h;
41     src = info->src;
42     srcskip = info->src_skip;
43     dst = info->dst;
44     dstskip = info->dst_skip;
45     map = info->table;
46     srcskip += width - (width + 7) / 8;
47 
48     if (map) {
49         while (height--) {
50             Uint8 byte = 0, bit;
51             for (c = 0; c < width; ++c) {
52                 if ((c & 7) == 0) {
53                     byte = *src++;
54                 }
55                 bit = (byte & 0x80) >> 7;
56                 if (1) {
57                     *dst = map[bit];
58                 }
59                 dst++;
60                 byte <<= 1;
61             }
62             src += srcskip;
63             dst += dstskip;
64         }
65     } else {
66         while (height--) {
67             Uint8 byte = 0, bit;
68             for (c = 0; c < width; ++c) {
69                 if ((c & 7) == 0) {
70                     byte = *src++;
71                 }
72                 bit = (byte & 0x80) >> 7;
73                 if (1) {
74                     *dst = bit;
75                 }
76                 dst++;
77                 byte <<= 1;
78             }
79             src += srcskip;
80             dst += dstskip;
81         }
82     }
83 }
84 
85 static void
BlitBto2(SDL_BlitInfo * info)86 BlitBto2(SDL_BlitInfo * info)
87 {
88     int c;
89     int width, height;
90     Uint8 *src;
91     Uint16 *map, *dst;
92     int srcskip, dstskip;
93 
94     /* Set up some basic variables */
95     width = info->dst_w;
96     height = info->dst_h;
97     src = info->src;
98     srcskip = info->src_skip;
99     dst = (Uint16 *) info->dst;
100     dstskip = info->dst_skip / 2;
101     map = (Uint16 *) info->table;
102     srcskip += width - (width + 7) / 8;
103 
104     while (height--) {
105         Uint8 byte = 0, bit;
106         for (c = 0; c < width; ++c) {
107             if ((c & 7) == 0) {
108                 byte = *src++;
109             }
110             bit = (byte & 0x80) >> 7;
111             if (1) {
112                 *dst = map[bit];
113             }
114             byte <<= 1;
115             dst++;
116         }
117         src += srcskip;
118         dst += dstskip;
119     }
120 }
121 
122 static void
BlitBto3(SDL_BlitInfo * info)123 BlitBto3(SDL_BlitInfo * info)
124 {
125     int c, o;
126     int width, height;
127     Uint8 *src, *map, *dst;
128     int srcskip, dstskip;
129 
130     /* Set up some basic variables */
131     width = info->dst_w;
132     height = info->dst_h;
133     src = info->src;
134     srcskip = info->src_skip;
135     dst = info->dst;
136     dstskip = info->dst_skip;
137     map = info->table;
138     srcskip += width - (width + 7) / 8;
139 
140     while (height--) {
141         Uint8 byte = 0, bit;
142         for (c = 0; c < width; ++c) {
143             if ((c & 7) == 0) {
144                 byte = *src++;
145             }
146             bit = (byte & 0x80) >> 7;
147             if (1) {
148                 o = bit * 4;
149                 dst[0] = map[o++];
150                 dst[1] = map[o++];
151                 dst[2] = map[o++];
152             }
153             byte <<= 1;
154             dst += 3;
155         }
156         src += srcskip;
157         dst += dstskip;
158     }
159 }
160 
161 static void
BlitBto4(SDL_BlitInfo * info)162 BlitBto4(SDL_BlitInfo * info)
163 {
164     int width, height;
165     Uint8 *src;
166     Uint32 *map, *dst;
167     int srcskip, dstskip;
168     int c;
169 
170     /* Set up some basic variables */
171     width = info->dst_w;
172     height = info->dst_h;
173     src = info->src;
174     srcskip = info->src_skip;
175     dst = (Uint32 *) info->dst;
176     dstskip = info->dst_skip / 4;
177     map = (Uint32 *) info->table;
178     srcskip += width - (width + 7) / 8;
179 
180     while (height--) {
181         Uint8 byte = 0, bit;
182         for (c = 0; c < width; ++c) {
183             if ((c & 7) == 0) {
184                 byte = *src++;
185             }
186             bit = (byte & 0x80) >> 7;
187             if (1) {
188                 *dst = map[bit];
189             }
190             byte <<= 1;
191             dst++;
192         }
193         src += srcskip;
194         dst += dstskip;
195     }
196 }
197 
198 static void
BlitBto1Key(SDL_BlitInfo * info)199 BlitBto1Key(SDL_BlitInfo * info)
200 {
201     int width = info->dst_w;
202     int height = info->dst_h;
203     Uint8 *src = info->src;
204     Uint8 *dst = info->dst;
205     int srcskip = info->src_skip;
206     int dstskip = info->dst_skip;
207     Uint32 ckey = info->colorkey;
208     Uint8 *palmap = info->table;
209     int c;
210 
211     /* Set up some basic variables */
212     srcskip += width - (width + 7) / 8;
213 
214     if (palmap) {
215         while (height--) {
216             Uint8 byte = 0, bit;
217             for (c = 0; c < width; ++c) {
218                 if ((c & 7) == 0) {
219                     byte = *src++;
220                 }
221                 bit = (byte & 0x80) >> 7;
222                 if (bit != ckey) {
223                     *dst = palmap[bit];
224                 }
225                 dst++;
226                 byte <<= 1;
227             }
228             src += srcskip;
229             dst += dstskip;
230         }
231     } else {
232         while (height--) {
233             Uint8 byte = 0, bit;
234             for (c = 0; c < width; ++c) {
235                 if ((c & 7) == 0) {
236                     byte = *src++;
237                 }
238                 bit = (byte & 0x80) >> 7;
239                 if (bit != ckey) {
240                     *dst = bit;
241                 }
242                 dst++;
243                 byte <<= 1;
244             }
245             src += srcskip;
246             dst += dstskip;
247         }
248     }
249 }
250 
251 static void
BlitBto2Key(SDL_BlitInfo * info)252 BlitBto2Key(SDL_BlitInfo * info)
253 {
254     int width = info->dst_w;
255     int height = info->dst_h;
256     Uint8 *src = info->src;
257     Uint16 *dstp = (Uint16 *) info->dst;
258     int srcskip = info->src_skip;
259     int dstskip = info->dst_skip;
260     Uint32 ckey = info->colorkey;
261     Uint8 *palmap = info->table;
262     int c;
263 
264     /* Set up some basic variables */
265     srcskip += width - (width + 7) / 8;
266     dstskip /= 2;
267 
268     while (height--) {
269         Uint8 byte = 0, bit;
270         for (c = 0; c < width; ++c) {
271             if ((c & 7) == 0) {
272                 byte = *src++;
273             }
274             bit = (byte & 0x80) >> 7;
275             if (bit != ckey) {
276                 *dstp = ((Uint16 *) palmap)[bit];
277             }
278             byte <<= 1;
279             dstp++;
280         }
281         src += srcskip;
282         dstp += dstskip;
283     }
284 }
285 
286 static void
BlitBto3Key(SDL_BlitInfo * info)287 BlitBto3Key(SDL_BlitInfo * info)
288 {
289     int width = info->dst_w;
290     int height = info->dst_h;
291     Uint8 *src = info->src;
292     Uint8 *dst = info->dst;
293     int srcskip = info->src_skip;
294     int dstskip = info->dst_skip;
295     Uint32 ckey = info->colorkey;
296     Uint8 *palmap = info->table;
297     int c;
298 
299     /* Set up some basic variables */
300     srcskip += width - (width + 7) / 8;
301 
302     while (height--) {
303         Uint8 byte = 0, bit;
304         for (c = 0; c < width; ++c) {
305             if ((c & 7) == 0) {
306                 byte = *src++;
307             }
308             bit = (byte & 0x80) >> 7;
309             if (bit != ckey) {
310                 SDL_memcpy(dst, &palmap[bit * 4], 3);
311             }
312             byte <<= 1;
313             dst += 3;
314         }
315         src += srcskip;
316         dst += dstskip;
317     }
318 }
319 
320 static void
BlitBto4Key(SDL_BlitInfo * info)321 BlitBto4Key(SDL_BlitInfo * info)
322 {
323     int width = info->dst_w;
324     int height = info->dst_h;
325     Uint8 *src = info->src;
326     Uint32 *dstp = (Uint32 *) info->dst;
327     int srcskip = info->src_skip;
328     int dstskip = info->dst_skip;
329     Uint32 ckey = info->colorkey;
330     Uint8 *palmap = info->table;
331     int c;
332 
333     /* Set up some basic variables */
334     srcskip += width - (width + 7) / 8;
335     dstskip /= 4;
336 
337     while (height--) {
338         Uint8 byte = 0, bit;
339         for (c = 0; c < width; ++c) {
340             if ((c & 7) == 0) {
341                 byte = *src++;
342             }
343             bit = (byte & 0x80) >> 7;
344             if (bit != ckey) {
345                 *dstp = ((Uint32 *) palmap)[bit];
346             }
347             byte <<= 1;
348             dstp++;
349         }
350         src += srcskip;
351         dstp += dstskip;
352     }
353 }
354 
355 static void
BlitBtoNAlpha(SDL_BlitInfo * info)356 BlitBtoNAlpha(SDL_BlitInfo * info)
357 {
358     int width = info->dst_w;
359     int height = info->dst_h;
360     Uint8 *src = info->src;
361     Uint8 *dst = info->dst;
362     int srcskip = info->src_skip;
363     int dstskip = info->dst_skip;
364     const SDL_Color *srcpal = info->src_fmt->palette->colors;
365     SDL_PixelFormat *dstfmt = info->dst_fmt;
366     int dstbpp;
367     int c;
368     Uint32 pixel;
369     unsigned sR, sG, sB;
370     unsigned dR, dG, dB, dA;
371     const unsigned A = info->a;
372 
373     /* Set up some basic variables */
374     dstbpp = dstfmt->BytesPerPixel;
375     srcskip += width - (width + 7) / 8;
376 
377     while (height--) {
378         Uint8 byte = 0, bit;
379         for (c = 0; c < width; ++c) {
380             if ((c & 7) == 0) {
381                 byte = *src++;
382             }
383             bit = (byte & 0x80) >> 7;
384             if (1) {
385                 sR = srcpal[bit].r;
386                 sG = srcpal[bit].g;
387                 sB = srcpal[bit].b;
388                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
389                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
390                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
391             }
392             byte <<= 1;
393             dst += dstbpp;
394         }
395         src += srcskip;
396         dst += dstskip;
397     }
398 }
399 
400 static void
BlitBtoNAlphaKey(SDL_BlitInfo * info)401 BlitBtoNAlphaKey(SDL_BlitInfo * info)
402 {
403     int width = info->dst_w;
404     int height = info->dst_h;
405     Uint8 *src = info->src;
406     Uint8 *dst = info->dst;
407     int srcskip = info->src_skip;
408     int dstskip = info->dst_skip;
409     SDL_PixelFormat *srcfmt = info->src_fmt;
410     SDL_PixelFormat *dstfmt = info->dst_fmt;
411     const SDL_Color *srcpal = srcfmt->palette->colors;
412     int dstbpp;
413     int c;
414     Uint32 pixel;
415     unsigned sR, sG, sB;
416     unsigned dR, dG, dB, dA;
417     const unsigned A = info->a;
418     Uint32 ckey = info->colorkey;
419 
420     /* Set up some basic variables */
421     dstbpp = dstfmt->BytesPerPixel;
422     srcskip += width - (width + 7) / 8;
423 
424     while (height--) {
425         Uint8 byte = 0, bit;
426         for (c = 0; c < width; ++c) {
427             if ((c & 7) == 0) {
428                 byte = *src++;
429             }
430             bit = (byte & 0x80) >> 7;
431             if (bit != ckey) {
432                 sR = srcpal[bit].r;
433                 sG = srcpal[bit].g;
434                 sB = srcpal[bit].b;
435                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
436                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
437                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
438             }
439             byte <<= 1;
440             dst += dstbpp;
441         }
442         src += srcskip;
443         dst += dstskip;
444     }
445 }
446 
447 static const SDL_BlitFunc bitmap_blit[] = {
448     (SDL_BlitFunc) NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4
449 };
450 
451 static const SDL_BlitFunc colorkey_blit[] = {
452     (SDL_BlitFunc) NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key
453 };
454 
455 SDL_BlitFunc
SDL_CalculateBlit0(SDL_Surface * surface)456 SDL_CalculateBlit0(SDL_Surface * surface)
457 {
458     int which;
459 
460     if (surface->format->BitsPerPixel != 1) {
461         /* We don't support sub 8-bit packed pixel modes */
462         return (SDL_BlitFunc) NULL;
463     }
464     if (surface->map->dst->format->BitsPerPixel < 8) {
465         which = 0;
466     } else {
467         which = surface->map->dst->format->BytesPerPixel;
468     }
469     switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
470     case 0:
471         return bitmap_blit[which];
472 
473     case SDL_COPY_COLORKEY:
474         return colorkey_blit[which];
475 
476     case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
477         return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc) NULL;
478 
479     case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
480         return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc) NULL;
481     }
482     return (SDL_BlitFunc) NULL;
483 }
484 
485 #endif /* SDL_HAVE_BLIT_0 */
486 
487 /* vi: set ts=4 sw=4 expandtab: */
488