comparison src/video/SDL_blendline.c @ 2898:e40448bc7727

Share code between fill and line drawing Added general RGB surface format fallbacks to drawing code Fixed issues with destination surface alpha channel
author Sam Lantinga <slouken@libsdl.org>
date Sun, 21 Dec 2008 08:28:25 +0000
parents 1ef2f1e75ff7
children a0c837a16e4c
comparison
equal deleted inserted replaced
2897:8be863ef68ee 2898:e40448bc7727
19 Sam Lantinga 19 Sam Lantinga
20 slouken@libsdl.org 20 slouken@libsdl.org
21 */ 21 */
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #include "SDL_video.h" 24 #include "SDL_draw.h"
25 #include "SDL_blit.h" 25
26 26 static int
27 #define ABS(_x) ((_x) < 0 ? -(_x) : (_x)) 27 SDL_BlendLine_RGB555(SDL_Surface * dst, int x1, int y1, int x2, int y2,
28 28 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
29 #define SWAP(_x, _y) do { int tmp; tmp = _x; _x = _y; _y = tmp; } while (0) 29 {
30 30 unsigned inva = 0xff - a;
31 #define BRESENHAM(x0, y0, x1, y1, op) \ 31
32 { \ 32 switch (blendMode) {
33 int deltax, deltay, steep, error, xstep, ystep, x, y; \ 33 case SDL_BLENDMODE_BLEND:
34 \ 34 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB555);
35 deltax = ABS(x1 - x0); \ 35 break;
36 deltay = ABS(y1 - y0); \ 36 case SDL_BLENDMODE_ADD:
37 steep = (deltay > deltax); \ 37 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB555);
38 if (steep) { \ 38 break;
39 SWAP(x0, y0); \ 39 case SDL_BLENDMODE_MOD:
40 SWAP(x1, y1); \ 40 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB555);
41 SWAP(deltax, deltay); \ 41 break;
42 } \ 42 default:
43 error = (x1 - x0) / 2; \ 43 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB555);
44 y = y0; \ 44 break;
45 if (x0 > x1) { \ 45 }
46 xstep = -1; \ 46 return 0;
47 } else { \ 47 }
48 xstep = 1; \ 48
49 } \ 49 static int
50 if (y0 < y1) { \ 50 SDL_BlendLine_RGB565(SDL_Surface * dst, int x1, int y1, int x2, int y2,
51 ystep = 1; \ 51 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
52 } else { \ 52 {
53 ystep = -1; \ 53 unsigned inva = 0xff - a;
54 } \ 54
55 if (!steep) { \ 55 switch (blendMode) {
56 for (x = x0; x != x1; x += xstep) { \ 56 case SDL_BLENDMODE_BLEND:
57 op(x, y); \ 57 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB565);
58 error -= deltay; \ 58 break;
59 if (error < 0) { \ 59 case SDL_BLENDMODE_ADD:
60 y += ystep; \ 60 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB565);
61 error += deltax; \ 61 break;
62 } \ 62 case SDL_BLENDMODE_MOD:
63 } \ 63 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB565);
64 } else { \ 64 break;
65 for (x = x0; x != x1; x += xstep) { \ 65 default:
66 op(y, x); \ 66 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB565);
67 error -= deltay; \ 67 break;
68 if (error < 0) { \ 68 }
69 y += ystep; \ 69 return 0;
70 error += deltax; \ 70 }
71 } \ 71
72 } \ 72 static int
73 } \ 73 SDL_BlendLine_RGB888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
74 } 74 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
75 75 {
76 #define MUL(_a, _b) (((Uint16)(_a)*(Uint16)(_b))/255) 76 unsigned inva = 0xff - a;
77 #define SHIFTAND(_v, _s, _a) (((_v)>>(_s)) & _a) 77
78 78 switch (blendMode) {
79 #define SETPIXEL_MASK(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ 79 case SDL_BLENDMODE_BLEND:
80 do { \ 80 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB888);
81 type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \ 81 break;
82 if (a) { \ 82 case SDL_BLENDMODE_ADD:
83 *pixel = (r<<rshift) | (g<<gshift) | (b<<bshift); \ 83 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB888);
84 } \ 84 break;
85 } while (0) 85 case SDL_BLENDMODE_MOD:
86 86 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB888);
87 #define SETPIXEL_BLEND(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ 87 break;
88 do { \ 88 default:
89 type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \ 89 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB888);
90 Uint8 sr = MUL(inva, SHIFTAND(*pixel, rshift, rmask)) + (Uint16) r; \ 90 break;
91 Uint8 sg = MUL(inva, SHIFTAND(*pixel, gshift, gmask)) + (Uint16) g; \ 91 }
92 Uint8 sb = MUL(inva, SHIFTAND(*pixel, bshift, bmask)) + (Uint16) b; \ 92 return 0;
93 *pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift); \ 93 }
94 } while (0) 94
95 95 static int
96 #define SETPIXEL_ADD(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ 96 SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,
97 do { \ 97 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
98 type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \ 98 {
99 Uint16 sr = SHIFTAND(*pixel, rshift, rmask) + (Uint16) r; \ 99 SDL_PixelFormat *fmt = dst->format;
100 Uint16 sg = SHIFTAND(*pixel, gshift, gmask) + (Uint16) g; \ 100 unsigned inva = 0xff - a;
101 Uint16 sb = SHIFTAND(*pixel, bshift, bmask) + (Uint16) b; \ 101
102 if (sr>rmask) sr = rmask; \ 102 switch (fmt->BytesPerPixel) {
103 if (sg>gmask) sg = gmask; \ 103 case 2:
104 if (sb>bmask) sb = bmask; \ 104 switch (blendMode) {
105 *pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift); \ 105 case SDL_BLENDMODE_BLEND:
106 } while (0) 106 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY2_BLEND_RGB);
107 107 break;
108 #define SETPIXEL_MOD(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ 108 case SDL_BLENDMODE_ADD:
109 do { \ 109 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY2_ADD_RGB);
110 type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \ 110 break;
111 Uint8 sr = MUL(SHIFTAND(*pixel, rshift, rmask), r); \ 111 case SDL_BLENDMODE_MOD:
112 Uint8 sg = MUL(SHIFTAND(*pixel, gshift, gmask), g); \ 112 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY2_MOD_RGB);
113 Uint8 sb = MUL(SHIFTAND(*pixel, bshift, bmask), b); \ 113 break;
114 *pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift); \ 114 default:
115 } while (0) 115 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY2_RGB);
116 116 break;
117 117 }
118 #define SETPIXEL15_MASK(x, y) SETPIXEL_MASK(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f); 118 return 0;
119 #define SETPIXEL15_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f); 119 case 4:
120 #define SETPIXEL15_ADD(x, y) SETPIXEL_ADD(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f); 120 switch (blendMode) {
121 #define SETPIXEL15_MOD(x, y) SETPIXEL_MOD(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f); 121 case SDL_BLENDMODE_BLEND:
122 122 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGB);
123 #define SETPIXEL16_MASK(x, y) SETPIXEL_MASK(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f); 123 break;
124 #define SETPIXEL16_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f); 124 case SDL_BLENDMODE_ADD:
125 #define SETPIXEL16_ADD(x, y) SETPIXEL_ADD(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f); 125 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGB);
126 #define SETPIXEL16_MOD(x, y) SETPIXEL_MOD(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f); 126 break;
127 127 case SDL_BLENDMODE_MOD:
128 #define SETPIXEL32_MASK(x, y) SETPIXEL_MASK(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff); 128 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGB);
129 #define SETPIXEL32_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff); 129 break;
130 #define SETPIXEL32_ADD(x, y) SETPIXEL_ADD(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff); 130 default:
131 #define SETPIXEL32_MOD(x, y) SETPIXEL_MOD(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff); 131 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGB);
132 break;
133 }
134 return 0;
135 default:
136 SDL_Unsupported();
137 return -1;
138 }
139 }
140
141 static int
142 SDL_BlendLine_RGBA(SDL_Surface * dst, int x1, int y1, int x2, int y2,
143 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
144 {
145 SDL_PixelFormat *fmt = dst->format;
146 unsigned inva = 0xff - a;
147
148 switch (fmt->BytesPerPixel) {
149 case 4:
150 switch (blendMode) {
151 case SDL_BLENDMODE_BLEND:
152 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGBA);
153 break;
154 case SDL_BLENDMODE_ADD:
155 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGBA);
156 break;
157 case SDL_BLENDMODE_MOD:
158 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGBA);
159 break;
160 default:
161 BRESENHAM(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGBA);
162 break;
163 }
164 return 0;
165 default:
166 SDL_Unsupported();
167 return -1;
168 }
169 }
132 170
133 int 171 int
134 SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, 172 SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
135 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 173 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
136 { 174 {
137 Uint8 inva = 0xff - a; 175 SDL_PixelFormat *fmt = dst->format;
176
138 /* This function doesn't work on surfaces < 8 bpp */ 177 /* This function doesn't work on surfaces < 8 bpp */
139 if (dst->format->BitsPerPixel < 8) { 178 if (dst->format->BitsPerPixel < 8) {
140 SDL_SetError("SDL_BlendLine(): Unsupported surface format"); 179 SDL_SetError("SDL_BlendLine(): Unsupported surface format");
141 return (-1); 180 return (-1);
142 } 181 }
148 } 187 }
149 */ 188 */
150 189
151 if ((blendMode == SDL_BLENDMODE_BLEND) 190 if ((blendMode == SDL_BLENDMODE_BLEND)
152 || (blendMode == SDL_BLENDMODE_ADD)) { 191 || (blendMode == SDL_BLENDMODE_ADD)) {
153 r = MUL(r, a); 192 r = DRAW_MUL(r, a);
154 g = MUL(g, a); 193 g = DRAW_MUL(g, a);
155 b = MUL(b, a); 194 b = DRAW_MUL(b, a);
156 } 195 }
157 switch (dst->format->BitsPerPixel) { 196
197 switch (fmt->BitsPerPixel) {
158 case 15: 198 case 15:
159 switch (blendMode) { 199 switch (fmt->Rmask) {
160 case SDL_BLENDMODE_MASK: 200 case 0x7C00:
161 BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MASK); 201 return SDL_BlendLine_RGB555(dst, x1, y1, x2, y2, blendMode, r, g,
162 break; 202 b, a);
163 case SDL_BLENDMODE_BLEND:
164 BRESENHAM(x1, y1, x2, y2, SETPIXEL15_BLEND);
165 break;
166 case SDL_BLENDMODE_ADD:
167 BRESENHAM(x1, y1, x2, y2, SETPIXEL15_ADD);
168 break;
169 case SDL_BLENDMODE_MOD:
170 BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MOD);
171 break;
172 } 203 }
173 break; 204 break;
174 case 16: 205 case 16:
175 switch (blendMode) { 206 switch (fmt->Rmask) {
176 case SDL_BLENDMODE_MASK: 207 case 0xF800:
177 BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MASK); 208 return SDL_BlendLine_RGB565(dst, x1, y1, x2, y2, blendMode, r, g,
178 break; 209 b, a);
179 case SDL_BLENDMODE_BLEND: 210 }
180 BRESENHAM(x1, y1, x2, y2, SETPIXEL16_BLEND); 211 break;
181 break;
182 case SDL_BLENDMODE_ADD:
183 BRESENHAM(x1, y1, x2, y2, SETPIXEL16_ADD);
184 break;
185 case SDL_BLENDMODE_MOD:
186 BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MOD);
187 break;
188 }
189 break;
190 case 24:
191 case 32: 212 case 32:
192 if (dst->format->BytesPerPixel != 4) { 213 switch (fmt->Rmask) {
193 SDL_Unsupported(); 214 case 0x00FF0000:
194 return -1; 215 if (!fmt->Amask) {
195 } 216 return SDL_BlendLine_RGB888(dst, x1, y1, x2, y2, blendMode, r,
196 switch (blendMode) { 217 g, b, a);
197 case SDL_BLENDMODE_MASK: 218 }
198 BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MASK); 219 break;
199 break; 220 }
200 case SDL_BLENDMODE_BLEND: 221 default:
201 BRESENHAM(x1, y1, x2, y2, SETPIXEL32_BLEND); 222 break;
202 break; 223 }
203 case SDL_BLENDMODE_ADD: 224
204 BRESENHAM(x1, y1, x2, y2, SETPIXEL32_ADD); 225 if (!fmt->Amask) {
205 break; 226 return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
206 case SDL_BLENDMODE_MOD: 227 } else {
207 BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MOD); 228 return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
208 break; 229 }
209 }
210 break;
211 default:
212 SDL_Unsupported();
213 return -1;
214 }
215 return 0;
216 } 230 }
217 231
218 /* vi: set ts=4 sw=4 expandtab: */ 232 /* vi: set ts=4 sw=4 expandtab: */