xsurface.cpp 53 KB

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