1
0

bitmap.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584
  1. #include <precomp.h>
  2. //#define NO_SIMPLEFASTMODE
  3. #include <api/imgldr/api_imgldr.h>
  4. #include <api/wnd/blending.h>
  5. #include "bitmap.h"
  6. #ifndef _NOSTUDIO
  7. #include <api/api.h>
  8. #endif
  9. #include <bfc/std.h>
  10. #include <api/wnd/bltcanvas.h>
  11. #include <api/memmgr/memmgrapi.h>
  12. #if !defined(WIN32) && !defined(LINUX)
  13. #error port me!
  14. #endif
  15. #define ERRORBMP L"wasabi.bitmapnotfound"
  16. #define HARDERRORBMP L"xml/wasabi/window/error.png"
  17. // do not define NO_MMX in this file. :)
  18. #ifndef NO_MMX
  19. #ifdef WIN32
  20. #define MMX_CONST const
  21. #else
  22. #define MMX_CONST
  23. #endif
  24. static unsigned int MMX_CONST SkinBitmap_mmx_revn2[2]={0x01000100,0x01000100};
  25. static unsigned int MMX_CONST SkinBitmap_mmx_zero[2];
  26. static unsigned int MMX_CONST SkinBitmap_mmx_one[2]={1,0};
  27. #define HAS_MMX Blenders::MMX_AVAILABLE()
  28. #else
  29. //NO_MMX defined
  30. #define HAS_MMX 0
  31. #endif
  32. #ifndef _NOSTUDIO
  33. #ifdef WASABI_COMPILE_IMGLDR
  34. SkinBitmap::SkinBitmap(HINSTANCE hInstance, int id, const wchar_t *forcegroup)
  35. {
  36. bitmapname = L"";
  37. subimage_w=-1;
  38. subimage_h=-1;
  39. x_offset=-1;
  40. y_offset=-1;
  41. fullimage_w=fullimage_h=0;
  42. has_alpha = 0;
  43. ASSERT(hInstance != NULL);
  44. ownbits=1;
  45. fromskin = 0;
  46. bits=WASABI_API_IMGLDR->imgldr_makeBmp(hInstance, id,&has_alpha,&fullimage_w,&fullimage_h, forcegroup);
  47. last_failed = 0;
  48. #ifdef WASABI_COMPILE_SKIN
  49. if (bits == NULL)
  50. {
  51. //last_failed = 1;
  52. //TODO: bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(ERRORBMP, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached);
  53. }
  54. #endif
  55. if (bits == NULL)
  56. {
  57. last_failed = 1;
  58. bits = WASABI_API_IMGLDR->imgldr_makeBmp(HARDERRORBMP, &has_alpha, &fullimage_w, &fullimage_h);
  59. }
  60. }
  61. #endif
  62. #endif
  63. // TODO: benski> make sure this works :)
  64. SkinBitmap::SkinBitmap(ARGB32 *_bits, int w, int h)
  65. {
  66. subimage_w=-1;
  67. subimage_h=-1;
  68. x_offset=-1;
  69. y_offset=-1;
  70. bitmapname = L"";
  71. fullimage_w=fullimage_h=0;
  72. has_alpha = 1;
  73. ownbits=0;
  74. bits = _bits;
  75. fromskin = 0;
  76. last_failed = 0;
  77. }
  78. // TODO: benski> could we be using GetDIBits here?
  79. void SkinBitmap::bmpToBits(HBITMAP hbmp, HDC defaultDC)
  80. {
  81. #ifdef WIN32
  82. if (hbmp && !bits)
  83. {
  84. BITMAPINFO srcbmi={0,};
  85. HDC hMemDC, hMemDC2;
  86. HBITMAP hprev,hprev2=0;
  87. HBITMAP hsrcdib;
  88. void *srcdib;
  89. BITMAP bm;
  90. int r = GetObject(hbmp, sizeof(BITMAP), &bm);
  91. ASSERT(r != 0);
  92. fullimage_w=bm.bmWidth;
  93. fullimage_h=ABS(bm.bmHeight);
  94. int bmw=getWidth();
  95. int bmh=getHeight();
  96. int xo=getX();
  97. int yo=getY();
  98. srcbmi.bmiHeader.biSize=sizeof(srcbmi.bmiHeader);
  99. srcbmi.bmiHeader.biWidth=bmw;
  100. srcbmi.bmiHeader.biHeight=-bmh;
  101. srcbmi.bmiHeader.biPlanes=1;
  102. srcbmi.bmiHeader.biBitCount=32;
  103. srcbmi.bmiHeader.biCompression=BI_RGB;
  104. hMemDC = CreateCompatibleDC(NULL);
  105. hsrcdib=CreateDIBSection(hMemDC,&srcbmi,DIB_RGB_COLORS,&srcdib,NULL,0);
  106. ASSERTPR(hsrcdib != 0, "CreateDIBSection() failed #6");
  107. if (defaultDC)
  108. hMemDC2 = defaultDC;
  109. else {
  110. hMemDC2 = CreateCompatibleDC(NULL);
  111. hprev2 = (HBITMAP) SelectObject(hMemDC2, hbmp);
  112. }
  113. hprev = (HBITMAP) SelectObject(hMemDC, hsrcdib);
  114. BitBlt(hMemDC,0,0,bmw,bmh,hMemDC2,xo,yo,SRCCOPY);
  115. SelectObject(hMemDC, hprev);
  116. if (!defaultDC) {
  117. SelectObject(hMemDC2, hprev2);
  118. DeleteDC(hMemDC2);
  119. }
  120. DeleteDC(hMemDC);
  121. bits=(ARGB32*)MALLOC_(bmw*bmh*4);
  122. if (getHeight()+getY() > bm.bmHeight || getWidth()+getX() > bm.bmWidth) {
  123. ASSERTALWAYS(StringPrintf("Subbitmap coordinates outside master bitmap [%d,%d,%d,%d in 0,0,%d,%d]", getX(), getY(), getWidth(), getHeight(), bm.bmWidth, bm.bmHeight));
  124. }
  125. MEMCPY32(bits,srcdib,bmw*bmh/**sizeof(ARGB32)*/);
  126. DeleteObject(hsrcdib);
  127. x_offset=-1;
  128. y_offset=-1;
  129. subimage_w=-1;
  130. subimage_h=-1;
  131. fullimage_w=bmw;
  132. fullimage_h=bmh;
  133. }
  134. #endif
  135. #ifdef LINUX
  136. if ( ! bits ) {
  137. fullimage_w=hbmp.bmWidth;
  138. fullimage_h=ABS(hbmp.bmHeight);
  139. bits=(ARGB32*)MALLOC_( fullimage_w * fullimage_h * 4 );
  140. MEMCPY32( bits, hbmp.shmseginfo->shmaddr, fullimage_w * fullimage_h );
  141. x_offset=-1;
  142. y_offset=-1;
  143. subimage_w=-1;
  144. subimage_h=-1;
  145. }
  146. #endif
  147. }
  148. #ifndef _NOSTUDIO
  149. #ifdef WASABI_COMPILE_IMGLDR
  150. SkinBitmap::SkinBitmap(const wchar_t *elementname, int _cached)
  151. {
  152. ASSERT(elementname!= NULL);
  153. bitmapname = elementname;
  154. x_offset = -1;
  155. y_offset = -1;
  156. subimage_w = -1;
  157. subimage_h = -1;
  158. fullimage_w=fullimage_h=0;
  159. ownbits=1;
  160. bits = NULL;
  161. fromskin = 0;
  162. last_failed = 0;
  163. #ifdef WASABI_COMPILE_SKIN
  164. bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(elementname, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached);
  165. fromskin = (bits != NULL);
  166. #endif
  167. if (bits == NULL)
  168. bits = WASABI_API_IMGLDR->imgldr_makeBmp(elementname, &has_alpha, &fullimage_w, &fullimage_h);
  169. #ifdef WASABI_COMPILE_SKIN
  170. if (bits == NULL)
  171. {
  172. bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(ERRORBMP, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached);
  173. last_failed = 1;
  174. }
  175. #endif
  176. if (bits == NULL)
  177. {
  178. bits = WASABI_API_IMGLDR->imgldr_makeBmp(HARDERRORBMP, &has_alpha, &fullimage_w, &fullimage_h);
  179. last_failed = 1;
  180. }
  181. // check that coordinates are correct
  182. if(x_offset!=-1 && x_offset>fullimage_w) x_offset=fullimage_w-1;
  183. if(y_offset!=-1 && y_offset>fullimage_h) y_offset=fullimage_h-1;
  184. if(subimage_w!=-1 && (x_offset+subimage_w)>fullimage_w) subimage_w=fullimage_w-x_offset;
  185. if(subimage_h!=-1 && (y_offset+subimage_h)>fullimage_h) subimage_h=fullimage_h-y_offset;
  186. // ASSERTPR(bits != NULL, elementname);
  187. if (bits == NULL) {
  188. DebugString("element not found ! %s\n", elementname);
  189. int n = 10*10;
  190. bits = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc(n * 4);
  191. ARGB32 *p = bits;
  192. while (n--)
  193. *p++ = 0xFFFF00FF;
  194. }
  195. }
  196. #endif
  197. #endif
  198. SkinBitmap::SkinBitmap(HBITMAP bitmap)
  199. {
  200. #ifdef WIN32
  201. ASSERT(bitmap != NULL);
  202. #endif
  203. subimage_w=-1;
  204. subimage_h=-1;
  205. x_offset=-1;
  206. y_offset=-1;
  207. bitmapname = L"";
  208. fullimage_w=fullimage_h=0;
  209. has_alpha = 0;
  210. ownbits=1;
  211. bits = NULL;
  212. fromskin = 0;
  213. last_failed = 0;
  214. bmpToBits(bitmap,NULL);
  215. }
  216. SkinBitmap::SkinBitmap(HBITMAP bitmap, HDC dc, int _has_alpha, void *_bits)
  217. {
  218. subimage_w=-1;
  219. subimage_h=-1;
  220. x_offset=-1;
  221. y_offset=-1;
  222. fromskin = 0;
  223. last_failed = 0;
  224. bitmapname = L"";
  225. fullimage_w=fullimage_h=0;
  226. #ifdef WIN32
  227. ASSERT(bitmap != NULL);
  228. #endif
  229. has_alpha = _has_alpha;
  230. bits = (ARGB32*)_bits;
  231. if (!_bits)
  232. {
  233. ownbits=1;
  234. bmpToBits(bitmap,dc);
  235. }
  236. else
  237. {
  238. #ifdef WIN32
  239. BITMAP bm;
  240. ownbits=0;
  241. int r = GetObject(bitmap, sizeof(BITMAP), &bm);
  242. ASSERT(r != 0);
  243. fullimage_w=bm.bmWidth;
  244. fullimage_h=ABS(bm.bmHeight);
  245. #endif
  246. #ifdef LINUX
  247. ownbits=0;
  248. fullimage_w=bitmap.bmWidth;
  249. fullimage_h=ABS(bitmap.bmHeight);
  250. #endif
  251. //port me
  252. }
  253. }
  254. SkinBitmap::SkinBitmap(int w, int h, DWORD bgcolor) {
  255. subimage_w=-1;
  256. subimage_h=-1;
  257. x_offset=-1;
  258. y_offset=-1;
  259. fullimage_w=w;
  260. bitmapname = L"";
  261. fullimage_h=h;
  262. fromskin = 0;
  263. last_failed = 0;
  264. int memsize = w*h*sizeof(ARGB32);
  265. if (memsize == 0) memsize++; // +1 so no failure when 0x0
  266. bits = (ARGB32*)MALLOC_(memsize);
  267. DWORD *dw = (DWORD *)bits;
  268. MEMFILL<DWORD>(dw, bgcolor, w*h);
  269. has_alpha = TRUE;
  270. ownbits=2; // 2 specifies should be FREE()'d
  271. }
  272. SkinBitmap::~SkinBitmap() {
  273. if (bits) {
  274. if (ownbits==2) FREE(bits);
  275. #ifndef _NOSTUDIO
  276. #ifdef WASABI_COMPILE_IMGLDR
  277. else if (ownbits) {
  278. #ifdef WASABI_COMPILE_SKIN
  279. if (fromskin)
  280. WASABI_API_IMGLDR->imgldr_releaseSkinBitmap(bits);
  281. else
  282. #endif
  283. #ifndef _WASABIRUNTIME
  284. WASABI_API_IMGLDR->imgldr_releaseBmp(bits);
  285. #else
  286. WASABI_API_IMGLDR->imgldr_releaseSkinBitmap(bits);
  287. #endif
  288. }
  289. #endif
  290. #endif
  291. }
  292. bits=NULL;
  293. }
  294. void SkinBitmap::blit(ifc_canvas *canvas, int x, int y) {
  295. RECT src, dst;
  296. src.left=0;
  297. src.top=0;
  298. src.bottom=getHeight();
  299. src.right=getWidth();
  300. dst.left=x;
  301. dst.right=x+getWidth();
  302. dst.top=y;
  303. dst.bottom=y+getHeight();
  304. blitToRect(canvas,&src,&dst,255);
  305. }
  306. void SkinBitmap::blitRectToTile(ifc_canvas *canvas, RECT *dest, RECT *src, int xoffs, int yoffs, int alpha) {
  307. int startx,starty;
  308. int w,h;
  309. w = src->right-src->left;
  310. h = src->bottom-src->top;
  311. if (w <= 0 || h <= 0) return; //wtfmf
  312. RECT c;
  313. if (canvas->getClipBox(&c) == NULLREGION) {
  314. c = *dest;
  315. } else {
  316. if (dest->left > c.left) c.left = dest->left;
  317. if (dest->top > c.top) c.top = dest->top;
  318. if (dest->right < c.right) c.right = dest->right;
  319. if (dest->bottom < c.bottom) c.bottom = dest->bottom;
  320. }
  321. starty = c.top-((c.top - dest->top) % h)- yoffs;
  322. startx = c.left-((c.left - dest->left) % w) - xoffs;
  323. for (int j=starty;j<c.bottom;j+=h)
  324. for (int i=startx;i<c.right;i+=w) {
  325. int xp=i;
  326. int yp=j;
  327. int xo=0;
  328. int yo=0;
  329. int _w=getWidth();
  330. int _h=getHeight();
  331. if (xp < c.left) {
  332. xo=c.left-xp;
  333. _w+=xo;
  334. xp=c.left;
  335. }
  336. if (yp < c.top) {
  337. yo=c.top-yp;
  338. _h+=yo;
  339. yp=c.top;
  340. }
  341. if (xp + _w >= c.right) _w=c.right-xp;
  342. if (yp + _h >= c.bottom) _h=c.bottom-yp;
  343. RECT _s={xo, yo, xo+_w, yo+_h};
  344. RECT _d={xp, yp, xp+_w, yp+_h};
  345. blitToRect(canvas, &_s, &_d, alpha);
  346. }
  347. }
  348. void SkinBitmap::blitTile(ifc_canvas *canvas, RECT *dest, int xoffs, int yoffs, int alpha) {
  349. RECT r={0,0,getWidth(),getHeight()};
  350. blitRectToTile(canvas, dest, &r, xoffs, yoffs, alpha);
  351. }
  352. #ifdef WIN32
  353. #pragma warning(push)
  354. #pragma warning(disable : 4799)
  355. #endif
  356. #define DEFAULT_CACHE_WIDTH 64
  357. #define DEFAULT_CACHE_HEIGHT 64
  358. int cacheWidth = DEFAULT_CACHE_WIDTH;
  359. int cacheHeight = DEFAULT_CACHE_HEIGHT;
  360. BltCanvas blitToRectCanvas(DEFAULT_CACHE_WIDTH,DEFAULT_CACHE_HEIGHT);
  361. void SkinBitmap::blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha) { // only dst(top,left) are used
  362. if (alpha <= 0) return;
  363. if (alpha > 255) alpha = 255;
  364. HDC hdc = canvas->getHDC();
  365. if (hdc == NULL) return;
  366. void *dib=canvas->getBits();
  367. int cwidth,cheight, pitch;
  368. BaseCloneCanvas clone(canvas);
  369. bool usingBlitCanvas = false;
  370. RECT destrect=*dst;
  371. destrect.bottom=destrect.top+(src->bottom-src->top);
  372. destrect.right=destrect.left+(src->right-src->left);
  373. RECT c;
  374. int ctype=canvas->getClipBox(&c);
  375. if (c.top > destrect.top) destrect.top=c.top;
  376. if (c.left > destrect.left) destrect.left=c.left;
  377. if (c.bottom < destrect.bottom) destrect.bottom=c.bottom;
  378. if (c.right < destrect.right) destrect.right=c.right;
  379. #ifdef NO_SIMPLEFASTMODE
  380. dib=NULL;
  381. #endif
  382. if (destrect.right <= destrect.left || destrect.bottom <= destrect.top) return;
  383. int xs,yp,xe,ye;
  384. if (!dib || canvas->getDim(NULL,&cheight,&cwidth) || !cwidth || cheight < 1 || ctype == COMPLEXREGION)
  385. {
  386. cwidth=destrect.right-destrect.left;
  387. cheight=destrect.bottom-destrect.top;
  388. if (cwidth > cacheWidth || cheight > cacheHeight)
  389. {
  390. cacheWidth=MAX(cacheWidth, cwidth);
  391. cacheHeight=MAX(cacheHeight, cheight);
  392. blitToRectCanvas.DestructiveResize(cacheWidth, cacheHeight);
  393. }
  394. dib = blitToRectCanvas.getBits();
  395. if (has_alpha || alpha < 255)
  396. clone.blit(destrect.left, destrect.top, &blitToRectCanvas, 0, 0, cwidth, cheight);
  397. xs=0;
  398. yp=0;
  399. xe=cwidth;
  400. ye=cheight;
  401. pitch=cacheWidth;
  402. usingBlitCanvas = true;
  403. }
  404. else
  405. {
  406. xs=destrect.left;
  407. xe=destrect.right;
  408. yp=destrect.top;
  409. ye=destrect.bottom;
  410. cwidth/=4;
  411. pitch=cwidth;
  412. }
  413. int xpo=(dst->left-destrect.left+xs)-(getX()+src->left);
  414. int ypo=(dst->top-destrect.top+yp)-(getY()+src->top);
  415. if (yp < 0) yp=0;
  416. if (xs < 0) xs=0;
  417. if (yp<getY()+ypo) yp=ypo+getY();
  418. if (xs<getX()+xpo) xs=xpo+getX();
  419. if (xe > getWidth()+getX()+xpo) xe=getWidth()+getX()+xpo;
  420. if (ye > getHeight()+getY()+ypo) ye=getHeight()+getY()+ypo;
  421. // blend bitmap to dib
  422. if (xs<xe) for (; yp < ye; yp ++) {
  423. int xp=xe-xs;
  424. unsigned int *dest=((unsigned int*)dib) + pitch*yp + xs;
  425. unsigned int *src=((unsigned int*)bits) + (yp-ypo)*fullimage_w + (xs-xpo);
  426. if (!has_alpha && alpha==255) // simple copy
  427. {
  428. MEMCPY32(dest,src,xp);
  429. }
  430. else if (!has_alpha) { // no alpha channel info, but just a simple blend
  431. if (!HAS_MMX)
  432. while (xp--) *dest++ = Blenders::BLEND_ADJ1(*src++, *dest, alpha);
  433. #ifndef NO_MMX
  434. else
  435. {
  436. #ifdef WIN32
  437. if (xp>1) __asm
  438. {
  439. movd mm3, [alpha]
  440. mov ecx, xp
  441. movq mm4, [SkinBitmap_mmx_revn2]
  442. packuswb mm3, mm3 // 0000HHVV
  443. paddusw mm3, [SkinBitmap_mmx_one]
  444. mov edi, dest
  445. punpcklwd mm3, mm3 // HHVVHHVV
  446. mov esi, src
  447. punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  448. shr ecx, 1
  449. psubw mm4, mm3
  450. align 16
  451. _blitAlpha_Loop1:
  452. movd mm0, [edi]
  453. movd mm1, [esi]
  454. punpcklbw mm0, [SkinBitmap_mmx_zero]
  455. movd mm7, [edi+4]
  456. punpcklbw mm1, [SkinBitmap_mmx_zero]
  457. pmullw mm0, mm4
  458. pmullw mm1, mm3
  459. movd mm6, [esi+4]
  460. punpcklbw mm7, [SkinBitmap_mmx_zero]
  461. punpcklbw mm6, [SkinBitmap_mmx_zero]
  462. pmullw mm7, mm4
  463. pmullw mm6, mm3
  464. paddw mm0, mm1
  465. psrlw mm0, 8
  466. packuswb mm0, mm0
  467. add esi, 8
  468. movd [edi], mm0
  469. paddw mm7, mm6
  470. psrlw mm7, 8
  471. packuswb mm7, mm7
  472. movd [edi+4], mm7
  473. add edi, 8
  474. dec ecx
  475. jnz _blitAlpha_Loop1
  476. mov src, esi
  477. mov dest, edi
  478. #else
  479. if ( xp > 1 ) {
  480. __asm__ volatile (
  481. "movd %6, %%mm3\n"
  482. "mov %2, %%ecx\n"
  483. "movq (SkinBitmap_mmx_revn2), %%mm4\n"
  484. "packuswb %%mm3, %%mm3\n"
  485. "paddusw (SkinBitmap_mmx_one), %%mm3\n"
  486. "mov %0, %%edi\n"
  487. "punpcklwd %%mm3, %%mm3\n"
  488. "mov %1, %%esi\n"
  489. "punpckldq %%mm3, %%mm3\n"
  490. "shr $1, %%ecx\n"
  491. "psubw %%mm3, %%mm4\n"
  492. ".align 16\n"
  493. "_blitAlpha_Loop1:\n"
  494. "movd (%%edi), %%mm0\n"
  495. "movd (%%esi), %%mm1\n"
  496. "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n"
  497. "movd 4(%%edi), %%mm7\n"
  498. "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n"
  499. "pmullw %%mm3, %%mm0\n"
  500. "pmullw %%mm4, %%mm1\n"
  501. "movd 4(%%esi), %%mm6\n"
  502. "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n"
  503. "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n"
  504. "pmullw %%mm4, %%mm6\n"
  505. "pmullw %%mm3, %%mm7\n"
  506. "paddw %%mm1, %%mm0\n"
  507. "psrlw $8, %%mm0\n"
  508. "packuswb %%mm0, %%mm0\n"
  509. "add $8, %%esi\n"
  510. "movd %%mm0, (%%edi)\n"
  511. "paddw %%mm6, %%mm7\n"
  512. "psrlw $8, %%mm7\n"
  513. "packuswb %%mm7, %%mm7\n"
  514. "movd %%mm7, 4(%%edi)\n"
  515. "add $8, %%edi\n"
  516. "dec %%ecx\n"
  517. "jnz _blitAlpha_Loop1\n"
  518. "mov %%esi, %1\n"
  519. "mov %%edi, %0\n"
  520. : "=m" (dest), "=m" (src), "=m" (xp)
  521. : "0" (dest), "1" (src), "2" (xp), "m" (alpha)
  522. : "%eax", "%ecx", "%esi", "%edi" );
  523. #endif
  524. }
  525. if (xp & 1) *dest++ = Blenders::BLEND_ADJ1_MMX(*src++, *dest, alpha);
  526. } // mmx available
  527. #endif // !NO_MMX
  528. }
  529. else if (alpha == 255) { // no global alpha, just alpha channel
  530. if (!HAS_MMX)
  531. while (xp--) *dest++ = Blenders::BLEND_ADJ2(*dest, *src++);
  532. #ifndef NO_MMX
  533. else
  534. {
  535. #ifdef WIN32
  536. if (xp > 1) __asm
  537. {
  538. mov ecx, xp
  539. shr ecx, 1
  540. mov edi, dest
  541. mov esi, src
  542. align 16
  543. _blitAlpha_Loop2:
  544. movd mm3, [esi]
  545. movd mm5, [esi+4]
  546. movq mm2, [SkinBitmap_mmx_revn2]
  547. psrld mm3, 24
  548. movq mm4, [SkinBitmap_mmx_revn2]
  549. psrld mm5, 24
  550. movd mm0, [edi]
  551. packuswb mm3, mm3 // 0000HHVV
  552. movd mm1, [esi]
  553. packuswb mm5, mm5 // 0000HHVV
  554. movd mm6, [esi+4]
  555. paddusw mm3, [SkinBitmap_mmx_one]
  556. punpcklwd mm3, mm3 // HHVVHHVV
  557. paddusw mm5, [SkinBitmap_mmx_one]
  558. movd mm7, [edi+4]
  559. punpcklwd mm5, mm5 // HHVVHHVV
  560. punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  561. punpckldq mm5, mm5 // HHVVHHVV HHVVHHVV
  562. punpcklbw mm6, [SkinBitmap_mmx_zero]
  563. psubw mm4, mm5
  564. punpcklbw mm0, [SkinBitmap_mmx_zero]
  565. psubw mm2, mm3
  566. punpcklbw mm7, [SkinBitmap_mmx_zero]
  567. pmullw mm0, mm2
  568. pmullw mm7, mm4
  569. punpcklbw mm1, [SkinBitmap_mmx_zero]
  570. psubw mm2, mm3
  571. psrlw mm0, 8
  572. psrlw mm7, 8
  573. paddw mm0, mm1
  574. paddw mm7, mm6
  575. packuswb mm0, mm0
  576. movd [edi], mm0
  577. packuswb mm7, mm7
  578. movd [edi+4], mm7
  579. add esi, 8
  580. add edi, 8
  581. dec ecx
  582. jnz _blitAlpha_Loop2
  583. mov src, esi
  584. mov dest, edi
  585. #else
  586. if( xp > 1 ) {
  587. __asm__ volatile (
  588. "mov %4, %%ecx\n"
  589. "shr $1, %%ecx\n"
  590. "mov %0, %%edi\n"
  591. "mov %1, %%esi\n"
  592. ".align 16\n"
  593. "_blitAlpha_Loop2:\n"
  594. "movd (%%esi), %%mm3\n"
  595. "movd 4(%%esi), %%mm5\n"
  596. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  597. "psrld $24, %%mm3\n"
  598. "movq (SkinBitmap_mmx_revn2), %%mm4\n"
  599. "psrld $24, %%mm5\n"
  600. "movd (%%edi), %%mm0\n"
  601. "packuswb %%mm3, %%mm3\n"
  602. "movd (%%esi), %%mm1\n"
  603. "packuswb %%mm5, %%mm5\n"
  604. "movd 4(%%esi), %%mm6\n"
  605. "paddusw (SkinBitmap_mmx_one), %%mm3\n"
  606. "punpcklwd %%mm3, %%mm3\n"
  607. "paddusw (SkinBitmap_mmx_one), %%mm5\n"
  608. "movd 4(%%edi), %%mm7\n"
  609. "punpcklwd %%mm5, %%mm5\n"
  610. "punpckldq %%mm3, %%mm3\n"
  611. "punpckldq %%mm5, %%mm5\n"
  612. "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n"
  613. "psubw %%mm5, %%mm4\n"
  614. "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n"
  615. "psubw %%mm3, %%mm2\n"
  616. "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n"
  617. "pmullw %%mm2, %%mm0\n"
  618. "pmullw %%mm4, %%mm7\n"
  619. "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n"
  620. "psubw %%mm3, %%mm2\n"
  621. "psrlw $8, %%mm0\n"
  622. "psrlw $8, %%mm7\n"
  623. "paddw %%mm1, %%mm0\n"
  624. "paddw %%mm6, %%mm7\n"
  625. "packuswb %%mm0, %%mm0\n"
  626. "movd %%mm0, (%%edi)\n"
  627. "packuswb %%mm7, %%mm7\n"
  628. "movd %%mm7, 4(%%edi)\n"
  629. "add $8, %%esi\n"
  630. "add $8, %%edi\n"
  631. "dec %%ecx\n"
  632. "jnz _blitAlpha_Loop2\n"
  633. "mov %%esi, %1\n"
  634. "mov %%edi, %0\n"
  635. : "=m" (dest), "=m" (src)
  636. : "0" (dest), "1" (src), "m" (xp)
  637. : "%eax", "%ecx", "%esi", "%edi" );
  638. #endif
  639. }
  640. if (xp&1) *dest++ = Blenders::BLEND_ADJ2_MMX(*dest, *src++);
  641. } // HAS_MMX
  642. #endif // ifndef NO_MMX
  643. }
  644. else { // both
  645. if (!HAS_MMX)
  646. while (xp--) *dest++ = Blenders::BLEND_ADJ3(*dest, *src++, alpha);
  647. #ifndef NO_MMX
  648. else
  649. {
  650. #ifdef WIN32
  651. if (xp > 1) __asm
  652. {
  653. movd mm5, [alpha]
  654. mov ecx, xp
  655. packuswb mm5, mm5
  656. shr ecx, 1
  657. paddusw mm5, [SkinBitmap_mmx_one]
  658. punpcklwd mm5, mm5
  659. mov edi, dest
  660. punpckldq mm5, mm5
  661. mov esi, src
  662. align 16
  663. _blitAlpha_Loop3:
  664. movd mm3, [esi] // VVVVVVVV
  665. movd mm4, [esi+4] // VVVVVVVV
  666. movd mm0, [edi]
  667. psrld mm3, 24
  668. movd mm1, [esi]
  669. psrld mm4, 24
  670. paddusw mm3, [SkinBitmap_mmx_one]
  671. paddusw mm4, [SkinBitmap_mmx_one]
  672. movd mm7, [edi+4]
  673. punpcklwd mm3, mm3
  674. movd mm6, [esi+4]
  675. punpcklwd mm4, mm4
  676. punpckldq mm3, mm3
  677. punpckldq mm4, mm4
  678. pmullw mm3, mm5
  679. pmullw mm4, mm5
  680. punpcklbw mm7, [SkinBitmap_mmx_zero]
  681. punpcklbw mm6, [SkinBitmap_mmx_zero]
  682. movq mm2, [SkinBitmap_mmx_revn2]
  683. psrlw mm3, 8
  684. psrlw mm4, 8
  685. punpcklbw mm0, [SkinBitmap_mmx_zero]
  686. punpcklbw mm1, [SkinBitmap_mmx_zero]
  687. psubw mm2, mm3
  688. pmullw mm0, mm2
  689. pmullw mm1, mm5
  690. add esi, 8
  691. movq mm2, [SkinBitmap_mmx_revn2]
  692. pmullw mm6, mm5
  693. paddusw mm0, mm1
  694. psubw mm2, mm4
  695. pmullw mm7, mm2
  696. psrlw mm0, 8
  697. packuswb mm0, mm0
  698. paddusw mm7, mm6
  699. movd [edi], mm0
  700. psrlw mm7, 8
  701. packuswb mm7, mm7
  702. movd [edi+4], mm7
  703. add edi, 8
  704. dec ecx
  705. jnz _blitAlpha_Loop3
  706. mov src, esi
  707. mov dest, edi
  708. #else
  709. if ( xp > 1 ) {
  710. __asm__ volatile (
  711. "movd %5, %%mm5\n"
  712. "mov %4, %%ecx\n"
  713. "packuswb %%mm5, %%mm5 \n"
  714. "shr $1, %%ecx\n"
  715. "paddusw (SkinBitmap_mmx_one), %%mm5\n"
  716. "punpcklwd %%mm5, %%mm5\n"
  717. "mov %0, %%edi\n"
  718. "punpckldq %%mm5, %%mm5\n"
  719. "mov %1, %%esi\n"
  720. ".align 16\n"
  721. "_blitAlpha_Loop3:\n"
  722. "movd (%%esi), %%mm3\n"
  723. "movd 4(%%esi), %%mm4\n"
  724. "movd (%%edi), %%mm0\n"
  725. "psrld $24, %%mm3\n"
  726. "movd (%%esi), %%mm1\n"
  727. "psrld $24, %%mm4\n"
  728. "paddusw (SkinBitmap_mmx_one), %%mm3\n"
  729. "paddusw (SkinBitmap_mmx_one), %%mm4\n"
  730. "movd 4(%%edi), %%mm7\n"
  731. "punpcklwd %%mm3, %%mm3\n"
  732. "movd 4(%%esi), %%mm6\n"
  733. "punpcklwd %%mm4, %%mm4\n"
  734. "punpckldq %%mm3, %%mm3\n"
  735. "punpckldq %%mm4, %%mm4\n"
  736. "pmullw %%mm5, %%mm3\n"
  737. "pmullw %%mm5, %%mm4\n"
  738. "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n"
  739. "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n"
  740. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  741. "psrlw $8, %%mm3\n"
  742. "psrlw $8, %%mm4\n"
  743. "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n"
  744. "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n"
  745. "psubw %%mm3, %%mm2\n"
  746. "pmullw %%mm2, %%mm0\n"
  747. "pmullw %%mm5, %%mm1\n"
  748. "add $8, %%esi\n"
  749. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  750. "pmullw %%mm5, %%mm6\n"
  751. "paddusw %%mm1, %%mm0\n"
  752. "psubw %%mm4, %%mm2\n"
  753. "pmullw %%mm2, %%mm7\n"
  754. "psrlw $8, %%mm0\n"
  755. "packuswb %%mm0, %%mm0\n"
  756. "paddusw %%mm6, %%mm7\n"
  757. "movd %%mm0, (%%edi)\n"
  758. "psrlw $8, %%mm7\n"
  759. "packuswb %%mm7, %%mm7\n"
  760. "movd %%mm7, 4(%%edi)\n"
  761. "add $8, %%edi\n"
  762. "dec %%ecx\n"
  763. "jnz _blitAlpha_Loop3\n"
  764. "mov %%esi, %1\n"
  765. "mov %%edi, %0\n"
  766. : "=m" (dest), "=m" (src)
  767. : "0" (dest), "1" (src), "m" (xp), "m" (alpha)
  768. : "%eax", "%ecx", "%esi", "%edi" );
  769. #endif
  770. }
  771. if (xp&1) *dest++ = Blenders::BLEND_ADJ3_MMX(*dest, *src++, alpha);
  772. } // HAS_MMX
  773. #endif // ifndef NO_MMX
  774. }
  775. }
  776. #ifndef NO_MMX
  777. Blenders::BLEND_MMX_END();
  778. #endif
  779. // write bits back to dib.
  780. if (usingBlitCanvas) {
  781. blitToRectCanvas.blit(0, 0, &clone, destrect.left, destrect.top, cwidth, cheight);
  782. }
  783. }
  784. #ifdef WIN32
  785. #pragma warning(pop)
  786. #endif
  787. void SkinBitmap::stretch(ifc_canvas *canvas, int x, int y, int w, int h) {
  788. RECT src, dst;
  789. src.left=0;
  790. src.top=0;
  791. src.right=getWidth();
  792. src.bottom=getHeight();
  793. dst.left=x;
  794. dst.right=x+w;
  795. dst.top=y;
  796. dst.bottom=y+h;
  797. stretchToRectAlpha(canvas,&src,&dst,255);
  798. }
  799. void SkinBitmap::stretchToRect(ifc_canvas *canvas, RECT *r) {
  800. stretch(canvas, r->left, r->top, r->right - r->left, r->bottom - r->top);
  801. }
  802. void SkinBitmap::stretchRectToRect(ifc_canvas *canvas, RECT *src, RECT *dst) {
  803. stretchToRectAlpha(canvas,src,dst,255);
  804. }
  805. void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha) {
  806. RECT re;
  807. re.left=0; re.top=0;
  808. re.right=getWidth(); re.bottom=getHeight();
  809. stretchToRectAlpha(canvas,&re,r,alpha);
  810. }
  811. void SkinBitmap::blitAlpha(ifc_canvas *canvas, int x, int y, int alpha)
  812. {
  813. RECT dst,src;
  814. dst.left=x;
  815. dst.top=y;
  816. src.left=0;
  817. src.top=0;
  818. src.bottom=getHeight();
  819. src.right=getWidth();
  820. blitToRect(canvas,&src,&dst,alpha);
  821. }
  822. #ifdef WIN32
  823. #pragma warning(push)
  824. #pragma warning(disable : 4799)
  825. #endif
  826. template <class C>
  827. class Stretcher {
  828. public:
  829. static void _stretchToRectAlpha(SkinBitmap *bitmap, int ys, int ye, int xe, int xs, int xstart, int yv, void *dib, int pitch, int dxv, int dyv, int alpha) {
  830. int bitmap_x = bitmap->getX();
  831. int bitmap_y = bitmap->getY();
  832. int bmpheight = bitmap->getHeight();
  833. int fullimage_w = bitmap->getFullWidth();
  834. void *bits = bitmap->getBits();
  835. int xp=xe-xs;
  836. for (int yp = ys; yp < ye; yp ++) {
  837. int t=yv>>16;
  838. if (t < 0) t=0;
  839. if (t >= bmpheight) t=bmpheight-1;
  840. int *psrc=((int*)bits) + (t+bitmap_y)*fullimage_w + bitmap_x;
  841. int *dest=((int*)dib) + pitch*yp + xs;
  842. C::stretch(xp, psrc, dest, xstart, dxv, alpha);
  843. yv+=dyv;
  844. }
  845. }
  846. };
  847. // no alpha, just stretch
  848. class Stretch {
  849. public:
  850. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  851. while (xp--) { //JFtodo: assembly optimize - these first two modes aren't used that much anyway
  852. *dest++ = psrc[xv>>16];
  853. xv+=dxv;
  854. }
  855. }
  856. };
  857. // no alpha channel, just a global alpha val
  858. class StretchGlobal {
  859. public:
  860. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  861. while (xp--) { //JFTODO: make MMX optimized version
  862. *dest++ = Blenders::BLEND_ADJ1(psrc[xv>>16], *dest, alpha);
  863. xv+=dxv;
  864. }
  865. }
  866. };
  867. // alpha channel, no global alpha val
  868. class StretchChannel {
  869. public:
  870. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  871. while (xp--) {
  872. *dest++ = Blenders::BLEND_ADJ2(*dest, psrc[xv>>16]);
  873. xv+=dxv;
  874. }
  875. }
  876. };
  877. class StretchGlobalChannel {
  878. public:
  879. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  880. while (xp--) {
  881. *dest++ = Blenders::BLEND_ADJ3(*dest, psrc[xv>>16], alpha);
  882. xv+=dxv;
  883. }
  884. }
  885. };
  886. #ifndef NO_MMX
  887. // no alpha channel, just a global alpha val
  888. class StretchGlobalMMX {
  889. public:
  890. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  891. while (xp--) { //JFTODO: make MMX optimized version
  892. *dest++ = Blenders::BLEND_ADJ1_MMX(psrc[xv>>16], *dest, alpha);
  893. xv+=dxv;
  894. }
  895. }
  896. };
  897. // alpha channel, no global alpha val
  898. class StretchChannelMMX {
  899. public:
  900. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  901. #ifdef WIN32
  902. if (xp>1) __asm
  903. {
  904. mov ecx, xp
  905. mov edi, dest
  906. shr ecx, 1
  907. mov esi, psrc
  908. mov edx, xv
  909. mov ebx, dxv
  910. align 16
  911. _stretchAlpha_Loop2:
  912. mov eax, edx
  913. movd mm0, [edi]
  914. movq mm4, [SkinBitmap_mmx_revn2]
  915. shr eax, 16
  916. movq mm2, [SkinBitmap_mmx_revn2]
  917. punpcklbw mm0, [SkinBitmap_mmx_zero]
  918. movd mm3, [esi+eax*4]
  919. movd mm1, [esi+eax*4]
  920. lea eax, [edx+ebx]
  921. shr eax, 16
  922. movd mm7, [edi+4]
  923. psrld mm3, 24
  924. packuswb mm3, mm3 // 0000HHVV
  925. movd mm5, [esi+eax*4]
  926. movd mm6, [esi+eax*4]
  927. psrld mm5, 24
  928. paddusw mm3, [SkinBitmap_mmx_one]
  929. punpcklbw mm6, [SkinBitmap_mmx_zero]
  930. packuswb mm5, mm5 // 0000HHVV
  931. lea edx, [edx+ebx*2]
  932. paddusw mm5, [SkinBitmap_mmx_one]
  933. punpcklwd mm3, mm3 // HHVVHHVV
  934. punpcklwd mm5, mm5 // HHVVHHVV
  935. add edi, 8
  936. punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  937. punpckldq mm5, mm5 // HHVVHHVV HHVVHHVV
  938. psubw mm4, mm5
  939. psubw mm2, mm3
  940. punpcklbw mm7, [SkinBitmap_mmx_zero]
  941. pmullw mm0, mm2
  942. pmullw mm7, mm4
  943. punpcklbw mm1, [SkinBitmap_mmx_zero]
  944. psubw mm2, mm3
  945. psrlw mm0, 8
  946. psrlw mm7, 8
  947. paddw mm0, mm1
  948. paddw mm7, mm6
  949. packuswb mm0, mm0
  950. movd [edi-8], mm0
  951. packuswb mm7, mm7
  952. movd [edi-4], mm7
  953. dec ecx
  954. jnz _stretchAlpha_Loop2
  955. mov dest, edi
  956. mov xv, edx
  957. }
  958. #else
  959. if (xp>1)
  960. {
  961. __asm__ volatile (
  962. "mov %5, %%ecx\n"
  963. "mov %0, %%edi\n"
  964. "shr $1, %%ecx\n"
  965. "mov %1, %%esi\n"
  966. "mov %2, %%edx\n"
  967. "mov %7, %%ebx\n"
  968. ".align 16\n"
  969. "_stretchAlpha_Loop2:\n"
  970. "mov %%edx, %%eax\n"
  971. "movd (%%edi), %%mm0\n"
  972. "movq (SkinBitmap_mmx_revn2), %%mm4\n"
  973. "shr $16, %%eax\n"
  974. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  975. "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n"
  976. "movd (%%esi,%%eax,4), %%mm3\n"
  977. "movd (%%esi,%%eax,4), %%mm1\n"
  978. "lea (%%edx,%%ebx), %%eax\n"
  979. "shr $16, %%eax\n"
  980. "movd 4(%%edi), %%mm7\n"
  981. "psrld $24, %%mm3\n"
  982. "packuswb %%mm3, %%mm3\n"
  983. "movd (%%esi,%%eax,4), %%mm5\n"
  984. "movd (%%esi,%%eax,4), %%mm6\n"
  985. "psrld $24, %%mm5\n"
  986. "paddusw (SkinBitmap_mmx_one), %%mm3\n"
  987. "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n"
  988. "packuswb %%mm5, %%mm5\n"
  989. "lea (%%edx,%%ebx,2), %%edx\n"
  990. "paddusw (SkinBitmap_mmx_one), %%mm5\n"
  991. "punpcklwd %%mm3, %%mm3\n"
  992. "punpcklwd %%mm5, %%mm5\n"
  993. "add $8, %%edi\n"
  994. "punpckldq %%mm3, %%mm3\n"
  995. "punpckldq %%mm5, %%mm5\n"
  996. "psubw %%mm5, %%mm4\n"
  997. "psubw %%mm3, %%mm2\n"
  998. "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n"
  999. "pmullw %%mm2, %%mm0\n"
  1000. "pmullw %%mm4, %%mm7\n"
  1001. "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n"
  1002. "psubw %%mm3, %%mm2\n"
  1003. "psrlw $8, %%mm0\n"
  1004. "psrlw $8, %%mm7\n"
  1005. "paddw %%mm1, %%mm0\n"
  1006. "paddw %%mm6, %%mm7\n"
  1007. "packuswb %%mm0, %%mm0\n"
  1008. "movd %%mm0, -8(%%edi)\n"
  1009. "packuswb %%mm7, %%mm7\n"
  1010. "movd %%mm7, -4(%%edi)\n"
  1011. "dec %%ecx\n"
  1012. "jnz _stretchAlpha_Loop2\n"
  1013. "mov %%edi, %0\n"
  1014. "mov %%edx, %2\n"
  1015. : "=m" (dest), "=m" (psrc), "=m" (xv)
  1016. : "0" (dest), "1" (psrc), "m" (xp),
  1017. "2" (xv), "m" (dxv), "m" (alpha)
  1018. : "%eax", "%ebx", "%ecx", "%edx",
  1019. "%esi", "%edi" );
  1020. }
  1021. #endif
  1022. if (xp&1) *dest++ = Blenders::BLEND_ADJ2_MMX(*dest, psrc[xv>>16]);
  1023. }
  1024. };
  1025. class StretchGlobalChannelMMX {
  1026. public:
  1027. static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) {
  1028. #ifdef WIN32
  1029. if (xp>1) __asm
  1030. {
  1031. movd mm5, [alpha]
  1032. mov ecx, xp
  1033. packuswb mm5, mm5
  1034. shr ecx, 1
  1035. paddusw mm5, [SkinBitmap_mmx_one]
  1036. punpcklwd mm5, mm5
  1037. mov edi, dest
  1038. punpckldq mm5, mm5
  1039. mov esi, psrc
  1040. mov edx, xv
  1041. mov ebx, dxv
  1042. align 16
  1043. _stretchAlpha_Loop3:
  1044. movd mm0, [edi]
  1045. mov eax, edx
  1046. movd mm7, [edi+4]
  1047. shr eax, 16
  1048. movd mm1, [esi+eax*4]
  1049. movd mm3, [esi+eax*4] // VVVVVVVV
  1050. lea eax, [edx+ebx]
  1051. psrld mm3, 24
  1052. paddusw mm3, [SkinBitmap_mmx_one]
  1053. punpcklwd mm3, mm3
  1054. shr eax, 16
  1055. punpckldq mm3, mm3
  1056. pmullw mm3, mm5
  1057. movd mm4, [esi+eax*4] // VVVVVVVV
  1058. movd mm6, [esi+eax*4]
  1059. movq mm2, [SkinBitmap_mmx_revn2]
  1060. psrld mm4, 24
  1061. paddusw mm4, [SkinBitmap_mmx_one]
  1062. punpcklbw mm7, [SkinBitmap_mmx_zero]
  1063. punpcklwd mm4, mm4
  1064. lea edx, [edx+ebx*2]
  1065. punpckldq mm4, mm4
  1066. add edi, 8
  1067. punpcklbw mm6, [SkinBitmap_mmx_zero]
  1068. pmullw mm4, mm5
  1069. psrlw mm3, 8
  1070. punpcklbw mm0, [SkinBitmap_mmx_zero]
  1071. punpcklbw mm1, [SkinBitmap_mmx_zero]
  1072. psubw mm2, mm3
  1073. pmullw mm0, mm2
  1074. pmullw mm1, mm5
  1075. pmullw mm6, mm5
  1076. psrlw mm4, 8
  1077. movq mm2, [SkinBitmap_mmx_revn2]
  1078. paddusw mm0, mm1
  1079. psubw mm2, mm4
  1080. pmullw mm7, mm2
  1081. psrlw mm0, 8
  1082. packuswb mm0, mm0
  1083. paddusw mm7, mm6
  1084. movd [edi-8], mm0
  1085. psrlw mm7, 8
  1086. packuswb mm7, mm7
  1087. movd [edi-4], mm7
  1088. dec ecx
  1089. jnz _stretchAlpha_Loop3
  1090. mov xv, edx
  1091. mov dest, edi
  1092. }
  1093. #else
  1094. if (xp>1)
  1095. {
  1096. __asm__ volatile (
  1097. "movd %8, %%mm5\n"
  1098. "mov %5, %%ecx\n"
  1099. "packuswb %%mm5, %%mm5 \n"
  1100. "shr $1, %%ecx\n"
  1101. "paddusw (SkinBitmap_mmx_one), %%mm5\n"
  1102. "punpcklwd %%mm5, %%mm5\n"
  1103. "mov %0, %%edi\n"
  1104. "punpckldq %%mm5, %%mm5\n"
  1105. "mov %1, %%esi\n"
  1106. "mov %6, %%edx\n"
  1107. "mov %7, %%ebx\n"
  1108. ".align 16\n"
  1109. "_stretchAlpha_Loop3:\n"
  1110. "movd (%%edi), %%mm0\n"
  1111. "mov %%edx, %%eax\n"
  1112. "movd 4(%%edi), %%mm7\n"
  1113. "shr $16, %%eax\n"
  1114. "movd (%%esi,%%eax,4), %%mm1\n"
  1115. "movd (%%esi,%%eax,4), %%mm3\n"
  1116. "lea (%%edx,%%ebx), %%eax\n"
  1117. "psrld $24, %%mm3\n"
  1118. "paddusw (SkinBitmap_mmx_one), %%mm3\n"
  1119. "punpcklwd %%mm3, %%mm3\n"
  1120. "shr $16, %%eax\n"
  1121. "punpckldq %%mm3, %%mm3\n"
  1122. "pmullw %%mm5, %%mm3\n"
  1123. "movd (%%esi,%%eax,4), %%mm4\n"
  1124. "movd (%%esi,%%eax,4), %%mm6\n"
  1125. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  1126. "psrld $24, %%mm4\n"
  1127. "paddusw (SkinBitmap_mmx_one), %%mm4\n"
  1128. "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n"
  1129. "punpcklwd %%mm4, %%mm4\n"
  1130. "lea (%%edx,%%ebx,2), %%edx\n"
  1131. "punpckldq %%mm4, %%mm4\n"
  1132. "add $8, %%edi\n"
  1133. "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n"
  1134. "pmullw %%mm5, %%mm4\n"
  1135. "psrlw $8, %%mm3\n"
  1136. "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n"
  1137. "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n"
  1138. "psubw %%mm3, %%mm2\n"
  1139. "pmullw %%mm2, %%mm0\n"
  1140. "pmullw %%mm5, %%mm1\n"
  1141. "pmullw %%mm5, %%mm6\n"
  1142. "psrlw $8, %%mm4\n"
  1143. "movq (SkinBitmap_mmx_revn2), %%mm2\n"
  1144. "paddusw %%mm1, %%mm0\n"
  1145. "psubw %%mm4, %%mm2\n"
  1146. "pmullw %%mm2, %%mm7\n"
  1147. "psrlw $8, %%mm0\n"
  1148. "packuswb %%mm0, %%mm0\n"
  1149. "paddusw %%mm6, %%mm7\n"
  1150. "movd %%mm0, -8(%%edi)\n"
  1151. "psrlw $8, %%mm7\n"
  1152. "packuswb %%mm7, %%mm7\n"
  1153. "movd %%mm7, -4(%%edi)\n"
  1154. "dec %%ecx\n"
  1155. "jnz _stretchAlpha_Loop3\n"
  1156. "mov %%edi, %0\n"
  1157. "mov %%edx, %2\n"
  1158. : "=m" (dest), "=m" (psrc), "=m" (xv)
  1159. : "0" (dest), "1" (psrc), "m" (xp),
  1160. "m" (xv), "m" (dxv), "m" (alpha)
  1161. : "%eax", "%ebx", "%ecx", "%edx",
  1162. "%esi", "%edi" );
  1163. }
  1164. #endif
  1165. if (xp&1) *dest++ = Blenders::BLEND_ADJ3_MMX(*dest, psrc[xv>>16], alpha);
  1166. }
  1167. };
  1168. #endif
  1169. class __Stretch : public Stretcher<Stretch> {};
  1170. class __StretchGlobal : public Stretcher<StretchGlobal> {};
  1171. class __StretchChannel : public Stretcher<StretchChannel> {};
  1172. class __StretchGlobalChannel : public Stretcher<StretchGlobalChannel> {};
  1173. #ifndef NO_MMX
  1174. class __StretchGlobalMMX : public Stretcher<StretchGlobalMMX> {};
  1175. class __StretchChannelMMX : public Stretcher<StretchChannelMMX> {};
  1176. class __StretchGlobalChannelMMX : public Stretcher<StretchGlobalChannelMMX> {};
  1177. #endif
  1178. #ifdef WIN32
  1179. #pragma warning(pop)
  1180. #endif
  1181. void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *_src, RECT *_dst, int alpha)
  1182. {
  1183. if (alpha <= 0) return;
  1184. if (alpha > 255) alpha = 255;
  1185. RECT src=*_src;
  1186. RECT dst=*_dst;
  1187. if ((src.right-src.left) == (dst.right-dst.left) &&
  1188. (src.bottom-src.top) == (dst.bottom-dst.top))
  1189. {
  1190. blitToRect(canvas,_src,_dst,alpha);
  1191. return;
  1192. }
  1193. //FG> this is a hack, we should support subpixels instead
  1194. if (src.left == src.right) {
  1195. if (src.right < getWidth())
  1196. src.right++;
  1197. else
  1198. src.left--;
  1199. }
  1200. if (src.top== src.bottom) {
  1201. if (src.bottom < getHeight())
  1202. src.bottom++;
  1203. else
  1204. src.top--;
  1205. }
  1206. if (src.left >= src.right || src.top >= src.bottom) return;
  1207. if (dst.left >= dst.right || dst.top >= dst.bottom) return;
  1208. void *dib=canvas->getBits();
  1209. HDC hdc=canvas->getHDC();
  1210. bool usingBlitCanvas = false;
  1211. BaseCloneCanvas clone(canvas);
  1212. int cwidth, cheight, pitch;
  1213. int dyv=((src.bottom-src.top)<<16)/(dst.bottom-dst.top);
  1214. int dxv=((src.right-src.left)<<16)/(dst.right-dst.left);
  1215. int yv=(src.top<<16);
  1216. int xstart=(src.left<<16);
  1217. RECT c;
  1218. int ctype=canvas->getClipBox(&c);
  1219. if (c.top > dst.top)
  1220. {
  1221. yv+=(c.top-dst.top)*dyv;
  1222. dst.top=c.top;
  1223. }
  1224. if (c.left > dst.left)
  1225. {
  1226. xstart+=(c.left-dst.left)*dxv;
  1227. dst.left=c.left;
  1228. }
  1229. if (c.bottom < dst.bottom) dst.bottom=c.bottom;
  1230. if (c.right < dst.right) dst.right=c.right;
  1231. if (dst.right <= dst.left || dst.bottom <= dst.top) return;
  1232. int xs,xe,ys,ye;
  1233. #ifdef NO_SIMPLEFASTMODE
  1234. dib=NULL;
  1235. #endif
  1236. if (!dib || canvas->getDim(NULL,&cheight,&cwidth) || !cwidth || cheight < 1 || ctype == COMPLEXREGION)
  1237. {
  1238. cwidth=dst.right-dst.left;
  1239. cheight=dst.bottom-dst.top;
  1240. if (cwidth > cacheWidth || cheight > cacheHeight)
  1241. {
  1242. cacheWidth=MAX(cacheWidth, cwidth);
  1243. cacheHeight=MAX(cacheHeight, cheight);
  1244. blitToRectCanvas.DestructiveResize(cacheWidth, cacheHeight);
  1245. }
  1246. dib = blitToRectCanvas.getBits();
  1247. if ( has_alpha || alpha < 255 )
  1248. clone.blit( dst.left, dst.top, &blitToRectCanvas, 0, 0, cwidth, cheight );
  1249. xs=0;
  1250. ys=0;
  1251. xe=cwidth;
  1252. ye=cheight;
  1253. pitch=cacheWidth;
  1254. usingBlitCanvas=true;
  1255. }
  1256. else
  1257. {
  1258. xs=dst.left;
  1259. xe=dst.right;
  1260. ys=dst.top;
  1261. ye=dst.bottom;
  1262. cwidth/=4;
  1263. pitch=cwidth;
  1264. }
  1265. // stretch and blend bitmap to dib
  1266. if (xstart < 0) xstart=0;
  1267. if (xs<xe) {
  1268. if (!has_alpha) { // doesn't have alpha channel
  1269. if (alpha == 255) { // no global alpha
  1270. __Stretch::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1271. } else { // has global alpha
  1272. #ifndef NO_MMX
  1273. if (HAS_MMX) {
  1274. __StretchGlobalMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1275. } else
  1276. #endif
  1277. {
  1278. __StretchGlobal::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1279. }
  1280. }
  1281. } else { // has alpha channel
  1282. // FUCKO: JF> BRENNAN FIX THESE BITCHES :)
  1283. if (alpha == 255) { // no global alpha
  1284. #ifndef NO_MMX
  1285. if (HAS_MMX) {
  1286. __StretchChannelMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1287. } else
  1288. #endif
  1289. {
  1290. __StretchChannel::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1291. }
  1292. } else { // has global alpha
  1293. #ifndef NO_MMX
  1294. if (HAS_MMX) {
  1295. __StretchGlobalChannelMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1296. } else
  1297. #endif
  1298. {
  1299. __StretchGlobalChannel::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha);
  1300. }
  1301. }
  1302. }
  1303. }
  1304. #ifndef NO_MMX
  1305. Blenders::BLEND_MMX_END();
  1306. #endif
  1307. // write bits back to dib.
  1308. if (usingBlitCanvas) {
  1309. blitToRectCanvas.blit(0, 0, &clone, dst.left, dst.top, cwidth, cheight);
  1310. }
  1311. }
  1312. COLORREF SkinBitmap::getPixel(int x, int y) {
  1313. ASSERT(bits != NULL);
  1314. if (x < 0 || y < 0 || x >= getFullWidth()-getX() || y>= getFullHeight()-getY()) return (COLORREF)0;
  1315. return (COLORREF)(((int*)bits)[x+getX()+(y+getY())*getFullWidth()]);
  1316. }
  1317. void *SkinBitmap::getBits() {
  1318. return bits;
  1319. }
  1320. int SkinBitmap::isInvalid() {
  1321. return last_failed;
  1322. }
  1323. void SkinBitmap::setHasAlpha(int ha) {
  1324. has_alpha=ha;
  1325. }
  1326. const wchar_t *SkinBitmap::getBitmapName() {
  1327. return bitmapname;
  1328. }