Mercurial > sdl-ios-xcode
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: */ |