FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
sdlimage.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <cassert>
24 #include <iostream>
25 
26 // 3rd party library includes
27 
28 // FIFE includes
29 // These includes are split up in two parts, separated by one empty line
30 // First block: files included from the FIFE root src directory
31 // Second block: files included from the same folder
32 #include "util/log/logger.h"
33 #include "util/structures/rect.h"
34 #include "video/imagemanager.h"
35 #include "video/renderbackend.h"
36 
37 #include "renderbackendsdl.h"
38 #include "sdlblendingfunctions.h"
39 #include "sdlimage.h"
40 
41 namespace FIFE {
45  static Logger _log(LM_VIDEO);
46 
48  Image(loader) {
49  resetSdlimage();
50  }
51 
52  SDLImage::SDLImage(const std::string& name, IResourceLoader* loader):
53  Image(name, loader) {
54  resetSdlimage();
55  }
56 
57  SDLImage::SDLImage(SDL_Surface* surface):
58  Image(surface) {
59  resetSdlimage();
60  }
61 
62  SDLImage::SDLImage(const std::string& name, SDL_Surface* surface):
63  Image(name, surface) {
64  resetSdlimage();
65  }
66 
67  SDLImage::SDLImage(const uint8_t* data, uint32_t width, uint32_t height):
68  Image(data, width, height) {
69  resetSdlimage();
70  }
71 
72  SDLImage::SDLImage(const std::string& name, const uint8_t* data, uint32_t width, uint32_t height):
73  Image(name, data, width, height) {
74  resetSdlimage();
75  }
76 
78  m_last_alpha = 255;
79  m_finalized = false;
81  m_scale_x = 1.0;
82  m_scale_y = 1.0;
83  m_zoom_surface = NULL;
84  }
85 
87  if (m_zoom_surface) {
88  SDL_FreeSurface(m_zoom_surface);
89  }
90  }
91 
92  void SDLImage::setSurface(SDL_Surface* surface) {
93  if (m_zoom_surface) {
94  SDL_FreeSurface(m_zoom_surface);
95  m_zoom_surface = NULL;
96  }
97  reset(surface);
98  resetSdlimage();
99  }
100 
101  void SDL_BlitSurfaceWithAlpha( const SDL_Surface* src, const SDL_Rect* srcRect,
102  SDL_Surface* dst, SDL_Rect* dstRect, uint8_t alpha ) {
103  if( 0 == alpha ) {
104  return;
105  }
106 
107  int32_t screenX, screenY;
108  if( dstRect ) {
109  screenX = dstRect->x;
110  screenY = dstRect->y;
111  } else {
112  screenX = dst->clip_rect.x;
113  screenY = dst->clip_rect.y;
114  }
115 
116  int32_t width, height, tX, tY;
117  if( srcRect ) {
118  tX = srcRect->x;
119  tY = srcRect->y;
120  width = srcRect->w;
121  height = srcRect->h;
122  } else {
123  tX = src->clip_rect.x;
124  tY = src->clip_rect.y;
125  width = src->clip_rect.w;
126  height = src->clip_rect.h;
127  }
128 
129  // Clipping.
130  if( ( screenX >= ( dst->clip_rect.x + dst->clip_rect.w ) ) ||
131  ( screenY >= ( dst->clip_rect.y + dst->clip_rect.h ) ) ||
132  ( ( screenX + width ) <= dst->clip_rect.x ) ||
133  ( ( screenY + height ) <= dst->clip_rect.y ) ) {
134  return;
135  }
136 
137  if( screenX < dst->clip_rect.x ) {
138  int32_t dX = dst->clip_rect.x - screenX;
139  screenX += dX;
140  width -= dX;
141  tX += dX;
142  }
143 
144  if( ( screenX + width ) > ( dst->clip_rect.x + dst->clip_rect.w ) ) {
145  int32_t dX = ( screenX + width ) - ( dst->clip_rect.x + dst->clip_rect.w );
146  width -= dX;
147  }
148 
149  if( screenY < dst->clip_rect.y ) {
150  int32_t dY = dst->clip_rect.y - screenY;
151  screenY += dY;
152  height -= dY;
153  tY += dY;
154  }
155 
156  if( ( screenY + height ) > ( dst->clip_rect.y + dst->clip_rect.h ) ) {
157  int32_t dY = ( screenY + height ) - ( dst->clip_rect.y + dst->clip_rect.h );
158  height -= dY;
159  }
160 
161  if( ( 0 >= height ) || ( 0 >= width ) ) {
162  return;
163  }
164 
165  SDL_LockSurface( dst );
166 
167  uint8_t* srcData = reinterpret_cast< uint8_t* > ( src->pixels );
168  uint8_t* dstData = reinterpret_cast< uint8_t* > ( dst->pixels );
169 
170  // move data pointers to the start of the pixels we're copying
171  srcData += tY * src->pitch + tX * src->format->BytesPerPixel;
172  dstData += screenY * dst->pitch + screenX * dst->format->BytesPerPixel;
173 
174  switch( src->format->BitsPerPixel ) {
175  case 32: {
176  switch( dst->format->BitsPerPixel ) {
177  case 16: {
178  if( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) {
179  for( int32_t y = height; y > 0; --y ) {
180  SDL_BlendRow_RGBA8_to_RGB565( srcData, dstData, alpha, width );
181  srcData += src->pitch;
182  dstData += dst->pitch;
183  }
184  }
185  }
186  break;
187 
188  case 24: {
189  for( int32_t y = height; y > 0; --y ) {
190  SDL_BlendRow_RGBA8_to_RGB8( srcData, dstData, alpha, width );
191  srcData += src->pitch;
192  dstData += dst->pitch;
193  }
194  }
195  break;
196 
197  case 32: {
198  for( int32_t y = height; y > 0; --y ) {
199  SDL_BlendRow_RGBA8_to_RGBA8( srcData, dstData, alpha, width );
200  srcData += src->pitch;
201  dstData += dst->pitch;
202  }
203  }
204  break;
205 
206  default:
207  break;
208  }
209  }
210  break;
211 
212  case 16: {
213  if( 0x000F == src->format->Amask ) {
214  if( ( 16 == dst->format->BitsPerPixel ) &&
215  ( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) ) {
216  for( int32_t y = height; y > 0; --y ) {
217  SDL_BlendRow_RGBA4_to_RGB565( srcData, dstData, alpha, width );
218  srcData += src->pitch;
219  dstData += dst->pitch;
220  }
221  }
222  }
223  }
224  break;
225 
226  default:
227  break;
228  }
229 
230  SDL_UnlockSurface( dst );
231  }
232 
233  void zoomSurface(SDL_Surface* src, SDL_Surface* dst) {
234  uint32_t* src_pointer = static_cast<uint32_t*>(src->pixels);
235  uint32_t* src_help_pointer = src_pointer;
236  uint32_t* dst_pointer = static_cast<uint32_t*>(dst->pixels);
237 
238  int32_t x, y, *sx_ca, *sy_ca;
239  int32_t sx = static_cast<int32_t>(0xffff * src->w / dst->w);
240  int32_t sy = static_cast<int32_t>(0xffff * src->h / dst->h);
241  int32_t sx_c = 0;
242  int32_t sy_c = 0;
243 
244  // Allocates memory and calculates row wide&height
245  int32_t* sx_a = new int32_t[dst->w + 1];
246  sx_ca = sx_a;
247  for (x = 0; x <= dst->w; x++) {
248  *sx_ca = sx_c;
249  sx_ca++;
250  sx_c &= 0xffff;
251  sx_c += sx;
252  }
253 
254  int32_t* sy_a = new int32_t[dst->h + 1];
255  sy_ca = sy_a;
256  for (y = 0; y <= dst->h; y++) {
257  *sy_ca = sy_c;
258  sy_ca++;
259  sy_c &= 0xffff;
260  sy_c += sy;
261  }
262  sy_ca = sy_a;
263 
264  // Transfers the image data
265 
266  if (SDL_MUSTLOCK(src)) {
267  SDL_LockSurface(src);
268  }
269  if (SDL_MUSTLOCK(dst)) {
270  SDL_LockSurface(dst);
271  }
272 
273  for (y = 0; y < dst->h; y++) {
274  src_pointer = src_help_pointer;
275  sx_ca = sx_a;
276  for (x = 0; x < dst->w; x++) {
277  *dst_pointer = *src_pointer;
278  sx_ca++;
279  src_pointer += (*sx_ca >> 16);
280  dst_pointer++;
281  }
282  sy_ca++;
283  src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
284  }
285 
286  if (SDL_MUSTLOCK(dst)) {
287  SDL_UnlockSurface(dst);
288  }
289  if (SDL_MUSTLOCK(src)) {
290  SDL_UnlockSurface(src);
291  }
292 
293  // Free memory
294  delete [] sx_a;
295  delete [] sy_a;
296  }
297 
298  SDL_Surface* getZoomedSurface(SDL_Surface * src, double zoomx, double zoomy) {
299  if (src == NULL)
300  return NULL;
301 
302  SDL_Surface *zoom_src;
303  SDL_Surface *zoom_dst;
304  int32_t dst_w = static_cast<int32_t>(round(src->w * zoomx));
305  int32_t dst_h = static_cast<int32_t>(round(src->h * zoomy));
306  if (dst_w < 1)
307  dst_w = 1;
308  if (dst_h < 1)
309  dst_h = 1;
310 
311  // If source surface has no alpha channel then convert it
312  if (src->format->Amask == 0) {
313  zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
314  RMASK, GMASK,
315  BMASK, AMASK);
316  SDL_BlitSurface(src, NULL, zoom_src, NULL);
317  } else {
318  zoom_src = src;
319  }
320  // Create destination surface
321  zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_w, dst_h, 32,
322  zoom_src->format->Rmask, zoom_src->format->Gmask,
323  zoom_src->format->Bmask, zoom_src->format->Amask);
324 
325  // Zoom surface
326  zoomSurface(zoom_src, zoom_dst);
327 
328  return zoom_dst;
329  }
330 
331  bool nearlyEqual(float a, float b) {
332  return ABS(a - b) <= 0.00001;
333  }
334 
335  void SDLImage::render(const Rect& rect, uint8_t alpha, uint8_t const* /*unused rgb*/) {
336  if (alpha == 0) {
337  return;
338  }
339  validateShared();
340  SDL_Surface* target = RenderBackend::instance()->getRenderTargetSurface();
341  assert(target != m_surface); // can't draw on the source surface
342 
343  if (rect.right() < 0 || rect.x > static_cast<int32_t>(target->w) ||
344  rect.bottom() < 0 || rect.y > static_cast<int32_t>(target->h)) {
345  return;
346  }
347  finalize();
348 
349  SDL_Rect r;
350  r.x = rect.x;
351  r.y = rect.y;
352  r.w = rect.w;
353  r.h = rect.h;
354 
355  float scale_x = static_cast<float>(rect.w) / static_cast<float>(m_surface->w);
356  float scale_y = static_cast<float>(rect.h) / static_cast<float>(m_surface->h);
357  bool zoomed = false;
358  bool equal = false;
359 
360  if (!nearlyEqual(scale_x, 1.0) && !nearlyEqual(scale_y, 1.0)) {
361  zoomed = true;
362  if(nearlyEqual(m_scale_x, scale_x) && nearlyEqual(m_scale_y, scale_y)) {
363  equal = true;
364  } else {
365  m_scale_x = scale_x;
366  m_scale_y = scale_y;
367  }
368  }
369 
370  if (m_surface->format->Amask == 0) {
371  // Image has no alpha channel. This allows us to use the per-surface alpha.
372  if (m_last_alpha != alpha) {
373  m_last_alpha = alpha;
374  SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
375  }
376  if (!zoomed) {
377  SDL_BlitSurface(m_surface, 0, target, &r);
378  } else if (equal && m_zoom_surface) {
379  SDL_BlitSurface(m_zoom_surface, 0, target, &r);
380  } else {
381  SDL_FreeSurface(m_zoom_surface);
383  SDL_BlitSurface(m_zoom_surface, 0, target, &r);
384  }
385  } else {
386  if( 255 != alpha ) {
387  // Special blitting routine with alpha blending:
388  // dst.rgb = ( src.rgb * src.a * alpha ) + ( dst.rgb * (255 - ( src.a * alpha ) ) );
389  if (!zoomed) {
390  SDL_BlitSurfaceWithAlpha( m_surface, 0, target, &r, alpha );
391  } else if (equal && m_zoom_surface) {
392  SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, target, &r, alpha );
393  } else {
394  SDL_FreeSurface(m_zoom_surface);
396  SDL_BlitSurfaceWithAlpha(m_zoom_surface, 0, target, &r, alpha );
397  }
398  } else {
399  if (!zoomed) {
400  SDL_BlitSurface(m_surface, 0, target, &r);
401  } else if (equal && m_zoom_surface) {
402  SDL_BlitSurface(m_zoom_surface, 0, target, &r);
403  } else {
404  SDL_FreeSurface(m_zoom_surface);
406  SDL_BlitSurface(m_zoom_surface, 0, target, &r);
407  }
408  }
409  }
410  }
411 
413  if( m_finalized ) {
414  return;
415  }
416  // ultimate possibility to load the image
417  // is used e.g. in case a cursor or gui image is freed even if there is a reference
418  if (!m_surface) {
420  load();
421  assert(m_surface);
422  }
423  m_finalized = true;
424  SDL_Surface *old_surface = m_surface;
425  Uint32 key = SDL_MapRGB(m_surface->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
426 
427  if (m_surface->format->Amask == 0) {
428  // only use color key if feature is enabled
429  if (RenderBackend::instance()->isColorKeyEnabled()) {
430  SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
431  }
432 
433  m_surface = SDL_DisplayFormat(m_surface);
434  } else {
436  bool m_isalphaoptimized = be->isAlphaOptimizerEnabled();
437  if( m_isalphaoptimized ) {
439  } else {
440  SDL_SetAlpha(m_surface, SDL_SRCALPHA, 255);
441 
442  // only use color key if feature is enabled
443  if (RenderBackend::instance()->isColorKeyEnabled()) {
444  SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
445  }
446 
447  m_surface = SDL_DisplayFormatAlpha(m_surface);
448  }
449  }
450  SDL_FreeSurface(old_surface);
451  }
452 
453  SDL_Surface* SDLImage::optimize(SDL_Surface* src) {
454  // The algorithm is originally by "Tim Goya" <tuxdev103@gmail.com>
455  // Few modifications and adaptions by the FIFE team.
456  //
457  // It tries to determine whether an image with a alpha channel
458  // actually uses that. Often PNGs contains an alpha channels
459  // as they don't provide a colorkey feature(?) - so to speed
460  // up SDL rendering we try to remove the alpha channel.
461 
462  // As a reminder: src->format->Amask != 0 here
463 
464  int32_t transparent = 0;
465  int32_t opaque = 0;
466  int32_t semitransparent = 0;
467  int32_t alphasum = 0;
468  int32_t alphasquaresum = 0;
469  bool colors[(1 << 12)];
470  memset(colors, 0, (1 << 12) * sizeof(bool));
471 
472  int32_t bpp = src->format->BytesPerPixel;
473  if(SDL_MUSTLOCK(src)) {
474  SDL_LockSurface(src);
475  }
476  /* In the first pass through we calculate avg(alpha), avg(alpha^2)
477  and the number of semitransparent pixels.
478  We also try to find a useable color.
479  */
480  for(int32_t y = 0;y < src->h;y++) {
481  for(int32_t x = 0;x < src->w;x++) {
482  Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
483  Uint32 mapped = 0;
484  switch(bpp) {
485  case 1:
486  mapped = *pixel;
487  break;
488  case 2:
489  mapped = *(Uint16 *)pixel;
490  break;
491  case 3:
492 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
493  mapped |= pixel[0] << 16;
494  mapped |= pixel[1] << 8;
495  mapped |= pixel[2] << 0;
496 #else
497  mapped |= pixel[0] << 0;
498  mapped |= pixel[1] << 8;
499  mapped |= pixel[2] << 16;
500 #endif
501  break;
502  case 4:
503  mapped = *(Uint32 *)pixel;
504  break;
505  }
506  Uint8 red, green, blue, alpha;
507  SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
508  if(alpha < 16) {
509  transparent++;
510  } else if (alpha > 240) {
511  opaque++;
512  alphasum += alpha;
513  alphasquaresum += alpha*alpha;
514  } else {
515  semitransparent++;
516  alphasum += alpha;
517  alphasquaresum += alpha*alpha;
518  }
519  // mark the color as used.
520  if( alpha != 0 ) {
521  colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true;
522  }
523  }
524  }
525  int32_t avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0;
526  int32_t alphavariance = 0;
527 
528  if(SDL_MUSTLOCK(src)) {
529  SDL_UnlockSurface(src);
530  }
531  alphasquaresum /= (opaque + semitransparent) ? (opaque + semitransparent) : 1;
532  alphavariance = alphasquaresum - avgalpha*avgalpha;
533  if(semitransparent > ((transparent + opaque + semitransparent) / 8)
534  && alphavariance > 16) {
535  FL_DBG(_log, LMsg("sdlimage")
536  << "Trying to alpha-optimize image. FAILED: real alpha usage. "
537  << " alphavariance=" << alphavariance
538  << " total=" << (transparent + opaque + semitransparent)
539  << " semitransparent=" << semitransparent
540  << "(" << (float(semitransparent)/(transparent + opaque + semitransparent))
541  << ")");
542  return SDL_DisplayFormatAlpha(src);
543  }
544 
545  // check availability of a suitable color as colorkey
546  int32_t keycolor = -1;
547  for(int32_t i = 0;i < (1 << 12);i++) {
548  if(!colors[i]) {
549  keycolor = i;
550  break;
551  }
552  }
553  if(keycolor == -1) {
554  FL_DBG(_log, LMsg("sdlimage") << "Trying to alpha-optimize image. FAILED: no free color");
555  return SDL_DisplayFormatAlpha(src);
556  }
557 
558  SDL_Surface *dst = SDL_CreateRGBSurface((src->flags & ~(SDL_SRCALPHA)) | SDL_SWSURFACE,
559  src->w, src->h,
560  src->format->BitsPerPixel,
561  src->format->Rmask, src->format->Gmask,
562  src->format->Bmask, 0);
563  bpp = dst->format->BytesPerPixel;
564 
565  Uint32 key = SDL_MapRGB(dst->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
566 
567  // if the global color key feature is disabled, then use the manually found color key
568  if (!RenderBackend::instance()->isColorKeyEnabled()) {
569  key = SDL_MapRGB(dst->format,
570  (((keycolor & 0xf00) >> 4) | 0xf),
571  ((keycolor & 0xf0) | 0xf),
572  (((keycolor & 0xf) << 4) | 0xf));
573  }
574 
575  if(SDL_MUSTLOCK(src)) {
576  SDL_LockSurface(src);
577  }
578  if(SDL_MUSTLOCK(dst)) {
579  SDL_LockSurface(dst);
580  }
581  for(int32_t y = 0;y < dst->h;y++) {
582  for(int32_t x = 0;x < dst->w;x++) {
583  Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
584  Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
585  Uint32 mapped = 0;
586  switch(bpp) {
587  case 1:
588  mapped = *srcpixel;
589  break;
590  case 2:
591  mapped = *(Uint16 *)srcpixel;
592  break;
593  case 3:
594 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
595  mapped |= srcpixel[0] << 16;
596  mapped |= srcpixel[1] << 8;
597  mapped |= srcpixel[2] << 0;
598 #else
599  mapped |= srcpixel[0] << 0;
600  mapped |= srcpixel[1] << 8;
601  mapped |= srcpixel[2] << 16;
602 #endif
603  break;
604  case 4:
605  mapped = *(Uint32 *)srcpixel;
606  break;
607  }
608  Uint8 red, green, blue, alpha;
609  SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
610  if(alpha < (avgalpha / 4)) {
611  mapped = key;
612  } else {
613  mapped = SDL_MapRGB(dst->format, red, green, blue);
614  }
615  switch(bpp) {
616  case 1:
617  *dstpixel = mapped;
618  break;
619  case 2:
620  *(Uint16 *)dstpixel = mapped;
621  break;
622  case 3:
623 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
624  dstpixel[0] = (mapped >> 16) & 0xff;
625  dstpixel[1] = (mapped >> 8) & 0xff;
626  dstpixel[2] = (mapped >> 0) & 0xff;
627 #else
628  dstpixel[0] = (mapped >> 0) & 0xff;
629  dstpixel[1] = (mapped >> 8) & 0xff;
630  dstpixel[2] = (mapped >> 16) & 0xff;
631 #endif
632  break;
633  case 4:
634  *(Uint32 *)dstpixel = mapped;
635  break;
636  }
637  }
638  }
639  if(SDL_MUSTLOCK(dst)) {
640  SDL_UnlockSurface(dst);
641  }
642  if(SDL_MUSTLOCK(src)) {
643  SDL_UnlockSurface(src);
644  }
645  // Using the per surface alpha value does not
646  // work out for mostly transparent pixels.
647  // Thus disabling the part here - this needs a
648  // more complex refactoring.
649  // if(avgalpha < 240) {
650  // SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha);
651  //}
652  SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key);
653  SDL_Surface *convert = SDL_DisplayFormat(dst);
654  SDL_FreeSurface(dst);
655  FL_DBG(_log, LMsg("sdlimage ")
656  << "Trying to alpha-optimize image. SUCCESS: colorkey is " << key);
657  return convert;
658  } // end optimize
659 
660  size_t SDLImage::getSize() {
661  size_t zoomSize = 0;
662  if (m_zoom_surface) {
663  zoomSize = m_zoom_surface->h * m_zoom_surface->pitch;
664  }
665  if (m_surface) {
666  zoomSize += m_surface->h * m_surface->pitch;
667  }
668 
669  return zoomSize;
670  }
671 
672  void SDLImage::useSharedImage(const ImagePtr& shared, const Rect& region) {
673  if(shared->getState() != IResource::RES_LOADED) {
674  shared->load();
675  }
676  SDL_Surface* src_surface = shared->getSurface();
677  SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, region.w, region.h,
678  src_surface->format->BitsPerPixel, src_surface->format->Rmask, src_surface->format->Gmask,
679  src_surface->format->Bmask, src_surface->format->Amask);
680 
681  SDL_SetAlpha(src_surface, 0, 0);
682  SDL_Rect srcrect = { region.x, region.y, region.w, region.h };
683  SDL_BlitSurface(src_surface, &srcrect, surface, NULL);
684  SDL_SetAlpha(src_surface, SDL_SRCALPHA, 0);
685 
686  setSurface(surface);
687  m_shared = false; // this isn't a mistake
688  m_subimagerect = region;
689  m_atlas_img = shared;
690  m_atlas_name = shared->getName();
692  }
693 
695  validateShared();
696  }
697 
699  if (m_atlas_name.empty()) {
700  return;
701  }
702 
705  load();
706  }
707  }
708 
709  void SDLImage::load() {
710  if (!m_atlas_name.empty()) {
711  // check atlas image
712  // if it does not exist, it is created.
715  m_atlas_img = newAtlas;
716  }
718  } else {
719  Image::load();
720  }
721  }
722 
723  void SDLImage::free() {
724  setSurface(NULL);
726  }
727 }
virtual ImagePtr create(IResourceLoader *loader=0)
Creates a blank Image but does not load it immediately.
void SDL_BlendRow_RGBA8_to_RGB8(const uint8_t *src, uint8_t *dst, uint32_t alpha, int32_t n)
Blends one row of n pixels from src with n pixels of dst.
void SDL_BlendRow_RGBA8_to_RGBA8(const uint8_t *src, uint8_t *dst, uint32_t alpha, int32_t n)
Blends one row of n pixels from src with n pixels of dst.
void reset(SDL_Surface *surface)
Resets the image to default values (including the x and y shift values), frees the current surface an...
Definition: image.cpp:110
bool m_finalized
Definition: sdlimage.h:76
virtual bool exists(const std::string &name)
Checks to see if an Image exists.
void validateShared()
Definition: sdlimage.cpp:698
virtual ResourceState getState()
Definition: resource.h:70
virtual void load()
Definition: image.cpp:124
Base Class for Images.
Definition: image.h:47
#define ABS(x)
Definition: fife_math.h:40
SDL_Surface * getZoomedSurface(SDL_Surface *src, double zoomx, double zoomy)
Definition: sdlimage.cpp:298
SDL_Surface * m_surface
Definition: image.h:155
T h
Height of the rectangle.
Definition: rect.h:93
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
SDL_Color m_colorkey
Definition: sdlimage.h:77
The main class of the SDL-based renderer.
T x
The X Coordinate.
Definition: rect.h:84
void zoomSurface(SDL_Surface *src, SDL_Surface *dst)
Definition: sdlimage.cpp:233
Uint8 m_last_alpha
Definition: sdlimage.h:74
const uint32_t RMASK
Definition: fife_stdint.h:53
static Logger _log(LM_AUDIO)
ImagePtr m_atlas_img
Definition: sdlimage.h:83
void SDL_BlitSurfaceWithAlpha(const SDL_Surface *src, const SDL_Rect *srcRect, SDL_Surface *dst, SDL_Rect *dstRect, uint8_t alpha)
Definition: sdlimage.cpp:101
virtual size_t getSize()
Definition: sdlimage.cpp:660
const uint32_t AMASK
Definition: fife_stdint.h:56
static RenderBackend * instance()
Definition: singleton.h:84
float m_scale_y
Definition: sdlimage.h:81
unsigned char uint8_t
Definition: core.h:38
virtual void render(const Rect &rect, uint8_t alpha=255, uint8_t const *rgb=0)
Renders itself to the current render target (main screen or attached destination image) at the rectan...
Definition: sdlimage.cpp:335
const uint32_t GMASK
Definition: fife_stdint.h:54
T bottom() const
The Y coordinate of the bottom edge.
Definition: rect.h:173
SDL_Surface * getSurface()
Definition: image.h:91
const SDL_Color & getColorKey() const
Gets the global colorkey setting.
virtual ~SDLImage()
Definition: sdlimage.cpp:86
virtual const std::string & getName()
Definition: resource.h:66
void finalize()
Definition: sdlimage.cpp:412
const uint32_t BMASK
Definition: fife_stdint.h:55
ResourceState m_state
Definition: resource.h:81
SDL_Surface * m_zoom_surface
Definition: sdlimage.h:79
T y
The Y Coordinate.
Definition: rect.h:87
void SDL_BlendRow_RGBA4_to_RGB565(const uint8_t *src, uint8_t *dst, uint32_t alpha, int32_t n)
Blends one row of n pixels from src with n pixels of dst.
Rect m_subimagerect
Definition: image.h:172
void resetSdlimage()
Definition: sdlimage.cpp:77
T right() const
The X coordinate of the right edge.
Definition: rect.h:168
virtual void setState(const ResourceState &state)
Definition: resource.h:71
SDL_Surface * getRenderTargetSurface()
Returns currently attached render surface.
bool nearlyEqual(float a, float b)
Definition: sdlimage.cpp:331
bool m_shared
Definition: image.h:170
virtual void forceLoadInternal()
Forces to load the image into internal memory of GPU.
Definition: sdlimage.cpp:694
float m_scale_x
Definition: sdlimage.h:80
std::string m_atlas_name
Definition: sdlimage.h:85
virtual void setSurface(SDL_Surface *surface)
This frees the current suface and replaces it with the surface passed in the parameter (which can be ...
Definition: sdlimage.cpp:92
unsigned int uint32_t
Definition: core.h:40
void SDL_BlendRow_RGBA8_to_RGB565(const uint8_t *src, uint8_t *dst, uint32_t alpha, int32_t n)
Blends one row of n pixels from src with n pixels of dst.
virtual void load()
Definition: sdlimage.cpp:709
SDLImage(IResourceLoader *loader=0)
Definition: sdlimage.cpp:47
virtual void free()
Definition: sdlimage.cpp:723
virtual void useSharedImage(const ImagePtr &shared, const Rect &region)
After this call all image data will be taken from the given image and its subregion.
Definition: sdlimage.cpp:672
T w
Width of the rectangle.
Definition: rect.h:90
#define FL_DBG(logger, msg)
Definition: logger.h:70
SDL_Surface * optimize(SDL_Surface *surface)
SDL Alpha Optimizer This tries to convert an image with a fake alpha channel to an RGB image when the...
Definition: sdlimage.cpp:453
bool isAlphaOptimizerEnabled() const