Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
blit.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:: /G/wwlib/blit.cpp $*
26 * *
27 * $Author:: Eric_c $*
28 * *
29 * $Modtime:: 4/15/99 10:13a $*
30 * *
31 * $Revision:: 3 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * Bit_Blit -- Blit a block of pixels to the destination surface. *
36 * Bit_Blit -- Blits data to a surface w/ clipping. *
37 * Buffer_Size -- Determines size of buffer for given dimensions. *
38 * From_Buffer -- Copy graphic data from a buffer to a surface. *
39 * RLE_Blit -- Blits RLE compressed data without extra clipping. *
40 * RLE_Blit -- Blits a rectangle of RLE compressed data to a surface. *
41 * To_Buffer -- Copies a graphic region into a linear RAM buffer. *
42 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43
44#include "always.h"
45#include "blit.h"
46#include "bsurface.h"
47//#include "rle.h"
48#include "xsurface.h"
49//#include <stdlib.h>
50
51
52/***********************************************************************************************
53 * Buffer_Size -- Determines size of buffer for given dimensions. *
54 * *
55 * This routine will determine the byte size of a buffer if it were to hold the pixels *
56 * of the dimensions specified. It takes into account the bytes per pixel. *
57 * *
58 * INPUT: surface -- The surface to base the buffer size calculation upon. *
59 * *
60 * width -- Pixel width of a graphic region. *
61 * *
62 * height -- Pixel height of a graphic region. *
63 * *
64 * OUTPUT: Returns with the number of bytes such a region would consume if it were linearly *
65 * packed into a memory buffer. *
66 * *
67 * WARNINGS: none *
68 * *
69 * HISTORY: *
70 * 02/07/1997 JLB : Created. *
71 *=============================================================================================*/
72int Buffer_Size(Surface const & surface, int width, int height)
73{
74 return(width * height * surface.Bytes_Per_Pixel());
75}
76
77
78/***********************************************************************************************
79 * To_Buffer -- Copies a graphic region into a linear RAM buffer. *
80 * *
81 * This routine will copy the graphic rectangle specified, into a RAM buffer. The size of *
82 * the RAM buffer must be big enough to hold the pixel data. Use the Buffer_Size() function *
83 * to determine how big it must be. *
84 * *
85 * INPUT: surface -- The surface to copy the pixel data from. *
86 * *
87 * rect -- The graphic rectangle to copy from. *
88 * *
89 * buffer -- Reference to the buffer that will be filled with the pixel data. *
90 * *
91 * OUTPUT: bool; Was the data copy performed without error? *
92 * *
93 * WARNINGS: none *
94 * *
95 * HISTORY: *
96 * 02/07/1997 JLB : Created. *
97 *=============================================================================================*/
98bool To_Buffer(Surface const & surface, Rect const & rect, Buffer & buffer)
99{
100 if (!rect.Is_Valid()) return(false);
101
102 BSurface from(rect.Width, rect.Height, surface.Bytes_Per_Pixel(), buffer);
103 return(from.Blit_From(Rect(0, 0, rect.Width, rect.Height), surface, rect));
104}
105
106
107/***********************************************************************************************
108 * From_Buffer -- Copy graphic data from a buffer to a surface. *
109 * *
110 * This routine will take pixel data and move it from the specified buffer and into the *
111 * surface rectangle specified. It is the counterpart routine of To_Buffer(). *
112 * *
113 * INPUT: surface -- The surface to store the pixel data to. *
114 * *
115 * rect -- The destination rectangle to store the pixel data to. *
116 * *
117 * buffer -- Reference to the buffer that contains the pixel data. *
118 * *
119 * OUTPUT: bool; Was the pixel data copy performed without error? *
120 * *
121 * WARNINGS: none *
122 * *
123 * HISTORY: *
124 * 02/07/1997 JLB : Created. *
125 *=============================================================================================*/
126bool From_Buffer(Surface & surface, Rect const & rect, Buffer const & buffer)
127{
128 if (!rect.Is_Valid()) return(false);
129
130 BSurface from(rect.Width, rect.Height, surface.Bytes_Per_Pixel(), buffer);
131 return(surface.Blit_From(rect, from, Rect(0, 0, rect.Width, rect.Height)));
132}
133
134
135
136/***********************************************************************************************
137 * Bit_Blit -- Blits data to a surface w/ clipping. *
138 * *
139 * This routine will take source pixel data and blit it to the surface specified while *
140 * also performing clipping on both the source and the destination data. Typical users of *
141 * this routine would be to draw shape (sprite) data. *
142 * *
143 * INPUT: dest -- Destintaion surface rect. This specifies the destination surface and *
144 * any coordinate clipping rectangle. *
145 * *
146 * destrect -- The destination rectangle of the blit. The coordinates are relative *
147 * to the destination clipping rectangle. *
148 * *
149 * source -- Source surface rect. This specifies the source surface as well as any *
150 * clipping rectangle it may contain. *
151 * *
152 * srcrect -- The rectange, relative to the source clipping rectangle, that *
153 * specifies the source blit data. It is presumed that the dimensions of *
154 * the source rectangle are the same as the destination rectangle. *
155 * *
156 * blitter -- The blitter to use for moving the source pixels to the destination *
157 * surface. *
158 * *
159 * OUTPUT: bool; Was the blit performed even if it was for only a single pixel. Failure would *
160 * indicate that the blit was completely clipped away. *
161 * *
162 * WARNINGS: none *
163 * *
164 * HISTORY: *
165 * 05/19/1997 JLB : Created. *
166 *=============================================================================================*/
167bool Bit_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, Blitter const & blitter)
168{
169 return(Bit_Blit(dest, dest.Get_Rect(), destrect, source, source.Get_Rect(), sourcerect, blitter));
170}
171
172
173/***********************************************************************************************
174 * Bit_Blit -- Blit a block of pixels to the destination surface. *
175 * *
176 * This routine will blit a block of pixels and perform clipping on the blit as controlled *
177 * by the clipping rectangles. *
178 * *
179 * INPUT: dest -- Surface to blit to. *
180 * *
181 * dcliprect-- The destination surface clipping rectangle. *
182 * *
183 * ddrect -- The destination rect of the blit. It is relative to the clipping *
184 * rectangle and will be clipped against same. *
185 * *
186 * source -- The source surface to blit from. *
187 * *
188 * scliprect-- The source surface clipping rectangle. *
189 * *
190 * ssrect -- The source rectangle of the blit. It is relative to the source *
191 * clipping rectangle and will be clipped against same. *
192 * *
193 * blitter -- The blitter to use for blitting of this rectangle. *
194 * *
195 * OUTPUT: bool; Was the blit performed? A 'false' return value would indicate that the *
196 * blit was clipped into nothing. *
197 * *
198 * WARNINGS: none *
199 * *
200 * HISTORY: *
201 * 05/27/1997 JLB : Created. *
202 *=============================================================================================*/
203bool Bit_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, Blitter const & blitter)
204{
205 Rect srect = ssrect;
206 Rect drect = ddrect;
207 bool overlapped = false;
208 void * dbuffer = NULL;
209 void * sbuffer = NULL;
210
211 /*
212 ** Prepare for the blit by performing any clipping as well as fetching pointers into the
213 ** pixel buffers. If there were any errors, then this blit cannot be performed.
214 */
215 if (!XSurface::Prep_For_Blit(dest, dcliprect, drect, source, scliprect, srect, overlapped, dbuffer, sbuffer)) {
216 return(false);
217 }
218
219 /*
220 ** If there is no difference between the width and the stride of the source and
221 ** destination surfaces, then the copy can be performed as one huge copy operation.
222 ** This is the simplist case and the one that is performed with a full screen
223 ** blit.
224 */
225 if (drect.Width * dest.Bytes_Per_Pixel() == dest.Stride() && dest.Stride() == source.Stride()) {
226
227 int length = MIN(srect.Height*srect.Width, drect.Height*drect.Width);
228 if (overlapped) {
229 blitter.BlitBackward(dbuffer, sbuffer, length);
230 } else {
231 blitter.BlitForward(dbuffer, sbuffer, length);
232 }
233
234 } else {
235
236 /*
237 ** If the rectangles overlap, then the copy must proceed from the
238 ** last row to the first rather than the normal direction.
239 */
240 int sstride = source.Stride();
241 int dstride = dest.Stride();
242 if (overlapped) {
243 sstride = -sstride;
244 dstride = -dstride;
245 sbuffer = ((char*)sbuffer) + (srect.Height-1) * source.Stride();
246 dbuffer = ((char*)dbuffer) + (drect.Height-1) * dest.Stride();
247 }
248
249 /*
250 ** This perform a line-by-line pixel copy.
251 */
252 int height = MIN(srect.Height, drect.Height);
253 if (overlapped) {
254 for (int y = 0; y < height; y++) {
255 blitter.BlitBackward(dbuffer, sbuffer, srect.Width);
256 dbuffer = (void*)(((char*)dbuffer) + dstride);
257 sbuffer = (void*)(((char*)sbuffer) + sstride);
258 }
259 } else {
260 for (int y = 0; y < height; y++) {
261 blitter.BlitForward(dbuffer, sbuffer, srect.Width);
262 dbuffer = (void*)(((char*)dbuffer) + dstride);
263 sbuffer = (void*)(((char*)sbuffer) + sstride);
264 }
265 }
266 }
267
268 dest.Unlock();
269 source.Unlock();
270
271 return(true);
272}
273
274
275/***********************************************************************************************
276 * RLE_Blit -- Blits RLE compressed data without extra clipping. *
277 * *
278 * This routine will blit a rectangle of RLE compressed data to the specified surface. It *
279 * is functionally similar to the other RLE blit routine, but does not use any sub *
280 * clipping rectangles. The blit is naturally clipped to the edge of the destination *
281 * surface. *
282 * *
283 * INPUT: dest -- Reference to the destination surface. *
284 * *
285 * destrect -- The destination rectangle to draw the pixels to. *
286 * *
287 * source -- Reference to the source RLE surface data. *
288 * *
289 * sourcerect -- The source rectangle of from the RLE surface to blit from. *
290 * *
291 * blitter -- Reference to the blitter to perform the blit operation with. *
292 * *
293 * OUTPUT: bool; Was a blit performed? A 'false' value would mean that the blit has been *
294 * clipped into nothing. *
295 * *
296 * WARNINGS: The dimensions of the source and destination rectangles should be the same *
297 * until such time that the blitter can support scaling (as of this writing, it *
298 * cannot). *
299 * *
300 * HISTORY: *
301 * 05/27/1997 JLB : Created. *
302 *=============================================================================================*/
303bool RLE_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, RLEBlitter const & blitter)
304{
305 return(RLE_Blit(dest, dest.Get_Rect(), destrect, source, source.Get_Rect(), sourcerect, blitter));
306}
307
308
309/***********************************************************************************************
310 * RLE_Blit -- Blits a rectangle of RLE compressed data to a surface. *
311 * *
312 * This routine will blit a rectangle of REL compressed pixel data from a sprite to the *
313 * surface specified. Appropriate clipping and coordinate adjustments will occur as *
314 * controlled by the parameters. This is the workhorse RLE blit dispatcher routine. *
315 * *
316 * INPUT: dest -- The destination surface to blit to. *
317 * *
318 * dcliprect-- The clipping rectangle to use on the destination. Pixels won't be *
319 * drawn outside of this rectangle and the destination rect coordinates *
320 * are biased to this clipping rectange. *
321 * *
322 * ddrect -- The destination rectangle of the blit. The upper left coordinates are *
323 * biased to the destination clipping rectangle when blitted. Thus, *
324 * a dest X,Y position of 0,0 really means the upper left corner of the *
325 * destination clipping rectangle. *
326 * *
327 * source -- The source surface of the RLE compressed data. *
328 * *
329 * scliprect-- It is quite likely that this will be the full size of the source *
330 * surface. *
331 * *
332 * ssrect -- The source rectangle to blit from within the source surface. It *
333 * behaves similarly to the ddrect parameter, but for the source. The *
334 * width and height of this rectangle should match the width and height *
335 * of the ddrect parameter (scaling is not yet supported). *
336 * *
337 * blitter -- The blitter to use for this pixel copy. It must be an RLE blitter. *
338 * *
339 * OUTPUT: bool; Did the blit draw at least one pixel? *
340 * *
341 * WARNINGS: none *
342 * *
343 * HISTORY: *
344 * 05/24/1997 JLB : Created. *
345 *=============================================================================================*/
346bool RLE_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, RLEBlitter const & blitter)
347{
348 Rect srect = ssrect; // Desired source rect.
349 Rect drect = ddrect; // Desired destination rect.
350
351 /*
352 ** Adjust the desired draw rectangles to account for clipping. This is where the desired rectangles
353 ** get clipped to the bounding rectangles of the surfaces.
354 */
355 if (!Blit_Clip(drect, dcliprect, srect, scliprect)) {
356 return(false);
357 }
358
359 /*
360 ** Determine the top and left skip margins. These require special handling
361 ** since the shape is compressed.
362 */
363 int leftmargin = srect.X - scliprect.X;
364 int topmargin = srect.Y - scliprect.Y;
365
366 void * dbuffer = dest.Lock(dcliprect.Top_Left() + drect.Top_Left());
367// void * dbuffer = dest.Lock(Point2D(dcliprect.X + drect.X, dcliprect.Y + drect.Y));
368 if (dbuffer == NULL) return(false);
369
370 /*
371 ** Lock the source pointer. This must always lock at location 0,0 since
372 ** normal pixel offset logic does not work for RLE compressed buffers. If there
373 ** is a pixel offset required, it is handled below.
374 */
375 void * sbuffer = source.Lock();
376 if (sbuffer == NULL) {
377 dest.Unlock();
378 return(false);
379 }
380
381 /*
382 ** Skip any top margin lines. This must be manually performed on a line
383 ** by line basis because the length of each line is Variable.
384 */
385 while (topmargin > 0) {
386 sbuffer = ((unsigned char *)sbuffer) + (*(unsigned short *)sbuffer);
387 topmargin--;
388 }
389
390 /*
391 ** This perform a line-by-line pixel copy.
392 */
393 int dstride = dest.Stride();
394 int height = MIN(srect.Height, drect.Height);
395 for (int y = 0; y < height; y++) {
396
397 /*
398 ** Blit the correct sub-portion to the destination surface.
399 */
400 blitter.Blit(dbuffer, ((unsigned short *)sbuffer)+1, srect.Width, leftmargin);
401
402 /*
403 ** Advance the source and dest pointers for the next line processing.
404 */
405 sbuffer = ((unsigned char *)sbuffer) + (*(unsigned short *)sbuffer);
406 dbuffer = (void*)(((char*)dbuffer) + dstride);
407 }
408
409 dest.Unlock();
410 source.Unlock();
411
412 return(true);
413}
414
415
#define NULL
Definition BaseType.h:92
#define MIN(a, b)
Definition always.h:189
bool Bit_Blit(Surface &dest, Rect const &destrect, Surface const &source, Rect const &sourcerect, Blitter const &blitter)
Definition blit.cpp:167
bool RLE_Blit(Surface &dest, Rect const &destrect, Surface const &source, Rect const &sourcerect, RLEBlitter const &blitter)
Definition blit.cpp:303
int Buffer_Size(Surface const &surface, int width, int height)
Definition blit.cpp:72
bool From_Buffer(Surface &surface, Rect const &rect, Buffer const &buffer)
Definition blit.cpp:126
bool To_Buffer(Surface const &surface, Rect const &rect, Buffer &buffer)
Definition blit.cpp:98
virtual void BlitForward(void *dest, void const *source, int length) const =0
virtual void BlitBackward(void *dest, void const *source, int length) const =0
Definition BUFF.H:57
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const =0
virtual Rect Get_Rect(void) const
Definition Surface.h:102
virtual bool Blit_From(Rect const &dcliprect, Rect const &destrect, Surface const &source, Rect const &scliprect, Rect const &sourcerect, bool trans=false)=0
virtual bool Unlock(void) const =0
virtual void * Lock(Point2D point=Point2D(0, 0)) const =0
virtual int Bytes_Per_Pixel(void) const =0
virtual int Stride(void) const =0
bool Is_Valid(void) const
Definition trect.h:82
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
T X
Definition trect.h:108
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
static bool Prep_For_Blit(Surface &dest, Rect &drect, Surface const &source, Rect &srect, bool &overlapped, void *&dbuffer, void *&sbuffer)
Definition xsurface.cpp:699
TRect< int > Rect
Definition trect.h:221
bool Blit_Clip(Rect &drect, Rect const &dwindow, Rect &srect, Rect const &swindow)
Definition xsurface.cpp:576