Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
surfaceclass.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(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/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/surfaceclass.cpp $*
26 * *
27 * Original Author:: Nathaniel Hoffman *
28 * *
29 * $Author:: Greg_h2 $*
30 * *
31 * $Modtime:: 8/30/01 2:01p $*
32 * *
33 * $Revision:: 25 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * SurfaceClass::Clear -- Clears a surface to 0 *
38 * SurfaceClass::Copy -- Copies a region from one surface to another of the same format *
39 * SurfaceClass::FindBBAlpha -- Finds the bounding box of non zero pixels in the region (x0, *
40 * PixelSize -- Helper Function to find the size in bytes of a pixel *
41 * SurfaceClass::Is_Transparent_Column -- Tests to see if the column is transparent or not *
42 * SurfaceClass::Copy -- Copies from a byte array to the surface *
43 * SurfaceClass::CreateCopy -- Creates a byte array copy of the surface *
44 * SurfaceClass::DrawHLine -- draws a horizontal line *
45 * SurfaceClass::DrawPixel -- draws a pixel *
46 * SurfaceClass::Copy -- Copies a block of system ram to the surface *
47 * SurfaceClass::Hue_Shift -- changes the hue of the surface *
48 * SurfaceClass::Is_Monochrome -- Checks if surface is monochrome or not *
49 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
50
51#include "surfaceclass.h"
52#include "formconv.h"
53#include "dx8wrapper.h"
54#include "vector2i.h"
55#include "colorspace.h"
56#include "bound.h"
57#include <d3dx8.h>
58
59/***********************************************************************************************
60 * PixelSize -- Helper Function to find the size in bytes of a pixel *
61 * *
62 * *
63 * *
64 * *
65 * INPUT: *
66 * *
67 * OUTPUT: *
68 * *
69 * WARNINGS: *
70 * *
71 * HISTORY: *
72 * 2/13/2001 hy : Created. *
73 *=============================================================================================*/
74
76{
77 unsigned int size=0;
78
79 switch (sd.Format)
80 {
83 size=4;
84 break;
86 size=3;
87 break;
94 case WW3D_FORMAT_A8P8:
96 size=2;
97 break;
99 case WW3D_FORMAT_A8:
100 case WW3D_FORMAT_P8:
101 case WW3D_FORMAT_L8:
102 case WW3D_FORMAT_A4L4:
103 size=1;
104 break;
105 }
106
107 return size;
108}
109
110void Convert_Pixel(Vector3 &rgb, const SurfaceClass::SurfaceDescription &sd, const unsigned char * pixel)
111{
112 const float scale=1/255.0f;
113 switch (sd.Format)
114 {
118 {
119 rgb.X=pixel[2]; // R
120 rgb.Y=pixel[1]; // G
121 rgb.Z=pixel[0]; // B
122 }
123 break;
125 {
126 unsigned short tmp;
127 tmp=*(unsigned short*)&pixel[0];
128 rgb.X=((tmp&0x0f00)>>4); // R
129 rgb.Y=((tmp&0x00f0)); // G
130 rgb.Z=((tmp&0x000f)<<4); // B
131 }
132 break;
134 {
135 unsigned short tmp;
136 tmp=*(unsigned short*)&pixel[0];
137 rgb.X=(tmp>>7)&0xf8; // R
138 rgb.Y=(tmp>>2)&0xf8; // G
139 rgb.Z=(tmp<<3)&0xf8; // B
140 }
141 break;
143 {
144 unsigned short tmp;
145 tmp=*(unsigned short*)&pixel[0];
146 rgb.X=(tmp>>8)&0xf8;
147 rgb.Y=(tmp>>3)&0xfc;
148 rgb.Z=(tmp<<3)&0xf8;
149 }
150 break;
151
152 default:
153 // TODO: Implement other pixel formats
154 WWASSERT(0);
155 }
156 rgb*=scale;
157}
158
159// Note: This function must never overwrite the original alpha
160void Convert_Pixel(unsigned char * pixel,const SurfaceClass::SurfaceDescription &sd, const Vector3 &rgb)
161{
162 unsigned char r,g,b;
163 r=(unsigned char) (rgb.X*255.0f);
164 g=(unsigned char) (rgb.Y*255.0f);
165 b=(unsigned char) (rgb.Z*255.0f);
166 switch (sd.Format)
167 {
171 pixel[0]=b;
172 pixel[1]=g;
173 pixel[2]=r;
174 break;
176 {
177 unsigned short tmp;
178 tmp=*(unsigned short*)&pixel[0];
179 tmp&=0xF000;
180 tmp|=(r&0xF0) << 4;
181 tmp|=(g&0xF0);
182 tmp|=(b&0xF0) >> 4;
183 *(unsigned short*)&pixel[0]=tmp;
184 }
185 break;
187 {
188 unsigned short tmp;
189 tmp=*(unsigned short*)&pixel[0];
190 tmp&=0x8000;
191 tmp|=(r&0xF8) << 7;
192 tmp|=(g&0xF8) << 2;
193 tmp|=(b&0xF8) >> 3;
194 *(unsigned short*)&pixel[0]=tmp;
195 }
196 break;
198 {
199 unsigned short tmp;
200 tmp=(r&0xf8) << 8;
201 tmp|=(g&0xfc) << 3;
202 tmp|=(b&0xf8) >> 3;
203 *(unsigned short*)&pixel[0]=tmp;
204 }
205 break;
206 default:
207 // TODO: Implement other pixel formats
208 WWASSERT(0);
209 }
210}
211
212/*************************************************************************
213** SurfaceClass
214*************************************************************************/
215SurfaceClass::SurfaceClass(unsigned width, unsigned height, WW3DFormat format):
216 D3DSurface(NULL),
217 SurfaceFormat(format)
218{
219 WWASSERT(width);
220 WWASSERT(height);
221 D3DSurface = DX8Wrapper::_Create_DX8_Surface(width, height, format);
222}
223
224SurfaceClass::SurfaceClass(const char *filename):
225 D3DSurface(NULL)
226{
227 D3DSurface = DX8Wrapper::_Create_DX8_Surface(filename);
229 Get_Description(desc);
230 SurfaceFormat=desc.Format;
231}
232
233SurfaceClass::SurfaceClass(IDirect3DSurface8 *d3d_surface) :
234 D3DSurface (NULL)
235{
236 Attach (d3d_surface);
238 Get_Description(desc);
239 SurfaceFormat=desc.Format;
240}
241
243{
244 if (D3DSurface) {
245 D3DSurface->Release();
246 D3DSurface = NULL;
247 }
248}
249
251{
252 D3DSURFACE_DESC d3d_desc;
253 ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC));
254 DX8_ErrorCode(D3DSurface->GetDesc(&d3d_desc));
255 surface_desc.Format = D3DFormat_To_WW3DFormat(d3d_desc.Format);
256 surface_desc.Height = d3d_desc.Height;
257 surface_desc.Width = d3d_desc.Width;
258}
259
260void * SurfaceClass::Lock(int * pitch)
261{
262 D3DLOCKED_RECT lock_rect;
263 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
264 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect, 0, 0));
265 *pitch = lock_rect.Pitch;
266 return (void *)lock_rect.pBits;
267}
268
270{
271 DX8_ErrorCode(D3DSurface->UnlockRect());
272}
273
274/***********************************************************************************************
275 * SurfaceClass::Clear -- Clears a surface to 0 *
276 * *
277 * *
278 * *
279 * *
280 * INPUT: *
281 * *
282 * OUTPUT: *
283 * *
284 * WARNINGS: *
285 * *
286 * HISTORY: *
287 * 2/13/2001 hy : Created. *
288 *=============================================================================================*/
290{
292 Get_Description(sd);
293
294 // size of each pixel in bytes
295 unsigned int size=PixelSize(sd);
296
297 D3DLOCKED_RECT lock_rect;
298 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
299 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,0));
300 unsigned int i;
301 unsigned char *mem=(unsigned char *) lock_rect.pBits;
302
303 for (i=0; i<sd.Height; i++)
304 {
305 memset(mem,0,size*sd.Width);
306 mem+=lock_rect.Pitch;
307 }
308
309 DX8_ErrorCode(D3DSurface->UnlockRect());
310}
311
312
313/***********************************************************************************************
314 * SurfaceClass::Copy -- Copies from a byte array to the surface *
315 * *
316 * *
317 * *
318 * *
319 * INPUT: *
320 * *
321 * OUTPUT: *
322 * *
323 * WARNINGS: *
324 * *
325 * HISTORY: *
326 * 3/15/2001 hy : Created. *
327 *=============================================================================================*/
328void SurfaceClass::Copy(const unsigned char *other)
329{
331 Get_Description(sd);
332
333 // size of each pixel in bytes
334 unsigned int size=PixelSize(sd);
335
336 D3DLOCKED_RECT lock_rect;
337 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
338 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,0));
339 unsigned int i;
340 unsigned char *mem=(unsigned char *) lock_rect.pBits;
341
342 for (i=0; i<sd.Height; i++)
343 {
344 memcpy(mem,&other[i*sd.Width*size],size*sd.Width);
345 mem+=lock_rect.Pitch;
346 }
347
348 DX8_ErrorCode(D3DSurface->UnlockRect());
349}
350
351
352/***********************************************************************************************
353 * SurfaceClass::Copy -- Copies a block of system ram to the surface *
354 * *
355 * *
356 * *
357 * *
358 * INPUT: *
359 * *
360 * OUTPUT: *
361 * *
362 * WARNINGS: *
363 * *
364 * HISTORY: *
365 * 5/2/2001 hy : Created. *
366 *=============================================================================================*/
367void SurfaceClass::Copy(Vector2i &min,Vector2i &max, const unsigned char *other)
368{
370 Get_Description(sd);
371
372 // size of each pixel in bytes
373 unsigned int size=PixelSize(sd);
374
375 D3DLOCKED_RECT lock_rect;
376 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
377 RECT rect;
378 rect.left=min.I;
379 rect.right=max.I;
380 rect.top=min.J;
381 rect.bottom=max.J;
382 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
383 int i;
384 unsigned char *mem=(unsigned char *) lock_rect.pBits;
385 int dx=max.I-min.I;
386
387 for (i=min.J; i<max.J; i++)
388 {
389 memcpy(mem,&other[(i*sd.Width+min.I)*size],size*dx);
390 mem+=lock_rect.Pitch;
391 }
392
393 DX8_ErrorCode(D3DSurface->UnlockRect());
394}
395
396
397/***********************************************************************************************
398 * SurfaceClass::CreateCopy -- Creates a byte array copy of the surface *
399 * *
400 * *
401 * *
402 * *
403 * INPUT: *
404 * *
405 * OUTPUT: *
406 * *
407 * WARNINGS: *
408 * *
409 * HISTORY: *
410 * 3/16/2001 hy : Created. *
411 *=============================================================================================*/
412unsigned char *SurfaceClass::CreateCopy(int *width,int *height,int*size,bool flip)
413{
415 Get_Description(sd);
416
417 // size of each pixel in bytes
418 unsigned int mysize=PixelSize(sd);
419
420 *width=sd.Width;
421 *height=sd.Height;
422 *size=mysize;
423
424 unsigned char *other=W3DNEWARRAY unsigned char [sd.Height*sd.Width*mysize];
425
426 D3DLOCKED_RECT lock_rect;
427 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
428 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,0,D3DLOCK_READONLY));
429 unsigned int i;
430 unsigned char *mem=(unsigned char *) lock_rect.pBits;
431
432 for (i=0; i<sd.Height; i++)
433 {
434 if (flip)
435 {
436 memcpy(&other[(sd.Height-i-1)*sd.Width*mysize],mem,mysize*sd.Width);
437 } else
438 {
439 memcpy(&other[i*sd.Width*mysize],mem,mysize*sd.Width);
440 }
441 mem+=lock_rect.Pitch;
442 }
443
444 DX8_ErrorCode(D3DSurface->UnlockRect());
445
446 return other;
447}
448
449
450/***********************************************************************************************
451 * SurfaceClass::Copy -- Copies a region from one surface to another *
452 * *
453 * *
454 * *
455 * *
456 * INPUT: *
457 * *
458 * OUTPUT: *
459 * *
460 * WARNINGS: *
461 * *
462 * HISTORY: *
463 * 2/13/2001 hy : Created. *
464 *=============================================================================================*/
466 unsigned int dstx, unsigned int dsty,
467 unsigned int srcx, unsigned int srcy,
468 unsigned int width, unsigned int height,
469 const SurfaceClass *other)
470{
471 WWASSERT(other);
472 WWASSERT(width);
473 WWASSERT(height);
474
475 SurfaceDescription sd,osd;
476 Get_Description(sd);
477 const_cast <SurfaceClass*>(other)->Get_Description(osd);
478
479 RECT src;
480 src.left=srcx;
481 src.right=srcx+width;
482 src.top=srcy;
483 src.bottom=srcy+height;
484
485 if (src.right>int(osd.Width)) src.right=int(osd.Width);
486 if (src.bottom>int(osd.Height)) src.bottom=int(osd.Height);
487
488 if (sd.Format==osd.Format && sd.Width==osd.Width && sd.Height==osd.Height)
489 {
490 POINT dst;
491 dst.x=dstx;
492 dst.y=dsty;
493 DX8Wrapper::_Copy_DX8_Rects(other->D3DSurface,&src,1,D3DSurface,&dst);
494 }
495 else
496 {
497 RECT dest;
498 dest.left=dstx;
499 dest.right=dstx+width;
500 dest.top=dsty;
501 dest.bottom=dsty+height;
502
503 if (dest.right>int(sd.Width)) dest.right=int(sd.Width);
504 if (dest.bottom>int(sd.Height)) dest.bottom=int(sd.Height);
505
506 DX8_ErrorCode(D3DXLoadSurfaceFromSurface(D3DSurface,NULL,&dest,other->D3DSurface,NULL,&src,D3DX_FILTER_NONE,0));
507 }
508}
509
510/***********************************************************************************************
511 * SurfaceClass::Copy -- Copies a region from one surface to another *
512 * *
513 * *
514 * *
515 * *
516 * INPUT: *
517 * *
518 * OUTPUT: *
519 * *
520 * WARNINGS: *
521 * *
522 * HISTORY: *
523 * 2/13/2001 hy : Created. *
524 *=============================================================================================*/
526 unsigned int dstx, unsigned int dsty, unsigned int dstwidth, unsigned int dstheight,
527 unsigned int srcx, unsigned int srcy, unsigned int srcwidth, unsigned int srcheight,
528 const SurfaceClass *other)
529{
530 WWASSERT(other);
531
532 SurfaceDescription sd,osd;
533 Get_Description(sd);
534 const_cast <SurfaceClass*>(other)->Get_Description(osd);
535
536 RECT src;
537 src.left=srcx;
538 src.right=srcx+srcwidth;
539 src.top=srcy;
540 src.bottom=srcy+srcheight;
541
542 RECT dest;
543 dest.left=dstx;
544 dest.right=dstx+dstwidth;
545 dest.top=dsty;
546 dest.bottom=dsty+dstheight;
547
548 DX8_ErrorCode(D3DXLoadSurfaceFromSurface(D3DSurface,NULL,&dest,other->D3DSurface,NULL,&src,D3DX_FILTER_TRIANGLE ,0));
549}
550
551/***********************************************************************************************
552 * SurfaceClass::FindBB -- Finds the bounding box of non zero pixels in the region *
553 * *
554 * *
555 * *
556 * *
557 * INPUT: *
558 * *
559 * OUTPUT: *
560 * *
561 * WARNINGS: *
562 * *
563 * HISTORY: *
564 * 2/13/2001 hy : Created. *
565 *=============================================================================================*/
567{
569 Get_Description(sd);
570
572
573 int alphabits=Alpha_Bits(sd.Format);
574 int mask=0;
575 switch (alphabits)
576 {
577 case 1: mask=1;
578 break;
579 case 4: mask=0xf;
580 break;
581 case 8: mask=0xff;
582 break;
583 }
584
585 D3DLOCKED_RECT lock_rect;
586 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
587 RECT rect;
588 ::ZeroMemory(&rect, sizeof(RECT));
589
590 rect.bottom=max->J;
591 rect.top=min->J;
592 rect.left=min->I;
593 rect.right=max->I;
594
595 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
596
597 int x,y;
598 unsigned int size=PixelSize(sd);
599 Vector2i realmin=*max;
600 Vector2i realmax=*min;
601
602 // the assumption here is that whenever a pixel has alpha it's in the MSB
603 for (y = min->J; y < max->J; y++) {
604 for (x = min->I; x < max->I; x++) {
605
606 // HY - this is not endian safe
607 unsigned char *alpha=(unsigned char*) ((unsigned int)lock_rect.pBits+(y-min->J)*lock_rect.Pitch+(x-min->I)*size);
608 unsigned char myalpha=alpha[size-1];
609 myalpha=(myalpha>>(8-alphabits)) & mask;
610 if (myalpha) {
611 realmin.I = MIN(realmin.I, x);
612 realmax.I = MAX(realmax.I, x);
613 realmin.J = MIN(realmin.J, y);
614 realmax.J = MAX(realmax.J, y);
615 }
616 }
617 }
618
619 DX8_ErrorCode(D3DSurface->UnlockRect());
620
621 *max=realmax;
622 *min=realmin;
623}
624
625
626/***********************************************************************************************
627 * SurfaceClass::Is_Transparent_Column -- Tests to see if the column is transparent or not *
628 * *
629 * *
630 * *
631 * *
632 * INPUT: *
633 * *
634 * OUTPUT: *
635 * *
636 * WARNINGS: *
637 * *
638 * HISTORY: *
639 * 2/13/2001 hy : Created. *
640 *=============================================================================================*/
641bool SurfaceClass::Is_Transparent_Column(unsigned int column)
642{
644 Get_Description(sd);
645
646 WWASSERT(column<sd.Width);
648
649 int alphabits=Alpha_Bits(sd.Format);
650 int mask=0;
651 switch (alphabits)
652 {
653 case 1: mask=1;
654 break;
655 case 4: mask=0xf;
656 break;
657 case 8: mask=0xff;
658 break;
659 }
660
661 unsigned int size=PixelSize(sd);
662
663 D3DLOCKED_RECT lock_rect;
664 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
665 RECT rect;
666 ::ZeroMemory(&rect, sizeof(RECT));
667
668 rect.bottom=sd.Height;
669 rect.top=0;
670 rect.left=column;
671 rect.right=column+1;
672
673 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
674
675 int y;
676
677 // the assumption here is that whenever a pixel has alpha it's in the MSB
678 for (y = 0; y < (int) sd.Height; y++)
679 {
680 // HY - this is not endian safe
681 unsigned char *alpha=(unsigned char*) ((unsigned int)lock_rect.pBits+y*lock_rect.Pitch);
682 unsigned char myalpha=alpha[size-1];
683 myalpha=(myalpha>>(8-alphabits)) & mask;
684 if (myalpha) {
685 DX8_ErrorCode(D3DSurface->UnlockRect());
686 return false;
687 }
688 }
689
690 DX8_ErrorCode(D3DSurface->UnlockRect());
691 return true;
692}
693
694/***********************************************************************************************
695 * SurfaceClass::Get_Pixel -- Returns the pixel's RGB valus to the caller *
696 * *
697 * *
698 * *
699 * *
700 * INPUT: *
701 * *
702 * OUTPUT: *
703 * *
704 * WARNINGS: *
705 * *
706 * HISTORY: *
707 * 2/13/2001 hy : Created. *
708 *=============================================================================================*/
709void SurfaceClass::Get_Pixel(Vector3 &rgb, int x,int y)
710{
712 Get_Description(sd);
713
714 x = min(x,(int)sd.Width - 1);
715 y = min(y,(int)sd.Height - 1);
716
717 D3DLOCKED_RECT lock_rect;
718 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
719 RECT rect;
720 ::ZeroMemory(&rect, sizeof(RECT));
721
722 rect.bottom=y+1;
723 rect.top=y;
724 rect.left=x;
725 rect.right=x+1;
726
727 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,D3DLOCK_READONLY));
728 Convert_Pixel(rgb,sd,(unsigned char *) lock_rect.pBits);
729 DX8_ErrorCode(D3DSurface->UnlockRect());
730}
731
732/***********************************************************************************************
733 * SurfaceClass::Attach -- Attaches a surface pointer to the object, releasing the current ptr.*
734 * *
735 * *
736 * *
737 * *
738 * INPUT: *
739 * *
740 * OUTPUT: *
741 * *
742 * WARNINGS: *
743 * *
744 * HISTORY: *
745 * 3/27/2001 pds : Created. *
746 *=============================================================================================*/
747void SurfaceClass::Attach (IDirect3DSurface8 *surface)
748{
749 Detach ();
750 D3DSurface = surface;
751
752 //
753 // Lock a reference onto the object
754 //
755 if (D3DSurface != NULL) {
756 D3DSurface->AddRef ();
757 }
758
759 return ;
760}
761
762
763/***********************************************************************************************
764 * SurfaceClass::Detach -- Releases the reference on the internal surface ptr, and NULLs it. .*
765 * *
766 * *
767 * *
768 * *
769 * INPUT: *
770 * *
771 * OUTPUT: *
772 * *
773 * WARNINGS: *
774 * *
775 * HISTORY: *
776 * 3/27/2001 pds : Created. *
777 *=============================================================================================*/
779{
780 //
781 // Release the hold we have on the D3D object
782 //
783 if (D3DSurface != NULL) {
784 D3DSurface->Release ();
785 }
786
787 D3DSurface = NULL;
788 return ;
789}
790
791
792/***********************************************************************************************
793 * SurfaceClass::DrawPixel -- draws a pixel *
794 * *
795 * *
796 * *
797 * *
798 * INPUT: *
799 * *
800 * OUTPUT: *
801 * *
802 * WARNINGS: *
803 * *
804 * HISTORY: *
805 *=============================================================================================*/
806void SurfaceClass::DrawPixel(const unsigned int x,const unsigned int y, unsigned int color)
807{
809 Get_Description(sd);
810
811 unsigned int size=PixelSize(sd);
812
813 D3DLOCKED_RECT lock_rect;
814 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
815 RECT rect;
816 ::ZeroMemory(&rect, sizeof(RECT));
817
818 rect.bottom=y+1;
819 rect.top=y;
820 rect.left=x;
821 rect.right=x+1;
822
823 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
824 unsigned char *cptr=(unsigned char*)lock_rect.pBits;
825 unsigned short *sptr=(unsigned short*)lock_rect.pBits;
826 unsigned int *lptr=(unsigned int*)lock_rect.pBits;
827
828 switch (size)
829 {
830 case 1:
831 *cptr=(unsigned char) (color & 0xFF);
832 break;
833 case 2:
834 *sptr=(unsigned short) (color & 0xFFFF);
835 break;
836 case 4:
837 *lptr=color;
838 break;
839 }
840
841 DX8_ErrorCode(D3DSurface->UnlockRect());
842}
843
844/***********************************************************************************************
845 * SurfaceClass::DrawHLine -- draws a horizontal line *
846 * *
847 * *
848 * *
849 * *
850 * INPUT: *
851 * *
852 * OUTPUT: *
853 * *
854 * WARNINGS: *
855 * *
856 * HISTORY: *
857 * 4/9/2001 hy : Created. *
858 * 4/9/2001 hy : Created. *
859 *=============================================================================================*/
860void SurfaceClass::DrawHLine(const unsigned int y,const unsigned int x1, const unsigned int x2, unsigned int color)
861{
863 Get_Description(sd);
864
865 unsigned int size=PixelSize(sd);
866
867 D3DLOCKED_RECT lock_rect;
868 ::ZeroMemory(&lock_rect, sizeof(D3DLOCKED_RECT));
869 RECT rect;
870 ::ZeroMemory(&rect, sizeof(RECT));
871
872 rect.bottom=y+1;
873 rect.top=y;
874 rect.left=x1;
875 rect.right=x2+1;
876
877 DX8_ErrorCode(D3DSurface->LockRect(&lock_rect,&rect,0));
878 unsigned char *cptr=(unsigned char*)lock_rect.pBits;
879 unsigned short *sptr=(unsigned short*)lock_rect.pBits;
880 unsigned int *lptr=(unsigned int*)lock_rect.pBits;
881
882 unsigned int x;
883 // the assumption here is that whenever a pixel has alpha it's in the MSB
884 for (x=x1; x<=x2; x++)
885 {
886 switch (size)
887 {
888 case 1:
889 *cptr++=(unsigned char) (color & 0xFF);
890 break;
891 case 2:
892 *sptr++=(unsigned short) (color & 0xFFFF);
893 break;
894 case 4:
895 *lptr++=color;
896 break;
897 }
898 }
899
900 DX8_ErrorCode(D3DSurface->UnlockRect());
901}
902
903
904/***********************************************************************************************
905 * SurfaceClass::Is_Monochrome -- Checks if surface is monochrome or not *
906 * *
907 * *
908 * *
909 * *
910 * INPUT: *
911 * *
912 * OUTPUT: *
913 * *
914 * WARNINGS: *
915 * *
916 * HISTORY: *
917 * 7/5/2001 hy : Created. *
918 *=============================================================================================*/
920{
921 unsigned int x,y;
923 Get_Description(sd);
924 bool is_compressed = false;
925
926 switch (sd.Format)
927 {
928 // these formats are always monochrome
929 case WW3D_FORMAT_A8L8:
930 case WW3D_FORMAT_A8:
931 case WW3D_FORMAT_L8:
932 case WW3D_FORMAT_A4L4:
933 return true;
934 break;
935 // these formats cannot be determined to be monochrome or not
937 case WW3D_FORMAT_A8P8:
938 case WW3D_FORMAT_P8:
939 case WW3D_FORMAT_U8V8: // Bumpmap
940 case WW3D_FORMAT_L6V5U5: // Bumpmap
941 case WW3D_FORMAT_X8L8V8U8: // Bumpmap
942 return false;
943 break;
944 // these formats need decompression first
945 case WW3D_FORMAT_DXT1:
946 case WW3D_FORMAT_DXT2:
947 case WW3D_FORMAT_DXT3:
948 case WW3D_FORMAT_DXT4:
949 case WW3D_FORMAT_DXT5:
950 is_compressed = true;
951 break;
952 }
953
954 // if it's in some compressed texture format, be sure to decompress first
955 if (is_compressed) {
956 WW3DFormat new_format = Get_Valid_Texture_Format(sd.Format, false);
957 SurfaceClass *new_surf = NEW_REF( SurfaceClass, (sd.Width, sd.Height, new_format) );
958 new_surf->Copy(0, 0, 0, 0, sd.Width, sd.Height, this);
959 bool result = new_surf->Is_Monochrome();
960 REF_PTR_RELEASE(new_surf);
961 return result;
962 }
963
964 int pitch,size;
965
966 size=PixelSize(sd);
967 unsigned char *bits=(unsigned char*) Lock(&pitch);
968
969 Vector3 rgb;
970 bool mono=true;
971
972 for (y=0; y<sd.Height; y++)
973 {
974 for (x=0; x<sd.Width; x++)
975 {
976 Convert_Pixel(rgb,sd,&bits[x*size]);
977 mono&=(rgb.X==rgb.Y);
978 mono&=(rgb.X==rgb.Z);
979 mono&=(rgb.Z==rgb.Y);
980 if (!mono)
981 {
982 Unlock();
983 return false;
984 }
985 }
986 bits+=pitch;
987 }
988
989 Unlock();
990
991 return true;
992}
993
994/***********************************************************************************************
995 * SurfaceClass::Hue_Shift -- changes the hue of the surface *
996 * *
997 * *
998 * *
999 * *
1000 * INPUT: *
1001 * *
1002 * OUTPUT: *
1003 * *
1004 * WARNINGS: *
1005 * *
1006 * HISTORY: *
1007 * 7/3/2001 hy : Created. *
1008 *=============================================================================================*/
1009void SurfaceClass::Hue_Shift(const Vector3 &hsv_shift)
1010{
1011 unsigned int x,y;
1013 Get_Description(sd);
1014 int pitch,size;
1015
1016 size=PixelSize(sd);
1017 unsigned char *bits=(unsigned char*) Lock(&pitch);
1018
1019 Vector3 rgb;
1020
1021 for (y=0; y<sd.Height; y++)
1022 {
1023 for (x=0; x<sd.Width; x++)
1024 {
1025 Convert_Pixel(rgb,sd,&bits[x*size]);
1026 Recolor(rgb,hsv_shift);
1027 rgb.X=Bound(rgb.X,0.0f,1.0f);
1028 rgb.Y=Bound(rgb.Y,0.0f,1.0f);
1029 rgb.Z=Bound(rgb.Z,0.0f,1.0f);
1030 Convert_Pixel(&bits[x*size],sd,rgb);
1031 }
1032 bits+=pitch;
1033 }
1034
1035 Unlock();
1036}
#define NULL
Definition BaseType.h:92
#define min(x, y)
Definition BaseType.h:101
#define max(x, y)
Definition BaseType.h:105
Color scale(const Color &a, const Color &b)
Definition GameMtl.cpp:722
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
#define MIN(a, b)
Definition always.h:189
#define MAX(a, b)
Definition always.h:185
unsigned int PixelSize(const SurfaceClass::SurfaceDescription &sd)
void Convert_Pixel(Vector3 &rgb, const SurfaceClass::SurfaceDescription &sd, const unsigned char *pixel)
T Bound(T original, T minval, T maxval)
Definition bound.h:44
static IDirect3DSurface8 * _Create_DX8_Surface(unsigned int width, unsigned int height, WW3DFormat format)
static void _Copy_DX8_Rects(IDirect3DSurface8 *pSourceSurface, CONST RECT *pSourceRectsArray, UINT cRects, IDirect3DSurface8 *pDestinationSurface, CONST POINT *pDestPointsArray)
Definition dx8wrapper.h:942
void DrawHLine(const unsigned int y, const unsigned int x1, const unsigned int x2, unsigned int color)
void Get_Description(SurfaceDescription &surface_desc)
void Copy(unsigned int dstx, unsigned int dsty, unsigned int srcx, unsigned int srcy, unsigned int width, unsigned int height, const SurfaceClass *other)
void Attach(IDirect3DSurface8 *surface)
void Unlock(void)
unsigned char * CreateCopy(int *width, int *height, int *size, bool flip=false)
bool Is_Transparent_Column(unsigned int column)
bool Is_Monochrome(void)
void Get_Pixel(Vector3 &rgb, int x, int y)
void * Lock(int *pitch)
void Hue_Shift(const Vector3 &hsv_shift)
void Detach(void)
void Stretch_Copy(unsigned int dstx, unsigned int dsty, unsigned int dstwidth, unsigned int dstheight, unsigned int srcx, unsigned int srcy, unsigned int srcwidth, unsigned int srcheight, const SurfaceClass *source)
void FindBB(Vector2i *min, Vector2i *max)
SurfaceClass(unsigned width, unsigned height, WW3DFormat format)
void DrawPixel(const unsigned int x, const unsigned int y, unsigned int color)
int I
Definition vector2i.h:51
int J
Definition vector2i.h:52
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
void Recolor(Vector3 &rgb, const Vector3 &hsv_shift)
Definition colorspace.h:131
WWINLINE void DX8_ErrorCode(unsigned res)
Definition dx8wrapper.h:125
WW3DFormat D3DFormat_To_WW3DFormat(D3DFORMAT d3d_format)
Definition formconv.cpp:150
#define I(x, y, z)
Definition md5.cpp:89
else return(RetVal)
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define NEW_REF(C, P)
Definition refcount.h:62
unsigned int PixelSize(const SurfaceClass::SurfaceDescription &sd)
void Convert_Pixel(Vector3 &rgb, const SurfaceClass::SurfaceDescription &sd, const unsigned char *pixel)
WW3DFormat Get_Valid_Texture_Format(WW3DFormat format, bool is_compression_allowed)
bool Has_Alpha(WW3DFormat format)
Definition ww3dformat.h:126
int Alpha_Bits(WW3DFormat format)
Definition ww3dformat.h:148
WW3DFormat
Definition ww3dformat.h:75
@ WW3D_FORMAT_R5G6B5
Definition ww3dformat.h:80
@ WW3D_FORMAT_X8L8V8U8
Definition ww3dformat.h:95
@ WW3D_FORMAT_DXT3
Definition ww3dformat.h:98
@ WW3D_FORMAT_R3G3B2
Definition ww3dformat.h:84
@ WW3D_FORMAT_L8
Definition ww3dformat.h:90
@ WW3D_FORMAT_DXT2
Definition ww3dformat.h:97
@ WW3D_FORMAT_X4R4G4B4
Definition ww3dformat.h:87
@ WW3D_FORMAT_A4L4
Definition ww3dformat.h:92
@ WW3D_FORMAT_P8
Definition ww3dformat.h:89
@ WW3D_FORMAT_X8R8G8B8
Definition ww3dformat.h:79
@ WW3D_FORMAT_A8
Definition ww3dformat.h:85
@ WW3D_FORMAT_DXT5
Definition ww3dformat.h:100
@ WW3D_FORMAT_UNKNOWN
Definition ww3dformat.h:76
@ WW3D_FORMAT_L6V5U5
Definition ww3dformat.h:94
@ WW3D_FORMAT_DXT4
Definition ww3dformat.h:99
@ WW3D_FORMAT_A8R3G3B2
Definition ww3dformat.h:86
@ WW3D_FORMAT_A8P8
Definition ww3dformat.h:88
@ WW3D_FORMAT_R8G8B8
Definition ww3dformat.h:77
@ WW3D_FORMAT_DXT1
Definition ww3dformat.h:96
@ WW3D_FORMAT_A4R4G4B4
Definition ww3dformat.h:83
@ WW3D_FORMAT_A8R8G8B8
Definition ww3dformat.h:78
@ WW3D_FORMAT_A1R5G5B5
Definition ww3dformat.h:82
@ WW3D_FORMAT_X1R5G5B5
Definition ww3dformat.h:81
@ WW3D_FORMAT_U8V8
Definition ww3dformat.h:93
@ WW3D_FORMAT_A8L8
Definition ww3dformat.h:91