BLIT.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // This file controls all of the uncompressed BLiTting about.
  19. // It hooks references to special areas (screens & their buffers), and
  20. // calls the appropriate functions...
  21. #ifdef PATHS_IN_INCLUDES
  22. #include "GREEN/BLiT/BLIT.H"
  23. #include "GREEN/BLiT/_BlitInt.H"
  24. #else
  25. #include "BLIT.H"
  26. #include "_BlitInt.H"
  27. #endif
  28. template <class PIXSIZE>
  29. void rspClipPlot(PIXSIZE color, RImage* pimDst,short sX,short sY,const RRect* prClip)
  30. {
  31. #ifdef _DEBUG
  32. if (pimDst == NULL)
  33. {
  34. TRACE("rspPlot: NULL Image passed.\n");
  35. return;
  36. }
  37. if (!ImageIsUncompressed(pimDst->m_type))
  38. {
  39. TRACE("rspPlot: Only uncompressed surfaces accepted.\n");
  40. return;
  41. }
  42. #endif
  43. RRect rClip(0,0,pimDst->m_sWidth,pimDst->m_sHeight);
  44. if (prClip) rClip = *prClip;
  45. if ( (sX < rClip.sX) || (sY < rClip.sY) || (sX >= (rClip.sX + rClip.sW)) ||
  46. (sY >= (rClip.sY + rClip.sH) ) )
  47. {
  48. // Live clipping.
  49. return;
  50. }
  51. short sNeedToUnlock = 0;
  52. //if (gsScreenLocked || gsBufferLocked) goto PLOT_DONTLOCK;
  53. // removed locking and unlocking except where needed for special cases:
  54. switch ((short)(((long)pimDst->m_pSpecial))) // 0 = normal image
  55. {
  56. case 0: // normal image, buffer in image
  57. break;
  58. case BUF_MEMORY: // draw a rectangle in the system buffer
  59. /*
  60. // need to lock / unlock this one:
  61. if (rspLockBuffer()
  62. !=0)
  63. {
  64. TRACE("rspPlot: Unable to lock the system buffer, failed!\n");
  65. }
  66. // Locked the system buffer, remember to unlock it:
  67. sNeedToUnlock = BUF_MEMORY;
  68. */
  69. break;
  70. case BUF_VRAM: // draw a rectangle to the visible vram screen
  71. // need to lock / unlock this one:
  72. /*
  73. if (rspLockScreen()
  74. !=0)
  75. {
  76. TRACE("rspPlot: Unable to lock the OnScreen buffer, failed!\n");
  77. }
  78. // Locked the system buffer, remember to unlock it:
  79. sNeedToUnlock = BUF_VRAM;
  80. */
  81. break;
  82. case BUF_VRAM2: // draw a rectangle to the hidden VRAM plane
  83. // need to lock / unlock this one:
  84. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  85. !=0)
  86. {
  87. TRACE("rspPlot: Unable to lock the OffScreen buffer, failed!\n");
  88. }
  89. // Locked the system buffer, remember to unlock it:
  90. sNeedToUnlock = BUF_VRAM2;
  91. break;
  92. default:
  93. TRACE("rspPlot: This type of copy is not yet supported.\n");
  94. }
  95. //PLOT_DONTLOCK:
  96. // Special check for buffer not locked correctly:
  97. if (!pimDst->m_pData)
  98. {
  99. TRACE("rspPlot: NULL image data - potential locking error\n");
  100. return;
  101. }
  102. // DO THE PLOT!
  103. PIXSIZE* pTemp = (PIXSIZE*) (pimDst->m_pData + sY * pimDst->m_lPitch) + sX;
  104. *pTemp = color;
  105. //********************
  106. // OS_SPECIFIC:
  107. //******************** UNLOCK WHATEVER YOU NEED TO
  108. //if (gsScreenLocked || gsBufferLocked) goto PLOT_DONTUNLOCK;
  109. switch (sNeedToUnlock)
  110. {
  111. case 0:
  112. break;
  113. case BUF_MEMORY:
  114. // rspUnlockBuffer();
  115. break;
  116. case BUF_VRAM:
  117. // rspUnlockScreen();
  118. break;
  119. case BUF_VRAM2:
  120. rspUnlockVideoFlipPage();
  121. break;
  122. default:
  123. TRACE("rspDrawRect: Unlocking error!\n");
  124. }
  125. //PLOT_DONTUNLOCK:
  126. return;
  127. }
  128. // force instantiation
  129. template void rspClipPlot<UCHAR>(UCHAR color, RImage* pimDst,short sX,short sY,const RRect* prClip);
  130. template void rspClipPlot<USHORT>(USHORT color, RImage* pimDst,short sX,short sY,const RRect* prClip);
  131. template void rspClipPlot<ULONG>(ULONG color, RImage* pimDst,short sX,short sY,const RRect* prClip);
  132. void instantiatePlot(void);
  133. void instantiatePlot()
  134. {
  135. RImage* pim = NULL;
  136. rspPlot((UCHAR)0,pim,(short)0,(short)0);
  137. rspPlot((USHORT)0,pim,(short)0,(short)0);
  138. rspPlot((ULONG)0,pim,(short)0,(short)0);
  139. }
  140. // This is not currently designed for 24-bit mode.
  141. // Returns 0 if something found...
  142. // The direction flags are non-zero to operate a direction. They refer to
  143. // the side shrinking.
  144. //
  145. template <class PIXSIZE>
  146. short rspLasso(PIXSIZE ignoreColor,RImage* pimSrc,short &x,short &y,short &w,short &h,
  147. int lFlag,int rFlag,int tFlag,int bFlag)
  148. {
  149. short sWordLen = sizeof(PIXSIZE);
  150. #ifdef _DEBUG
  151. // Parameter Validation:
  152. if ((sWordLen != 1) && (sWordLen != 2) &&(sWordLen != 4))
  153. {
  154. TRACE("rspLasso: Pixel size not supported.\n");
  155. return -1;
  156. }
  157. if ( (x<0) || (y<0) || ( (x+w) > pimSrc->m_sWidth) || ( (y+h) > pimSrc->m_sHeight) )
  158. {
  159. TRACE("rspLasso: Outside Source Buffer!\n");
  160. return -1;
  161. }
  162. if ( !ImageIsUncompressed(pimSrc->m_type) )
  163. {
  164. TRACE("rspLasso: Only uncompressed RAM surfaces accepted.\n");
  165. return -1;
  166. }
  167. if ((w < 0) || (h < 0))
  168. {
  169. TRACE("rspLasso: Negative area passed.\n");
  170. return -1;
  171. }
  172. #endif
  173. short btos[] = {-1,0,1,-1,2};
  174. PIXSIZE* pCursor = NULL;
  175. PIXSIZE* pCursorLine = NULL;
  176. long lSkipV;
  177. short i,j;
  178. if (pimSrc->m_lPitch > 0)
  179. lSkipV = pimSrc->m_lPitch << btos[sWordLen];
  180. else
  181. lSkipV = -((-pimSrc->m_lPitch) << btos[sWordLen]);
  182. // Move the left wall, if specified:
  183. if (lFlag)
  184. {
  185. pCursorLine = (PIXSIZE*)pimSrc->m_pData + lSkipV * y + x;
  186. for (i=w;i>0;i--) // w will change!
  187. {
  188. pCursor = pCursorLine;
  189. for (j=0;j<h;j++)
  190. {
  191. if ( (*pCursor) != ignoreColor ) goto DoneL; // break all looping!
  192. pCursor += lSkipV;
  193. }
  194. x++;
  195. w--;
  196. pCursorLine++;
  197. }
  198. TRACE("rspLasso: ERROR: nothing found to lasso!\n");
  199. return -1;
  200. }
  201. DoneL:
  202. // Move the right wall, if specified:
  203. if (rFlag)
  204. {
  205. pCursorLine = (PIXSIZE*)pimSrc->m_pData + lSkipV * y + (x + w - 1);
  206. for (i=w;i>0;i--) // w will change!
  207. {
  208. pCursor = pCursorLine;
  209. for (j=0;j<h;j++)
  210. {
  211. if ( (*pCursor) != ignoreColor ) goto DoneR; // break all looping!
  212. pCursor += lSkipV;
  213. }
  214. w--;
  215. pCursorLine--;
  216. }
  217. TRACE("rspLasso: ERROR: nothing found to lasso!\n");
  218. return -1;
  219. }
  220. DoneR:
  221. // Move the top wall, if specified:
  222. if (tFlag)
  223. {
  224. pCursorLine = (PIXSIZE*)pimSrc->m_pData + lSkipV * y + x;
  225. for (i=h;i>0;i--) // h will change!
  226. {
  227. pCursor = pCursorLine;
  228. for (j=0;j<w;j++)
  229. {
  230. if ( (*pCursor) != ignoreColor ) goto DoneT; // break all looping!
  231. pCursor ++;
  232. }
  233. y++;
  234. h--;
  235. pCursorLine+=lSkipV;
  236. }
  237. TRACE("rspLasso: ERROR: nothing found to lasso!\n");
  238. return -1;
  239. }
  240. DoneT:
  241. // Move the bottom wall, if specified:
  242. if (bFlag)
  243. {
  244. pCursorLine = (PIXSIZE*)pimSrc->m_pData + lSkipV * (y + h - 1) + x;
  245. for (i=h;i>0;i--) // h will change!
  246. {
  247. pCursor = pCursorLine;
  248. for (j=0;j<w;j++)
  249. {
  250. if ( (*pCursor) != ignoreColor ) goto DoneB; // break all looping!
  251. pCursor ++;
  252. }
  253. h--;
  254. pCursorLine-=lSkipV;
  255. }
  256. TRACE("rspLasso: ERROR: nothing found to lasso!\n");
  257. return -1;
  258. }
  259. DoneB:
  260. return 0; // lasso'd it!
  261. }
  262. // force instantiation
  263. template short rspLasso<UCHAR>(UCHAR ignoreColor,RImage* pimSrc,short &x,short &y,short &w,short &h,
  264. int lFlag,int rFlag,int tFlag,int bFlag);
  265. template short rspLasso<USHORT>(USHORT ignoreColor,RImage* pimSrc,short &x,short &y,short &w,short &h,
  266. int lFlag,int rFlag,int tFlag,int bFlag);
  267. template short rspLasso<ULONG>(ULONG ignoreColor,RImage* pimSrc,short &x,short &y,short &w,short &h,
  268. int lFlag,int rFlag,int tFlag,int bFlag);
  269. // attempt to create the templated version in the lib:
  270. void instantiateLasso(void);
  271. void instantiateLasso()
  272. {
  273. RImage* pim = NULL;
  274. short i = 0;
  275. rspLasso( (UCHAR)i, pim, i,i,i,i, 1,1,1,1);
  276. rspLasso( (USHORT)i, pim, i,i,i,i, 1,1,1,1);
  277. rspLasso( (ULONG)i, pim, i,i,i,i, 1,1,1,1);
  278. }
  279. // Insert this into your functions... It assumes pre-clipped, pre-sorted,
  280. // pre-validated rect copy: (Pitch will be sign based!)
  281. //
  282. template <class PIXSIZE>
  283. inline void _BLiT(PIXSIZE* pSrc,PIXSIZE* pDst,long lSrcPitch, long lDstPitch,
  284. short sHeight,short sByteWidth)
  285. {
  286. union {
  287. PIXSIZE *w;
  288. UCHAR *b;
  289. } pSrcLine,pDstLine;
  290. int i;
  291. const static short SizeToShift[] = {0,0,1,0,2,0,0,0,3,0,0,0,0,0,0,0,4};
  292. // 0 1 2 3 4 5 6 7 8 9 a b c d e f *
  293. short sWordWidth = short(sByteWidth >> SizeToShift[sizeof(PIXSIZE)]);
  294. pSrcLine.w = pSrc;
  295. pDstLine.w = pDst;
  296. while (sHeight--)
  297. {
  298. pSrc = pSrcLine.w;
  299. pDst = pDstLine.w;
  300. i = sWordWidth;
  301. while (i--) *(pDst++) = *(pSrc++);
  302. pSrcLine.b += lSrcPitch;
  303. pDstLine.b += lDstPitch;
  304. }
  305. }
  306. // This uses misaligned 32-bit copies to be "faster" than byte copying:
  307. //
  308. // But this is a garatied SegBus on ARM with NEON vectorisation, as misaligned are not possible
  309. inline void _BLiT_MA(UCHAR* pSrc,UCHAR* pDst,long lSrcPitch, long lDstPitch,
  310. short sHeight,short sWidth)
  311. {
  312. #ifdef __ARM_NEON__
  313. while (sHeight--)
  314. {
  315. memcpy(pDst, pSrc, sWidth);
  316. pSrc += lSrcPitch;
  317. pDst += lDstPitch;
  318. }
  319. #else
  320. union {
  321. U32 *w;
  322. UCHAR *b;
  323. } pSrcLine,pDstLine,pS,pD;
  324. short i;
  325. short sWordWidth = short (sWidth >> 2); //32 bit words....
  326. short sExtraWidth = sWidth - short(sWordWidth << 2);
  327. pS.b = pSrcLine.b = pSrc;
  328. pD.b = pDstLine.b = pDst;
  329. while (sHeight--)
  330. {
  331. pS.w = pSrcLine.w;
  332. pD.w = pDstLine.w;
  333. i = sWordWidth;
  334. while (i--) *(pD.w++) = *(pS.w++);
  335. // extra cleanup:
  336. i = sExtraWidth;
  337. while (i--) *(pD.b++) = *(pS.b++);
  338. pSrcLine.b += lSrcPitch;
  339. pDstLine.b += lDstPitch;
  340. }
  341. #endif
  342. }
  343. // Used only to punch a rectangle between two 128-bit aligned buffers.
  344. // Source and Destination (X,Y) must be the same.
  345. // Will widen your rectangle to take advantage of your bus!
  346. //
  347. short rspBlitA(RImage* pimSrc,RImage* pimDst,short sX,short sY,
  348. short sW,short sH,const RRect* prDst,const RRect* prSrc)
  349. {
  350. #ifdef _DEBUG
  351. // Since all parameter validation is done in BLiT, we don't try here!
  352. if (!pimSrc || !pimDst)
  353. {
  354. TRACE("BLiTA: null images passed.\n");
  355. return -1;
  356. }
  357. if (pimSrc->m_sDepth == 24)
  358. {
  359. TRACE("BLiTA: 24-bit color NYI. Try 32-bit color.\n");
  360. return -1;
  361. }
  362. #endif
  363. // adjust for color depth based on source:
  364. short sDepth = pimSrc->m_sDepth >> 3; // depth in bytes (1,2,4)
  365. short sDepthToShift[] = {-1, 0, 1, -1, 2};
  366. short sDepthS = sDepthToShift[sDepth]; // convert to a shift value
  367. const long clChosenAlignment = 4; // in bytes
  368. // govern the best possible alignment based on pitch
  369. short sBestAlign = (short)(clChosenAlignment | pimSrc->m_lPitch | pimDst->m_lPitch);
  370. // in bytes!
  371. short sx1 = sX << sDepthS;
  372. short sx2 = (sX + sW) << sDepthS;
  373. // Optimize the 8-bit case:
  374. //***********************************************************************
  375. if (sDepth == 1)
  376. {
  377. if (sBestAlign & 15) // try for 128-bit alignment
  378. {
  379. if (sx1 & 15) // widen to the left:
  380. {
  381. sx1 &= ~15;
  382. }
  383. if (sx2 & 15) // widen to the right
  384. {
  385. sx2 &= ~15;
  386. sx2 += 16;
  387. }
  388. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  389. }
  390. else if (sBestAlign & 7) // try for 64-bit alignment
  391. {
  392. if (sx1 & 7) // widen to the left:
  393. {
  394. sx1 &= ~7;
  395. }
  396. if (sx2 & 7) // widen to the right
  397. {
  398. sx2 &= ~7;
  399. sx2 += 8;
  400. }
  401. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  402. }
  403. else if (sBestAlign & 3) // try for 32-bit alignment
  404. {
  405. if (sx1 & 3) // widen to the left:
  406. {
  407. sx1 &= ~3;
  408. }
  409. if (sx2 & 3) // widen to the right
  410. {
  411. sx2 &= ~3;
  412. sx2 += 4;
  413. }
  414. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  415. }
  416. else if (sBestAlign & 1) // try for 16-bit alignment
  417. {
  418. if (sx1 & 1) // widen to the left:
  419. {
  420. sx1 &= ~1;
  421. }
  422. if (sx2 & 1) // widen to the right
  423. {
  424. sx2 &= ~1;
  425. sx2 += 2;
  426. }
  427. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  428. }
  429. }
  430. //***********************************************************************
  431. // Other color depths
  432. if (sBestAlign & 15) // try for 128-bit alignment
  433. {
  434. if (sx1 & 15) // widen to the left:
  435. {
  436. sx1 &= ~15;
  437. // snap left to sDepth
  438. sx1 = (sx1 >> sDepthS) << sDepthS;
  439. }
  440. if (sx2 & 15) // widen to the right
  441. {
  442. sx2 &= ~15;
  443. sx2 += 16;
  444. // snap right to sDepth
  445. sx2 = ((sx2 + sDepth - 1) >> sDepthS) << sDepthS;
  446. }
  447. sX = sx1 >> sDepthS;
  448. sW = (sx2 - sx1) >> sDepthS;
  449. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  450. }
  451. else if (sBestAlign & 7) // try for 64-bit alignment
  452. {
  453. if (sx1 & 7) // widen to the left:
  454. {
  455. sx1 &= ~7;
  456. // snap left to sDepth
  457. sx1 = (sx1 >> sDepthS) << sDepthS;
  458. }
  459. if (sx2 & 7) // widen to the right
  460. {
  461. sx2 &= ~7;
  462. sx2 += 8;
  463. // snap right to sDepth
  464. sx2 = ((sx2 + sDepth - 1) >> sDepthS) << sDepthS;
  465. }
  466. sX = sx1 >> sDepthS;
  467. sW = (sx2 - sx1) >> sDepthS;
  468. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  469. }
  470. else if (sBestAlign & 3) // try for 32-bit alignment
  471. {
  472. if (sx1 & 3) // widen to the left:
  473. {
  474. sx1 &= ~3;
  475. // snap left to sDepth
  476. sx1 = (sx1 >> sDepthS) << sDepthS;
  477. }
  478. if (sx2 & 3) // widen to the right
  479. {
  480. sx2 &= ~3;
  481. sx2 += 4;
  482. // snap right to sDepth
  483. sx2 = ((sx2 + sDepth - 1) >> sDepthS) << sDepthS;
  484. }
  485. sX = sx1 >> sDepthS;
  486. sW = (sx2 - sx1) >> sDepthS;
  487. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  488. }
  489. else if (sBestAlign & 1) // try for 16-bit alignment
  490. {
  491. if (sx1 & 1) // widen to the left:
  492. {
  493. sx1 &= ~1;
  494. // snap left to sDepth
  495. sx1 = (sx1 >> sDepthS) << sDepthS;
  496. }
  497. if (sx2 & 1) // widen to the right
  498. {
  499. sx2 &= ~1;
  500. sx2 += 2;
  501. // snap right to sDepth
  502. sx2 = ((sx2 + sDepth - 1) >> sDepthS) << sDepthS;
  503. }
  504. sX = sx1 >> sDepthS;
  505. sW = (sx2 - sx1) >> sDepthS;
  506. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  507. }
  508. return rspBlit(pimSrc,pimDst,sX,sY,sX,sY,sW,sH,prDst,prSrc);
  509. }
  510. //*****************************************************************************
  511. // This is the main controller... It clips in pixels, then thinks in bytes:
  512. //
  513. short rspBlit(RImage* pimSrc,RImage* pimDst,short sSrcX,short sSrcY,short sDstX,
  514. short sDstY,short sW,short sH,const RRect* prDst,const RRect* prSrc)
  515. {
  516. short sClip;
  517. // 1) preliminary parameter validation:
  518. #ifdef _DEBUG
  519. if ((pimSrc == NULL) || (pimDst == NULL))
  520. {
  521. TRACE("BLiT: null RImage* passed\n");
  522. return -1;
  523. }
  524. if ( (sW < 1) || (sH < 1) )
  525. {
  526. TRACE("BLiT: zero or negative area passed\n");
  527. return -1;
  528. }
  529. if ( !ImageIsUncompressed(pimSrc->m_type) ||
  530. !ImageIsUncompressed(pimDst->m_type) )
  531. {
  532. TRACE("BLiT: To BLiT using COMPRESSED Images, you must specify"
  533. "your parameters differently (see BLiT.DOC)!\n");
  534. return -1;
  535. }
  536. #endif
  537. // 2) Optional Source Clipping
  538. if (prSrc)
  539. {
  540. // clip rect to source
  541. // clip against user values
  542. /*
  543. sClip = prSrc->sX - sDstX; // positive = clipped
  544. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prSrc->sX; }
  545. sClip = prSrc->sY - sDstY; // positive = clipped
  546. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prSrc->sY; }
  547. sClip = sDstX + sW - prSrc->sX - prSrc->sW; // positive = clipped
  548. if (sClip > 0) { sW -= sClip; }
  549. sClip = sDstY + sH - prSrc->sY - prSrc->sH; // positive = clipped
  550. if (sClip > 0) { sH -= sClip; }
  551. */
  552. sClip = prSrc->sX - sSrcX; // positive = clipped
  553. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX += sClip; }
  554. sClip = prSrc->sY - sSrcY; // positive = clipped
  555. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY += sClip; }
  556. sClip = sSrcX + sW - prSrc->sX - prSrc->sW; // positive = clipped
  557. if (sClip > 0) { sW -= sClip; }
  558. sClip = sSrcY + sH - prSrc->sY - prSrc->sH; // positive = clipped
  559. if (sClip > 0) { sH -= sClip; }
  560. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  561. }
  562. // 2) Source clipping is SO critical in locked screen stuff, that we MUST check it:
  563. #ifdef _DEBUG
  564. else // no source clipping:
  565. {
  566. if ( (sSrcX < 0) || (sSrcY < 0) ||
  567. ((sSrcX + sW) > pimSrc->m_sWidth) || ((sSrcY + sH) > pimSrc->m_sHeight) )
  568. {
  569. TRACE("BLiT: Gone outside source buffer. Must source clip.\n");
  570. return -1;
  571. }
  572. }
  573. #endif
  574. // 3) Destination Clipping:
  575. if (prDst)
  576. {
  577. // clip against user values
  578. sClip = prDst->sX - sDstX; // positive = clipped
  579. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prDst->sX; }
  580. sClip = prDst->sY - sDstY; // positive = clipped
  581. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prDst->sY; }
  582. sClip = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
  583. if (sClip > 0) { sW -= sClip; }
  584. sClip = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
  585. if (sClip > 0) { sH -= sClip; }
  586. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  587. }
  588. else
  589. {
  590. // clip against full destination buffer
  591. if (sDstX < 0) { sW += sDstX; sSrcX -= sDstX; sDstX = 0; }
  592. if (sDstY < 0) { sH += sDstY; sSrcY -= sDstY; sDstY = 0; }
  593. sClip = sDstX + sW - pimDst->m_sWidth; // positive = clipped
  594. if (sClip > 0) sW -= sClip; // positive = clipped
  595. sClip = sDstY + sH - pimDst->m_sHeight; // positive = clipped
  596. if (sClip > 0) sH -= sClip; // positive = clipped
  597. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  598. }
  599. //************** INSERT BUFFER HOOKS HERE! ************************
  600. // do OS based copying!
  601. //short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  602. short sBlitTypeSrc = 0;
  603. short sBlitTypeDst = 0;
  604. // if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  605. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  606. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  607. // has completed. (Lord help me if a blit gets interrupted)
  608. if (pimSrc->m_type == RImage::IMAGE_STUB) sBlitTypeSrc = (short)((long)pimSrc->m_pSpecial);
  609. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  610. switch ( (sBlitTypeSrc<<3) + sBlitTypeDst) // 0 = normal image
  611. {
  612. case (BUF_MEMORY<<3) + 0: // system buffer to an image
  613. // need to lock / unlock this one:
  614. /*
  615. if (rspLockBuffer()
  616. !=0)
  617. {
  618. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  619. return -1;
  620. }
  621. // Locked the system buffer, remember to unlock it:
  622. sNeedToUnlock = BUF_MEMORY;
  623. */
  624. break;
  625. case (0<<3) + BUF_MEMORY: // image to system buffer
  626. /*
  627. // need to lock / unlock this one:
  628. if (rspLockBuffer()
  629. !=0)
  630. {
  631. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  632. return -1;
  633. }
  634. // Locked the system buffer, remember to unlock it:
  635. sNeedToUnlock = BUF_MEMORY;
  636. */
  637. break;
  638. case (BUF_VRAM<<3) + 0: // front screen to image
  639. /*
  640. // need to lock / unlock this one:
  641. if (rspLockScreen()
  642. !=0)
  643. {
  644. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  645. return -1;
  646. }
  647. // Locked the front VRAM, remember to unlock it:
  648. sNeedToUnlock = BUF_VRAM;
  649. */
  650. break;
  651. case (0<<3) + BUF_VRAM: // image to front screen
  652. /*
  653. // need to lock / unlock this one:
  654. if (rspLockScreen()
  655. !=0)
  656. {
  657. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  658. return -1;
  659. }
  660. // Locked the front VRAM, remember to unlock it:
  661. sNeedToUnlock = BUF_VRAM;
  662. */
  663. break;
  664. // HOOK the special case of sytem buffer to front VRAM
  665. case (BUF_MEMORY<<3) + BUF_VRAM: // system buffer to front screen
  666. rspUpdateDisplay(sDstX,sDstY,sW,sH);
  667. return 0; // DONE!!!!!
  668. break;
  669. case (BUF_VRAM<<3) + BUF_MEMORY: // front screen to system buffer
  670. /*
  671. sNeedToUnlock = (BUF_VRAM<<3) + BUF_MEMORY;
  672. */
  673. break;
  674. case 0: // image to image, no need to lock!
  675. break;
  676. default:
  677. TRACE("BLiT: This type of copy is not yet supported.\n");
  678. return -1;
  679. }
  680. //BLIT_PRELOCKED:
  681. // Check for locking error:
  682. if (!pimDst->m_pData)
  683. {
  684. TRACE("BLiT: NULL data - possible locking error.\n");
  685. return FAILURE;
  686. }
  687. //********************************************************************
  688. // Done clipping, convert to bytes to find best alignment:
  689. // Currently based on source, assumes source = destination depth:
  690. switch (pimSrc->m_sDepth)
  691. {
  692. case 16:
  693. sDstX <<= 1;
  694. sSrcX <<= 1;
  695. sW <<= 1;
  696. break;
  697. case 32:
  698. sDstX <<= 2;
  699. sSrcX <<= 2;
  700. sW <<= 2;
  701. break;
  702. case 24:
  703. sDstX += (sDstX << 1);
  704. sSrcX += (sSrcX << 1);
  705. sW += (sW << 1);
  706. break;
  707. // 8-bit needs nothing...
  708. }
  709. // Calculate memory offsets using signed pitch:
  710. // sSrcX, sDstX, and sSrcW are in BYTES:
  711. U8* pSrc = pimSrc->m_pData + sSrcX + pimSrc->m_lPitch * sSrcY;
  712. U8* pDst = pimDst->m_pData + sDstX + pimDst->m_lPitch * sDstY;
  713. // Determine Byte Alignment:
  714. short sAlign = sSrcX | sDstX | sW |
  715. (short)( ABS(pimSrc->m_lPitch) | ABS(pimDst->m_lPitch) );
  716. // Do the rect copy as fast as possible!
  717. // we are passing the width in BYTES!
  718. //
  719. if ( (sAlign & 15) == 0 )
  720. {
  721. // 128-bit copy
  722. _BLiT((U128*)pSrc,(U128*)pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  723. }
  724. else if ( (sAlign & 7) == 0)
  725. {
  726. // 64-bit copy
  727. _BLiT((U64*)pSrc,(U64*)pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  728. }
  729. else if ( (sAlign & 3) == 0)
  730. {
  731. // 32-bit copy
  732. _BLiT((U32*)pSrc,(U32*)pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  733. }
  734. else if ( (sAlign & 1) == 0)
  735. {
  736. // 16-bit copy
  737. _BLiT((U16*)pSrc,(U16*)pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  738. }
  739. else
  740. {
  741. // 8-bit copy
  742. //************* GAMBLE that misaligned 32-bit copies are faster than byte copies,
  743. // then handle extra off the end:
  744. if (sW < 16)
  745. _BLiT(pSrc,pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  746. else
  747. _BLiT_MA(pSrc,pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  748. }
  749. #if 0 // We always want the safety mode.
  750. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  751. #ifndef _DEBUG
  752. // if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  753. #endif
  754. #endif
  755. //********************
  756. // OS_SPECIFIC:
  757. //******************** UNLOCK WHATEVER YOU NEED TO
  758. #if 0
  759. switch (sNeedToUnlock)
  760. {
  761. case 0:
  762. break;
  763. case BUF_MEMORY:
  764. // rspUnlockBuffer();
  765. break;
  766. case BUF_VRAM:
  767. // rspUnlockScreen();
  768. break;
  769. case BUF_VRAM2:
  770. // rspUnlockVideoFlipPage();
  771. break;
  772. case (BUF_VRAM<<3) + BUF_MEMORY:
  773. // rspUnlockBuffer();
  774. // rspUnlockScreen();
  775. break;
  776. default:
  777. TRACE("BLiT: Unlocking error!\n");
  778. }
  779. #endif
  780. //BLIT_DONTUNLOCK:
  781. return 0;
  782. }
  783. //**************************************************************************
  784. //**************************************************************************
  785. //**************************************************************************
  786. // Insert this into your functions... It assumes pre-clipped, pre-sorted,
  787. // pre-validated rect copy: (Pitch will be sign based!)
  788. //
  789. template <class WORDSIZE>
  790. inline void _ClearRect(WORDSIZE color,WORDSIZE* pDst,long lDstPitch,
  791. short sHeight,short sByteWidth)
  792. {
  793. union {
  794. WORDSIZE *w;
  795. UCHAR *b;
  796. } pDstLine;
  797. short i,sWordWidth = sByteWidth;
  798. const static short SizeToShift[] = {0,0,1,0,2,0,0,0,3,0,0,0,0,0,0,0,4};
  799. // 0 1 2 3 4 5 6 7 8 9 a b c d e f *
  800. sWordWidth = short(sByteWidth >> SizeToShift[sizeof(WORDSIZE)]);
  801. pDstLine.w = pDst;
  802. while (sHeight--)
  803. {
  804. pDst = pDstLine.w;
  805. i = sWordWidth;
  806. while (i--) *(pDst++) = color;
  807. pDstLine.b += lDstPitch;
  808. }
  809. }
  810. // Must make TC possible!
  811. //
  812. short rspRect(U32 color,RImage* pimDst,short sX,short sY,short sW,short sH,RRect* prClip)
  813. {
  814. // A cheap hook for mono:
  815. if (pimDst->m_type == RImage::BMP1) // monochrome hook
  816. {
  817. return rspRectToMono(color,pimDst,sX,sY,sW,sH);
  818. }
  819. // 1) preliminary parameter validation:
  820. #ifdef _DEBUG
  821. if (pimDst == NULL)
  822. {
  823. TRACE("rspRect: null RImage* passed\n");
  824. return -1;
  825. }
  826. /*
  827. if ( (sW < 1) || (sH < 1) )
  828. {
  829. TRACE("rspRect: zero or negative area passed\n");
  830. return -1;
  831. }
  832. */
  833. if (!ImageIsUncompressed(pimDst->m_type))
  834. {
  835. TRACE("rspRect: Can only draw RECTs into uncompressed images!\n");
  836. return -1;
  837. }
  838. #endif
  839. // UNMIRROR THE RECTANGLE:
  840. if (!sW && !sH) return 0; // nothing to draw
  841. if (sW < 0) { sX += (sW+1); sW = -sW; }
  842. if (sH < 0) { sY += (sH+1); sH = -sH; }
  843. short sClip;
  844. // 2) Destination Clipping:
  845. if (prClip)
  846. {
  847. // clip against user values
  848. sClip = prClip->sX - sX; // positive = clipped
  849. if (sClip > 0) { sW -= sClip; sX = prClip->sX; }
  850. sClip = prClip->sY - sY; // positive = clipped
  851. if (sClip > 0) { sH -= sClip; sY = prClip->sY; }
  852. sClip = sX + sW - prClip->sX - prClip->sW; // positive = clipped
  853. if (sClip > 0) { sW -= sClip; }
  854. sClip = sY + sH - prClip->sY - prClip->sH; // positive = clipped
  855. if (sClip > 0) { sH -= sClip; }
  856. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  857. }
  858. else
  859. {
  860. // clip against full destination buffer
  861. if (sX < 0) { sW += sX; sX = 0; }
  862. if (sY < 0) { sH += sY; sY = 0; }
  863. sClip = sX + sW - pimDst->m_sWidth; // positive = clipped
  864. if (sClip > 0) sW -= sClip; // positive = clipped
  865. sClip = sY + sH - pimDst->m_sHeight; // positive = clipped
  866. if (sClip > 0) sH -= sClip; // positive = clipped
  867. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  868. }
  869. //************** INSERT BUFFER HOOKS HERE! ************************
  870. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  871. short sBlitTypeDst = 0;
  872. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  873. #ifndef _DEBUG
  874. //if (gsScreenLocked || gsBufferLocked) goto RECT_DONTLOCK;
  875. #endif
  876. // do OS based copying!
  877. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  878. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  879. // has completed. (Lord help me if a blit gets interrupted)
  880. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  881. switch (sBlitTypeDst) // 0 = normal image
  882. {
  883. case 0: // normal image, buffer in image
  884. break;
  885. case BUF_MEMORY: // draw a rectangle in the system buffer
  886. // need to lock / unlock this one:
  887. /*
  888. if (rspLockBuffer()
  889. !=0)
  890. {
  891. TRACE("rspDrawRect: Unable to lock the system buffer, failed!\n");
  892. return -1;
  893. }
  894. // Locked the system buffer, remember to unlock it:
  895. sNeedToUnlock = BUF_MEMORY;
  896. */
  897. break;
  898. case BUF_VRAM: // draw a rectangle to the visible vram screen
  899. // need to lock / unlock this one:
  900. /*
  901. if (rspLockScreen()
  902. !=0)
  903. {
  904. TRACE("rspDrawRect: Unable to lock the OnScreen buffer, failed!\n");
  905. return -1;
  906. }
  907. // Locked the system buffer, remember to unlock it:
  908. sNeedToUnlock = BUF_VRAM;
  909. */
  910. break;
  911. case BUF_VRAM2: // draw a rectangle to the hidden VRAM plane
  912. // need to lock / unlock this one:
  913. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  914. !=0)
  915. {
  916. TRACE("rspDrawRect: Unable to lock the OffScreen buffer, failed!\n");
  917. return -1;
  918. }
  919. // Locked the system buffer, remember to unlock it:
  920. sNeedToUnlock = BUF_VRAM2;
  921. break;
  922. default:
  923. TRACE("rspDrawRect: This type of copy is not yet supported.\n");
  924. return -1;
  925. }
  926. //RECT_DONTLOCK:
  927. //********************************************************************
  928. // Done clipping, convert to bytes to find best alignment:
  929. // Currently based on source, assumes source = destination depth:
  930. // Multiply color word based on 8-bit concepts:
  931. //
  932. color &= 255;
  933. short sByteW = sW;
  934. switch (pimDst->m_sDepth)
  935. {
  936. case 16:
  937. sX <<= 1;
  938. sByteW <<= 1; // width for ALIGMENT!
  939. break;
  940. case 32:
  941. sX <<= 2;
  942. sByteW <<= 2;
  943. break;
  944. case 24:
  945. sX += (sX << 1);
  946. sByteW += (sByteW << 1);
  947. break;
  948. // 8-bit needs nothing...
  949. }
  950. // Calculate memory offsets using signed pitch:
  951. // sX and sByteW are in BYTES!
  952. U8* pDst = pimDst->m_pData + sX + pimDst->m_lPitch * sY;
  953. // Determine Byte Alignment:
  954. // sX and sByteW are in BYTES!
  955. short sAlign = sX | sByteW | (short)( ABS(pimDst->m_lPitch) );
  956. // Do the draw rect as fast as possible!
  957. if ( (sAlign & 3) == 0)
  958. {
  959. // 32-bit copy
  960. ULONG ulColor = color;
  961. ulColor += (color << 8); // 16-bit
  962. ulColor += (ulColor << 16); // 32-bit
  963. _ClearRect(ulColor,(U32*)pDst,pimDst->m_lPitch,sH,sByteW);
  964. }
  965. else if ( (sAlign & 1) == 0)
  966. {
  967. // 16-bit copy
  968. USHORT usColor = (USHORT)(color + (color << 8)); // 16-bit;
  969. _ClearRect(usColor,(U16*)pDst,pimDst->m_lPitch,sH,sByteW);
  970. }
  971. else
  972. {
  973. // 8-bit copy
  974. _ClearRect((U8)color,(U8*)pDst,pimDst->m_lPitch,sH,sByteW);
  975. }
  976. //********************
  977. // OS_SPECIFIC:
  978. //******************** UNLOCK WHATEVER YOU NEED TO
  979. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  980. #ifndef _DEBUG
  981. // if (gsScreenLocked || gsBufferLocked) goto RECT_DONTUNLOCK;
  982. #endif
  983. switch (sNeedToUnlock)
  984. {
  985. case 0:
  986. break;
  987. case BUF_MEMORY:
  988. // rspUnlockBuffer();
  989. break;
  990. case BUF_VRAM:
  991. // rspUnlockScreen();
  992. break;
  993. case BUF_VRAM2:
  994. rspUnlockVideoFlipPage();
  995. break;
  996. default:
  997. TRACE("rspDrawRect: Unlocking error!\n");
  998. }
  999. //RECT_DONTUNLOCK:
  1000. return 0;
  1001. }
  1002. // Does a "hollow" rectangle! (grows inwards)
  1003. //
  1004. short rspRect(short sThickness,U32 color,RImage* pimDst,short sX,short sY,short sW,short sH,RRect* prClip)
  1005. {
  1006. // 1) preliminary parameter validation:
  1007. #ifdef _DEBUG
  1008. if (pimDst == NULL)
  1009. {
  1010. TRACE("rspRect: null RImage* passed\n");
  1011. return -1;
  1012. }
  1013. if ( /*(sW < 1) || (sH < 1) ||*/ (sThickness < 1))
  1014. {
  1015. TRACE("rspRect: zero or negative thickness passed\n");
  1016. return -1;
  1017. }
  1018. if (!ImageIsUncompressed(pimDst->m_type) && (pimDst->m_type != RImage::BMP1))
  1019. {
  1020. TRACE("rspRect: You may onlt draw rects into uncompressed images.!\n");
  1021. return -1;
  1022. }
  1023. if ( (sThickness > (sW >> 1) ) || (sThickness > (sH >> 1) ) )
  1024. {
  1025. TRACE("rspRect: Rect to thick to show!\n");
  1026. return -1;
  1027. }
  1028. #endif
  1029. // UNMIRROR THE RECTANGLE:
  1030. if (!sW && !sH) return 0; // nothing to draw
  1031. if (sW < 0) { sX += (sW+1); sW = -sW; }
  1032. if (sH < 0) { sY += (sH+1); sH = -sH; }
  1033. // make up 4 rectangles: (Horizontal Major)
  1034. // order of blit is for maxim VSYNC ability
  1035. //
  1036. rspRect(color,pimDst,sX,sY,sW,sThickness,prClip); // top
  1037. rspRect(color,pimDst,sX,sY+sThickness,sThickness,sH - (sThickness<<1) ,prClip); // left
  1038. rspRect(color,pimDst,sX + sW - sThickness,sY+sThickness,sThickness,sH - (sThickness<<1) ,prClip); // left
  1039. rspRect(color,pimDst,sX,sY + sH - sThickness,sW,sThickness,prClip); // bottom
  1040. return 0;
  1041. }
  1042. // This creates a new image whose uncompressed image is the requested selection
  1043. // of the old image. You are responsible for "clipping" the requested region.
  1044. // Returns 0 on success. If you supply a RImage destination pointer, it will
  1045. // create a new image for you, otherwise it will crop the current image.
  1046. // This only crops uncompressed images.
  1047. //
  1048. // Modify current:
  1049. short rspCrop(RImage* pimSrc,short sX,short sY,short sW,short sH,
  1050. short sAlign) // sAlign in BYTES
  1051. {
  1052. #ifdef _DEBUG
  1053. if (pimSrc == NULL)
  1054. {
  1055. TRACE("rspCrop: NULL image passed\n");
  1056. return -1;
  1057. }
  1058. if ( (sW < 0) || (sH < 0) )
  1059. {
  1060. TRACE("rspCrop: Bad width or height passed!\n");
  1061. return -1;
  1062. }
  1063. if ( (sX < 0) || (sY < 0) || ( (sX + sW) > pimSrc->m_sWidth) ||
  1064. ( (sY + sH) > pimSrc->m_sHeight) )
  1065. {
  1066. TRACE("rspCrop: Crop rectangle is outside buffer size!\n");
  1067. return -1;
  1068. }
  1069. if (!ImageIsUncompressed(pimSrc->m_type))
  1070. {
  1071. TRACE("rspCrop: Can only crop uncompressed buffers!\n");
  1072. return -1;
  1073. }
  1074. #endif
  1075. long lNewPitch;
  1076. // 2) Create a new buffer with 128-bit alignment and pitch:
  1077. // Determine pixel size:
  1078. short sPixSize = pimSrc->m_sDepth >> 3;
  1079. short sShift[] = {-1,0,1,-1,2};
  1080. short sAlignMask = sAlign - 1; // sAlign is in BYTES
  1081. short sPixShift = sShift[sPixSize];
  1082. // Determine Optimum Pitch...
  1083. lNewPitch = (sW + sAlignMask) & (~sAlignMask);
  1084. // Create a new buffer and Image Stub to BLiT can use it:
  1085. RImage imDst;
  1086. imDst.CreateImage(sW,sH,pimSrc->m_type,
  1087. lNewPitch,pimSrc->m_sDepth);
  1088. // 3) Copy the new one in...
  1089. rspBlit(pimSrc,&imDst,sX,sY,0,0,sW,sH);
  1090. // tricky part: Swap buffers...
  1091. UCHAR *pSrcMem,*pSrcBuf;
  1092. pimSrc->DetachData((void**)&pSrcMem,(void**)&pSrcBuf);
  1093. // Move the new buffer back to the original
  1094. imDst.DetachData((void**)&(pimSrc->m_pMem),(void**)&(pimSrc->m_pData));
  1095. //******* IMPORTANT! COPY ALL NEW INFO OVER!
  1096. pimSrc->m_ulSize = imDst.m_ulSize;
  1097. pimSrc->m_sWidth = imDst.m_sWidth;
  1098. pimSrc->m_sHeight = imDst.m_sHeight;
  1099. pimSrc->m_sWinWidth = imDst.m_sWidth;
  1100. pimSrc->m_sWinHeight = imDst.m_sHeight;
  1101. pimSrc->m_lPitch = imDst.m_lPitch;
  1102. // 4) Destroy the old...
  1103. RImage::DestroyDetachedData((void**)&pSrcMem);
  1104. // On exit, imDst will auto destruct....
  1105. return 0;
  1106. }
  1107. // This creates a new image whose uncompressed image is the requested selection
  1108. // of the old image.
  1109. // Returns 0 on success.
  1110. // This only pads uncompressed images.
  1111. //
  1112. // Modify current:
  1113. short rspPad(RImage* pimSrc,short sX,short sY, // where to move the old image to
  1114. short sW,short sH, // new width and height
  1115. short sAlign) // sAlign in BYTES
  1116. {
  1117. #ifdef _DEBUG
  1118. if (pimSrc == NULL)
  1119. {
  1120. TRACE("rspPad: NULL image passed\n");
  1121. return -1;
  1122. }
  1123. if ( (sW < 0) || (sH < 0) )
  1124. {
  1125. TRACE("rspPad: Bad width or height passed!\n");
  1126. return -1;
  1127. }
  1128. /*
  1129. if ( ( sW < pimSrc->m_sWidth) || ( sH < pimSrc->m_sHeight) )
  1130. {
  1131. TRACE("rspPad: You cannot yet combine cropping and padding!\n");
  1132. return -1;
  1133. }
  1134. if ( (sX < 0) || (sY < 0) || ( (sX + pimSrc->m_sWidth) > sW) ||
  1135. ( (sY + pimSrc->m_sHeight) > sH) )
  1136. {
  1137. TRACE("rspPad: Cannot move image outside of new buffer!\n");
  1138. return -1;
  1139. }
  1140. */
  1141. if (!ImageIsUncompressed(pimSrc->m_type))
  1142. {
  1143. TRACE("rspPad: Can only crop uncompressed buffers!\n");
  1144. return -1;
  1145. }
  1146. #endif
  1147. // Save size of old image...
  1148. long lNewPitch;
  1149. short sOldW = pimSrc->m_sWidth;
  1150. short sOldH = pimSrc->m_sHeight;
  1151. // 2) Create a new buffer with 128-bit alignment and pitch:
  1152. // Determine pixel size:
  1153. short sPixSize = pimSrc->m_sDepth >> 3;
  1154. short sShift[] = {-1,0,1,-1,2};
  1155. short sAlignMask = sAlign - 1; // sAlign is in BYTES
  1156. short sPixShift = sShift[sPixSize];
  1157. // Determine Optimum Pitch...
  1158. lNewPitch = (sW + sAlignMask) & (~sAlignMask);
  1159. // Create a new buffer and Image Stub to BLiT can use it:
  1160. RImage imDst;
  1161. imDst.CreateImage(sW,sH,pimSrc->m_type,
  1162. lNewPitch,pimSrc->m_sDepth);
  1163. // 3) Copy the new one in...
  1164. // First, it is necessary to source clip the image:
  1165. RRect rCopy(sX,sY,sOldW,sOldH); // source
  1166. RRect rDst(0,0,sW,sH);
  1167. if (rCopy.ClipTo(&rDst))
  1168. {
  1169. TRACE("rspPad: Warning, image clipped out.\n");
  1170. }
  1171. else
  1172. {
  1173. // Express in terms of an offset:
  1174. rCopy.sX -= sX;
  1175. rCopy.sY -= sY;
  1176. // do the blit with source clipping
  1177. rspBlit(pimSrc,&imDst,rCopy.sX,rCopy.sY,
  1178. sX + rCopy.sX,sY + rCopy.sY,rCopy.sW,rCopy.sH);
  1179. }
  1180. // tricky part: Swap buffers...
  1181. UCHAR *pSrcMem,*pSrcBuf;
  1182. pimSrc->DetachData((void**)&pSrcMem,(void**)&pSrcBuf);
  1183. // Move the new buffer back to the original
  1184. imDst.DetachData((void**)&(pimSrc->m_pMem),(void**)&(pimSrc->m_pData));
  1185. //******* IMPORTANT! COPY ALL NEW INFO OVER!
  1186. pimSrc->m_ulSize = imDst.m_ulSize;
  1187. pimSrc->m_sWidth = imDst.m_sWidth;
  1188. pimSrc->m_sHeight = imDst.m_sHeight;
  1189. pimSrc->m_lPitch = imDst.m_lPitch;
  1190. pimSrc->m_sWinX = sX;
  1191. pimSrc->m_sWinY = sY;
  1192. // 4) Destroy the old...
  1193. RImage::DestroyDetachedData((void**)&pSrcMem);
  1194. // On exit, imDst will auto destruct....
  1195. return 0;
  1196. }
  1197. // Returns -1 if clipped completely out,
  1198. // It clips your rect to the input rect
  1199. // If clipped completely, sets rect to 0
  1200. // & sets this rect to {0,0,0,0}
  1201. //
  1202. short RRect::ClipTo(RRect* prClipTo)
  1203. {
  1204. short sClipL,sClipT,sClipR,sClipB;
  1205. sClipL = prClipTo->sX - sX;
  1206. sClipT = prClipTo->sY - sY;
  1207. sClipR = sX + sW - prClipTo->sX - prClipTo->sW;
  1208. sClipB = sY + sH - prClipTo->sY - prClipTo->sH;
  1209. if (sClipL > 0)
  1210. {
  1211. sX += sClipL;
  1212. sW -= sClipL;
  1213. }
  1214. if (sClipT > 0)
  1215. {
  1216. sY += sClipT;
  1217. sH -= sClipT;
  1218. }
  1219. if (sClipR > 0) sW -= sClipR;
  1220. if (sClipB > 0) sH -= sClipB;
  1221. if ( (sW < 0) || (sH < 0) )
  1222. {
  1223. sX = sY = sW = sH = 0;
  1224. return -1;
  1225. }
  1226. return 0;
  1227. }