surfaceclass.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/surfaceclass.cpp $*
  25. * *
  26. * Original Author:: Nathaniel Hoffman *
  27. * *
  28. * $Author:: Vss_sync $*
  29. * *
  30. * $Modtime:: 8/29/01 7:29p $*
  31. * *
  32. * $Revision:: 24 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * SurfaceClass::Clear -- Clears a surface to 0 *
  37. * SurfaceClass::Copy -- Copies a region from one surface to another of the same format *
  38. * SurfaceClass::FindBBAlpha -- Finds the bounding box of non zero pixels in the region (x0, *
  39. * PixelSize -- Helper Function to find the size in bytes of a pixel *
  40. * SurfaceClass::Is_Transparent_Column -- Tests to see if the column is transparent or not *
  41. * SurfaceClass::Copy -- Copies from a byte array to the surface *
  42. * SurfaceClass::CreateCopy -- Creates a byte array copy of the surface *
  43. * SurfaceClass::DrawHLine -- draws a horizontal line *
  44. * SurfaceClass::DrawPixel -- draws a pixel *
  45. * SurfaceClass::Copy -- Copies a block of system ram to the surface *
  46. * SurfaceClass::Hue_Shift -- changes the hue of the surface *
  47. * SurfaceClass::Is_Monochrome -- Checks if surface is monochrome or not *
  48. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  49. #include "surfaceclass.h"
  50. #include "formconv.h"
  51. #include "dx8wrapper.h"
  52. #include "vector2i.h"
  53. #include "colorspace.h"
  54. #include "bound.h"
  55. #include <d3dx8.h>
  56. /***********************************************************************************************
  57. * PixelSize -- Helper Function to find the size in bytes of a pixel *
  58. * *
  59. * *
  60. * *
  61. * *
  62. * INPUT: *
  63. * *
  64. * OUTPUT: *
  65. * *
  66. * WARNINGS: *
  67. * *
  68. * HISTORY: *
  69. * 2/13/2001 hy : Created. *
  70. *=============================================================================================*/
  71. unsigned int PixelSize(const SurfaceClass::SurfaceDescription &sd)
  72. {
  73. unsigned int size=0;
  74. switch (sd.Format)
  75. {
  76. case WW3D_FORMAT_A8R8G8B8:
  77. case WW3D_FORMAT_X8R8G8B8:
  78. size=4;
  79. break;
  80. case WW3D_FORMAT_R8G8B8:
  81. size=3;
  82. break;
  83. case WW3D_FORMAT_R5G6B5:
  84. case WW3D_FORMAT_X1R5G5B5:
  85. case WW3D_FORMAT_A1R5G5B5:
  86. case WW3D_FORMAT_A4R4G4B4:
  87. case WW3D_FORMAT_A8R3G3B2:
  88. case WW3D_FORMAT_X4R4G4B4:
  89. case WW3D_FORMAT_A8P8:
  90. case WW3D_FORMAT_A8L8:
  91. size=2;
  92. break;
  93. case WW3D_FORMAT_R3G3B2:
  94. case WW3D_FORMAT_A8:
  95. case WW3D_FORMAT_P8:
  96. case WW3D_FORMAT_L8:
  97. case WW3D_FORMAT_A4L4:
  98. size=1;
  99. break;
  100. }
  101. return size;
  102. }
  103. void Convert_Pixel(Vector3 &rgb, const SurfaceClass::SurfaceDescription &sd, const unsigned char * pixel)
  104. {
  105. const float scale=1/255.0f;
  106. switch (sd.Format)
  107. {
  108. case WW3D_FORMAT_A8R8G8B8:
  109. case WW3D_FORMAT_X8R8G8B8:
  110. case WW3D_FORMAT_R8G8B8:
  111. {
  112. rgb.X=pixel[2]; // R
  113. rgb.Y=pixel[1]; // G
  114. rgb.Z=pixel[0]; // B
  115. }
  116. break;
  117. case WW3D_FORMAT_A4R4G4B4:
  118. {
  119. unsigned short tmp;
  120. tmp=*(unsigned short*)&pixel[0];
  121. rgb.X=((tmp&0x0f00)>>4); // R
  122. rgb.Y=((tmp&0x00f0)); // G
  123. rgb.Z=((tmp&0x000f)<<4); // B
  124. }
  125. break;
  126. case WW3D_FORMAT_A1R5G5B5:
  127. {
  128. unsigned short tmp;
  129. tmp=*(unsigned short*)&pixel[0];
  130. rgb.X=(tmp>>7)&0xf8; // R
  131. rgb.Y=(tmp>>2)&0xf8; // G
  132. rgb.Z=(tmp<<3)&0xf8; // B
  133. }
  134. break;
  135. case WW3D_FORMAT_R5G6B5:
  136. {
  137. unsigned short tmp;
  138. tmp=*(unsigned short*)&pixel[0];
  139. rgb.X=(tmp>>8)&0xf8;
  140. rgb.Y=(tmp>>3)&0xfc;
  141. rgb.Z=(tmp<<3)&0xf8;
  142. }
  143. break;
  144. default:
  145. // TODO: Implement other pixel formats
  146. WWASSERT(0);
  147. }
  148. rgb*=scale;
  149. }
  150. // Note: This function must never overwrite the original alpha
  151. void Convert_Pixel(unsigned char * pixel,const SurfaceClass::SurfaceDescription &sd, const Vector3 &rgb)
  152. {
  153. unsigned char r,g,b;
  154. r=(unsigned char) (rgb.X*255.0f);
  155. g=(unsigned char) (rgb.Y*255.0f);
  156. b=(unsigned char) (rgb.Z*255.0f);
  157. switch (sd.Format)
  158. {
  159. case WW3D_FORMAT_A8R8G8B8:
  160. case WW3D_FORMAT_X8R8G8B8:
  161. case WW3D_FORMAT_R8G8B8:
  162. pixel[0]=b;
  163. pixel[1]=g;
  164. pixel[2]=r;
  165. break;
  166. case WW3D_FORMAT_A4R4G4B4:
  167. {
  168. unsigned short tmp;
  169. tmp=*(unsigned short*)&pixel[0];
  170. tmp&=0xF000;
  171. tmp|=(r&0xF0) << 4;
  172. tmp|=(g&0xF0);
  173. tmp|=(b&0xF0) >> 4;
  174. *(unsigned short*)&pixel[0]=tmp;
  175. }
  176. break;
  177. case WW3D_FORMAT_A1R5G5B5:
  178. {
  179. unsigned short tmp;
  180. tmp=*(unsigned short*)&pixel[0];
  181. tmp&=0x8000;
  182. tmp|=(r&0xF8) << 7;
  183. tmp|=(g&0xF8) << 2;
  184. tmp|=(b&0xF8) >> 3;
  185. *(unsigned short*)&pixel[0]=tmp;
  186. }
  187. break;
  188. case WW3D_FORMAT_R5G6B5:
  189. {
  190. unsigned short tmp;
  191. tmp=(r&0xf8) << 8;
  192. tmp|=(g&0xfc) << 3;
  193. tmp|=(b&0xf8) >> 3;
  194. *(unsigned short*)&pixel[0]=tmp;
  195. }
  196. break;
  197. default:
  198. // TODO: Implement other pixel formats
  199. WWASSERT(0);
  200. }
  201. }
  202. /*************************************************************************
  203. ** SurfaceClass
  204. *************************************************************************/
  205. SurfaceClass::SurfaceClass(unsigned width, unsigned height, WW3DFormat format):
  206. D3DSurface(NULL),
  207. SurfaceFormat(format)
  208. {
  209. WWASSERT(width);
  210. WWASSERT(height);
  211. D3DSurface = DX8Wrapper::_Create_DX8_Surface(width, height, format);
  212. }
  213. SurfaceClass::SurfaceClass(const char *filename):
  214. D3DSurface(NULL)
  215. {
  216. D3DSurface = DX8Wrapper::_Create_DX8_Surface(filename);
  217. SurfaceDescription desc;
  218. Get_Description(desc);
  219. SurfaceFormat=desc.Format;
  220. }
  221. SurfaceClass::SurfaceClass(IDirect3DSurface8 *d3d_surface) :
  222. D3DSurface (NULL)
  223. {
  224. Attach (d3d_surface);
  225. SurfaceDescription desc;
  226. Get_Description(desc);
  227. SurfaceFormat=desc.Format;
  228. }
  229. SurfaceClass::~SurfaceClass(void)
  230. {
  231. if (D3DSurface) {
  232. D3DSurface->Release();
  233. D3DSurface = NULL;
  234. }
  235. }
  236. void SurfaceClass::Get_Description(SurfaceDescription &surface_desc)
  237. {
  238. D3DSURFACE_DESC d3d_desc;
  239. ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC));
  240. DX8_ErrorCode(D3DSurface->GetDesc(&d3d_desc));
  241. surface_desc.Format = D3DFormat_To_WW3DFormat(d3d_desc.Format);
  242. surface_desc.Height = d3d_desc.Height;
  243. surface_desc.Width = d3d_desc.Width;
  244. }
  245. void * SurfaceClass::Lock(int * pitch)
  246. {
  247. D3DLOCKED_RECT lock_rect;
  248. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  249. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect, 0, 0));
  250. *pitch = lock_rect.Pitch;
  251. return (void *)lock_rect.pBits;
  252. }
  253. void SurfaceClass::Unlock(void)
  254. {
  255. DX8_ErrorCode(D3DSurface->UnlockRect());
  256. }
  257. /***********************************************************************************************
  258. * SurfaceClass::Clear -- Clears a surface to 0 *
  259. * *
  260. * *
  261. * *
  262. * *
  263. * INPUT: *
  264. * *
  265. * OUTPUT: *
  266. * *
  267. * WARNINGS: *
  268. * *
  269. * HISTORY: *
  270. * 2/13/2001 hy : Created. *
  271. *=============================================================================================*/
  272. void SurfaceClass::Clear()
  273. {
  274. SurfaceDescription sd;
  275. Get_Description(sd);
  276. // size of each pixel in bytes
  277. unsigned int size=PixelSize(sd);
  278. D3DLOCKED_RECT lock_rect;
  279. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  280. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,0));
  281. unsigned int i;
  282. unsigned char *mem=(unsigned char *) lock_rect.pBits;
  283. for (i=0; i<sd.Height; i++)
  284. {
  285. memset(mem,0,size*sd.Width);
  286. mem+=lock_rect.Pitch;
  287. }
  288. DX8_ErrorCode(D3DSurface->UnlockRect());
  289. }
  290. /***********************************************************************************************
  291. * SurfaceClass::Copy -- Copies from a byte array to the surface *
  292. * *
  293. * *
  294. * *
  295. * *
  296. * INPUT: *
  297. * *
  298. * OUTPUT: *
  299. * *
  300. * WARNINGS: *
  301. * *
  302. * HISTORY: *
  303. * 3/15/2001 hy : Created. *
  304. *=============================================================================================*/
  305. void SurfaceClass::Copy(const unsigned char *other)
  306. {
  307. SurfaceDescription sd;
  308. Get_Description(sd);
  309. // size of each pixel in bytes
  310. unsigned int size=PixelSize(sd);
  311. D3DLOCKED_RECT lock_rect;
  312. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  313. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,0));
  314. unsigned int i;
  315. unsigned char *mem=(unsigned char *) lock_rect.pBits;
  316. for (i=0; i<sd.Height; i++)
  317. {
  318. memcpy(mem,&other[i*sd.Width*size],size*sd.Width);
  319. mem+=lock_rect.Pitch;
  320. }
  321. DX8_ErrorCode(D3DSurface->UnlockRect());
  322. }
  323. /***********************************************************************************************
  324. * SurfaceClass::Copy -- Copies a block of system ram to the surface *
  325. * *
  326. * *
  327. * *
  328. * *
  329. * INPUT: *
  330. * *
  331. * OUTPUT: *
  332. * *
  333. * WARNINGS: *
  334. * *
  335. * HISTORY: *
  336. * 5/2/2001 hy : Created. *
  337. *=============================================================================================*/
  338. void SurfaceClass::Copy(Vector2i &min,Vector2i &max, const unsigned char *other)
  339. {
  340. SurfaceDescription sd;
  341. Get_Description(sd);
  342. // size of each pixel in bytes
  343. unsigned int size=PixelSize(sd);
  344. D3DLOCKED_RECT lock_rect;
  345. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  346. RECT rect;
  347. rect.left=min.I;
  348. rect.right=max.I;
  349. rect.top=min.J;
  350. rect.bottom=max.J;
  351. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
  352. int i;
  353. unsigned char *mem=(unsigned char *) lock_rect.pBits;
  354. int dx=max.I-min.I;
  355. for (i=min.J; i<max.J; i++)
  356. {
  357. memcpy(mem,&other[(i*sd.Width+min.I)*size],size*dx);
  358. mem+=lock_rect.Pitch;
  359. }
  360. DX8_ErrorCode(D3DSurface->UnlockRect());
  361. }
  362. /***********************************************************************************************
  363. * SurfaceClass::CreateCopy -- Creates a byte array copy of the surface *
  364. * *
  365. * *
  366. * *
  367. * *
  368. * INPUT: *
  369. * *
  370. * OUTPUT: *
  371. * *
  372. * WARNINGS: *
  373. * *
  374. * HISTORY: *
  375. * 3/16/2001 hy : Created. *
  376. *=============================================================================================*/
  377. unsigned char *SurfaceClass::CreateCopy(int *width,int *height,int*size,bool flip)
  378. {
  379. SurfaceDescription sd;
  380. Get_Description(sd);
  381. // size of each pixel in bytes
  382. unsigned int mysize=PixelSize(sd);
  383. *width=sd.Width;
  384. *height=sd.Height;
  385. *size=mysize;
  386. unsigned char *other=W3DNEWARRAY unsigned char [sd.Height*sd.Width*mysize];
  387. D3DLOCKED_RECT lock_rect;
  388. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  389. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,D3DLOCK_READONLY));
  390. unsigned int i;
  391. unsigned char *mem=(unsigned char *) lock_rect.pBits;
  392. for (i=0; i<sd.Height; i++)
  393. {
  394. if (flip)
  395. {
  396. memcpy(&other[(sd.Height-i-1)*sd.Width*mysize],mem,mysize*sd.Width);
  397. } else
  398. {
  399. memcpy(&other[i*sd.Width*mysize],mem,mysize*sd.Width);
  400. }
  401. mem+=lock_rect.Pitch;
  402. }
  403. DX8_ErrorCode(D3DSurface->UnlockRect());
  404. return other;
  405. }
  406. /***********************************************************************************************
  407. * SurfaceClass::Copy -- Copies a region from one surface to another *
  408. * *
  409. * *
  410. * *
  411. * *
  412. * INPUT: *
  413. * *
  414. * OUTPUT: *
  415. * *
  416. * WARNINGS: *
  417. * *
  418. * HISTORY: *
  419. * 2/13/2001 hy : Created. *
  420. *=============================================================================================*/
  421. void SurfaceClass::Copy(
  422. unsigned int dstx, unsigned int dsty,
  423. unsigned int srcx, unsigned int srcy,
  424. unsigned int width, unsigned int height,
  425. const SurfaceClass *other)
  426. {
  427. WWASSERT(other);
  428. WWASSERT(width);
  429. WWASSERT(height);
  430. SurfaceDescription sd,osd;
  431. Get_Description(sd);
  432. const_cast <SurfaceClass*>(other)->Get_Description(osd);
  433. RECT src;
  434. src.left=srcx;
  435. src.right=srcx+width;
  436. src.top=srcy;
  437. src.bottom=srcy+height;
  438. if (src.right>int(osd.Width)) src.right=int(osd.Width);
  439. if (src.bottom>int(osd.Height)) src.bottom=int(osd.Height);
  440. if (sd.Format==osd.Format && sd.Width==osd.Width && sd.Height==osd.Height)
  441. {
  442. POINT dst;
  443. dst.x=dstx;
  444. dst.y=dsty;
  445. DX8Wrapper::_Copy_DX8_Rects(other->D3DSurface,&src,1,D3DSurface,&dst);
  446. }
  447. else
  448. {
  449. RECT dest;
  450. dest.left=dstx;
  451. dest.right=dstx+width;
  452. dest.top=dsty;
  453. dest.bottom=dsty+height;
  454. if (dest.right>int(sd.Width)) dest.right=int(sd.Width);
  455. if (dest.bottom>int(sd.Height)) dest.bottom=int(sd.Height);
  456. DX8_ErrorCode(D3DXLoadSurfaceFromSurface(D3DSurface,NULL,&dest,other->D3DSurface,NULL,&src,D3DX_FILTER_NONE,0));
  457. }
  458. }
  459. /***********************************************************************************************
  460. * SurfaceClass::Copy -- Copies a region from one surface to another *
  461. * *
  462. * *
  463. * *
  464. * *
  465. * INPUT: *
  466. * *
  467. * OUTPUT: *
  468. * *
  469. * WARNINGS: *
  470. * *
  471. * HISTORY: *
  472. * 2/13/2001 hy : Created. *
  473. *=============================================================================================*/
  474. void SurfaceClass::Stretch_Copy(
  475. unsigned int dstx, unsigned int dsty, unsigned int dstwidth, unsigned int dstheight,
  476. unsigned int srcx, unsigned int srcy, unsigned int srcwidth, unsigned int srcheight,
  477. const SurfaceClass *other)
  478. {
  479. WWASSERT(other);
  480. SurfaceDescription sd,osd;
  481. Get_Description(sd);
  482. const_cast <SurfaceClass*>(other)->Get_Description(osd);
  483. RECT src;
  484. src.left=srcx;
  485. src.right=srcx+srcwidth;
  486. src.top=srcy;
  487. src.bottom=srcy+srcheight;
  488. RECT dest;
  489. dest.left=dstx;
  490. dest.right=dstx+dstwidth;
  491. dest.top=dsty;
  492. dest.bottom=dsty+dstheight;
  493. DX8_ErrorCode(D3DXLoadSurfaceFromSurface(D3DSurface,NULL,&dest,other->D3DSurface,NULL,&src,D3DX_FILTER_TRIANGLE ,0));
  494. }
  495. /***********************************************************************************************
  496. * SurfaceClass::FindBB -- Finds the bounding box of non zero pixels in the region *
  497. * *
  498. * *
  499. * *
  500. * *
  501. * INPUT: *
  502. * *
  503. * OUTPUT: *
  504. * *
  505. * WARNINGS: *
  506. * *
  507. * HISTORY: *
  508. * 2/13/2001 hy : Created. *
  509. *=============================================================================================*/
  510. void SurfaceClass::FindBB(Vector2i *min,Vector2i*max)
  511. {
  512. SurfaceDescription sd;
  513. Get_Description(sd);
  514. WWASSERT(Has_Alpha(sd.Format));
  515. int alphabits=Alpha_Bits(sd.Format);
  516. int mask=0;
  517. switch (alphabits)
  518. {
  519. case 1: mask=1;
  520. break;
  521. case 4: mask=0xf;
  522. break;
  523. case 8: mask=0xff;
  524. break;
  525. }
  526. D3DLOCKED_RECT lock_rect;
  527. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  528. RECT rect;
  529. ::ZeroMemory(&rect, sizeof(RECT));
  530. rect.bottom=max->J;
  531. rect.top=min->J;
  532. rect.left=min->I;
  533. rect.right=max->I;
  534. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
  535. int x,y;
  536. unsigned int size=PixelSize(sd);
  537. Vector2i realmin=*max;
  538. Vector2i realmax=*min;
  539. // the assumption here is that whenever a pixel has alpha it's in the MSB
  540. for (y = min->J; y < max->J; y++) {
  541. for (x = min->I; x < max->I; x++) {
  542. unsigned char *alpha=(unsigned char*) ((unsigned int)lock_rect.pBits+(y-min->J)*lock_rect.Pitch+(x-min->I)*size);
  543. #pragma MESSAGE("HY - this is not endian safe")
  544. unsigned char myalpha=alpha[size-1];
  545. myalpha=(myalpha>>(8-alphabits)) & mask;
  546. if (myalpha) {
  547. realmin.I = MIN(realmin.I, x);
  548. realmax.I = MAX(realmax.I, x);
  549. realmin.J = MIN(realmin.J, y);
  550. realmax.J = MAX(realmax.J, y);
  551. }
  552. }
  553. }
  554. DX8_ErrorCode(D3DSurface->UnlockRect());
  555. *max=realmax;
  556. *min=realmin;
  557. }
  558. /***********************************************************************************************
  559. * SurfaceClass::Is_Transparent_Column -- Tests to see if the column is transparent or not *
  560. * *
  561. * *
  562. * *
  563. * *
  564. * INPUT: *
  565. * *
  566. * OUTPUT: *
  567. * *
  568. * WARNINGS: *
  569. * *
  570. * HISTORY: *
  571. * 2/13/2001 hy : Created. *
  572. *=============================================================================================*/
  573. bool SurfaceClass::Is_Transparent_Column(unsigned int column)
  574. {
  575. SurfaceDescription sd;
  576. Get_Description(sd);
  577. WWASSERT(column<sd.Width);
  578. WWASSERT(Has_Alpha(sd.Format));
  579. int alphabits=Alpha_Bits(sd.Format);
  580. int mask=0;
  581. switch (alphabits)
  582. {
  583. case 1: mask=1;
  584. break;
  585. case 4: mask=0xf;
  586. break;
  587. case 8: mask=0xff;
  588. break;
  589. }
  590. unsigned int size=PixelSize(sd);
  591. D3DLOCKED_RECT lock_rect;
  592. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  593. RECT rect;
  594. ::ZeroMemory(&rect, sizeof(RECT));
  595. rect.bottom=sd.Height;
  596. rect.top=0;
  597. rect.left=column;
  598. rect.right=column+1;
  599. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
  600. int y;
  601. // the assumption here is that whenever a pixel has alpha it's in the MSB
  602. for (y = 0; y < (int) sd.Height; y++)
  603. {
  604. unsigned char *alpha=(unsigned char*) ((unsigned int)lock_rect.pBits+y*lock_rect.Pitch);
  605. #pragma MESSAGE("HY - this is not endian safe")
  606. unsigned char myalpha=alpha[size-1];
  607. myalpha=(myalpha>>(8-alphabits)) & mask;
  608. if (myalpha) {
  609. DX8_ErrorCode(D3DSurface->UnlockRect());
  610. return false;
  611. }
  612. }
  613. DX8_ErrorCode(D3DSurface->UnlockRect());
  614. return true;
  615. }
  616. /***********************************************************************************************
  617. * SurfaceClass::Get_Pixel -- Returns the pixel's RGB valus to the caller *
  618. * *
  619. * *
  620. * *
  621. * *
  622. * INPUT: *
  623. * *
  624. * OUTPUT: *
  625. * *
  626. * WARNINGS: *
  627. * *
  628. * HISTORY: *
  629. * 2/13/2001 hy : Created. *
  630. *=============================================================================================*/
  631. void SurfaceClass::Get_Pixel(Vector3 &rgb, int x,int y)
  632. {
  633. SurfaceDescription sd;
  634. Get_Description(sd);
  635. x = min(x,(int)sd.Width - 1);
  636. y = min(y,(int)sd.Height - 1);
  637. D3DLOCKED_RECT lock_rect;
  638. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  639. RECT rect;
  640. ::ZeroMemory(&rect, sizeof(RECT));
  641. rect.bottom=y+1;
  642. rect.top=y;
  643. rect.left=x;
  644. rect.right=x+1;
  645. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
  646. Convert_Pixel(rgb,sd,(unsigned char *) lock_rect.pBits);
  647. DX8_ErrorCode(D3DSurface->UnlockRect());
  648. }
  649. /***********************************************************************************************
  650. * SurfaceClass::Attach -- Attaches a surface pointer to the object, releasing the current ptr.*
  651. * *
  652. * *
  653. * *
  654. * *
  655. * INPUT: *
  656. * *
  657. * OUTPUT: *
  658. * *
  659. * WARNINGS: *
  660. * *
  661. * HISTORY: *
  662. * 3/27/2001 pds : Created. *
  663. *=============================================================================================*/
  664. void SurfaceClass::Attach (IDirect3DSurface8 *surface)
  665. {
  666. Detach ();
  667. D3DSurface = surface;
  668. //
  669. // Lock a reference onto the object
  670. //
  671. if (D3DSurface != NULL) {
  672. D3DSurface->AddRef ();
  673. }
  674. return ;
  675. }
  676. /***********************************************************************************************
  677. * SurfaceClass::Detach -- Releases the reference on the internal surface ptr, and NULLs it. .*
  678. * *
  679. * *
  680. * *
  681. * *
  682. * INPUT: *
  683. * *
  684. * OUTPUT: *
  685. * *
  686. * WARNINGS: *
  687. * *
  688. * HISTORY: *
  689. * 3/27/2001 pds : Created. *
  690. *=============================================================================================*/
  691. void SurfaceClass::Detach (void)
  692. {
  693. //
  694. // Release the hold we have on the D3D object
  695. //
  696. if (D3DSurface != NULL) {
  697. D3DSurface->Release ();
  698. }
  699. D3DSurface = NULL;
  700. return ;
  701. }
  702. /***********************************************************************************************
  703. * SurfaceClass::DrawPixel -- draws a pixel *
  704. * *
  705. * *
  706. * *
  707. * *
  708. * INPUT: *
  709. * *
  710. * OUTPUT: *
  711. * *
  712. * WARNINGS: *
  713. * *
  714. * HISTORY: *
  715. *=============================================================================================*/
  716. void SurfaceClass::DrawPixel(const unsigned int x,const unsigned int y, unsigned int color)
  717. {
  718. SurfaceDescription sd;
  719. Get_Description(sd);
  720. unsigned int size=PixelSize(sd);
  721. D3DLOCKED_RECT lock_rect;
  722. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  723. RECT rect;
  724. ::ZeroMemory(&rect, sizeof(RECT));
  725. rect.bottom=y+1;
  726. rect.top=y;
  727. rect.left=x;
  728. rect.right=x+1;
  729. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
  730. unsigned char *cptr=(unsigned char*)lock_rect.pBits;
  731. unsigned short *sptr=(unsigned short*)lock_rect.pBits;
  732. unsigned int *lptr=(unsigned int*)lock_rect.pBits;
  733. switch (size)
  734. {
  735. case 1:
  736. *cptr=(unsigned char) (color & 0xFF);
  737. break;
  738. case 2:
  739. *sptr=(unsigned short) (color & 0xFFFF);
  740. break;
  741. case 4:
  742. *lptr=color;
  743. break;
  744. }
  745. DX8_ErrorCode(D3DSurface->UnlockRect());
  746. }
  747. /***********************************************************************************************
  748. * SurfaceClass::DrawHLine -- draws a horizontal line *
  749. * *
  750. * *
  751. * *
  752. * *
  753. * INPUT: *
  754. * *
  755. * OUTPUT: *
  756. * *
  757. * WARNINGS: *
  758. * *
  759. * HISTORY: *
  760. * 4/9/2001 hy : Created. *
  761. * 4/9/2001 hy : Created. *
  762. *=============================================================================================*/
  763. void SurfaceClass::DrawHLine(const unsigned int y,const unsigned int x1, const unsigned int x2, unsigned int color)
  764. {
  765. SurfaceDescription sd;
  766. Get_Description(sd);
  767. unsigned int size=PixelSize(sd);
  768. D3DLOCKED_RECT lock_rect;
  769. ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
  770. RECT rect;
  771. ::ZeroMemory(&rect, sizeof(RECT));
  772. rect.bottom=y+1;
  773. rect.top=y;
  774. rect.left=x1;
  775. rect.right=x2+1;
  776. DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
  777. unsigned char *cptr=(unsigned char*)lock_rect.pBits;
  778. unsigned short *sptr=(unsigned short*)lock_rect.pBits;
  779. unsigned int *lptr=(unsigned int*)lock_rect.pBits;
  780. unsigned int x;
  781. // the assumption here is that whenever a pixel has alpha it's in the MSB
  782. for (x=x1; x<=x2; x++)
  783. {
  784. switch (size)
  785. {
  786. case 1:
  787. *cptr++=(unsigned char) (color & 0xFF);
  788. break;
  789. case 2:
  790. *sptr++=(unsigned short) (color & 0xFFFF);
  791. break;
  792. case 4:
  793. *lptr++=color;
  794. break;
  795. }
  796. }
  797. DX8_ErrorCode(D3DSurface->UnlockRect());
  798. }
  799. /***********************************************************************************************
  800. * SurfaceClass::Is_Monochrome -- Checks if surface is monochrome or not *
  801. * *
  802. * *
  803. * *
  804. * *
  805. * INPUT: *
  806. * *
  807. * OUTPUT: *
  808. * *
  809. * WARNINGS: *
  810. * *
  811. * HISTORY: *
  812. * 7/5/2001 hy : Created. *
  813. *=============================================================================================*/
  814. bool SurfaceClass::Is_Monochrome(void)
  815. {
  816. unsigned int x,y;
  817. SurfaceDescription sd;
  818. Get_Description(sd);
  819. switch (sd.Format)
  820. {
  821. case WW3D_FORMAT_A8L8:
  822. case WW3D_FORMAT_A8:
  823. case WW3D_FORMAT_L8:
  824. case WW3D_FORMAT_A4L4:
  825. return true;
  826. break;
  827. }
  828. int pitch,size;
  829. size=PixelSize(sd);
  830. unsigned char *bits=(unsigned char*) Lock(&pitch);
  831. Vector3 rgb;
  832. bool mono=true;
  833. for (y=0; y<sd.Height; y++)
  834. {
  835. for (x=0; x<sd.Width; x++)
  836. {
  837. Convert_Pixel(rgb,sd,&bits[x*size]);
  838. mono&=(rgb.X==rgb.Y);
  839. mono&=(rgb.X==rgb.Z);
  840. mono&=(rgb.Z==rgb.Y);
  841. if (!mono)
  842. {
  843. Unlock();
  844. return false;
  845. }
  846. }
  847. bits+=pitch;
  848. }
  849. Unlock();
  850. return true;
  851. }
  852. /***********************************************************************************************
  853. * SurfaceClass::Hue_Shift -- changes the hue of the surface *
  854. * *
  855. * *
  856. * *
  857. * *
  858. * INPUT: *
  859. * *
  860. * OUTPUT: *
  861. * *
  862. * WARNINGS: *
  863. * *
  864. * HISTORY: *
  865. * 7/3/2001 hy : Created. *
  866. *=============================================================================================*/
  867. void SurfaceClass::Hue_Shift(const Vector3 &hsv_shift)
  868. {
  869. unsigned int x,y;
  870. SurfaceDescription sd;
  871. Get_Description(sd);
  872. int pitch,size;
  873. size=PixelSize(sd);
  874. unsigned char *bits=(unsigned char*) Lock(&pitch);
  875. Vector3 rgb;
  876. for (y=0; y<sd.Height; y++)
  877. {
  878. for (x=0; x<sd.Width; x++)
  879. {
  880. Convert_Pixel(rgb,sd,&bits[x*size]);
  881. Recolor(rgb,hsv_shift);
  882. rgb.X=Bound(rgb.X,0.0f,1.0f);
  883. rgb.Y=Bound(rgb.Y,0.0f,1.0f);
  884. rgb.Z=Bound(rgb.Z,0.0f,1.0f);
  885. Convert_Pixel(&bits[x*size],sd,rgb);
  886. }
  887. bits+=pitch;
  888. }
  889. Unlock();
  890. }