GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* The ManaPlus Client |
||
3 |
* Copyright (C) 2004-2009 The Mana World Development Team |
||
4 |
* Copyright (C) 2009-2010 The Mana Developers |
||
5 |
* Copyright (C) 2011-2019 The ManaPlus Developers |
||
6 |
* Copyright (C) 2019-2021 Andrei Karas |
||
7 |
* |
||
8 |
* This file is part of The ManaPlus Client. |
||
9 |
* |
||
10 |
* This program is free software; you can redistribute it and/or modify |
||
11 |
* it under the terms of the GNU General Public License as published by |
||
12 |
* the Free Software Foundation; either version 2 of the License, or |
||
13 |
* any later version. |
||
14 |
* |
||
15 |
* This program is distributed in the hope that it will be useful, |
||
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 |
* GNU General Public License for more details. |
||
19 |
* |
||
20 |
* You should have received a copy of the GNU General Public License |
||
21 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
22 |
*/ |
||
23 |
|||
24 |
#ifndef USE_SDL2 |
||
25 |
|||
26 |
#include "render/sdlgraphics.h" |
||
27 |
|||
28 |
#include "graphicsmanager.h" |
||
29 |
|||
30 |
#include "utils/sdlcheckutils.h" |
||
31 |
|||
32 |
#include "utils/sdlpixel.h" |
||
33 |
|||
34 |
#include "render/vertexes/imagecollection.h" |
||
35 |
|||
36 |
#include "resources/imagerect.h" |
||
37 |
|||
38 |
#include "resources/image/image.h" |
||
39 |
|||
40 |
#include "debug.h" |
||
41 |
|||
42 |
#ifndef SDL_BIG_ENDIAN |
||
43 |
#error missing SDL_endian.h |
||
44 |
#endif // SDL_BYTEORDER |
||
45 |
|||
46 |
#if SDL_BYTEORDER == SDL_LIL_ENDIAN |
||
47 |
static unsigned int *cR = nullptr; |
||
48 |
static unsigned int *cG = nullptr; |
||
49 |
static unsigned int *cB = nullptr; |
||
50 |
#endif // SDL_BYTEORDER == SDL_LIL_ENDIAN |
||
51 |
|||
52 |
161 |
SDLGraphics::SDLGraphics() : |
|
53 |
Graphics(), |
||
54 |
mOldPixel(0), |
||
55 |
161 |
mOldAlpha(0) |
|
56 |
{ |
||
57 |
161 |
mOpenGL = RENDER_SOFTWARE; |
|
58 |
322 |
mName = "Software"; |
|
59 |
161 |
} |
|
60 |
|||
61 |
161 |
SDLGraphics::~SDLGraphics() |
|
62 |
{ |
||
63 |
161 |
} |
|
64 |
|||
65 |
void SDLGraphics::drawRescaledImage(const Image *restrict const image, |
||
66 |
int dstX, int dstY, |
||
67 |
const int desiredWidth, |
||
68 |
const int desiredHeight) restrict2 |
||
69 |
{ |
||
70 |
FUNC_BLOCK("Graphics::drawRescaledImage", 1) |
||
71 |
// Check that preconditions for blitting are met. |
||
72 |
if (mWindow == nullptr || |
||
73 |
image == nullptr || |
||
74 |
image->mSDLSurface == nullptr) |
||
75 |
{ |
||
76 |
return; |
||
77 |
} |
||
78 |
|||
79 |
Image *const tmpImage = image->SDLgetScaledImage( |
||
80 |
desiredWidth, desiredHeight); |
||
81 |
|||
82 |
if ((tmpImage == nullptr) || (tmpImage->mSDLSurface == nullptr)) |
||
83 |
return; |
||
84 |
|||
85 |
const ClipRect &top = mClipStack.top(); |
||
86 |
const SDL_Rect &bounds = image->mBounds; |
||
87 |
|||
88 |
SDL_Rect srcRect = |
||
89 |
{ |
||
90 |
CAST_S16(bounds.x), |
||
91 |
CAST_S16(bounds.y), |
||
92 |
CAST_U16(bounds.w), |
||
93 |
CAST_U16(bounds.h) |
||
94 |
}; |
||
95 |
|||
96 |
SDL_Rect dstRect = |
||
97 |
{ |
||
98 |
CAST_S16(dstX + top.xOffset), |
||
99 |
CAST_S16(dstY + top.yOffset), |
||
100 |
0, |
||
101 |
0 |
||
102 |
}; |
||
103 |
|||
104 |
SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, mWindow, &dstRect); |
||
105 |
delete tmpImage; |
||
106 |
} |
||
107 |
|||
108 |
331 |
void SDLGraphics::drawImage(const Image *restrict const image, |
|
109 |
int dstX, int dstY) restrict2 |
||
110 |
{ |
||
111 |
331 |
drawImageInline(image, dstX, dstY); |
|
112 |
331 |
} |
|
113 |
|||
114 |
void SDLGraphics::drawImageInline(const Image *restrict const image, |
||
115 |
int dstX, int dstY) restrict2 |
||
116 |
{ |
||
117 |
FUNC_BLOCK("Graphics::drawImage", 1) |
||
118 |
// Check that preconditions for blitting are met. |
||
119 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ |
515 |
if (mWindow == nullptr || |
120 |
✓✗✓✗ ✓✗✓✗ ✗✗✓✗ |
515 |
image == nullptr || |
121 |
515 |
image->mSDLSurface == nullptr) |
|
122 |
{ |
||
123 |
return; |
||
124 |
} |
||
125 |
|||
126 |
515 |
const ClipRect &top = mClipStack.top(); |
|
127 |
515 |
const SDL_Rect &bounds = image->mBounds; |
|
128 |
|||
129 |
515 |
SDL_Surface *const src = image->mSDLSurface; |
|
130 |
|||
131 |
515 |
int srcX = bounds.x; |
|
132 |
515 |
int srcY = bounds.y; |
|
133 |
515 |
dstX += top.xOffset; |
|
134 |
515 |
dstY += top.yOffset; |
|
135 |
|||
136 |
515 |
int w = bounds.w; |
|
137 |
515 |
int h = bounds.h; |
|
138 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✓ |
515 |
if (srcX < 0) |
139 |
{ |
||
140 |
w += srcX; |
||
141 |
dstX -= CAST_S16(srcX); |
||
142 |
srcX = 0; |
||
143 |
} |
||
144 |
515 |
const int maxw = src->w - srcX; |
|
145 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✓ |
515 |
if (maxw < w) |
146 |
w = maxw; |
||
147 |
|||
148 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✓ |
515 |
if (srcY < 0) |
149 |
{ |
||
150 |
h += srcY; |
||
151 |
dstY -= CAST_S16(srcY); |
||
152 |
srcY = 0; |
||
153 |
} |
||
154 |
515 |
const int maxh = src->h - srcY; |
|
155 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✓ |
515 |
if (maxh < h) |
156 |
h = maxh; |
||
157 |
|||
158 |
515 |
const SDL_Rect *const clip = &mWindow->clip_rect; |
|
159 |
515 |
const int clipX = clip->x; |
|
160 |
515 |
const int clipY = clip->y; |
|
161 |
515 |
int dx = clipX - dstX; |
|
162 |
✗✓✗✓ ✗✓✗✓ ✗✗✓✓ |
515 |
if (dx > 0) |
163 |
{ |
||
164 |
69 |
w -= dx; |
|
165 |
69 |
dstX += CAST_S16(dx); |
|
166 |
69 |
srcX += dx; |
|
167 |
} |
||
168 |
515 |
dx = dstX + w - clipX - clip->w; |
|
169 |
✓✗✓✗ ✓✗✓✗ ✗✗✓✓ |
515 |
if (dx > 0) |
170 |
514 |
w -= dx; |
|
171 |
|||
172 |
515 |
int dy = clipY - dstY; |
|
173 |
✗✓✗✓ ✗✓✗✓ ✗✗✓✓ |
515 |
if (dy > 0) |
174 |
{ |
||
175 |
67 |
h -= dy; |
|
176 |
67 |
dstY += CAST_S16(dy); |
|
177 |
67 |
srcY += dy; |
|
178 |
} |
||
179 |
515 |
dy = dstY + h - clipY - clip->h; |
|
180 |
✓✗✓✗ ✓✗✓✗ ✗✗✓✗ |
515 |
if (dy > 0) |
181 |
515 |
h -= dy; |
|
182 |
|||
183 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✓ |
515 |
if (w > 0 && h > 0) |
184 |
{ |
||
185 |
SDL_Rect srcRect = |
||
186 |
{ |
||
187 |
CAST_S16(srcX), |
||
188 |
CAST_S16(srcY), |
||
189 |
CAST_U16(w), |
||
190 |
CAST_U16(h) |
||
191 |
}; |
||
192 |
|||
193 |
SDL_Rect dstRect = |
||
194 |
{ |
||
195 |
CAST_S16(dstX), |
||
196 |
CAST_S16(dstY), |
||
197 |
CAST_U16(w), |
||
198 |
CAST_U16(h) |
||
199 |
}; |
||
200 |
|||
201 |
SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); |
||
202 |
} |
||
203 |
} |
||
204 |
|||
205 |
void SDLGraphics::copyImage(const Image *restrict const image, |
||
206 |
int dstX, int dstY) restrict2 |
||
207 |
{ |
||
208 |
drawImageInline(image, dstX, dstY); |
||
209 |
} |
||
210 |
|||
211 |
void SDLGraphics::drawImageCached(const Image *restrict const image, |
||
212 |
int x, int y) restrict2 |
||
213 |
{ |
||
214 |
FUNC_BLOCK("Graphics::drawImageCached", 1) |
||
215 |
// Check that preconditions for blitting are met. |
||
216 |
if (mWindow == nullptr || |
||
217 |
image == nullptr || |
||
218 |
image->mSDLSurface == nullptr) |
||
219 |
{ |
||
220 |
return; |
||
221 |
} |
||
222 |
|||
223 |
const ClipRect &top = mClipStack.top(); |
||
224 |
const SDL_Rect &bounds = image->mBounds; |
||
225 |
|||
226 |
SDL_Surface *const src = image->mSDLSurface; |
||
227 |
|||
228 |
int srcX = bounds.x; |
||
229 |
int srcY = bounds.y; |
||
230 |
x += top.xOffset; |
||
231 |
y += top.yOffset; |
||
232 |
|||
233 |
int w = bounds.w; |
||
234 |
int h = bounds.h; |
||
235 |
if (srcX < 0) |
||
236 |
{ |
||
237 |
w += srcX; |
||
238 |
x -= CAST_S16(srcX); |
||
239 |
srcX = 0; |
||
240 |
} |
||
241 |
const int maxw = src->w - srcX; |
||
242 |
if (maxw < w) |
||
243 |
w = maxw; |
||
244 |
|||
245 |
if (srcY < 0) |
||
246 |
{ |
||
247 |
h += srcY; |
||
248 |
y -= CAST_S16(srcY); |
||
249 |
srcY = 0; |
||
250 |
} |
||
251 |
const int maxh = src->h - srcY; |
||
252 |
if (maxh < h) |
||
253 |
h = maxh; |
||
254 |
|||
255 |
const SDL_Rect *const clip = &mWindow->clip_rect; |
||
256 |
const int clipX = clip->x; |
||
257 |
const int clipY = clip->y; |
||
258 |
int dx = clipX - x; |
||
259 |
if (dx > 0) |
||
260 |
{ |
||
261 |
w -= dx; |
||
262 |
x += CAST_S16(dx); |
||
263 |
srcX += dx; |
||
264 |
} |
||
265 |
dx = x + w - clipX - clip->w; |
||
266 |
if (dx > 0) |
||
267 |
w -= dx; |
||
268 |
|||
269 |
int dy = clipY - y; |
||
270 |
if (dy > 0) |
||
271 |
{ |
||
272 |
h -= dy; |
||
273 |
y += CAST_S16(dy); |
||
274 |
srcY += dy; |
||
275 |
} |
||
276 |
dy = y + h - clipY - clip->h; |
||
277 |
if (dy > 0) |
||
278 |
h -= dy; |
||
279 |
|||
280 |
if (w > 0 && h > 0) |
||
281 |
{ |
||
282 |
SDL_Rect srcRect = |
||
283 |
{ |
||
284 |
CAST_S16(srcX), |
||
285 |
CAST_S16(srcY), |
||
286 |
CAST_U16(w), |
||
287 |
CAST_U16(h) |
||
288 |
}; |
||
289 |
|||
290 |
SDL_Rect dstRect = |
||
291 |
{ |
||
292 |
CAST_S16(x), |
||
293 |
CAST_S16(y), |
||
294 |
CAST_U16(w), |
||
295 |
CAST_U16(h) |
||
296 |
}; |
||
297 |
|||
298 |
SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); |
||
299 |
} |
||
300 |
} |
||
301 |
|||
302 |
void SDLGraphics::drawPatternCached(const Image *restrict const image, |
||
303 |
const int x, const int y, |
||
304 |
const int w, const int h) restrict2 |
||
305 |
{ |
||
306 |
FUNC_BLOCK("Graphics::drawPatternCached", 1) |
||
307 |
// Check that preconditions for blitting are met. |
||
308 |
if ((mWindow == nullptr) || (image == nullptr)) |
||
309 |
return; |
||
310 |
if (image->mSDLSurface == nullptr) |
||
311 |
return; |
||
312 |
|||
313 |
const SDL_Rect &bounds = image->mBounds; |
||
314 |
const int iw = bounds.w; |
||
315 |
const int ih = bounds.h; |
||
316 |
if (iw == 0 || ih == 0) |
||
317 |
return; |
||
318 |
|||
319 |
const ClipRect &top = mClipStack.top(); |
||
320 |
const int xOffset = top.xOffset + x; |
||
321 |
const int yOffset = top.yOffset + y; |
||
322 |
const int srcX = bounds.x; |
||
323 |
const int srcY = bounds.y; |
||
324 |
SDL_Surface *const src = image->mSDLSurface; |
||
325 |
const SDL_Rect *const clip = &mWindow->clip_rect; |
||
326 |
const int clipX = clip->x; |
||
327 |
const int clipY = clip->y; |
||
328 |
|||
329 |
for (int py = 0; py < h; py += ih) |
||
330 |
{ |
||
331 |
const int dh = (py + ih >= h) ? h - py : ih; |
||
332 |
int dstY = py + yOffset; |
||
333 |
int y2 = srcY; |
||
334 |
int h2 = dh; |
||
335 |
if (y2 < 0) |
||
336 |
{ |
||
337 |
h2 += y2; |
||
338 |
dstY -= CAST_S16(y2); |
||
339 |
y2 = 0; |
||
340 |
} |
||
341 |
const int maxh = src->h - y2; |
||
342 |
if (maxh < h2) |
||
343 |
h2 = maxh; |
||
344 |
|||
345 |
int dy = clipY - dstY; |
||
346 |
if (dy > 0) |
||
347 |
{ |
||
348 |
h2 -= dy; |
||
349 |
dstY += CAST_S16(dy); |
||
350 |
y2 += dy; |
||
351 |
} |
||
352 |
dy = dstY + h2 - clipY - clip->h; |
||
353 |
if (dy > 0) |
||
354 |
h2 -= dy; |
||
355 |
|||
356 |
if (h2 > 0) |
||
357 |
{ |
||
358 |
for (int px = 0; px < w; px += iw) |
||
359 |
{ |
||
360 |
const int dw = (px + iw >= w) ? w - px : iw; |
||
361 |
int dstX = px + xOffset; |
||
362 |
int x2 = srcX; |
||
363 |
int w2 = dw; |
||
364 |
if (x2 < 0) |
||
365 |
{ |
||
366 |
w2 += x2; |
||
367 |
dstX -= CAST_S16(x2); |
||
368 |
x2 = 0; |
||
369 |
} |
||
370 |
const int maxw = src->w - x2; |
||
371 |
if (maxw < w2) |
||
372 |
w2 = maxw; |
||
373 |
|||
374 |
int dx = clipX - dstX; |
||
375 |
if (dx > 0) |
||
376 |
{ |
||
377 |
w2 -= dx; |
||
378 |
dstX += CAST_S16(dx); |
||
379 |
x2 += dx; |
||
380 |
} |
||
381 |
dx = dstX + w2 - clipX - clip->w; |
||
382 |
if (dx > 0) |
||
383 |
w2 -= dx; |
||
384 |
|||
385 |
if (w2 > 0) |
||
386 |
{ |
||
387 |
SDL_Rect srcRect = |
||
388 |
{ |
||
389 |
CAST_S16(x2), |
||
390 |
CAST_S16(y2), |
||
391 |
CAST_U16(w2), |
||
392 |
CAST_U16(h2) |
||
393 |
}; |
||
394 |
|||
395 |
SDL_Rect dstRect = |
||
396 |
{ |
||
397 |
CAST_S16(dstX), |
||
398 |
CAST_S16(dstY), |
||
399 |
CAST_U16(w2), |
||
400 |
CAST_U16(h2) |
||
401 |
}; |
||
402 |
|||
403 |
SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); |
||
404 |
} |
||
405 |
|||
406 |
// SDL_BlitSurface(image->mSDLSurface, &srcRect, mWindow, &dstRect); |
||
407 |
} |
||
408 |
} |
||
409 |
} |
||
410 |
} |
||
411 |
|||
412 |
void SDLGraphics::completeCache() restrict2 |
||
413 |
{ |
||
414 |
} |
||
415 |
|||
416 |
void SDLGraphics::drawPattern(const Image *restrict const image, |
||
417 |
const int x, const int y, |
||
418 |
const int w, const int h) restrict2 |
||
419 |
{ |
||
420 |
drawPatternInline(image, x, y, w, h); |
||
421 |
} |
||
422 |
|||
423 |
void SDLGraphics::drawPatternInline(const Image *restrict const image, |
||
424 |
const int x, const int y, |
||
425 |
const int w, const int h) restrict2 |
||
426 |
{ |
||
427 |
FUNC_BLOCK("Graphics::drawPattern", 1) |
||
428 |
// Check that preconditions for blitting are met. |
||
429 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ |
230 |
if ((mWindow == nullptr) || (image == nullptr)) |
430 |
return; |
||
431 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✗ |
230 |
if (image->mSDLSurface == nullptr) |
432 |
return; |
||
433 |
|||
434 |
230 |
const SDL_Rect &bounds = image->mBounds; |
|
435 |
230 |
const int iw = bounds.w; |
|
436 |
230 |
const int ih = bounds.h; |
|
437 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✗ |
230 |
if (iw == 0 || ih == 0) |
438 |
return; |
||
439 |
|||
440 |
230 |
const ClipRect &top = mClipStack.top(); |
|
441 |
230 |
const int xOffset = top.xOffset + x; |
|
442 |
230 |
const int yOffset = top.yOffset + y; |
|
443 |
230 |
const int srcX = bounds.x; |
|
444 |
230 |
const int srcY = bounds.y; |
|
445 |
230 |
SDL_Surface *const src = image->mSDLSurface; |
|
446 |
230 |
const SDL_Rect *const clip = &mWindow->clip_rect; |
|
447 |
230 |
const int clipX = clip->x; |
|
448 |
230 |
const int clipY = clip->y; |
|
449 |
|||
450 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✗ |
230 |
for (int py = 0; py < h; py += ih) |
451 |
{ |
||
452 |
✓✓✓✗ ✓✗✓✓ ✓✓✗✗ |
413 |
const int dh = (py + ih >= h) ? h - py : ih; |
453 |
413 |
int dstY = py + yOffset; |
|
454 |
413 |
int y2 = srcY; |
|
455 |
413 |
int h2 = dh; |
|
456 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✗ |
413 |
if (y2 < 0) |
457 |
{ |
||
458 |
h2 += y2; |
||
459 |
dstY -= CAST_S16(y2); |
||
460 |
y2 = 0; |
||
461 |
} |
||
462 |
413 |
const int maxh = src->h - y2; |
|
463 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✗ |
413 |
if (maxh < h2) |
464 |
h2 = maxh; |
||
465 |
|||
466 |
413 |
int dy = clipY - dstY; |
|
467 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✗ |
413 |
if (dy > 0) |
468 |
{ |
||
469 |
h2 -= dy; |
||
470 |
dstY += CAST_S16(dy); |
||
471 |
y2 += dy; |
||
472 |
} |
||
473 |
413 |
dy = dstY + h2 - clipY - clip->h; |
|
474 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✗ |
413 |
if (dy > 0) |
475 |
413 |
h2 -= dy; |
|
476 |
|||
477 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✗ |
413 |
if (h2 > 0) |
478 |
{ |
||
479 |
for (int px = 0; px < w; px += iw) |
||
480 |
{ |
||
481 |
const int dw = (px + iw >= w) ? w - px : iw; |
||
482 |
int dstX = px + xOffset; |
||
483 |
int x2 = srcX; |
||
484 |
int w2 = dw; |
||
485 |
if (x2 < 0) |
||
486 |
{ |
||
487 |
w2 += x2; |
||
488 |
dstX -= CAST_S16(x2); |
||
489 |
x2 = 0; |
||
490 |
} |
||
491 |
const int maxw = src->w - x2; |
||
492 |
if (maxw < w2) |
||
493 |
w2 = maxw; |
||
494 |
|||
495 |
int dx = clipX - dstX; |
||
496 |
if (dx > 0) |
||
497 |
{ |
||
498 |
w2 -= dx; |
||
499 |
dstX += CAST_S16(dx); |
||
500 |
x2 += dx; |
||
501 |
} |
||
502 |
dx = dstX + w2 - clipX - clip->w; |
||
503 |
if (dx > 0) |
||
504 |
w2 -= dx; |
||
505 |
|||
506 |
if (w2 > 0) |
||
507 |
{ |
||
508 |
SDL_Rect srcRect = |
||
509 |
{ |
||
510 |
CAST_S16(x2), |
||
511 |
CAST_S16(y2), |
||
512 |
CAST_U16(w2), |
||
513 |
CAST_U16(h2) |
||
514 |
}; |
||
515 |
|||
516 |
SDL_Rect dstRect = |
||
517 |
{ |
||
518 |
CAST_S16(dstX), |
||
519 |
CAST_S16(dstY), |
||
520 |
CAST_U16(w2), |
||
521 |
CAST_U16(h2) |
||
522 |
}; |
||
523 |
|||
524 |
SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); |
||
525 |
} |
||
526 |
|||
527 |
// SDL_BlitSurface(image->mSDLSurface, &srcRect, mWindow, &dstRect); |
||
528 |
} |
||
529 |
} |
||
530 |
} |
||
531 |
} |
||
532 |
|||
533 |
void SDLGraphics::drawRescaledPattern(const Image *restrict const image, |
||
534 |
const int x, const int y, |
||
535 |
const int w, const int h, |
||
536 |
const int scaledWidth, |
||
537 |
const int scaledHeight) restrict2 |
||
538 |
{ |
||
539 |
// Check that preconditions for blitting are met. |
||
540 |
if ((mWindow == nullptr) || (image == nullptr)) |
||
541 |
return; |
||
542 |
if (image->mSDLSurface == nullptr) |
||
543 |
return; |
||
544 |
|||
545 |
if (scaledHeight == 0 || scaledWidth == 0) |
||
546 |
return; |
||
547 |
|||
548 |
Image *const tmpImage = image->SDLgetScaledImage( |
||
549 |
scaledWidth, scaledHeight); |
||
550 |
if (tmpImage == nullptr) |
||
551 |
return; |
||
552 |
|||
553 |
const SDL_Rect &bounds = tmpImage->mBounds; |
||
554 |
const int iw = bounds.w; |
||
555 |
const int ih = bounds.h; |
||
556 |
if (iw == 0 || ih == 0) |
||
557 |
return; |
||
558 |
|||
559 |
const ClipRect &top = mClipStack.top(); |
||
560 |
const int xOffset = top.xOffset + x; |
||
561 |
const int yOffset = top.yOffset + y; |
||
562 |
const int srcX = bounds.x; |
||
563 |
const int srcY = bounds.y; |
||
564 |
|||
565 |
for (int py = 0; py < h; py += ih) // Y position on pattern plane |
||
566 |
{ |
||
567 |
const int dh = (py + ih >= h) ? h - py : ih; |
||
568 |
const int dstY = py + yOffset; |
||
569 |
|||
570 |
for (int px = 0; px < w; px += iw) // X position on pattern plane |
||
571 |
{ |
||
572 |
const int dw = (px + iw >= w) ? w - px : iw; |
||
573 |
const int dstX = px + xOffset; |
||
574 |
|||
575 |
SDL_Rect srcRect = |
||
576 |
{ |
||
577 |
CAST_S16(srcX), |
||
578 |
CAST_S16(srcY), |
||
579 |
CAST_U16(dw), |
||
580 |
CAST_U16(dh) |
||
581 |
}; |
||
582 |
|||
583 |
SDL_Rect dstRect = |
||
584 |
{ |
||
585 |
CAST_S16(dstX), |
||
586 |
CAST_S16(dstY), |
||
587 |
0, |
||
588 |
0 |
||
589 |
}; |
||
590 |
|||
591 |
SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, |
||
592 |
mWindow, &dstRect); |
||
593 |
} |
||
594 |
} |
||
595 |
|||
596 |
delete tmpImage; |
||
597 |
} |
||
598 |
|||
599 |
void SDLGraphics::calcPattern(ImageVertexes *restrict const vert, |
||
600 |
const Image *restrict const image, |
||
601 |
const int x, const int y, |
||
602 |
const int w, const int h) const restrict2 |
||
603 |
{ |
||
604 |
calcPatternInline(vert, image, x, y, w, h); |
||
605 |
} |
||
606 |
|||
607 |
void SDLGraphics::calcPatternInline(ImageVertexes *restrict const vert, |
||
608 |
const Image *restrict const image, |
||
609 |
const int x, const int y, |
||
610 |
const int w, const int h) const restrict2 |
||
611 |
{ |
||
612 |
// Check that preconditions for blitting are met. |
||
613 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗ |
860 |
if (vert == nullptr || |
614 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗ |
1640 |
mWindow == nullptr || |
615 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗ |
820 |
image == nullptr || |
616 |
820 |
image->mSDLSurface == nullptr) |
|
617 |
{ |
||
618 |
return; |
||
619 |
} |
||
620 |
|||
621 |
820 |
const SDL_Rect &bounds = image->mBounds; |
|
622 |
820 |
const int iw = bounds.w; |
|
623 |
820 |
const int ih = bounds.h; |
|
624 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗ |
820 |
if (iw == 0 || ih == 0) |
625 |
return; |
||
626 |
|||
627 |
820 |
const ClipRect &top = mClipStack.top(); |
|
628 |
820 |
const int xOffset = top.xOffset + x; |
|
629 |
820 |
const int yOffset = top.yOffset + y; |
|
630 |
820 |
const int srcX = bounds.x; |
|
631 |
820 |
const int srcY = bounds.y; |
|
632 |
|||
633 |
✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✗ |
820 |
for (int py = 0; py < h; py += ih) // Y position on pattern plane |
634 |
{ |
||
635 |
✓✓✓✗ ✓✗✓✓ ✓✓✓✓ ✗✗ |
3748 |
const int dh = (py + ih >= h) ? h - py : ih; |
636 |
3748 |
const int dstY = py + yOffset; |
|
637 |
|||
638 |
✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✗ |
20241 |
for (int px = 0; px < w; px += iw) // X position on pattern plane |
639 |
{ |
||
640 |
✓✓✓✓ ✓✓✓✗ ✓✗✓✓ ✗✗ |
16493 |
const int dw = (px + iw >= w) ? w - px : iw; |
641 |
16493 |
const int dstX = px + xOffset; |
|
642 |
|||
643 |
16493 |
DoubleRect *const r = new DoubleRect; |
|
644 |
16493 |
SDL_Rect &srcRect = r->src; |
|
645 |
16493 |
srcRect.x = CAST_S16(srcX); |
|
646 |
16493 |
srcRect.y = CAST_S16(srcY); |
|
647 |
16493 |
srcRect.w = CAST_U16(dw); |
|
648 |
16493 |
srcRect.h = CAST_U16(dh); |
|
649 |
16493 |
SDL_Rect &dstRect = r->dst; |
|
650 |
16493 |
dstRect.x = CAST_S16(dstX); |
|
651 |
16493 |
dstRect.y = CAST_S16(dstY); |
|
652 |
|||
653 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✗ |
16493 |
if (SDL_FakeUpperBlit(image->mSDLSurface, &srcRect, |
654 |
16493 |
mWindow, &dstRect) == 1) |
|
655 |
{ |
||
656 |
vert->sdl.push_back(r); |
||
657 |
} |
||
658 |
else |
||
659 |
{ |
||
660 |
16493 |
delete r; |
|
661 |
} |
||
662 |
} |
||
663 |
} |
||
664 |
} |
||
665 |
|||
666 |
40 |
void SDLGraphics::calcPattern(ImageCollection *restrict const vertCol, |
|
667 |
const Image *restrict const image, |
||
668 |
const int x, const int y, |
||
669 |
const int w, const int h) const restrict2 |
||
670 |
{ |
||
671 |
✓✗ | 40 |
if (vertCol == nullptr || image == nullptr) |
672 |
return; |
||
673 |
|||
674 |
40 |
ImageVertexes *vert = nullptr; |
|
675 |
✓✗ | 40 |
if (vertCol->currentImage != image) |
676 |
{ |
||
677 |
✓✗ | 40 |
vert = new ImageVertexes; |
678 |
40 |
vertCol->currentImage = image; |
|
679 |
40 |
vertCol->currentVert = vert; |
|
680 |
40 |
vert->image = image; |
|
681 |
40 |
vertCol->draws.push_back(vert); |
|
682 |
} |
||
683 |
else |
||
684 |
{ |
||
685 |
vert = vertCol->currentVert; |
||
686 |
} |
||
687 |
|||
688 |
80 |
calcPatternInline(vert, image, x, y, w, h); |
|
689 |
} |
||
690 |
|||
691 |
void SDLGraphics::calcTileVertexes(ImageVertexes *restrict const vert, |
||
692 |
const Image *restrict const image, |
||
693 |
int x, int y) const restrict2 |
||
694 |
{ |
||
695 |
vert->image = image; |
||
696 |
calcTileSDL(vert, x, y); |
||
697 |
} |
||
698 |
|||
699 |
void SDLGraphics::calcTileVertexesInline(ImageVertexes *restrict const vert, |
||
700 |
const Image *restrict const image, |
||
701 |
int x, int y) const restrict2 |
||
702 |
{ |
||
703 |
635 |
vert->image = image; |
|
704 |
635 |
calcTileSDL(vert, x, y); |
|
705 |
} |
||
706 |
|||
707 |
697 |
void SDLGraphics::calcTileSDL(ImageVertexes *restrict const vert, |
|
708 |
int x, int y) const restrict2 |
||
709 |
{ |
||
710 |
// Check that preconditions for blitting are met. |
||
711 |
✓✗✓✗ |
1394 |
if (vert == nullptr || |
712 |
✓✗ | 1394 |
vert->image == nullptr || |
713 |
697 |
vert->image->mSDLSurface == nullptr) |
|
714 |
{ |
||
715 |
return; |
||
716 |
} |
||
717 |
|||
718 |
697 |
const Image *const image = vert->image; |
|
719 |
697 |
const ClipRect &top = mClipStack.top(); |
|
720 |
697 |
const SDL_Rect &bounds = image->mBounds; |
|
721 |
|||
722 |
697 |
DoubleRect *rect = new DoubleRect; |
|
723 |
697 |
rect->src.x = CAST_S16(bounds.x); |
|
724 |
697 |
rect->src.y = CAST_S16(bounds.y); |
|
725 |
697 |
rect->src.w = CAST_U16(bounds.w); |
|
726 |
697 |
rect->src.h = CAST_U16(bounds.h); |
|
727 |
697 |
rect->dst.x = CAST_S16(x + top.xOffset); |
|
728 |
697 |
rect->dst.y = CAST_S16(y + top.yOffset); |
|
729 |
✗✓ | 1394 |
if (SDL_FakeUpperBlit(image->mSDLSurface, &rect->src, |
730 |
697 |
mWindow, &rect->dst) == 1) |
|
731 |
{ |
||
732 |
vert->sdl.push_back(rect); |
||
733 |
} |
||
734 |
else |
||
735 |
{ |
||
736 |
697 |
delete rect; |
|
737 |
} |
||
738 |
} |
||
739 |
|||
740 |
62 |
void SDLGraphics::calcTileCollection(ImageCollection *restrict const vertCol, |
|
741 |
const Image *restrict const image, |
||
742 |
int x, int y) restrict2 |
||
743 |
{ |
||
744 |
✓✗ | 62 |
if (vertCol == nullptr) |
745 |
return; |
||
746 |
✓✗ | 62 |
if (vertCol->currentImage != image) |
747 |
{ |
||
748 |
✓✗ | 62 |
ImageVertexes *const vert = new ImageVertexes; |
749 |
62 |
vertCol->currentImage = image; |
|
750 |
62 |
vertCol->currentVert = vert; |
|
751 |
62 |
vert->image = image; |
|
752 |
62 |
vertCol->draws.push_back(vert); |
|
753 |
62 |
calcTileSDL(vert, x, y); |
|
754 |
} |
||
755 |
else |
||
756 |
{ |
||
757 |
calcTileSDL(vertCol->currentVert, x, y); |
||
758 |
} |
||
759 |
} |
||
760 |
|||
761 |
241 |
void SDLGraphics::drawTileCollection(const ImageCollection |
|
762 |
*restrict const vertCol) restrict2 |
||
763 |
{ |
||
764 |
241 |
const ImageVertexesVector &draws = vertCol->draws; |
|
765 |
482 |
const ImageCollectionCIter it_end = draws.end(); |
|
766 |
✓✓ | 992 |
for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it) |
767 |
{ |
||
768 |
269 |
const ImageVertexes *const vert = *it; |
|
769 |
269 |
const Image *const img = vert->image; |
|
770 |
269 |
const DoubleRects *const rects = &vert->sdl; |
|
771 |
538 |
DoubleRects::const_iterator it2 = rects->begin(); |
|
772 |
538 |
const DoubleRects::const_iterator it2_end = rects->end(); |
|
773 |
✗✓ | 269 |
while (it2 != it2_end) |
774 |
{ |
||
775 |
SDL_LowerBlit(img->mSDLSurface, &(*it2)->src, |
||
776 |
mWindow, &(*it2)->dst); |
||
777 |
++ it2; |
||
778 |
} |
||
779 |
} |
||
780 |
241 |
} |
|
781 |
|||
782 |
void SDLGraphics::drawTileVertexes(const ImageVertexes * |
||
783 |
restrict const vert) restrict2 |
||
784 |
{ |
||
785 |
if (vert == nullptr) |
||
786 |
return; |
||
787 |
// vert and img must be != 0 |
||
788 |
const Image *const img = vert->image; |
||
789 |
const DoubleRects *const rects = &vert->sdl; |
||
790 |
DoubleRects::const_iterator it = rects->begin(); |
||
791 |
const DoubleRects::const_iterator it_end = rects->end(); |
||
792 |
while (it != it_end) |
||
793 |
{ |
||
794 |
SDL_LowerBlit(img->mSDLSurface, &(*it)->src, mWindow, &(*it)->dst); |
||
795 |
++ it; |
||
796 |
} |
||
797 |
} |
||
798 |
|||
799 |
67 |
void SDLGraphics::updateScreen() restrict2 |
|
800 |
{ |
||
801 |
BLOCK_START("Graphics::updateScreen") |
||
802 |
✗✓ | 67 |
if (mDoubleBuffer) |
803 |
{ |
||
804 |
SDL_Flip(mWindow); |
||
805 |
} |
||
806 |
else |
||
807 |
{ |
||
808 |
67 |
SDL_UpdateRects(mWindow, 1, &mRect); |
|
809 |
// SDL_UpdateRect(mWindow, 0, 0, 0, 0); |
||
810 |
} |
||
811 |
BLOCK_END("Graphics::updateScreen") |
||
812 |
67 |
} |
|
813 |
|||
814 |
167 |
void SDLGraphics::calcWindow(ImageCollection *restrict const vertCol, |
|
815 |
const int x, const int y, |
||
816 |
const int w, const int h, |
||
817 |
const ImageRect &restrict imgRect) restrict2 |
||
818 |
{ |
||
819 |
167 |
ImageVertexes *vert = nullptr; |
|
820 |
167 |
Image *const image = imgRect.grid[4]; |
|
821 |
✓✗ | 167 |
if (image == nullptr) |
822 |
return; |
||
823 |
✓✗ | 167 |
if (vertCol->currentImage != image) |
824 |
{ |
||
825 |
✓✗ | 167 |
vert = new ImageVertexes; |
826 |
167 |
vertCol->currentImage = image; |
|
827 |
167 |
vertCol->currentVert = vert; |
|
828 |
167 |
vert->image = image; |
|
829 |
167 |
vertCol->draws.push_back(vert); |
|
830 |
} |
||
831 |
else |
||
832 |
{ |
||
833 |
vert = vertCol->currentVert; |
||
834 |
} |
||
835 |
334 |
calcImageRect(vert, x, y, w, h, imgRect); |
|
836 |
} |
||
837 |
|||
838 |
17190 |
int SDLGraphics::SDL_FakeUpperBlit(const SDL_Surface *restrict const src, |
|
839 |
SDL_Rect *restrict const srcrect, |
||
840 |
const SDL_Surface *restrict const dst, |
||
841 |
SDL_Rect *restrict dstrect) const restrict2 |
||
842 |
{ |
||
843 |
int srcx; |
||
844 |
int srcy; |
||
845 |
int w; |
||
846 |
int h; |
||
847 |
|||
848 |
// Make sure the surfaces aren't locked |
||
849 |
✓✗ | 17190 |
if ((src == nullptr) || (dst == nullptr)) |
850 |
return -1; |
||
851 |
|||
852 |
✓✗ | 17190 |
if ((srcrect == nullptr) || (dstrect == nullptr)) |
853 |
return -1; |
||
854 |
|||
855 |
17190 |
srcx = srcrect->x; |
|
856 |
17190 |
w = srcrect->w; |
|
857 |
✗✓ | 17190 |
if (srcx < 0) |
858 |
{ |
||
859 |
w += srcx; |
||
860 |
dstrect->x -= CAST_S16(srcx); |
||
861 |
srcx = 0; |
||
862 |
} |
||
863 |
17190 |
int maxw = src->w - srcx; |
|
864 |
✗✓ | 17190 |
if (maxw < w) |
865 |
w = maxw; |
||
866 |
|||
867 |
17190 |
srcy = srcrect->y; |
|
868 |
17190 |
h = srcrect->h; |
|
869 |
✗✓ | 17190 |
if (srcy < 0) |
870 |
{ |
||
871 |
h += srcy; |
||
872 |
dstrect->y -= CAST_S16(srcy); |
||
873 |
srcy = 0; |
||
874 |
} |
||
875 |
17190 |
int maxh = src->h - srcy; |
|
876 |
✗✓ | 17190 |
if (maxh < h) |
877 |
h = maxh; |
||
878 |
|||
879 |
17190 |
const SDL_Rect *const clip = &dst->clip_rect; |
|
880 |
17190 |
const int clipX = clip->x; |
|
881 |
17190 |
const int clipY = clip->y; |
|
882 |
17190 |
int dx = clipX - dstrect->x; |
|
883 |
✓✓ | 17190 |
if (dx > 0) |
884 |
{ |
||
885 |
171 |
w -= dx; |
|
886 |
171 |
dstrect->x += CAST_S16(dx); |
|
887 |
171 |
srcx += dx; |
|
888 |
} |
||
889 |
17190 |
dx = dstrect->x + w - clipX - clip->w; |
|
890 |
✓✓ | 17190 |
if (dx > 0) |
891 |
17028 |
w -= dx; |
|
892 |
|||
893 |
17190 |
int dy = clipY - dstrect->y; |
|
894 |
✓✓ | 17190 |
if (dy > 0) |
895 |
{ |
||
896 |
1 |
h -= dy; |
|
897 |
1 |
dstrect->y += CAST_S16(dy); |
|
898 |
1 |
srcy += dy; |
|
899 |
} |
||
900 |
17190 |
dy = dstrect->y + h - clipY - clip->h; |
|
901 |
✓✗ | 17190 |
if (dy > 0) |
902 |
17190 |
h -= dy; |
|
903 |
|||
904 |
✗✓ | 17190 |
if (w > 0 && h > 0) |
905 |
{ |
||
906 |
srcrect->x = CAST_S16(srcx); |
||
907 |
srcrect->y = CAST_S16(srcy); |
||
908 |
srcrect->w = CAST_S16(w); |
||
909 |
srcrect->h = CAST_S16(h); |
||
910 |
dstrect->w = CAST_S16(w); |
||
911 |
dstrect->h = CAST_S16(h); |
||
912 |
|||
913 |
return 1; |
||
914 |
// return SDL_LowerBlit(src, &sr, dst, dstrect); |
||
915 |
} |
||
916 |
17190 |
dstrect->w = dstrect->h = 0; |
|
917 |
17190 |
return 0; |
|
918 |
} |
||
919 |
|||
920 |
2 |
void SDLGraphics::fillRectangle(const Rect &restrict rectangle) restrict2 |
|
921 |
{ |
||
922 |
FUNC_BLOCK("Graphics::fillRectangle", 1) |
||
923 |
✓✗ | 2 |
if (mClipStack.empty()) |
924 |
2 |
return; |
|
925 |
|||
926 |
2 |
const ClipRect &restrict top = mClipStack.top(); |
|
927 |
|||
928 |
2 |
Rect area = rectangle; |
|
929 |
2 |
area.x += top.xOffset; |
|
930 |
2 |
area.y += top.yOffset; |
|
931 |
|||
932 |
✗✓ | 2 |
if (!area.isIntersecting(top)) |
933 |
return; |
||
934 |
|||
935 |
if (mAlpha) |
||
936 |
{ |
||
937 |
const int x1 = area.x > top.x ? area.x : top.x; |
||
938 |
const int y1 = area.y > top.y ? area.y : top.y; |
||
939 |
const int x2 = area.x + area.width < top.x + top.width ? |
||
940 |
area.x + area.width : top.x + top.width; |
||
941 |
const int y2 = area.y + area.height < top.y + top.height ? |
||
942 |
area.y + area.height : top.y + top.height; |
||
943 |
|||
944 |
SDL_LockSurface(mWindow); |
||
945 |
|||
946 |
const int bpp = mWindow->format->BytesPerPixel; |
||
947 |
const uint32_t pixel = SDL_MapRGB(mWindow->format, |
||
948 |
CAST_U8(mColor.r), CAST_U8(mColor.g), |
||
949 |
CAST_U8(mColor.b)); |
||
950 |
|||
951 |
switch (bpp) |
||
952 |
{ |
||
953 |
case 1: |
||
954 |
for (int y = y1; y < y2; y++) |
||
955 |
{ |
||
956 |
uint8_t *const p = static_cast<uint8_t *>(mWindow->pixels) |
||
957 |
+ CAST_SIZE(y * mWindow->pitch); |
||
958 |
for (int x = x1; x < x2; x++) |
||
959 |
{ |
||
960 |
*(p + CAST_SIZE(x)) |
||
961 |
= CAST_U8(pixel); |
||
962 |
} |
||
963 |
} |
||
964 |
break; |
||
965 |
case 2: |
||
966 |
for (int y = y1; y < y2; y++) |
||
967 |
{ |
||
968 |
uint8_t *const p0 = static_cast<uint8_t *>(mWindow->pixels) |
||
969 |
+ CAST_SIZE(y * mWindow->pitch); |
||
970 |
for (int x = x1; x < x2; x++) |
||
971 |
{ |
||
972 |
uint8_t *const p = p0 + CAST_SIZE(x * 2); |
||
973 |
*reinterpret_cast<uint16_t *>(p) = SDLAlpha16( |
||
974 |
CAST_U16(pixel), |
||
975 |
*reinterpret_cast<uint16_t *>(p), |
||
976 |
CAST_U8(mColor.a), mWindow->format); |
||
977 |
} |
||
978 |
} |
||
979 |
break; |
||
980 |
case 3: |
||
981 |
{ |
||
982 |
const int ca = 255 - mColor.a; |
||
983 |
const int cr = mColor.r * mColor.a; |
||
984 |
const int cg = mColor.g * mColor.a; |
||
985 |
const int cb = mColor.b * mColor.a; |
||
986 |
|||
987 |
for (int y = y1; y < y2; y++) |
||
988 |
{ |
||
989 |
uint8_t *const p0 = static_cast<uint8_t *>(mWindow->pixels) |
||
990 |
+ CAST_SIZE(y * mWindow->pitch); |
||
991 |
for (int x = x1; x < x2; x++) |
||
992 |
{ |
||
993 |
uint8_t *const p = p0 + CAST_SIZE(x * 3); |
||
994 |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
995 |
p[2] = CAST_U8((p[2] * ca + cb) >> 8); |
||
996 |
p[1] = CAST_U8((p[1] * ca + cg) >> 8); |
||
997 |
p[0] = CAST_U8((p[0] * ca + cr) >> 8); |
||
998 |
#else // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
999 |
p[0] = CAST_U8((p[0] * ca + cb) >> 8); |
||
1000 |
p[1] = CAST_U8((p[1] * ca + cg) >> 8); |
||
1001 |
p[2] = CAST_U8((p[2] * ca + cr) >> 8); |
||
1002 |
#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1003 |
} |
||
1004 |
} |
||
1005 |
break; |
||
1006 |
} |
||
1007 |
case 4: |
||
1008 |
{ |
||
1009 |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1010 |
const unsigned pb = (pixel & 0xff) * mColor.a; |
||
1011 |
const unsigned pg = (pixel & 0xff00) * mColor.a; |
||
1012 |
const unsigned pr = (pixel & 0xff0000) * mColor.a; |
||
1013 |
const unsigned a1 = (255 - mColor.a); |
||
1014 |
|||
1015 |
for (int y = y1; y < y2; y++) |
||
1016 |
{ |
||
1017 |
uint8_t *const p0 = static_cast<uint8_t *>(mWindow->pixels) |
||
1018 |
+ y * mWindow->pitch; |
||
1019 |
for (int x = x1; x < x2; x++) |
||
1020 |
{ |
||
1021 |
uint8_t *p = p0 + x * 4; |
||
1022 |
uint32_t dst = *reinterpret_cast<uint32_t *>(p); |
||
1023 |
const unsigned int b = (pb + (dst & 0xff) * a1) >> 8; |
||
1024 |
const unsigned int g = (pg + (dst & 0xff00) * a1) >> 8; |
||
1025 |
const unsigned int r = (pr |
||
1026 |
+ (dst & 0xff0000) * a1) >> 8; |
||
1027 |
|||
1028 |
*reinterpret_cast<uint32_t *>(p) = ((b & 0xff) |
||
1029 |
| (g & 0xff00) | (r & 0xff0000)); |
||
1030 |
} |
||
1031 |
} |
||
1032 |
#else // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1033 |
if (cR == nullptr) |
||
1034 |
{ |
||
1035 |
cR = new unsigned int[0x100]; |
||
1036 |
cG = new unsigned int[0x100]; |
||
1037 |
cB = new unsigned int[0x100]; |
||
1038 |
mOldPixel = 0; |
||
1039 |
mOldAlpha = mColor.a; |
||
1040 |
} |
||
1041 |
|||
1042 |
const SDL_PixelFormat * const format = mWindow->format; |
||
1043 |
const unsigned rMask = format->Rmask; |
||
1044 |
const unsigned gMask = format->Gmask; |
||
1045 |
const unsigned bMask = format->Bmask; |
||
1046 |
// const unsigned aMask = format->Amask; |
||
1047 |
unsigned rShift = rMask / 0xff; |
||
1048 |
unsigned gShift = gMask / 0xff; |
||
1049 |
unsigned bShift = bMask / 0xff; |
||
1050 |
if (rShift == 0U) |
||
1051 |
rShift = 1; |
||
1052 |
if (gShift == 0U) |
||
1053 |
gShift = 1; |
||
1054 |
if (bShift == 0U) |
||
1055 |
bShift = 1; |
||
1056 |
if (pixel != mOldPixel || mColor.a != mOldAlpha) |
||
1057 |
{ |
||
1058 |
const unsigned pb = (pixel & bMask) * mColor.a; |
||
1059 |
const unsigned pg = (pixel & gMask) * mColor.a; |
||
1060 |
const unsigned pr = (pixel & rMask) * mColor.a; |
||
1061 |
const unsigned a0 = 255 - mColor.a; |
||
1062 |
|||
1063 |
const unsigned int a1 = a0 * bShift; |
||
1064 |
const unsigned int a2 = a0 * gShift; |
||
1065 |
const unsigned int a3 = a0 * rShift; |
||
1066 |
|||
1067 |
for (int f = 0; f <= 0xff; f ++) |
||
1068 |
{ |
||
1069 |
cB[f] = ((pb + f * a1) >> 8) & bMask; |
||
1070 |
cG[f] = ((pg + f * a2) >> 8) & gMask; |
||
1071 |
cR[f] = ((pr + f * a3) >> 8) & rMask; |
||
1072 |
} |
||
1073 |
|||
1074 |
mOldPixel = pixel; |
||
1075 |
mOldAlpha = mColor.a; |
||
1076 |
} |
||
1077 |
|||
1078 |
for (int y = y1; y < y2; y++) |
||
1079 |
{ |
||
1080 |
uint32_t *const p0 = reinterpret_cast<uint32_t*>( |
||
1081 |
static_cast<uint8_t*>(mWindow->pixels) |
||
1082 |
+ CAST_SIZE(y * mWindow->pitch)); |
||
1083 |
for (int x = x1; x < x2; x++) |
||
1084 |
{ |
||
1085 |
uint32_t *const p = p0 + CAST_SIZE(x); |
||
1086 |
const uint32_t dst = *p; |
||
1087 |
*p = cB[dst & bMask / bShift] |
||
1088 |
| cG[(dst & gMask) / gShift] |
||
1089 |
| cR[(dst & rMask) / rShift]; |
||
1090 |
} |
||
1091 |
} |
||
1092 |
#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1093 |
break; |
||
1094 |
} |
||
1095 |
default: |
||
1096 |
break; |
||
1097 |
} |
||
1098 |
|||
1099 |
SDL_UnlockSurface(mWindow); |
||
1100 |
} |
||
1101 |
else |
||
1102 |
{ |
||
1103 |
SDL_Rect rect = |
||
1104 |
{ |
||
1105 |
CAST_S16(area.x), |
||
1106 |
CAST_S16(area.y), |
||
1107 |
CAST_U16(area.width), |
||
1108 |
CAST_U16(area.height) |
||
1109 |
}; |
||
1110 |
|||
1111 |
const uint32_t color = SDL_MapRGBA(mWindow->format, |
||
1112 |
CAST_S8(mColor.r), |
||
1113 |
CAST_S8(mColor.g), |
||
1114 |
CAST_S8(mColor.b), |
||
1115 |
CAST_S8(mColor.a)); |
||
1116 |
SDL_FillRect(mWindow, &rect, color); |
||
1117 |
} |
||
1118 |
} |
||
1119 |
|||
1120 |
void SDLGraphics::beginDraw() restrict2 |
||
1121 |
{ |
||
1122 |
pushClipArea(Rect(0, 0, mRect.w, mRect.h)); |
||
1123 |
} |
||
1124 |
|||
1125 |
void SDLGraphics::endDraw() restrict2 |
||
1126 |
{ |
||
1127 |
popClipArea(); |
||
1128 |
} |
||
1129 |
|||
1130 |
571 |
void SDLGraphics::pushClipArea(const Rect &restrict area) restrict2 |
|
1131 |
{ |
||
1132 |
571 |
Graphics::pushClipArea(area); |
|
1133 |
571 |
const ClipRect &restrict carea = mClipStack.top(); |
|
1134 |
const SDL_Rect rect = |
||
1135 |
{ |
||
1136 |
571 |
CAST_S16(carea.x), |
|
1137 |
571 |
CAST_S16(carea.y), |
|
1138 |
571 |
CAST_U16(carea.width), |
|
1139 |
571 |
CAST_U16(carea.height) |
|
1140 |
2284 |
}; |
|
1141 |
571 |
SDL_SetClipRect(mWindow, &rect); |
|
1142 |
571 |
} |
|
1143 |
|||
1144 |
571 |
void SDLGraphics::popClipArea() restrict2 |
|
1145 |
{ |
||
1146 |
571 |
Graphics::popClipArea(); |
|
1147 |
|||
1148 |
✓✓ | 571 |
if (mClipStack.empty()) |
1149 |
67 |
return; |
|
1150 |
|||
1151 |
504 |
const ClipRect &restrict carea = mClipStack.top(); |
|
1152 |
const SDL_Rect rect = |
||
1153 |
{ |
||
1154 |
504 |
CAST_S16(carea.x), |
|
1155 |
504 |
CAST_S16(carea.y), |
|
1156 |
504 |
CAST_U16(carea.width), |
|
1157 |
504 |
CAST_U16(carea.height) |
|
1158 |
2016 |
}; |
|
1159 |
|||
1160 |
504 |
SDL_SetClipRect(mWindow, &rect); |
|
1161 |
} |
||
1162 |
|||
1163 |
void SDLGraphics::drawPoint(int x, int y) restrict2 |
||
1164 |
{ |
||
1165 |
if (mClipStack.empty()) |
||
1166 |
return; |
||
1167 |
|||
1168 |
const ClipRect& top = mClipStack.top(); |
||
1169 |
|||
1170 |
x += top.xOffset; |
||
1171 |
y += top.yOffset; |
||
1172 |
|||
1173 |
if (!top.isPointInRect(x, y)) |
||
1174 |
return; |
||
1175 |
|||
1176 |
if (mAlpha) |
||
1177 |
SDLputPixelAlpha(mWindow, x, y, mColor); |
||
1178 |
else |
||
1179 |
SDLputPixel(mWindow, x, y, mColor); |
||
1180 |
} |
||
1181 |
|||
1182 |
void SDLGraphics::drawHLine(int x1, int y, int x2) restrict2 |
||
1183 |
{ |
||
1184 |
if (mClipStack.empty()) |
||
1185 |
return; |
||
1186 |
|||
1187 |
const ClipRect& top = mClipStack.top(); |
||
1188 |
|||
1189 |
const int xOffset = top.xOffset; |
||
1190 |
x1 += xOffset; |
||
1191 |
y += top.yOffset; |
||
1192 |
x2 += xOffset; |
||
1193 |
|||
1194 |
const int topY = top.y; |
||
1195 |
if (y < topY || y >= topY + top.height) |
||
1196 |
return; |
||
1197 |
|||
1198 |
if (x1 > x2) |
||
1199 |
{ |
||
1200 |
x1 ^= x2; |
||
1201 |
x2 ^= x1; |
||
1202 |
x1 ^= x2; |
||
1203 |
} |
||
1204 |
|||
1205 |
const int topX = top.x; |
||
1206 |
if (topX > x1) |
||
1207 |
{ |
||
1208 |
if (topX > x2) |
||
1209 |
return; |
||
1210 |
|||
1211 |
x1 = topX; |
||
1212 |
} |
||
1213 |
|||
1214 |
const int sumX = topX + top.width; |
||
1215 |
if (sumX <= x2) |
||
1216 |
{ |
||
1217 |
if (sumX <= x1) |
||
1218 |
return; |
||
1219 |
|||
1220 |
x2 = sumX -1; |
||
1221 |
} |
||
1222 |
|||
1223 |
const int bpp = mWindow->format->BytesPerPixel; |
||
1224 |
|||
1225 |
SDL_LockSurface(mWindow); |
||
1226 |
|||
1227 |
uint8_t *p = static_cast<uint8_t*>(mWindow->pixels) |
||
1228 |
+ CAST_SIZE(y * mWindow->pitch + x1 * bpp); |
||
1229 |
|||
1230 |
const uint32_t pixel = SDL_MapRGB(mWindow->format, |
||
1231 |
CAST_U8(mColor.r), |
||
1232 |
CAST_U8(mColor.g), |
||
1233 |
CAST_U8(mColor.b)); |
||
1234 |
switch (bpp) |
||
1235 |
{ |
||
1236 |
case 1: |
||
1237 |
for (; x1 <= x2; ++x1) |
||
1238 |
*(p++) = CAST_U8(pixel); |
||
1239 |
break; |
||
1240 |
|||
1241 |
case 2: |
||
1242 |
{ |
||
1243 |
uint16_t* q = reinterpret_cast<uint16_t*>(p); |
||
1244 |
const uint16_t pixel1 = CAST_U16(pixel); |
||
1245 |
for (; x1 <= x2; ++x1) |
||
1246 |
*(q++) = pixel1; |
||
1247 |
break; |
||
1248 |
} |
||
1249 |
|||
1250 |
case 3: |
||
1251 |
{ |
||
1252 |
const uint8_t b0 = CAST_U8((pixel >> 16) & 0xff); |
||
1253 |
const uint8_t b1 = CAST_U8((pixel >> 8) & 0xff); |
||
1254 |
const uint8_t b2 = CAST_U8(pixel & 0xff); |
||
1255 |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1256 |
for (; x1 <= x2; ++x1) |
||
1257 |
{ |
||
1258 |
p[0] = b0; |
||
1259 |
p[1] = b1; |
||
1260 |
p[2] = b2; |
||
1261 |
p += 3; |
||
1262 |
} |
||
1263 |
#else // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1264 |
for (; x1 <= x2; ++x1) |
||
1265 |
{ |
||
1266 |
p[0] = b2; |
||
1267 |
p[1] = b1; |
||
1268 |
p[2] = b0; |
||
1269 |
p += 3; |
||
1270 |
} |
||
1271 |
#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1272 |
break; |
||
1273 |
} |
||
1274 |
|||
1275 |
case 4: |
||
1276 |
{ |
||
1277 |
uint32_t *q = reinterpret_cast<uint32_t*>(p); |
||
1278 |
if (mAlpha) |
||
1279 |
{ |
||
1280 |
unsigned char a = CAST_U8(mColor.a); |
||
1281 |
unsigned char a1 = CAST_U8(255U - a); |
||
1282 |
const int b0 = (pixel & 0xff) * a; |
||
1283 |
const int g0 = (pixel & 0xff00) * a; |
||
1284 |
const int r0 = (pixel & 0xff0000) * a; |
||
1285 |
for (; x1 <= x2; ++x1) |
||
1286 |
{ |
||
1287 |
const unsigned int b = (b0 + (*q & 0xff) * a1) >> 8; |
||
1288 |
const unsigned int g = (g0 + (*q & 0xff00) * a1) >> 8; |
||
1289 |
const unsigned int r = (r0 + (*q & 0xff0000) * a1) >> 8; |
||
1290 |
*q = (b & 0xff) | (g & 0xff00) | (r & 0xff0000); |
||
1291 |
|||
1292 |
q++; |
||
1293 |
} |
||
1294 |
} |
||
1295 |
else |
||
1296 |
{ |
||
1297 |
for (; x1 <= x2; ++x1) |
||
1298 |
*(q++) = pixel; |
||
1299 |
} |
||
1300 |
break; |
||
1301 |
} |
||
1302 |
default: |
||
1303 |
break; |
||
1304 |
} // end switch |
||
1305 |
|||
1306 |
SDL_UnlockSurface(mWindow); |
||
1307 |
} |
||
1308 |
|||
1309 |
4 |
void SDLGraphics::drawVLine(int x, int y1, int y2) restrict2 |
|
1310 |
{ |
||
1311 |
✓✗ | 4 |
if (mClipStack.empty()) |
1312 |
return; |
||
1313 |
|||
1314 |
4 |
const ClipRect &restrict top = mClipStack.top(); |
|
1315 |
|||
1316 |
4 |
const int yOffset = top.yOffset; |
|
1317 |
4 |
x += top.xOffset; |
|
1318 |
4 |
y1 += yOffset; |
|
1319 |
4 |
y2 += yOffset; |
|
1320 |
|||
1321 |
✓✗✗✓ |
4 |
if (x < top.x || x >= top.x + top.width) |
1322 |
return; |
||
1323 |
|||
1324 |
if (y1 > y2) |
||
1325 |
{ |
||
1326 |
y1 ^= y2; |
||
1327 |
y2 ^= y1; |
||
1328 |
y1 ^= y2; |
||
1329 |
} |
||
1330 |
|||
1331 |
if (top.y > y1) |
||
1332 |
{ |
||
1333 |
if (top.y > y2) |
||
1334 |
return; |
||
1335 |
|||
1336 |
y1 = top.y; |
||
1337 |
} |
||
1338 |
|||
1339 |
const int sumY = top.y + top.height; |
||
1340 |
if (sumY <= y2) |
||
1341 |
{ |
||
1342 |
if (sumY <= y1) |
||
1343 |
return; |
||
1344 |
|||
1345 |
y2 = sumY - 1; |
||
1346 |
} |
||
1347 |
|||
1348 |
const int bpp = mWindow->format->BytesPerPixel; |
||
1349 |
|||
1350 |
SDL_LockSurface(mWindow); |
||
1351 |
|||
1352 |
uint8_t *p = static_cast<uint8_t*>(mWindow->pixels) |
||
1353 |
+ CAST_SIZE(y1 * mWindow->pitch + x * bpp); |
||
1354 |
|||
1355 |
const uint32_t pixel = SDL_MapRGB(mWindow->format, |
||
1356 |
CAST_U8(mColor.r), |
||
1357 |
CAST_U8(mColor.g), |
||
1358 |
CAST_U8(mColor.b)); |
||
1359 |
|||
1360 |
const int pitch = mWindow->pitch; |
||
1361 |
switch (bpp) |
||
1362 |
{ |
||
1363 |
case 1: |
||
1364 |
for (; y1 <= y2; ++y1) |
||
1365 |
{ |
||
1366 |
*p = CAST_U8(pixel); |
||
1367 |
p += pitch; |
||
1368 |
} |
||
1369 |
break; |
||
1370 |
|||
1371 |
case 2: |
||
1372 |
for (; y1 <= y2; ++ y1) |
||
1373 |
{ |
||
1374 |
*reinterpret_cast<uint16_t*>(p) |
||
1375 |
= CAST_U16(pixel); |
||
1376 |
p += pitch; |
||
1377 |
} |
||
1378 |
break; |
||
1379 |
|||
1380 |
case 3: |
||
1381 |
{ |
||
1382 |
const uint8_t b0 = CAST_U8((pixel >> 16) & 0xff); |
||
1383 |
const uint8_t b1 = CAST_U8((pixel >> 8) & 0xff); |
||
1384 |
const uint8_t b2 = CAST_U8(pixel & 0xff); |
||
1385 |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1386 |
for (; y1 <= y2; ++y1) |
||
1387 |
{ |
||
1388 |
p[0] = b0; |
||
1389 |
p[1] = b1; |
||
1390 |
p[2] = b2; |
||
1391 |
p += pitch; |
||
1392 |
} |
||
1393 |
#else // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1394 |
for (; y1 <= y2; ++y1) |
||
1395 |
{ |
||
1396 |
p[0] = b2; |
||
1397 |
p[1] = b1; |
||
1398 |
p[2] = b0; |
||
1399 |
p += pitch; |
||
1400 |
} |
||
1401 |
#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN |
||
1402 |
break; |
||
1403 |
} |
||
1404 |
|||
1405 |
case 4: |
||
1406 |
{ |
||
1407 |
if (mAlpha) |
||
1408 |
{ |
||
1409 |
unsigned char a = CAST_U8(mColor.a); |
||
1410 |
unsigned char a1 = CAST_U8(255U - a); |
||
1411 |
const int b0 = (pixel & 0xff) * a; |
||
1412 |
const int g0 = (pixel & 0xff00) * a; |
||
1413 |
const int r0 = (pixel & 0xff0000) * a; |
||
1414 |
for (; y1 <= y2; ++y1) |
||
1415 |
{ |
||
1416 |
const unsigned int dst = *reinterpret_cast<uint32_t*>(p); |
||
1417 |
const unsigned int b = (b0 + (dst & 0xff) * a1) >> 8; |
||
1418 |
const unsigned int g = (g0 + (dst & 0xff00) * a1) >> 8; |
||
1419 |
const unsigned int r = (r0 + (dst & 0xff0000) * a1) >> 8; |
||
1420 |
*reinterpret_cast<uint32_t*>(p) = |
||
1421 |
(b & 0xff) | (g & 0xff00) | (r & 0xff0000); |
||
1422 |
|||
1423 |
p += pitch; |
||
1424 |
} |
||
1425 |
} |
||
1426 |
else |
||
1427 |
{ |
||
1428 |
for (; y1 <= y2; ++y1) |
||
1429 |
{ |
||
1430 |
*reinterpret_cast<uint32_t*>(p) = pixel; |
||
1431 |
p += pitch; |
||
1432 |
} |
||
1433 |
} |
||
1434 |
break; |
||
1435 |
} |
||
1436 |
|||
1437 |
default: |
||
1438 |
break; |
||
1439 |
} // end switch |
||
1440 |
|||
1441 |
SDL_UnlockSurface(mWindow); |
||
1442 |
} |
||
1443 |
|||
1444 |
void SDLGraphics::drawRectangle(const Rect &restrict rectangle) restrict2 |
||
1445 |
{ |
||
1446 |
const int x1 = rectangle.x; |
||
1447 |
const int x2 = x1 + rectangle.width - 1; |
||
1448 |
const int y1 = rectangle.y; |
||
1449 |
const int y2 = y1 + rectangle.height - 1; |
||
1450 |
|||
1451 |
drawHLine(x1, y1, x2); |
||
1452 |
drawHLine(x1, y2, x2); |
||
1453 |
|||
1454 |
drawVLine(x1, y1, y2); |
||
1455 |
drawVLine(x2, y1, y2); |
||
1456 |
} |
||
1457 |
|||
1458 |
4 |
void SDLGraphics::drawLine(int x1, int y1, |
|
1459 |
int x2, int y2) restrict2 |
||
1460 |
{ |
||
1461 |
✓✗ | 4 |
if (x1 == x2) |
1462 |
{ |
||
1463 |
4 |
drawVLine(x1, y1, y2); |
|
1464 |
4 |
return; |
|
1465 |
} |
||
1466 |
if (y1 == y2) |
||
1467 |
{ |
||
1468 |
drawHLine(x1, y1, x2); |
||
1469 |
return; |
||
1470 |
} |
||
1471 |
|||
1472 |
// other cases not implemented |
||
1473 |
} |
||
1474 |
|||
1475 |
77 |
bool SDLGraphics::setVideoMode(const int w, const int h, |
|
1476 |
const int scale, |
||
1477 |
const int bpp, |
||
1478 |
const bool fs, |
||
1479 |
const bool hwaccel, |
||
1480 |
const bool resize, |
||
1481 |
const bool noFrame, |
||
1482 |
const bool allowHighDPI) restrict2 |
||
1483 |
{ |
||
1484 |
77 |
setMainFlags(w, h, |
|
1485 |
scale, |
||
1486 |
bpp, |
||
1487 |
fs, |
||
1488 |
hwaccel, |
||
1489 |
resize, |
||
1490 |
noFrame, |
||
1491 |
77 |
allowHighDPI); |
|
1492 |
|||
1493 |
✗✓ | 77 |
if ((mWindow = GraphicsManager::createWindow(w, h, bpp, |
1494 |
getSoftwareFlags())) == nullptr) |
||
1495 |
{ |
||
1496 |
mRect.w = 0; |
||
1497 |
mRect.h = 0; |
||
1498 |
return false; |
||
1499 |
} |
||
1500 |
|||
1501 |
77 |
mRect.w = CAST_U16(mWindow->w); |
|
1502 |
77 |
mRect.h = CAST_U16(mWindow->h); |
|
1503 |
|||
1504 |
77 |
return videoInfo(); |
|
1505 |
} |
||
1506 |
|||
1507 |
46 |
void SDLGraphics::drawImageRect(const int x, const int y, |
|
1508 |
const int w, const int h, |
||
1509 |
const ImageRect &restrict imgRect) restrict2 |
||
1510 |
{ |
||
1511 |
#include "render/graphics_drawImageRect.hpp" |
||
1512 |
46 |
} |
|
1513 |
|||
1514 |
void SDLGraphics::calcImageRect(ImageVertexes *restrict const vert, |
||
1515 |
const int x, const int y, |
||
1516 |
const int w, const int h, |
||
1517 |
const ImageRect &restrict imgRect) restrict2 |
||
1518 |
{ |
||
1519 |
#include "render/graphics_calcImageRect.hpp" |
||
1520 |
} |
||
1521 |
|||
1522 |
#endif // USE_SDL2 |
Generated by: GCOVR (Version 3.3) |