SDL_Extensions.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. #include "StdInc.h"
  2. #include "SDL_Extensions.h"
  3. #include "SDL_Pixels.h"
  4. #include <SDL_ttf.h>
  5. #include "../CGameInfo.h"
  6. #include "../CMessage.h"
  7. #include "../CDefHandler.h"
  8. #include "../Graphics.h"
  9. /*
  10. * SDL_Extensions.cpp, part of VCMI engine
  11. *
  12. * Authors: listed in file AUTHORS in main folder
  13. *
  14. * License: GNU General Public License v2.0 or later
  15. * Full text of license available in license.txt file, in main folder
  16. *
  17. */
  18. SDL_Color Colors::createColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a /*= 0*/)
  19. {
  20. SDL_Color temp = {r, g, b, a};
  21. return temp;
  22. }
  23. SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
  24. {
  25. return SDL_CreateRGBSurface(mod->flags,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask);
  26. }
  27. SDL_Surface * CSDL_Ext::copySurface(SDL_Surface * mod) //returns copy of given surface
  28. {
  29. //return SDL_DisplayFormat(mod);
  30. return SDL_ConvertSurface(mod, mod->format, mod->flags);
  31. }
  32. bool isItIn(const SDL_Rect * rect, int x, int y)
  33. {
  34. return (x>rect->x && x<rect->x+rect->w) && (y>rect->y && y<rect->y+rect->h);
  35. }
  36. void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst)
  37. {
  38. if(!dst) dst = screen;
  39. SDL_Rect pom = genRect(src->h,src->w,x,y);
  40. CSDL_Ext::blitSurface(src,NULL,dst,&pom);
  41. }
  42. void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst)
  43. {
  44. blitAt(src,pos.x,pos.y,dst);
  45. }
  46. SDL_Color genRGB(int r, int g, int b, int a=0)
  47. {
  48. SDL_Color ret;
  49. ret.b=b;
  50. ret.g=g;
  51. ret.r=r;
  52. ret.unused=a;
  53. return ret;
  54. }
  55. void updateRect (SDL_Rect * rect, SDL_Surface * scr)
  56. {
  57. SDL_UpdateRect(scr,rect->x,rect->y,rect->w,rect->h);
  58. }
  59. void printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
  60. {
  61. std::vector<std::string> ws = CMessage::breakText(text,charpr);
  62. std::vector<SDL_Surface*> wesu;
  63. wesu.resize(ws.size());
  64. for (size_t i=0; i < wesu.size(); ++i)
  65. {
  66. wesu[i]=TTF_RenderText_Blended(font,ws[i].c_str(),kolor);
  67. }
  68. int tox=0, toy=0;
  69. for (size_t i=0; i < wesu.size(); ++i)
  70. {
  71. toy+=wesu[i]->h;
  72. if (tox < wesu[i]->w)
  73. tox=wesu[i]->w;
  74. }
  75. int evx, evy = y - (toy/2);
  76. for (size_t i=0; i < wesu.size(); ++i)
  77. {
  78. evx = (x - (tox/2)) + ((tox-wesu[i]->w)/2);
  79. blitAt(wesu[i],evx,evy,dst);
  80. evy+=wesu[i]->h;
  81. }
  82. for (size_t i=0; i < wesu.size(); ++i)
  83. SDL_FreeSurface(wesu[i]);
  84. }
  85. void printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
  86. {
  87. std::vector<std::string> ws = CMessage::breakText(text,charpr);
  88. std::vector<SDL_Surface*> wesu;
  89. wesu.resize(ws.size());
  90. for (size_t i=0; i < wesu.size(); ++i)
  91. wesu[i]=TTF_RenderText_Blended(font,ws[i].c_str(),kolor);
  92. int evy = y;
  93. for (size_t i=0; i < wesu.size(); ++i)
  94. {
  95. blitAt(wesu[i],x,evy,dst);
  96. evy+=wesu[i]->h;
  97. }
  98. for (size_t i=0; i < wesu.size(); ++i)
  99. SDL_FreeSurface(wesu[i]);
  100. }
  101. void CSDL_Ext::printAtWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst)
  102. {
  103. if (graphics->fontsTrueType[font])
  104. {
  105. printAtWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
  106. return;
  107. }
  108. const Font *f = graphics->fonts[font];
  109. std::vector<std::string> ws = CMessage::breakText(text,charpr);
  110. int cury = y;
  111. for (size_t i=0; i < ws.size(); ++i)
  112. {
  113. printAt(ws[i], x, cury, font, kolor, dst);
  114. cury += f->height;
  115. }
  116. }
  117. void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor/*=Colors::Jasmine*/, SDL_Surface * dst/*=screen*/ )
  118. {
  119. if (graphics->fontsTrueType[font])
  120. {
  121. printAtMiddleWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
  122. return;
  123. }
  124. const Font *f = graphics->fonts[font];
  125. std::vector<std::string> ws = CMessage::breakText(text,charpr);
  126. int totalHeight = ws.size() * f->height;
  127. int cury = y - totalHeight/2;
  128. for (size_t i=0; i < ws.size(); ++i)
  129. {
  130. printAt(ws[i], x - f->getWidth(ws[i].c_str())/2, cury, font, kolor, dst);
  131. cury += f->height;
  132. }
  133. }
  134. void printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, ui8 quality=2)
  135. {
  136. if(text.length()==0) return;
  137. SDL_Surface * temp;
  138. switch (quality)
  139. {
  140. case 0:
  141. temp = TTF_RenderText_Solid(font,text.c_str(),kolor);
  142. break;
  143. case 1:
  144. SDL_Color tem;
  145. tem.b = 0xff-kolor.b;
  146. tem.g = 0xff-kolor.g;
  147. tem.r = 0xff-kolor.r;
  148. tem.unused = 0xff-kolor.unused;
  149. temp = TTF_RenderText_Shaded(font,text.c_str(),kolor,tem);
  150. break;
  151. case 2:
  152. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  153. break;
  154. default:
  155. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  156. break;
  157. }
  158. SDL_Rect dstRect = genRect(temp->h, temp->w, x-(temp->w/2), y-(temp->h/2));
  159. CSDL_Ext::blitSurface(temp, NULL, dst, &dstRect);
  160. SDL_FreeSurface(temp);
  161. }
  162. void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=Colors::Cornsilk*/, SDL_Surface * dst/*=screen*/ )
  163. {
  164. if (graphics->fontsTrueType[font])
  165. {
  166. printAtMiddle(text,x, y, graphics->fontsTrueType[font], kolor, dst);
  167. return;
  168. }
  169. const Font *f = graphics->fonts[font];
  170. int nx = x - f->getWidth(text.c_str())/2,
  171. ny = y - f->height/2;
  172. printAt(text, nx, ny, font, kolor, dst);
  173. }
  174. void printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, ui8 quality=2, bool refresh=false)
  175. {
  176. if (text.length()==0)
  177. return;
  178. SDL_Surface * temp;
  179. switch (quality)
  180. {
  181. case 0:
  182. temp = TTF_RenderText_Solid(font,text.c_str(),kolor);
  183. break;
  184. case 1:
  185. SDL_Color tem;
  186. tem.b = 0xff-kolor.b;
  187. tem.g = 0xff-kolor.g;
  188. tem.r = 0xff-kolor.r;
  189. tem.unused = 0xff-kolor.unused;
  190. temp = TTF_RenderText_Shaded(font,text.c_str(),kolor,tem);
  191. break;
  192. case 2:
  193. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  194. break;
  195. default:
  196. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  197. break;
  198. }
  199. SDL_Rect dstRect = genRect(temp->h,temp->w,x,y);
  200. CSDL_Ext::blitSurface(temp,NULL,dst,&dstRect);
  201. if(refresh)
  202. SDL_UpdateRect(dst,x,y,temp->w,temp->h);
  203. SDL_FreeSurface(temp);
  204. }
  205. void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=Colors::Cornsilk*/, SDL_Surface * dst/*=screen*/ )
  206. {
  207. if(!text.size())
  208. return;
  209. if (graphics->fontsTrueType[font])
  210. {
  211. printAt(text,x, y, graphics->fontsTrueType[font], kolor, dst);
  212. return;
  213. }
  214. assert(dst);
  215. assert(font < Graphics::FONTS_NUMBER);
  216. //assume BGR dst surface, TODO - make it general in a tidy way
  217. assert(dst->format->Rshift > dst->format->Gshift);
  218. assert(dst->format->Gshift > dst->format->Bshift);
  219. const Font *f = graphics->fonts[font];
  220. const Uint8 bpp = dst->format->BytesPerPixel;
  221. Uint8 *px = NULL;
  222. Uint8 *src = NULL;
  223. TColorPutter colorPutter = getPutterFor(dst, false);
  224. //if text is in {} braces, we'll ommit them
  225. const int first = (text[0] == '{' ? 1 : 0);
  226. const int beyondEnd = (text[text.size()-1] == '}' ? text.size()-1 : text.size());
  227. for(int txti = first; txti < beyondEnd; txti++)
  228. {
  229. const ui8 c = text[txti];
  230. x += f->chars[c].unknown1;
  231. for(int i = std::max(0, -y); i < f->height && (y + i) < (dst->h - 1); i++)
  232. {
  233. px = (Uint8*)dst->pixels;
  234. px += (y+i) * dst->pitch + x * bpp;
  235. src = f->chars[c].pixels;
  236. src += i * f->chars[c].width;//if we have reached end of surface in previous line
  237. for(int j = std::max(0, -x); j < f->chars[c].width && (j + x) < (dst->w - 1); j++)
  238. {
  239. switch(*src)
  240. {
  241. case 1: //black "shadow"
  242. memset(px, 0, bpp);
  243. break;
  244. case 255: //text colour
  245. colorPutter(px, kolor.r, kolor.g, kolor.b);
  246. break;
  247. }
  248. src++;
  249. px += bpp;
  250. }
  251. }
  252. x += f->chars[c].width;
  253. x += f->chars[c].unknown2;
  254. }
  255. }
  256. void printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, ui8 quality=2)
  257. {
  258. if (text.length()==0)
  259. return;
  260. SDL_Surface * temp;
  261. switch (quality)
  262. {
  263. case 0:
  264. temp = TTF_RenderText_Solid(font,text.c_str(),kolor);
  265. break;
  266. case 1:
  267. SDL_Color tem;
  268. tem.b = 0xff-kolor.b;
  269. tem.g = 0xff-kolor.g;
  270. tem.r = 0xff-kolor.r;
  271. tem.unused = 0xff-kolor.unused;
  272. temp = TTF_RenderText_Shaded(font,text.c_str(),kolor,tem);
  273. break;
  274. case 2:
  275. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  276. break;
  277. default:
  278. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  279. break;
  280. }
  281. SDL_Rect dstRect = genRect(temp->h,temp->w,x-temp->w,y-temp->h);
  282. CSDL_Ext::blitSurface(temp,NULL,dst,&dstRect);
  283. SDL_UpdateRect(dst,x-temp->w,y-temp->h,temp->w,temp->h);
  284. SDL_FreeSurface(temp);
  285. }
  286. void CSDL_Ext::printTo( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=Colors::Cornsilk*/, SDL_Surface * dst/*=screen*/ )
  287. {
  288. if (graphics->fontsTrueType[font])
  289. {
  290. printTo(text,x, y, graphics->fontsTrueType[font], kolor, dst);
  291. return;
  292. }
  293. const Font *f = graphics->fonts[font];
  294. printAt(text, x - f->getWidth(text.c_str()), y - f->height, font, kolor, dst);
  295. }
  296. void printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, ui8 quality=2)
  297. {
  298. if (text.length()==0)
  299. return;
  300. SDL_Surface * temp;
  301. switch (quality)
  302. {
  303. case 0:
  304. temp = TTF_RenderText_Solid(font,text.c_str(),kolor);
  305. break;
  306. case 1:
  307. SDL_Color tem;
  308. tem.b = 0xff-kolor.b;
  309. tem.g = 0xff-kolor.g;
  310. tem.r = 0xff-kolor.r;
  311. tem.unused = 0xff-kolor.unused;
  312. temp = TTF_RenderText_Shaded(font,text.c_str(),kolor,tem);
  313. break;
  314. case 2:
  315. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  316. break;
  317. default:
  318. temp = TTF_RenderText_Blended(font,text.c_str(),kolor);
  319. break;
  320. }
  321. SDL_Rect dstRect = genRect(temp->h,temp->w,x-temp->w,y-temp->h);
  322. CSDL_Ext::blitSurface(temp,NULL,dst,&dstRect);
  323. SDL_FreeSurface(temp);
  324. }
  325. // Vertical flip
  326. SDL_Surface * CSDL_Ext::rotate01(SDL_Surface * toRot)
  327. {
  328. SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
  329. const int bpl = ret->pitch;
  330. const int bpp = ret->format->BytesPerPixel;
  331. for(int i=0; i<ret->h; i++) {
  332. char *src = (char *)toRot->pixels + i*bpl;
  333. char *dst = (char *)ret->pixels + i*bpl;
  334. for(int j=0; j<ret->w; j++) {
  335. for (int k=0; k<bpp; k++) {
  336. dst[j*bpp + k] = src[(ret->w-j-1)*bpp + k];
  337. }
  338. }
  339. }
  340. return ret;
  341. }
  342. // Horizontal flip
  343. SDL_Surface * CSDL_Ext::hFlip(SDL_Surface * toRot)
  344. {
  345. SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
  346. int bpl = ret->pitch;
  347. for(int i=0; i<ret->h; i++) {
  348. memcpy((char *)ret->pixels + i*bpl, (char *)toRot->pixels + (ret->h-i-1)*bpl, bpl);
  349. }
  350. return ret;
  351. };
  352. ///**************/
  353. ///Rotates toRot surface by 90 degrees left
  354. ///**************/
  355. SDL_Surface * CSDL_Ext::rotate02(SDL_Surface * toRot)
  356. {
  357. SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
  358. //SDL_SetColorKey(ret, SDL_SRCCOLORKEY, toRot->format->colorkey);
  359. for(int i=0; i<ret->w; ++i)
  360. {
  361. for(int j=0; j<ret->h; ++j)
  362. {
  363. {
  364. Uint8 *p = (Uint8 *)toRot->pixels + i * toRot->pitch + j * toRot->format->BytesPerPixel;
  365. SDL_PutPixelWithoutRefresh(ret, i, j, p[2], p[1], p[0]);
  366. }
  367. }
  368. }
  369. return ret;
  370. }
  371. ///*************/
  372. ///Rotates toRot surface by 180 degrees
  373. ///*************/
  374. SDL_Surface * CSDL_Ext::rotate03(SDL_Surface * toRot)
  375. {
  376. SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
  377. if(ret->format->BytesPerPixel!=1)
  378. {
  379. for(int i=0; i<ret->w; ++i)
  380. {
  381. for(int j=0; j<ret->h; ++j)
  382. {
  383. {
  384. Uint8 *p = (Uint8 *)toRot->pixels + (ret->h - j - 1) * toRot->pitch + (ret->w - i - 1) * toRot->format->BytesPerPixel+2;
  385. SDL_PutPixelWithoutRefresh(ret, i, j, p[2], p[1], p[0], 0);
  386. }
  387. }
  388. }
  389. }
  390. else
  391. {
  392. for(int i=0; i<ret->w; ++i)
  393. {
  394. for(int j=0; j<ret->h; ++j)
  395. {
  396. Uint8 *p = (Uint8 *)toRot->pixels + (ret->h - j - 1) * toRot->pitch + (ret->w - i - 1) * toRot->format->BytesPerPixel;
  397. (*((Uint8*)ret->pixels + j*ret->pitch + i*ret->format->BytesPerPixel)) = *p;
  398. }
  399. }
  400. }
  401. return ret;
  402. }
  403. Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte)
  404. {
  405. int bpp = surface->format->BytesPerPixel;
  406. /* Here p is the address to the pixel we want to retrieve */
  407. Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
  408. switch(bpp)
  409. {
  410. case 1:
  411. if(colorByte)
  412. {
  413. return colorToUint32(surface->format->palette->colors+(*p));
  414. }
  415. else
  416. return *p;
  417. case 2:
  418. return *(Uint16 *)p;
  419. case 3:
  420. return p[0] | p[1] << 8 | p[2] << 16;
  421. case 4:
  422. return *(Uint32 *)p;
  423. default:
  424. return 0; // shouldn't happen, but avoids warnings
  425. }
  426. }
  427. void CSDL_Ext::alphaTransform(SDL_Surface *src)
  428. {
  429. assert(src->format->BitsPerPixel == 8);
  430. SDL_Color colors[] = {{0,0,0,255}, {0,0,0,214}, {0,0,0,164}, {0,0,0,82}, {0,0,0,128},
  431. {255,0,0,0}, {255,0,0,0}, {255,0,0,0}, {0,0,0,192}, {0,0,0,192}};
  432. SDL_SetColors(src, colors, 0, ARRAY_COUNT(colors));
  433. SDL_SetColorKey(src, SDL_SRCCOLORKEY, SDL_MapRGBA(src->format, 0, 0, 0, 255));
  434. }
  435. static void prepareOutRect(SDL_Rect *src, SDL_Rect *dst, const SDL_Rect & clip_rect)
  436. {
  437. const int xoffset = std::max(clip_rect.x - dst->x, 0),
  438. yoffset = std::max(clip_rect.y - dst->y, 0);
  439. src->x += xoffset;
  440. src->y += yoffset;
  441. dst->x += xoffset;
  442. dst->y += yoffset;
  443. src->w = dst->w = std::max(0,std::min(dst->w - xoffset, clip_rect.x + clip_rect.w - dst->x));
  444. src->h = dst->h = std::max(0,std::min(dst->h - yoffset, clip_rect.y + clip_rect.h - dst->y));
  445. }
  446. template<int bpp>
  447. void CSDL_Ext::blitWithRotateClip(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation)//srcRect is not used, works with 8bpp sources and 24bpp dests
  448. {
  449. static void (*blitWithRotate[])(const SDL_Surface *, const SDL_Rect *, SDL_Surface *, const SDL_Rect *) = {blitWithRotate1<bpp>, blitWithRotate2<bpp>, blitWithRotate3<bpp>};
  450. if(!rotation)
  451. {
  452. CSDL_Ext::blitSurface(src, srcRect, dst, dstRect);
  453. }
  454. else
  455. {
  456. prepareOutRect(srcRect, dstRect, dst->clip_rect);
  457. blitWithRotate[rotation-1](src, srcRect, dst, dstRect);
  458. }
  459. }
  460. template<int bpp>
  461. void CSDL_Ext::blitWithRotateClipVal( SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation )
  462. {
  463. blitWithRotateClip<bpp>(src, &srcRect, dst, &dstRect, rotation);
  464. }
  465. template<int bpp>
  466. void CSDL_Ext::blitWithRotateClipWithAlpha(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation)//srcRect is not used, works with 8bpp sources and 24bpp dests
  467. {
  468. static void (*blitWithRotate[])(const SDL_Surface *, const SDL_Rect *, SDL_Surface *, const SDL_Rect *) = {blitWithRotate1WithAlpha<bpp>, blitWithRotate2WithAlpha<bpp>, blitWithRotate3WithAlpha<bpp>};
  469. if(!rotation)
  470. {
  471. blit8bppAlphaTo24bpp(src, srcRect, dst, dstRect);
  472. }
  473. else
  474. {
  475. prepareOutRect(srcRect, dstRect, dst->clip_rect);
  476. blitWithRotate[rotation-1](src, srcRect, dst, dstRect);
  477. }
  478. }
  479. template<int bpp>
  480. void CSDL_Ext::blitWithRotateClipValWithAlpha( SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation )
  481. {
  482. blitWithRotateClipWithAlpha<bpp>(src, &srcRect, dst, &dstRect, rotation);
  483. }
  484. template<int bpp>
  485. void CSDL_Ext::blitWithRotate1(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  486. {
  487. Uint8 *sp = getPxPtr(src, src->w - srcRect->w - srcRect->x, srcRect->y);
  488. Uint8 *dporg = (Uint8 *)dst->pixels + dstRect->y*dst->pitch + (dstRect->x+dstRect->w)*bpp;
  489. const SDL_Color * const colors = src->format->palette->colors;
  490. for(int i=dstRect->h; i>0; i--, dporg += dst->pitch)
  491. {
  492. Uint8 *dp = dporg;
  493. for(int j=dstRect->w; j>0; j--, sp++)
  494. ColorPutter<bpp, -1>::PutColor(dp, colors[*sp]);
  495. sp += src->w - dstRect->w;
  496. }
  497. }
  498. template<int bpp>
  499. void CSDL_Ext::blitWithRotate2(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  500. {
  501. Uint8 *sp = getPxPtr(src, srcRect->x, src->h - srcRect->h - srcRect->y);
  502. Uint8 *dporg = (Uint8 *)dst->pixels + (dstRect->y + dstRect->h - 1)*dst->pitch + dstRect->x*bpp;
  503. const SDL_Color * const colors = src->format->palette->colors;
  504. for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch)
  505. {
  506. Uint8 *dp = dporg;
  507. for(int j=dstRect->w; j>0; j--, sp++)
  508. ColorPutter<bpp, 1>::PutColor(dp, colors[*sp]);
  509. sp += src->w - dstRect->w;
  510. }
  511. }
  512. template<int bpp>
  513. void CSDL_Ext::blitWithRotate3(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  514. {
  515. Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + (src->w - srcRect->w - srcRect->x);
  516. Uint8 *dporg = (Uint8 *)dst->pixels +(dstRect->y + dstRect->h - 1)*dst->pitch + (dstRect->x+dstRect->w)*bpp;
  517. const SDL_Color * const colors = src->format->palette->colors;
  518. for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch)
  519. {
  520. Uint8 *dp = dporg;
  521. for(int j=dstRect->w; j>0; j--, sp++)
  522. ColorPutter<bpp, -1>::PutColor(dp, colors[*sp]);
  523. sp += src->w - dstRect->w;
  524. }
  525. }
  526. template<int bpp>
  527. void CSDL_Ext::blitWithRotate1WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  528. {
  529. Uint8 *sp = (Uint8 *)src->pixels + srcRect->y*src->pitch + (src->w - srcRect->w - srcRect->x);
  530. Uint8 *dporg = (Uint8 *)dst->pixels + dstRect->y*dst->pitch + (dstRect->x+dstRect->w)*bpp;
  531. const SDL_Color * const colors = src->format->palette->colors;
  532. for(int i=dstRect->h; i>0; i--, dporg += dst->pitch)
  533. {
  534. Uint8 *dp = dporg;
  535. for(int j=dstRect->w; j>0; j--, sp++)
  536. {
  537. if(*sp)
  538. ColorPutter<bpp, -1>::PutColor(dp, colors[*sp]);
  539. else
  540. dp -= bpp;
  541. }
  542. sp += src->w - dstRect->w;
  543. }
  544. }
  545. template<int bpp>
  546. void CSDL_Ext::blitWithRotate2WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  547. {
  548. Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + srcRect->x;
  549. Uint8 *dporg = (Uint8 *)dst->pixels + (dstRect->y + dstRect->h - 1)*dst->pitch + dstRect->x*bpp;
  550. const SDL_Color * const colors = src->format->palette->colors;
  551. for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch)
  552. {
  553. Uint8 *dp = dporg;
  554. for(int j=dstRect->w; j>0; j--, sp++)
  555. {
  556. if(*sp)
  557. ColorPutter<bpp, 1>::PutColor(dp, colors[*sp]);
  558. else
  559. dp += bpp;
  560. }
  561. sp += src->w - dstRect->w;
  562. }
  563. }
  564. template<int bpp>
  565. void CSDL_Ext::blitWithRotate3WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests
  566. {
  567. Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + (src->w - srcRect->w - srcRect->x);
  568. Uint8 *dporg = (Uint8 *)dst->pixels +(dstRect->y + dstRect->h - 1)*dst->pitch + (dstRect->x+dstRect->w)*bpp;
  569. const SDL_Color * const colors = src->format->palette->colors;
  570. for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch)
  571. {
  572. Uint8 *dp = dporg;
  573. for(int j=dstRect->w; j>0; j--, sp++)
  574. {
  575. if(*sp)
  576. ColorPutter<bpp, -1>::PutColor(dp, colors[*sp]);
  577. else
  578. dp -= bpp;
  579. }
  580. sp += src->w - dstRect->w;
  581. }
  582. }
  583. template<int bpp>
  584. int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
  585. {
  586. if (src && src->format->BytesPerPixel==1 && dst && (bpp==3 || bpp==4 || bpp==2)) //everything's ok
  587. {
  588. SDL_Rect fulldst;
  589. int srcx, srcy, w, h;
  590. /* Make sure the surfaces aren't locked */
  591. if ( ! src || ! dst )
  592. {
  593. SDL_SetError("SDL_UpperBlit: passed a NULL surface");
  594. return -1;
  595. }
  596. if ( src->locked || dst->locked )
  597. {
  598. SDL_SetError("Surfaces must not be locked during blit");
  599. return -1;
  600. }
  601. /* If the destination rectangle is NULL, use the entire dest surface */
  602. if ( dstRect == NULL )
  603. {
  604. fulldst.x = fulldst.y = 0;
  605. dstRect = &fulldst;
  606. }
  607. /* clip the source rectangle to the source surface */
  608. if(srcRect)
  609. {
  610. int maxw, maxh;
  611. srcx = srcRect->x;
  612. w = srcRect->w;
  613. if(srcx < 0)
  614. {
  615. w += srcx;
  616. dstRect->x -= srcx;
  617. srcx = 0;
  618. }
  619. maxw = src->w - srcx;
  620. if(maxw < w)
  621. w = maxw;
  622. srcy = srcRect->y;
  623. h = srcRect->h;
  624. if(srcy < 0)
  625. {
  626. h += srcy;
  627. dstRect->y -= srcy;
  628. srcy = 0;
  629. }
  630. maxh = src->h - srcy;
  631. if(maxh < h)
  632. h = maxh;
  633. }
  634. else
  635. {
  636. srcx = srcy = 0;
  637. w = src->w;
  638. h = src->h;
  639. }
  640. /* clip the destination rectangle against the clip rectangle */
  641. {
  642. SDL_Rect *clip = &dst->clip_rect;
  643. int dx, dy;
  644. dx = clip->x - dstRect->x;
  645. if(dx > 0)
  646. {
  647. w -= dx;
  648. dstRect->x += dx;
  649. srcx += dx;
  650. }
  651. dx = dstRect->x + w - clip->x - clip->w;
  652. if(dx > 0)
  653. w -= dx;
  654. dy = clip->y - dstRect->y;
  655. if(dy > 0)
  656. {
  657. h -= dy;
  658. dstRect->y += dy;
  659. srcy += dy;
  660. }
  661. dy = dstRect->y + h - clip->y - clip->h;
  662. if(dy > 0)
  663. h -= dy;
  664. }
  665. if(w > 0 && h > 0)
  666. {
  667. dstRect->w = w;
  668. dstRect->h = h;
  669. if(SDL_LockSurface(dst))
  670. return -1; //if we cannot lock the surface
  671. const SDL_Color *colors = src->format->palette->colors;
  672. Uint8 *colory = (Uint8*)src->pixels + srcy*src->pitch + srcx;
  673. Uint8 *py = (Uint8*)dst->pixels + dstRect->y*dst->pitch + dstRect->x*bpp;
  674. for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
  675. {
  676. Uint8 *color = colory;
  677. Uint8 *p = py;
  678. for(int x = w; x; x--)
  679. {
  680. const SDL_Color &tbc = colors[*color++]; //color to blit
  681. ColorPutter<bpp, +1>::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.unused);
  682. }
  683. }
  684. SDL_UnlockSurface(dst);
  685. }
  686. }
  687. return 0;
  688. }
  689. int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
  690. {
  691. switch(dst->format->BytesPerPixel)
  692. {
  693. case 2: return blit8bppAlphaTo24bppT<2>(src, srcRect, dst, dstRect);
  694. case 3: return blit8bppAlphaTo24bppT<3>(src, srcRect, dst, dstRect);
  695. case 4: return blit8bppAlphaTo24bppT<4>(src, srcRect, dst, dstRect);
  696. default:
  697. tlog1 << (int)dst->format->BitsPerPixel << " bpp is not supported!!!\n";
  698. return -1;
  699. }
  700. }
  701. Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
  702. {
  703. Uint32 ret = 0;
  704. ret+=color->unused;
  705. ret<<=8; //*=256
  706. ret+=color->b;
  707. ret<<=8; //*=256
  708. ret+=color->g;
  709. ret<<=8; //*=256
  710. ret+=color->r;
  711. return ret;
  712. }
  713. void CSDL_Ext::update(SDL_Surface * what)
  714. {
  715. if(what)
  716. SDL_UpdateRect(what, 0, 0, what->w, what->h);
  717. }
  718. void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
  719. {
  720. for(int i = 0; i < w; i++)
  721. {
  722. SDL_PutPixelWithoutRefreshIfInSurf(sur,x+i,y,color.x,color.y,color.z);
  723. SDL_PutPixelWithoutRefreshIfInSurf(sur,x+i,y+h-1,color.x,color.y,color.z);
  724. }
  725. for(int i = 0; i < h; i++)
  726. {
  727. SDL_PutPixelWithoutRefreshIfInSurf(sur,x,y+i,color.x,color.y,color.z);
  728. SDL_PutPixelWithoutRefreshIfInSurf(sur,x+w-1,y+i,color.x,color.y,color.z);
  729. }
  730. }
  731. void CSDL_Ext::drawBorder( SDL_Surface * sur, const SDL_Rect &r, const int3 &color )
  732. {
  733. drawBorder(sur, r.x, r.y, r.w, r.h, color);
  734. }
  735. void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &color)
  736. {
  737. const int y1 = r.y, y2 = r.y + r.h-1;
  738. for (int i=0; i<r.w; i++)
  739. {
  740. const int x = r.x + i;
  741. if (i%4 || (i==0))
  742. {
  743. SDL_PutPixelWithoutRefreshIfInSurf(sur, x, y1, color.x, color.y, color.z);
  744. SDL_PutPixelWithoutRefreshIfInSurf(sur, x, y2, color.x, color.y, color.z);
  745. }
  746. }
  747. const int x1 = r.x, x2 = r.x + r.w-1;
  748. for (int i=0; i<r.h; i++)
  749. {
  750. const int y = r.y + i;
  751. if ((i%4) || (i==0))
  752. {
  753. SDL_PutPixelWithoutRefreshIfInSurf(sur, x1, y, color.x, color.y, color.z);
  754. SDL_PutPixelWithoutRefreshIfInSurf(sur, x2, y, color.x, color.y, color.z);
  755. }
  756. }
  757. }
  758. void CSDL_Ext::setPlayerColor(SDL_Surface * sur, ui8 player)
  759. {
  760. if(player==254)
  761. return;
  762. if(sur->format->BitsPerPixel==8)
  763. {
  764. SDL_Color *color = (player == 255
  765. ? graphics->neutralColor
  766. : &graphics->playerColors[player]);
  767. SDL_SetColors(sur, color, 5, 1);
  768. }
  769. else
  770. tlog3 << "Warning, setPlayerColor called on not 8bpp surface!\n";
  771. }
  772. const TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing)
  773. {
  774. #define CASE_BPP(BytesPerPixel) \
  775. case BytesPerPixel: \
  776. if(incrementing > 0) \
  777. return ColorPutter<BytesPerPixel, 1>::PutColor; \
  778. else if(incrementing == 0) \
  779. return ColorPutter<BytesPerPixel, 0>::PutColor; \
  780. else \
  781. return ColorPutter<BytesPerPixel, -1>::PutColor;\
  782. break;
  783. switch(dest->format->BytesPerPixel)
  784. {
  785. CASE_BPP(2)
  786. CASE_BPP(3)
  787. CASE_BPP(4)
  788. default:
  789. tlog1 << (int)dest->format->BitsPerPixel << "bpp is not supported!\n";
  790. return NULL;
  791. }
  792. }
  793. const TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, int incrementing)
  794. {
  795. switch(dest->format->BytesPerPixel)
  796. {
  797. CASE_BPP(2)
  798. CASE_BPP(3)
  799. CASE_BPP(4)
  800. default:
  801. tlog1 << (int)dest->format->BitsPerPixel << "bpp is not supported!\n";
  802. return NULL;
  803. }
  804. #undef CASE_BPP
  805. }
  806. Uint8 * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y)
  807. {
  808. return (Uint8 *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel;
  809. }
  810. std::string CSDL_Ext::processStr(std::string str, std::vector<std::string> & tor)
  811. {
  812. for (size_t i=0; (i<tor.size())&&(boost::find_first(str,"%s")); ++i)
  813. {
  814. boost::replace_first(str,"%s",tor[i]);
  815. }
  816. return str;
  817. }
  818. bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y )
  819. {
  820. if (x < 0 || y < 0 || x >= srf->w || y >= srf->h)
  821. return true;
  822. if(srf->format->BytesPerPixel == 1)
  823. {
  824. return ((ui8*)srf->pixels)[x + srf->pitch * y] == 0;
  825. }
  826. else
  827. {
  828. assert(!"isTransparent called with non-8bpp surface!");
  829. }
  830. return false;
  831. }
  832. void CSDL_Ext::VflipSurf(SDL_Surface * surf)
  833. {
  834. char buf[4]; //buffer
  835. int bpp = surf->format->BytesPerPixel;
  836. for (int y=0; y<surf->h; ++y)
  837. {
  838. char * base = (char*)surf->pixels + y * surf->pitch;
  839. for (int x=0; x<surf->w/2; ++x)
  840. {
  841. memcpy(buf, base + x * bpp, bpp);
  842. memcpy(base + x * bpp, base + (surf->w - x - 1) * bpp, bpp);
  843. memcpy(base + (surf->w - x - 1) * bpp, buf, bpp);
  844. }
  845. }
  846. }
  847. void CSDL_Ext::SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A /*= 255*/)
  848. {
  849. Uint8 *p = getPxPtr(ekran, x, y);
  850. getPutterFor(ekran, false)(p, R, G, B);
  851. }
  852. void CSDL_Ext::SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A /*= 255*/)
  853. {
  854. if(x >= 0 && x < ekran->w && y >= 0 && y < ekran->h)
  855. SDL_PutPixelWithoutRefresh(ekran, x, y, R, G, B, A);
  856. }
  857. BlitterWithRotationVal CSDL_Ext::getBlitterWithRotation(SDL_Surface *dest)
  858. {
  859. switch(dest->format->BytesPerPixel)
  860. {
  861. case 2: return blitWithRotateClipVal<2>;
  862. case 3: return blitWithRotateClipVal<3>;
  863. case 4: return blitWithRotateClipVal<4>;
  864. default:
  865. tlog1 << (int)dest->format->BitsPerPixel << " bpp is not supported!!!\n";
  866. break;
  867. }
  868. assert(0);
  869. return NULL;
  870. }
  871. BlitterWithRotationVal CSDL_Ext::getBlitterWithRotationAndAlpha(SDL_Surface *dest)
  872. {
  873. switch(dest->format->BytesPerPixel)
  874. {
  875. case 2: return blitWithRotateClipValWithAlpha<2>;
  876. case 3: return blitWithRotateClipValWithAlpha<3>;
  877. case 4: return blitWithRotateClipValWithAlpha<4>;
  878. default:
  879. tlog1 << (int)dest->format->BitsPerPixel << " bpp is not supported!!!\n";
  880. break;
  881. }
  882. assert(0);
  883. return NULL;
  884. }
  885. template<int bpp>
  886. void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode )
  887. {
  888. switch(mode)
  889. {
  890. case 0: //sepia
  891. {
  892. const int sepiaDepth = 20;
  893. const int sepiaIntensity = 30;
  894. for(int xp = rect->x; xp < rect->x + rect->w; ++xp)
  895. {
  896. for(int yp = rect->y; yp < rect->y + rect->h; ++yp)
  897. {
  898. Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
  899. int r = Channels::px<bpp>::r.get(pixel);
  900. int g = Channels::px<bpp>::g.get(pixel);
  901. int b = Channels::px<bpp>::b.get(pixel);
  902. int gray = 0.299 * r + 0.587 * g + 0.114 *b;
  903. r = g = b = gray;
  904. r = r + (sepiaDepth * 2);
  905. g = g + sepiaDepth;
  906. if (r>255) r=255;
  907. if (g>255) g=255;
  908. if (b>255) b=255;
  909. // Darken blue color to increase sepia effect
  910. b -= sepiaIntensity;
  911. // normalize if out of bounds
  912. if (b<0) b=0;
  913. Channels::px<bpp>::r.set(pixel, r);
  914. Channels::px<bpp>::g.set(pixel, g);
  915. Channels::px<bpp>::b.set(pixel, b);
  916. }
  917. }
  918. }
  919. break;
  920. case 1: //grayscale
  921. {
  922. for(int xp = rect->x; xp < rect->x + rect->w; ++xp)
  923. {
  924. for(int yp = rect->y; yp < rect->y + rect->h; ++yp)
  925. {
  926. Uint8 * pixel = (ui8*)surf->pixels + yp * surf->pitch + xp * surf->format->BytesPerPixel;
  927. int r = Channels::px<bpp>::r.get(pixel);
  928. int g = Channels::px<bpp>::g.get(pixel);
  929. int b = Channels::px<bpp>::b.get(pixel);
  930. int gray = 0.299 * r + 0.587 * g + 0.114 *b;
  931. vstd::amax(gray, 255);
  932. Channels::px<bpp>::r.set(pixel, gray);
  933. Channels::px<bpp>::g.set(pixel, gray);
  934. Channels::px<bpp>::b.set(pixel, gray);
  935. }
  936. }
  937. }
  938. break;
  939. default:
  940. throw std::runtime_error("Unsuppoerted efftct!");
  941. }
  942. }
  943. void CSDL_Ext::applyEffect( SDL_Surface * surf, const SDL_Rect * rect, int mode )
  944. {
  945. switch(surf->format->BytesPerPixel)
  946. {
  947. case 2: applyEffectBpp<2>(surf, rect, mode); break;
  948. case 3: applyEffectBpp<3>(surf, rect, mode); break;
  949. case 4: applyEffectBpp<4>(surf, rect, mode); break;
  950. }
  951. }
  952. void CSDL_Ext::blitSurface( SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect )
  953. {
  954. if (dst != screen)
  955. {
  956. SDL_BlitSurface(src, srcRect, dst, dstRect);
  957. }
  958. else
  959. {
  960. SDL_Rect betterDst;
  961. if (dstRect)
  962. {
  963. betterDst = *dstRect;
  964. }
  965. else
  966. {
  967. betterDst = Rect(0, 0, dst->w, dst->h);
  968. }
  969. SDL_BlitSurface(src, srcRect, dst, &betterDst);
  970. }
  971. }
  972. void CSDL_Ext::fillRect( SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color )
  973. {
  974. SDL_Rect newRect;
  975. if (dstrect)
  976. {
  977. newRect = *dstrect;
  978. }
  979. else
  980. {
  981. newRect = Rect(0, 0, dst->w, dst->h);
  982. }
  983. SDL_FillRect(dst, &newRect, color);
  984. }
  985. std::string CSDL_Ext::trimToFit(std::string text, int widthLimit, EFonts font)
  986. {
  987. int widthSoFar = 0;
  988. for(auto i = text.begin(); i != text.end(); i++)
  989. {
  990. widthSoFar += graphics->fonts[font]->getCharWidth(*i);
  991. if(widthSoFar > widthLimit)
  992. {
  993. //remove all characteres past limit
  994. text.erase(i, text.end());
  995. break;
  996. }
  997. }
  998. return text;
  999. }
  1000. SDL_Surface * CSDL_Ext::std32bppSurface = NULL;