Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
xsurface.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 : Command & Conquer *
24 * *
25 * $Archive:: /VSS_Sync/wwlib/xsurface.cpp $*
26 * *
27 * $Author:: Vss_sync $*
28 * *
29 * $Modtime:: 10/16/00 11:42a $*
30 * *
31 * $Revision:: 3 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * Blit_Clip -- Perform rectangle clipping in preparation for a blit. *
36 * XSurface::Blit_From -- Blit entire surface. *
37 * XSurface::Blit_From -- Blit from one surface to this one w/ clipping. *
38 * XSurface::Blit_From -- Blit one region to another. *
39 * XSurface::Blit_Plain -- Blit a plain rectangle from one surface to another. *
40 * XSurface::Blit_Trans -- Blit a rectangle with transparency checking. *
41 * XSurface::Draw_Line -- Draw a line and perform clipping. *
42 * XSurface::Draw_Line -- Draws a line upon the surface. *
43 * XSurface::Draw_Rect -- Draw a rectangle with an arbitrary clipping rectangle. *
44 * XSurface::Draw_Rect -- Draws a rectangle on the surface. *
45 * XSurface::Fill -- Fill the entire surface with the color specified. *
46 * XSurface::Fill_Rect -- Fill a rectangle but perform clipping on the fill. *
47 * XSurface::Fill_Rect -- Fills a rectangle with the color specified. *
48 * XSurface::Get_Pixel -- Fetches a pixel from the surface. *
49 * XSurface::Prep_For_Blit -- Clips and prepares pointers for a blit operation. *
50 * XSurface::Put_Pixel -- Stores a pixel at the location specified. *
51 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
52
53#include "always.h"
54#include "blit.h"
55#include "blitblit.h"
56#include "bsurface.h"
57#include "swap.h"
58#include "xsurface.h"
59//#include <stdlib.h>
60#include <string.h>
61
62
63/***********************************************************************************************
64 * XSurface::Draw_Line -- Draws a line upon the surface. *
65 * *
66 * This routine will draw a line on the surface between the points specified. *
67 * *
68 * INPUT: startpoint -- Pixel coordinate of one end point to the line. *
69 * *
70 * endpoint -- Pixel coordinate of the other end point to the line. *
71 * *
72 * color -- The color to draw the line with. *
73 * *
74 * OUTPUT: bool; Was the line drawn without error? *
75 * *
76 * WARNINGS: This routine is currently very brain-dead. It only draws vertical or *
77 * horizontal lines. It needs to be updated to handle any angle lines and should *
78 * perform line-clipping rather than point-pushing if the line intersects the *
79 * clipping rectangle. *
80 * *
81 * HISTORY: *
82 * 02/07/1997 JLB : Created. *
83 *=============================================================================================*/
84bool XSurface::Draw_Line(Point2D const & startpoint, Point2D const & endpoint, int color)
85{
86 return(XSurface::Draw_Line(Get_Rect(), startpoint, endpoint, color));
87}
88
89
90/***********************************************************************************************
91 * XSurface::Draw_Line -- Draw a line and perform clipping. *
92 * *
93 * Use this routine to draw a line on the surface but also clip the line draw against *
94 * an arbitrary sub-rectangle within the surface. *
95 * *
96 * INPUT: cliprect -- The clipping rectangle for this line draw. *
97 * *
98 * startpoint -- The starting point of the line draw. This point is relative to the *
99 * clipping rectangle. *
100 * *
101 * endpoint -- The ending point fo the line draw. This point is also relative to *
102 * the clipping rectangle. *
103 * *
104 * color -- The screen format color value to store for each pixel of the line. *
105 * *
106 * OUTPUT: bool; Was the line drawn? A 'false' return value would indicate that the line *
107 * was clipped away. *
108 * *
109 * WARNINGS: none *
110 * *
111 * HISTORY: *
112 * 05/27/1997 JLB : Created. *
113 *=============================================================================================*/
114bool XSurface::Draw_Line(Rect const & xcliprect, Point2D const & startpoint, Point2D const & endpoint, int color)
115{
116 /*
117 ** Ensure that the clipping rectangle is legal.
118 */
119 Rect cliprect = xcliprect.Intersect(Get_Rect());
120
121 /*
122 ** High-speed working variables for the clipping rectangle and clipping operation.
123 */
124 Point2D start = startpoint.Bias_To(cliprect);
125 Point2D end = endpoint.Bias_To(cliprect);
126
127 /*
128 ** Build bits that indicate which end points lie outside the clipping rectangle.
129 ** Quick checks against these flag bits will speed the clipping process.
130 */
131 enum {
132 OFF_TOP=0x01,
133 OFF_BOTTOM=0x02,
134 OFF_RIGHT=0x04,
135 OFF_LEFT=0x08
136 };
137 int sflag = 0;
138 int dflag = 0;
139
140 if (start.X < cliprect.X) sflag |= OFF_LEFT;
141 if (start.Y < cliprect.Y) sflag |= OFF_TOP;
142 if (start.X >= cliprect.X+cliprect.Width) sflag |= OFF_RIGHT;
143 if (start.Y >= cliprect.Y+cliprect.Height) sflag |= OFF_BOTTOM;
144 if (end.X < cliprect.X) dflag |= OFF_LEFT;
145 if (end.Y < cliprect.Y) dflag |= OFF_TOP;
146 if (end.X >= cliprect.X+cliprect.Width) dflag |= OFF_RIGHT;
147 if (end.Y >= cliprect.Y+cliprect.Height) dflag |= OFF_BOTTOM;
148
149 /*
150 ** Check to see if the line segment falls outside of the viewing rectangle.
151 */
152 if ((sflag & dflag) != 0) return(false);
153
154 /*
155 ** Clip the start point if necessary. This clipping should really check for
156 ** line intersect rather than pushing the end-point within bounds.
157 */
158 if (sflag != 0) {
159 if (sflag & OFF_LEFT) start.X = cliprect.X;
160 if (sflag & OFF_RIGHT) start.X = cliprect.X+cliprect.Width-1;
161 if (sflag & OFF_TOP) start.Y = cliprect.Y;
162 if (sflag & OFF_BOTTOM) start.Y = cliprect.Y+cliprect.Height-1;
163 }
164 if (dflag != 0) {
165 if (dflag & OFF_LEFT) end.X = cliprect.X;
166 if (dflag & OFF_RIGHT) end.X = cliprect.X+cliprect.Width-1;
167 if (dflag & OFF_TOP) end.Y = cliprect.Y;
168 if (dflag & OFF_BOTTOM) end.Y = cliprect.Y+cliprect.Height-1;
169 }
170
171 /*
172 ** Force the line segment to be either vertical or horizontal. This is because
173 ** we are not using brezenham's alogorithm (which we should be using instead here).
174 */
175 if (start.X != end.X) start.Y = end.Y;
176
177 /*
178 ** Ensure that the source point is always to the left and up
179 ** from the dest point.
180 */
181 if (start.X > end.X || start.Y > end.Y) {
182 swap(start, end);
183 swap(sflag, dflag);
184 }
185
186 int bbp = Bytes_Per_Pixel();
187 void * buffer = Lock(start);
188 if (buffer != NULL) {
189
190 if (start.Y == end.Y) {
191 if (bbp == 1) {
192 memset(buffer, color, (end.X-start.X)+1);
193 } else {
194 for (int x = 0; x <= end.X-start.X; x++) {
195 ((short *)buffer)[x] = (short)color;
196 }
197 }
198 } else {
199 for (int y = 0; y <= end.Y-start.Y; y++) {
200 if (bbp == 1) {
201 *(char*)buffer = (char)color;
202 } else {
203 *(short*)buffer = (short)color;
204 }
205 buffer = (void*)(((char*)buffer) + Stride());
206 }
207 }
208
209 Unlock();
210 return(true);
211 }
212 return(false);
213}
214
215
216/***********************************************************************************************
217 * XSurface::Draw_Rect -- Draws a rectangle on the surface. *
218 * *
219 * This routine will draw a line around the rectangle specified. The line will lie just *
220 * within the rectangle. *
221 * *
222 * INPUT: crect -- The rectangle dimensions to use. *
223 * *
224 * color -- The color to draw the rectangle. *
225 * *
226 * OUTPUT: none *
227 * *
228 * WARNINGS: none *
229 * *
230 * HISTORY: *
231 * 02/07/1997 JLB : Created. *
232 *=============================================================================================*/
233bool XSurface::Draw_Rect(Rect const & crect, int color)
234{
235 return(XSurface::Draw_Rect(Get_Rect(), crect, color));
236}
237
238
239/***********************************************************************************************
240 * XSurface::Draw_Rect -- Draw a rectangle with an arbitrary clipping rectangle. *
241 * *
242 * This routine will draw the rectangle but will also clip the draw against the clipping *
243 * rectangle provided. *
244 * *
245 * INPUT: cliprect -- The clipping rectangle to clip the draw against. *
246 * *
247 * rect -- The rectangle to draw. The coordinates are relative to the clipping *
248 * rectangle. *
249 * *
250 * color -- The color ot use for this rectangle draw. *
251 * *
252 * OUTPUT: none *
253 * *
254 * WARNINGS: none *
255 * *
256 * HISTORY: *
257 * 05/27/1997 JLB : Created. *
258 *=============================================================================================*/
259bool XSurface::Draw_Rect(Rect const & cliprect, Rect const & crect, int color)
260{
261 Point2D ul(crect.X, crect.Y);
262 Point2D ur(crect.X+crect.Width-1, crect.Y);
263 Point2D ll(crect.X, crect.Y+crect.Height-1);
264 Point2D lr(crect.X+crect.Width-1, crect.Y+crect.Height-1);
265
266 Draw_Line(cliprect, ul, ur, color);
267 Draw_Line(cliprect, ul, ll, color);
268 Draw_Line(cliprect, ur, lr, color);
269 Draw_Line(cliprect, ll, lr, color);
270 return(true);
271}
272
273
274/***********************************************************************************************
275 * XSurface::Get_Pixel -- Fetches a pixel from the surface. *
276 * *
277 * This routine will fetch a pixel element from the surface at the location specified. *
278 * *
279 * INPUT: point -- Coordinate to fetch the pixel from. *
280 * *
281 * OUTPUT: Returns with the pixel value at that coordinate. The interpretation of the return *
282 * value depends on the pixel format of the surface. *
283 * *
284 * WARNINGS: none *
285 * *
286 * HISTORY: *
287 * 02/07/1997 JLB : Created. *
288 *=============================================================================================*/
289int XSurface::Get_Pixel(Point2D const & point) const
290{
291 int color = 0;
292 void * pointer = ((Surface*)this)->Lock(point);
293 if (pointer != NULL) {
294 if (Bytes_Per_Pixel() == 2) {
295 color = *((unsigned short*)pointer);
296 } else {
297 color = *((unsigned char*)pointer);
298 }
299 ((Surface*)this)->Unlock();
300 }
301 return(color);
302}
303
304
305/***********************************************************************************************
306 * XSurface::Put_Pixel -- Stores a pixel at the location specified. *
307 * *
308 * This routine will store a pixel at the coordinate specified on the surface. *
309 * *
310 * INPUT: point -- The coordinate to place the pixel at. *
311 * *
312 * color -- The pixel data to store. *
313 * *
314 * OUTPUT: bool; Was the pixel stored? *
315 * *
316 * WARNINGS: The color value specified is the raw pixel value that will be stored. The *
317 * format of this value is dependant upon the pixel format of the surface. *
318 * *
319 * HISTORY: *
320 * 02/07/1997 JLB : Created. *
321 *=============================================================================================*/
322bool XSurface::Put_Pixel(Point2D const & point, int color)
323{
324 void * pointer = Lock(point);
325 if (pointer != NULL) {
326 if (Bytes_Per_Pixel() == 2) {
327 *((unsigned short*)pointer) = (unsigned short)color;
328 } else {
329 *((unsigned char*)pointer) = (unsigned char)color;
330 }
331 Unlock();
332 return(true);
333 }
334 return(false);
335}
336
337
338/***********************************************************************************************
339 * XSurface::Fill_Rect -- Fills a rectangle with the color specified. *
340 * *
341 * This routine will fill the rectangle with a specified color. The rectangle filled will *
342 * be clipped appropriately. *
343 * *
344 * INPUT: fillrect -- The rectangle to fill. *
345 * *
346 * color -- The color to use when filling the rectangle. *
347 * *
348 * OUTPUT: bool; Was the rectangle filled without error? *
349 * *
350 * WARNINGS: none *
351 * *
352 * HISTORY: *
353 * 02/07/1997 JLB : Created. *
354 *=============================================================================================*/
355bool XSurface::Fill_Rect(Rect const & fillrect, int color)
356{
357 return(XSurface::Fill_Rect(fillrect, Get_Rect(), color));
358}
359
360
361/***********************************************************************************************
362 * XSurface::Fill_Rect -- Fill a rectangle but perform clipping on the fill. *
363 * *
364 * This will fill a rectangle of the specified dimensions. The fill request will be *
365 * clipped against the clipping rectangle provided. *
366 * *
367 * INPUT: cliprect -- The clipping rectangle to use for this fill. *
368 * *
369 * fillrect -- The rectangle to fill with the specified color. The rectangle is *
370 * relative to the clipping rectangle coordinates. *
371 * *
372 * color -- The screen format pixel value to draw with. *
373 * *
374 * OUTPUT: bool; Was the fill request carried out? A 'false' return value would indicate *
375 * that the fill was clipped away. *
376 * *
377 * WARNINGS: none *
378 * *
379 * HISTORY: *
380 * 05/27/1997 JLB : Created. *
381 *=============================================================================================*/
382bool XSurface::Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color)
383{
384 if (!fillrect.Is_Valid()) return(false);
385
386 /*
387 ** Ensure that the requested clipping rectangle is actually legal.
388 */
389 Rect wrect = cliprect.Intersect(Get_Rect());
390
391 /*
392 ** Clip the rectangle to be filled against the clipping rectangle supplied.
393 */
394 Rect crect = wrect.Intersect(fillrect.Bias_To(cliprect));
395 if (!crect.Is_Valid()) return(false);
396
397 void * buffer = Lock(crect.Top_Left());
398 if (buffer != NULL) {
399 if (Bytes_Per_Pixel() == 1) {
400 for (int y = 0; y < crect.Height; y++) {
401 memset(buffer, color, crect.Width);
402 buffer = ((char *)buffer) + Stride();
403 }
404 } else {
405 for (int y = 0; y < crect.Height; y++) {
406 for (int x = 0; x < crect.Width; x++) {
407 ((unsigned short*)buffer)[x] = (unsigned short)color;
408 }
409 buffer = ((char *)buffer) + Stride();
410 }
411 }
412 Unlock();
413 return(true);
414 }
415 return(false);
416}
417
418
419/***********************************************************************************************
420 * XSurface::Fill -- Fill the entire surface with the color specified. *
421 * *
422 * The color specified will be filled into the entire surface area (but limited by the *
423 * surface's current window). *
424 * *
425 * INPUT: color -- The pixel value to use when filling the surface. *
426 * *
427 * OUTPUT: bool; Was the surface fill performed without error? *
428 * *
429 * WARNINGS: none *
430 * *
431 * HISTORY: *
432 * 02/07/1997 JLB : Created. *
433 *=============================================================================================*/
434bool XSurface::Fill(int color)
435{
436 return(Fill_Rect(Get_Rect(), Get_Rect(), color));
437}
438
439
440/***********************************************************************************************
441 * XSurface::Blit_From -- Blit entire surface. *
442 * *
443 * This routine will blit the entire surface. *
444 * *
445 * INPUT: source -- Pointer to the source surface to blit from. *
446 * *
447 * trans -- Perform a transparency aware blit? *
448 * *
449 * OUTPUT: bool; Was the surface blit performed without error? *
450 * *
451 * WARNINGS: none *
452 * *
453 * HISTORY: *
454 * 02/07/1997 JLB : Created. *
455 *=============================================================================================*/
456bool XSurface::Blit_From(Surface const & source, bool trans)
457{
458 Rect drect = Get_Rect();
459 drect.X = 0;
460 drect.Y = 0;
461
462 Rect srect = source.Get_Rect();
463 srect.X = 0;
464 srect.Y = 0;
465 bool result = Blit_From(drect, source, srect, trans);
466
467 return(result);
468}
469
470
471/***********************************************************************************************
472 * XSurface::Blit_From -- Blit one region to another. *
473 * *
474 * Use this routine to copy one rectangle of pixel data to another. The pixels being *
475 * copied may be processed according to the parameters specified. *
476 * *
477 * INPUT: destrect -- The destination rectangle to bit to. *
478 * *
479 * source -- Pointer to the source surface to blit from. *
480 * *
481 * sourcerect -- The source rectangle to blit from. *
482 * *
483 * trans -- Should transparent pixels be scanned for an skipped? *
484 * *
485 * OUTPUT: bool; Was the blit operation performed without error? *
486 * *
487 * WARNINGS: none *
488 * *
489 * HISTORY: *
490 * 02/07/1997 JLB : Created. *
491 *=============================================================================================*/
492bool XSurface::Blit_From(Rect const & destrect, Surface const & source, Rect const & sourcerect, bool trans)
493{
494 return(XSurface::Blit_From(Get_Rect(), destrect, source, source.Get_Rect(), sourcerect, trans));
495}
496
497
498/***********************************************************************************************
499 * XSurface::Blit_From -- Blit from one surface to this one w/ clipping. *
500 * *
501 * This routine will blit a clipped rectangle from the specified surface to this one. *
502 * *
503 * INPUT: dcliprect -- The clipping rectangle to use for this (destination) surface. *
504 * *
505 * destrect -- The destanation rect of the blit. Coordinates are relative to the *
506 * destination clipping rectangle. *
507 * *
508 * source -- The source surface to blit from. *
509 * *
510 * scliprect -- The source clipping rectangle for the blit. *
511 * *
512 * sourcrect -- The source rectangle of the blit. The coordinates are relative to *
513 * the source clipping rectangle. *
514 * *
515 * trans -- Is this a transparent pixel aware blit request? *
516 * *
517 * OUTPUT: bool; Was a blit performed? A 'false' value would mean that the blit was clipped *
518 * away. *
519 * *
520 * WARNINGS: none *
521 * *
522 * HISTORY: *
523 * 05/27/1997 JLB : Created. *
524 *=============================================================================================*/
525bool XSurface::Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & source, Rect const & scliprect, Rect const & sourcerect, bool trans)
526{
527 Rect drect = destrect;
528 Rect srect = sourcerect;
529
530 /*
531 ** Perform any clipping against the clipping rectangles. Proceed with the blit only
532 ** if there are pixels left unclipped.
533 */
534 if (Blit_Clip(drect, dcliprect, srect, scliprect)) {
535
536 if (trans) {
537 return(Blit_Trans(*this, drect, source, srect));
538 }
539 return(Blit_Plain(*this, drect, source, srect));
540 }
541 return(false);
542}
543
544
545/***********************************************************************************************
546 * Blit_Clip -- Perform rectangle clipping in preparation for a blit. *
547 * *
548 * This routine will take a source rectangle and a source clipping window and intersect *
549 * these with a dest rectangle and a dest clipping window. The effect will be to alter *
550 * the source and dest rectangles so that they will stay within the clipping rectangles *
551 * imposed upon the source and destination surfaces. The process clips the rectangles *
552 * rather than displacing them when performing its adjustment. It is possible that one *
553 * or both rectangles are clipped into oblivion by this routine. This condition will be *
554 * flagged with the return value. *
555 * *
556 * INPUT: drect -- Reference to the destination rectangle (relative coordinates to the *
557 * destination window). This is both an input and output parameter. *
558 * *
559 * dwindow -- The destination window to clip the dest rect against. *
560 * *
561 * srect -- Reference to the source rectangle (relative to the source window). *
562 * This is both an input and output parameter. *
563 * *
564 * swindow -- The source window to clip the srect against. *
565 * *
566 * OUTPUT: bool; Was the clip performed and the srect and drect parameters still valid. *
567 * i.e., they represent at least one pixel that has not been clipped away. *
568 * *
569 * WARNINGS: The rectangles may be clipped into nothingness by this routine. Be sure to *
570 * check the return value for this condition and perform no blit operation in *
571 * that case. *
572 * *
573 * HISTORY: *
574 * 05/19/1997 JLB : Created. *
575 *=============================================================================================*/
576bool Blit_Clip(Rect & drect, Rect const & dwindow, Rect & srect, Rect const & swindow)
577{
578 /*
579 ** If the rectangles are of the same dimensions, then a coordinated clipping process is
580 ** possible. This results in an intelligent blit even if the source or destination
581 ** rectangles is partially outside the clipping rectangle.
582 */
583 if (drect.Width == srect.Width && drect.Height == srect.Height) {
584 /*
585 ** Clip the left and top edges against the clipping window.
586 */
587 if (drect.X < 0) {
588 srect.X += -drect.X;
589 srect.Width -= -drect.X;
590 drect.Width -= -drect.X;
591 drect.X = 0;
592 }
593 if (drect.Y < 0) {
594 srect.Y += -drect.Y;
595 srect.Height -= -drect.Y;
596 drect.Height -= -drect.Y;
597 drect.Y = 0;
598 }
599
600 /*
601 ** Clip the right and bottom edges if they spill past the
602 ** clipping window boundaries.
603 */
604 int rightspill = (drect.X+drect.Width) - dwindow.Width;
605 if (rightspill > 0) {
606 srect.Width -= rightspill;
607 drect.Width -= rightspill;
608 }
609 int bottomspill = (drect.Y+drect.Height) - dwindow.Height;
610 if (bottomspill > 0) {
611 srect.Height -= bottomspill;
612 drect.Height -= bottomspill;
613 }
614
615 /*
616 ** Clip the left and top edges against the clipping
617 ** window.
618 */
619 if (srect.X < 0) {
620 drect.X += -srect.X;
621 srect.Width -= -srect.X;
622 drect.Width -= -srect.X;
623 srect.X = 0;
624 }
625 if (srect.Y < 0) {
626 drect.Y += -srect.Y;
627 srect.Height -= -srect.Y;
628 drect.Height -= -srect.Y;
629 srect.Y = 0;
630 }
631
632 /*
633 ** Clip the right and bottom edges agaist the clipping window.
634 */
635 rightspill = (srect.X+srect.Width) - swindow.Width;
636 if (rightspill > 0) {
637 srect.Width -= rightspill;
638 drect.Width -= rightspill;
639 }
640 bottomspill = (srect.Y+srect.Height) - swindow.Height;
641 if (bottomspill > 0) {
642 srect.Height -= bottomspill;
643 drect.Height -= bottomspill;
644 }
645
646 } else {
647
648 /*
649 ** Since the rectangles are not of the same dimensions, scaling is presumed. Clipping
650 ** in such a case is merely a legality clip against the bounding rectangle. No coordinated
651 ** adjustments can occur. For best results, boundary clipping should be performed prior to
652 ** calling this routine.
653 */
654 drect = drect.Intersect(dwindow);
655 srect = srect.Intersect(swindow);
656 }
657
658 return(drect.Is_Valid() && srect.Is_Valid());
659}
660
661
662/***********************************************************************************************
663 * XSurface::Prep_For_Blit -- Clips and prepares pointers for a blit operation. *
664 * *
665 * This performs the clipping operation required before a blit occurs. It examines the *
666 * source and destination coordinate constraints and performs clipping such that only *
667 * legal pixels will be blitted. As a consequence it can determine if the blit has been *
668 * completely clipped and thus can be skipped. *
669 * *
670 * INPUT: dest -- The destination surface rect for the blit. *
671 * *
672 * drect -- The rectangle within the destination surface rect for the blit. This *
673 * rectangle reference will be adjusted as necessary. *
674 * *
675 * source -- The source surface rect of the blit. *
676 * *
677 * srect -- The source rectangle within the source surface rect for the blit. *
678 * This rectangle reference will be adjusted as necessary. *
679 * *
680 * overlapped -- Output reference that stores the boolean answer to the question -- *
681 * are the blit rectangles overlapping on the same surface? *
682 * *
683 * dbuffer -- Output reference that stores a pointer to the locked destination *
684 * surface. It points to the upper left destination corner pixel. *
685 * *
686 * sbuffer -- Output reference that stores a pointer to the locked source surface. *
687 * It points to the upper left corner source pixel. *
688 * *
689 * OUTPUT: bool; Can the blit proceed since there is at least one pixel that has not been *
690 * clipped away? It can also fail if a lock could not be performed on the *
691 * source or destination surfaces. *
692 * *
693 * WARNINGS: The surfaces locked by this routine must be unlocked. If the return value is *
694 * 'true', then the surfaces must be unlocked. *
695 * *
696 * HISTORY: *
697 * 05/19/1997 JLB : Created. *
698 *=============================================================================================*/
699bool XSurface::Prep_For_Blit(Surface & dest, Rect & drect, Surface const & source, Rect & srect, bool & overlapped, void * & dbuffer, void * & sbuffer)
700{
701 return(XSurface::Prep_For_Blit(dest, dest.Get_Rect(), drect, source, source.Get_Rect(), srect, overlapped, dbuffer, sbuffer));
702#ifdef NEVER
703 overlapped = false;
704 dbuffer = NULL;
705 sbuffer = NULL;
706
707 if (!drect.Is_Valid() || !srect.Is_Valid()) return(false);
708
709 /*
710 ** Perform the clipping of the desired blit rectangles against the surface clipping
711 ** rectangles. If it happens that the blit is clipped into oblivion, then bail
712 ** immediately -- there is nothing left to do.
713 */
714 Rect swindow = source.Get_Rect();
715 Rect dwindow = dest.Get_Rect();
716 if (!Blit_Clip(drect, dwindow, srect, swindow)) {
717 return(false);
718 }
719
720 /*
721 ** Determine if the rectangles overlap such that a forward blit would
722 ** be prohibited. This only occurs if the source and destination refer to the
723 ** same surface and the rectangles overlap.
724 */
725 overlapped = false;
726 if (&source == &dest && srect.Is_Overlapping(drect)) {
727 if (srect.Y < drect.Y || (srect.Y == drect.Y && srect.X < drect.X)) {
728 overlapped = true;
729 }
730 }
731
732 /*
733 ** Fetch pointers to the source and dest upper left pixel. That is, the upper
734 ** left pixel of the source and dest sub-rectangles within each surface
735 ** respectively.
736 */
737 dbuffer = dest.Lock(drect.Point());
738 if (dbuffer == NULL) return(false);
739 sbuffer = ((Surface &)source).Lock(srect.Point());
740 if (sbuffer == NULL) {
741 dest.Unlock();
742 return(false);
743 }
744
745 return(true);
746#endif
747}
748
749
750/***********************************************************************************************
751 * XSurface::Prep_For_Blit -- Clips and prepares pointers for a blit operation. *
752 * *
753 * This performs the clipping operation required before a blit occurs. It examines the *
754 * source and destination coordinate constraints and performs clipping such that only *
755 * legal pixels will be blitted. As a consequence it can determine if the blit has been *
756 * completely clipped and thus can be skipped. *
757 * *
758 * INPUT: dest -- The destination surface rect for the blit. *
759 * *
760 * dcliprect-- The destination clipping rectangle. *
761 * *
762 * drect -- The rectangle within the destination surface rect for the blit. This *
763 * rectangle reference will be adjusted as necessary. *
764 * *
765 * source -- The source surface rect of the blit. *
766 * *
767 * scliprect-- The source clipping rectangle. *
768 * *
769 * srect -- The source rectangle within the source surface rect for the blit. *
770 * This rectangle reference will be adjusted as necessary. *
771 * *
772 * overlapped -- Output reference that stores the boolean answer to the question -- *
773 * are the blit rectangles overlapping on the same surface? *
774 * *
775 * dbuffer -- Output reference that stores a pointer to the locked destination *
776 * surface. It points to the upper left destination corner pixel. *
777 * *
778 * sbuffer -- Output reference that stores a pointer to the locked source surface. *
779 * It points to the upper left corner source pixel. *
780 * *
781 * OUTPUT: bool; Can the blit proceed since there is at least one pixel that has not been *
782 * clipped away? It can also fail if a lock could not be performed on the *
783 * source or destination surfaces. *
784 * *
785 * WARNINGS: The surfaces locked by this routine must be unlocked. If the return value is *
786 * 'true', then the surfaces must be unlocked. *
787 * *
788 * HISTORY: *
789 * 05/19/1997 JLB : Created. *
790 *=============================================================================================*/
791bool XSurface::Prep_For_Blit(Surface & dest, Rect const & dcliprect, Rect & drect, Surface const & source, Rect const & scliprect, Rect & srect, bool & overlapped, void * & dbuffer, void * & sbuffer)
792{
793 overlapped = false;
794 dbuffer = NULL;
795 sbuffer = NULL;
796
797 if (!drect.Is_Valid() || !dcliprect.Is_Valid() || !srect.Is_Valid() || !scliprect.Is_Valid()) return(false);
798
799 /*
800 ** Perform the clipping of the desired blit rectangles against the surface clipping
801 ** rectangles. If it happens that the blit is clipped into oblivion, then bail
802 ** immediately -- there is nothing left to do.
803 */
804 if (!Blit_Clip(drect, dcliprect, srect, scliprect)) {
805 return(false);
806 }
807
808 /*
809 ** Determine if the rectangles overlap such that a forward blit would
810 ** be prohibited. This only occurs if the source and destination refer to the
811 ** same surface and the rectangles overlap.
812 */
813 overlapped = false;
814 if (&source == &dest && srect.Is_Overlapping(drect)) {
815 if (srect.Y < drect.Y || (srect.Y == drect.Y && srect.X < drect.X)) {
816 overlapped = true;
817 }
818 }
819
820 /*
821 ** Fetch pointers to the source and dest upper left pixel. That is, the upper
822 ** left pixel of the source and dest sub-rectangles within each surface
823 ** respectively.
824 */
825 dbuffer = dest.Lock(dcliprect.Top_Left() + drect.Top_Left());
826 if (dbuffer == NULL) return(false);
827 sbuffer = source.Lock(scliprect.Top_Left() + srect.Top_Left());
828 if (sbuffer == NULL) {
829 dest.Unlock();
830 return(false);
831 }
832
833 return(true);
834}
835
836
837/***********************************************************************************************
838 * XSurface::Blit_Plain -- Blit a plain rectangle from one surface to another. *
839 * *
840 * This routine will perform a simple blit of a rectangle from one surface to another. *
841 * *
842 * INPUT: dest -- The destination surface for the blit. *
843 * *
844 * destrect -- The destination rectangle for the blit. *
845 * *
846 * source -- The source surface. *
847 * *
848 * sourcerect -- The rectangle in the source surface to blit from. *
849 * *
850 * OUTPUT: bool; Was the blit performed? *
851 * *
852 * WARNINGS: none *
853 * *
854 * HISTORY: *
855 * 05/19/1997 JLB : Created. *
856 *=============================================================================================*/
857bool XSurface::Blit_Plain(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect)
858{
859 if (dest.Bytes_Per_Pixel() == 1) {
860 return(Bit_Blit(dest, destrect, source, sourcerect, BlitPlain<unsigned char>()));
861 }
862 return(Bit_Blit(dest, destrect, source, sourcerect, BlitPlain<unsigned short>()));
863}
864
865
866/***********************************************************************************************
867 * XSurface::Blit_Trans -- Blit a rectangle with transparency checking. *
868 * *
869 * This routine will perform a simple blit of one rectangle to another on the surfaces *
870 * specified. *
871 * *
872 * INPUT: dest -- The destination surface. *
873 * *
874 * destrect -- The destination rectangle within the surface. *
875 * *
876 * source -- The source surface. *
877 * *
878 * sourcerect -- The source rectangle. *
879 * *
880 * OUTPUT: bool; Was the blit performed? *
881 * *
882 * WARNINGS: none *
883 * *
884 * HISTORY: *
885 * 05/19/1997 JLB : Created. *
886 *=============================================================================================*/
887bool XSurface::Blit_Trans(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect)
888{
889 switch (dest.Bytes_Per_Pixel())
890 {
891 case 1:
892 return(Bit_Blit(dest, destrect, source, sourcerect, BlitTrans<unsigned char>()));
893 case 2:
894 return(Bit_Blit(dest, destrect, source, sourcerect, BlitTrans<unsigned short>()));
895 case 4:
896 return(Bit_Blit(dest, destrect, source, sourcerect, BlitTrans<unsigned int>()));
897 default:
898 return(false);
899 }
900}
901
902
903
#define NULL
Definition BaseType.h:92
bool Bit_Blit(Surface &dest, Rect const &destrect, Surface const &source, Rect const &sourcerect, Blitter const &blitter)
Definition blit.cpp:167
virtual Rect Get_Rect(void) const
Definition Surface.h:102
virtual bool Unlock(void) const =0
virtual void * Lock(Point2D point=Point2D(0, 0)) const =0
virtual int Bytes_Per_Pixel(void) const =0
Surface(int width, int height)
Definition Surface.h:55
TPoint2D< T > const Bias_To(TRect< T > const &rect) const
Definition trect.h:211
TRect< T > const Bias_To(TRect< T > const &rect) const
Definition trect.h:72
bool Is_Valid(void) const
Definition trect.h:82
bool Is_Overlapping(TRect< T > const &rect) const
Definition trect.h:77
T Width
Definition trect.h:115
TPoint2D< T > Top_Left(void) const
Definition trect.h:93
T Y
Definition trect.h:109
T Height
Definition trect.h:116
TRect< T > const Intersect(TRect< T > const &rectangle, T *x=NULL, T *y=NULL) const
Definition trect.h:121
T X
Definition trect.h:108
virtual bool Draw_Rect(Rect const &rect, int color)
Definition xsurface.cpp:233
virtual bool Draw_Line(Point2D const &startpoint, Point2D const &endpoint, int color)
Definition xsurface.cpp:84
virtual int Bytes_Per_Pixel(void) const =0
static bool Blit_Plain(Surface &dest, Rect const &destrect, Surface const &source, Rect const &sourcerect)
Definition xsurface.cpp:857
virtual int Stride(void) const =0
virtual bool Unlock(void) const
Definition xsurface.h:93
virtual bool Blit_From(Rect const &dcliprect, Rect const &destrect, Surface const &source, Rect const &scliprect, Rect const &sourcerect, bool trans=false)
Definition xsurface.cpp:525
virtual void * Lock(Point2D=Point2D(0, 0)) const
Definition xsurface.h:92
virtual int Get_Pixel(Point2D const &point) const
Definition xsurface.cpp:289
static bool Blit_Trans(Surface &dest, Rect const &destrect, Surface const &source, Rect const &sourcerect)
Definition xsurface.cpp:887
virtual bool Put_Pixel(Point2D const &point, int color)
Definition xsurface.cpp:322
virtual bool Fill(int color)
Definition xsurface.cpp:434
static bool Prep_For_Blit(Surface &dest, Rect &drect, Surface const &source, Rect &srect, bool &overlapped, void *&dbuffer, void *&sbuffer)
Definition xsurface.cpp:699
virtual bool Fill_Rect(Rect const &rect, int color)
Definition xsurface.cpp:355
void swap(T &a, T &b)
TRect< int > Rect
Definition trect.h:221
bool Blit_Clip(Rect &drect, Rect const &dwindow, Rect &srect, Rect const &swindow)
Definition xsurface.cpp:576
bool Blit_Clip(Rect &drect, Rect const &dwindow, Rect &srect, Rect const &swindow)
Definition xsurface.cpp:576