1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 | |