1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "engines/icb/common/px_common.h"
29 #include "engines/icb/global_objects.h"
30 #include "engines/icb/p4_generic_pc.h"
31
32 namespace ICB {
33
34 // This type is used by General_quad_draw_24_32().
35 typedef struct { int32 nX, nY; } Span;
36
37 // This function is used only inside this file.
38 static void RawSpriteDraw(uint8 *pSurfaceBitmap, uint32 nPitch, uint32 nSurfaceWidth, uint32 nSurfaceHeight, _pxSprite *pSprite, uint8 *pPalette, int32 nX, int32 nY,
39 uint32 *nTransparencyRef, uint8 nOpacity);
40
Draw_horizontal_line(int32 xx,int32 yy,uint32 len,_rgb * pen,uint8 * ad,uint32 pitch)41 void Draw_horizontal_line(int32 xx, int32 yy, uint32 len, _rgb *pen, uint8 *ad, uint32 pitch) {
42 // viewport coordinates
43 // 640*480 screen
44 // 24 or 32but colour
45
46 uint32 j;
47
48 // check top and bottom
49 if (yy < 0)
50 return;
51 if (yy > 479)
52 return;
53
54 // line totaly off left
55 if ((int32)(xx + len) < 0)
56 return;
57
58 // line totally off right
59 if (xx > 639)
60 return;
61
62 // clip left
63 if (xx < 0) {
64 len -= (0 - xx); // 0 - -5 == 5 so len=len-5
65 xx = 0;
66 }
67
68 // clip right
69 if ((xx + len) > 639) {
70 len -= ((xx + len) - 639);
71 }
72
73 // move to y
74 ad += (yy * pitch);
75
76 // move to x
77 ad += (xx * 4);
78
79 for (j = 0; j < len; j++) {
80 *(ad++) = pen->blue;
81 *(ad++) = pen->green;
82 *(ad++) = pen->red;
83 ad++;
84 }
85 }
86
Draw_vertical_line(int32 xx,int32 yy,uint32 len,_rgb * pen,uint8 * ad,uint32 pitch)87 void Draw_vertical_line(int32 xx, int32 yy, uint32 len, _rgb *pen, uint8 *ad, uint32 pitch) {
88 // viewport coordinates
89 // 640*480 screen
90 // 24 or 32but colour
91
92 uint32 j;
93
94 // check left/right
95 if (xx < 0)
96 return;
97 if (xx > 639)
98 return;
99
100 // line totaly off top
101 if ((int32)(yy + len) < 0)
102 return;
103
104 // line totally off bottom
105 if (yy > 479)
106 return;
107
108 // clip top
109 if (yy < 0) {
110 len -= (0 - yy); // 0 - -5 == 5 so len=len-5
111 yy = 0;
112 }
113
114 // clip bottom
115 if ((yy + len) > 479) {
116 len -= ((yy + len) - 479);
117 }
118
119 // move to y
120 ad += (yy * pitch);
121
122 // ove to x
123 ad += (xx * 4);
124
125 for (j = 0; j < len; j++) {
126 *(ad) = pen->blue;
127 *(ad + 1) = pen->green;
128 *(ad + 2) = pen->red;
129 ad += pitch;
130 }
131 }
132
Fill_rect(int32 x,int32 y,int32 x2,int32 y2,uint32 pen,int32)133 void Fill_rect(int32 x, int32 y, int32 x2, int32 y2, uint32 pen, int32 /*z*/) {
134 // put a filled rectangle on the screen
135 // backbuffer must be unlocked
136
137 LRECT blank;
138
139 // completely off screen
140 if ((x2 <= 0) || (x >= 640) || (y >= 480) || (y2 <= 0))
141 return;
142
143 // clip
144 if (x < 0)
145 x = 0;
146
147 if (x2 > 640)
148 x2 = 640;
149
150 if (y < 0)
151 y = 0;
152
153 if (y2 > 480)
154 y2 = 480;
155
156 // setup LRECT for bottom line of the screen
157 blank.left = x;
158 blank.right = x2;
159 blank.top = y;
160 blank.bottom = y2;
161
162 surface_manager->Blit_fillfx(working_buffer_id, &blank, pen);
163 }
164
General_draw_line_24_32(int16 x0,int16 y0,int16 x1,int16 y1,_rgb * colour,uint8 * myScreenBuffer,uint32 pitch,int32 surface_width,int32 surface_height)165 void General_draw_line_24_32(int16 x0, int16 y0, int16 x1, int16 y1, _rgb *colour, uint8 *myScreenBuffer, uint32 pitch, int32 surface_width, int32 surface_height) {
166 // Uses Bressnham's incremental algorithm!
167 // we pass a colour
168 // we pass the surface base
169 // assume 640*480
170
171 int32 dx, dy;
172 int32 dxmod, dymod;
173 int32 ince, incne;
174 int32 d;
175 int32 x, y;
176 int32 addTo;
177 uint32 BYTEWIDE;
178 uint32 vram = 4;
179
180 //#define RENDERWIDE 640
181 //#define RENDERDEEP 480
182 BYTEWIDE = pitch;
183
184 // Make sure we're going from left to right
185 if (x1 < x0) {
186 x = x1;
187 x1 = x0;
188 x0 = (int16)x;
189 y = y1;
190 y1 = y0;
191 y0 = (int16)y;
192 }
193 dx = x1 - x0;
194 dy = y1 - y0;
195
196 if (dx < 0)
197 dxmod = -dx;
198 else
199 dxmod = dx;
200
201 if (dy < 0)
202 dymod = -dy;
203 else
204 dymod = dy;
205
206 if (dxmod >= dymod) {
207 if (dy > 0) {
208 d = 2 * dy - dx;
209 ince = 2 * dy;
210 incne = 2 * (dy - dx);
211 x = x0;
212 y = y0;
213 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
214 myScreenBuffer[y * BYTEWIDE + (x * vram)] = colour->blue;
215 myScreenBuffer[y * BYTEWIDE + (x * vram) + 1] = colour->green;
216 myScreenBuffer[y * BYTEWIDE + (x * vram) + 2] = colour->red;
217 }
218
219 while (x < x1) {
220 if (d <= 0) {
221 d += ince;
222 x += 1;
223 } else {
224 d += incne;
225 x += 1;
226 y += 1;
227 }
228 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
229 myScreenBuffer[y * BYTEWIDE + (x * vram)] = colour->blue;
230 myScreenBuffer[y * BYTEWIDE + (x * vram) + 1] = colour->green;
231 myScreenBuffer[y * BYTEWIDE + (x * vram) + 2] = colour->red;
232 }
233 }
234 } else {
235 addTo = y0;
236 y0 = 0;
237 y1 = (int16)(y1 - addTo);
238 y1 = (int16)-y1;
239 dy = y1 - y0;
240
241 d = 2 * dy - dx;
242 ince = 2 * dy;
243 incne = 2 * (dy - dx);
244 x = x0;
245 y = y0;
246 if ((x >= 0) && (x < surface_width) && (addTo - y >= 0) && (addTo - y < surface_height)) {
247 // myScreenBuffer[(addTo - y) * surface_width + x] = colour;
248
249 myScreenBuffer[(addTo - y) * BYTEWIDE + (x * vram)] = colour->blue;
250 myScreenBuffer[(addTo - y) * BYTEWIDE + ((x * vram) + 1)] = colour->green;
251 myScreenBuffer[(addTo - y) * BYTEWIDE + ((x * vram) + 2)] = colour->red;
252 }
253
254 while (x < x1) {
255 if (d <= 0) {
256 d += ince;
257 x += 1;
258 } else {
259 d += incne;
260 x += 1;
261 y += 1;
262 }
263 if ((x >= 0) && (x < surface_width) && (addTo - y >= 0) && (addTo - y < surface_height)) {
264 // myScreenBuffer[(addTo - y) * surface_width + x] = colour;
265
266 myScreenBuffer[(addTo - y) * BYTEWIDE + (x * vram)] = colour->blue;
267 myScreenBuffer[(addTo - y) * BYTEWIDE + ((x * vram) + 1)] = colour->green;
268 myScreenBuffer[(addTo - y) * BYTEWIDE + ((x * vram) + 2)] = colour->red;
269 }
270 }
271 }
272 } else {
273 // OK, y is now going to be the single increment.
274 // Ensure the line is going top to bottom
275 if (y1 < y0) {
276 x = x1;
277 x1 = x0;
278 x0 = (int16)x;
279 y = y1;
280 y1 = y0;
281 y0 = (int16)y;
282 }
283 dx = x1 - x0;
284 dy = y1 - y0;
285
286 if (dx > 0) {
287 d = 2 * dx - dy;
288 ince = 2 * dx;
289 incne = 2 * (dx - dy);
290 x = x0;
291 y = y0;
292 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
293 myScreenBuffer[y * BYTEWIDE + (x * vram)] = colour->blue;
294 myScreenBuffer[y * BYTEWIDE + (x * vram) + 1] = colour->green;
295 myScreenBuffer[y * BYTEWIDE + (x * vram) + 2] = colour->red;
296 }
297 while (y < y1) {
298 if (d <= 0) {
299 d += ince;
300 y += 1;
301 } else {
302 d += incne;
303 x += 1;
304 y += 1;
305 }
306 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
307 myScreenBuffer[y * BYTEWIDE + (x * vram)] = colour->blue;
308 myScreenBuffer[y * BYTEWIDE + (x * vram) + 1] = colour->green;
309 myScreenBuffer[y * BYTEWIDE + (x * vram) + 2] = colour->red;
310 }
311 }
312 } else {
313 addTo = x0;
314 x0 = 0;
315 x1 = (int16)(x1 - addTo);
316 x1 = (int16)-x1;
317 dx = x1 - x0;
318
319 d = 2 * dx - dy;
320 ince = 2 * dx;
321 incne = 2 * (dx - dy);
322 x = x0;
323 y = y0;
324 if ((addTo - x >= 0) && (addTo - x < surface_width) && (y >= 0) && (y < surface_height)) {
325 // myScreenBuffer[y * surface_width + addTo - x] = colour;
326
327 myScreenBuffer[y * BYTEWIDE + ((addTo - x) * vram)] = colour->blue;
328 myScreenBuffer[y * BYTEWIDE + (((addTo - x) * vram) + 1)] = colour->green;
329 myScreenBuffer[y * BYTEWIDE + (((addTo - x) * vram) + 2)] = colour->red;
330 }
331
332 while (y < y1) {
333 if (d <= 0) {
334 d += ince;
335 y += 1;
336 } else {
337 d += incne;
338 x += 1;
339 y += 1;
340 }
341 if ((addTo - x >= 0) && (addTo - x < surface_width) && (y >= 0) && (y < surface_height)) {
342 // myScreenBuffer[y * surface_width + addTo - x] = colour;
343
344 myScreenBuffer[y * BYTEWIDE + ((addTo - x) * vram)] = colour->blue;
345 myScreenBuffer[y * BYTEWIDE + (((addTo - x) * vram) + 1)] = colour->green;
346 myScreenBuffer[y * BYTEWIDE + (((addTo - x) * vram) + 2)] = colour->red;
347 }
348 }
349 }
350 }
351 }
352
AdditiveGouraudLine(int16 x0,int16 y0,_rgb c0,int16 x1,int16 y1,_rgb c1,uint32 surface_id)353 void AdditiveGouraudLine(int16 x0, int16 y0, _rgb c0, int16 x1, int16 y1, _rgb c1, uint32 surface_id) {
354 // Uses Bressnham's incremental algorithm!
355 // We have a start colour and an end colour
356 int32 dx, dy;
357 int32 dxmod, dymod;
358 int32 ince, incne;
359 int32 d;
360 int32 x, y;
361 int32 addTo;
362
363 uint8 *surface = (uint8 *)surface_manager->Lock_surface(surface_id);
364 uint32 pitch = surface_manager->Get_pitch(surface_id);
365 int32 surface_width = surface_manager->Get_width(surface_id);
366 int32 surface_height = surface_manager->Get_height(surface_id);
367
368 // Make sure we're going from left to right
369 if (x1 < x0) {
370 x = x1;
371 x1 = x0;
372 x0 = (int16)x;
373 y = y1;
374 y1 = y0;
375 y0 = (int16)y;
376
377 _rgb tC = c1;
378 c1 = c0;
379 c0 = tC;
380 }
381 dx = x1 - x0;
382 dy = y1 - y0;
383
384 if (dx < 0)
385 dxmod = -dx;
386 else
387 dxmod = dx;
388
389 if (dy < 0)
390 dymod = -dy;
391 else
392 dymod = dy;
393
394 if (dxmod >= dymod) {
395 if (dy > 0) {
396 d = 2 * dy - dx;
397 ince = 2 * dy;
398 incne = 2 * (dy - dx);
399 x = x0;
400 y = y0;
401 uint8 r = c0.red;
402 uint8 g = c0.green;
403 uint8 b = c0.blue;
404 int32 dr = (dx) ? (c1.red - c0.red) / dx : 0;
405 int32 dg = (dx) ? (c1.green - c0.green) / dx : 0;
406 int32 db = (dx) ? (c1.blue - c0.blue) / dx : 0;
407 uint32 offset = y * pitch + (x << 2);
408 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
409 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
410 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
411 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
412 }
413
414 while (x < x1) {
415 r = (uint8)(r + dr);
416 g = (uint8)(g + dg);
417 b = (uint8)(b + db);
418 offset += 4;
419 x++;
420
421 if (d <= 0) {
422 d += ince;
423 } else {
424 d += incne;
425 y++;
426 offset += pitch;
427 }
428 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
429 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
430 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
431 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
432 }
433 }
434 } else {
435 addTo = y0;
436 y0 = 0;
437 y1 = (int16)(y1 - addTo);
438 y1 = (int16)-y1;
439 dy = y1 - y0;
440
441 d = 2 * dy - dx;
442 ince = 2 * dy;
443 incne = 2 * (dy - dx);
444 x = x0;
445 y = y0;
446 uint8 r = c0.red;
447 uint8 g = c0.green;
448 uint8 b = c0.blue;
449 int32 dr = (dx) ? (c1.red - c0.red) / dx : 0;
450 int32 dg = (dx) ? (c1.green - c0.green) / dx : 0;
451 int32 db = (dx) ? (c1.blue - c0.blue) / dx : 0;
452
453 uint32 offset = (addTo - y) * pitch + (x << 2);
454 if ((x >= 0) && (x < surface_width) && (addTo - y >= 0) && (addTo - y < surface_height)) {
455 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
456 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
457 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
458 }
459
460 while (x < x1) {
461 r = (uint8)(r + dr);
462 g = (uint8)(g + dg);
463 b = (uint8)(b + db);
464
465 x++;
466 offset += 4;
467 if (d <= 0) {
468 d += ince;
469 } else {
470 d += incne;
471 y++;
472 offset -= pitch;
473 }
474 if ((x >= 0) && (x < surface_width) && (addTo - y >= 0) && (addTo - y < surface_height)) {
475 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
476 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
477 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
478 }
479 }
480 }
481 } else {
482 // OK, y is now going to be the single increment.
483 // Ensure the line is going top to bottom
484 if (y1 < y0) {
485 x = x1;
486 x1 = x0;
487 x0 = (int16)x;
488 y = y1;
489 y1 = y0;
490 y0 = (int16)y;
491
492 _rgb tC = c1;
493 c1 = c0;
494 c0 = tC;
495 }
496 dx = x1 - x0;
497 dy = y1 - y0;
498
499 if (dx > 0) {
500 d = 2 * dx - dy;
501 ince = 2 * dx;
502 incne = 2 * (dx - dy);
503 x = x0;
504 y = y0;
505
506 uint8 r = c0.red;
507 uint8 g = c0.green;
508 uint8 b = c0.blue;
509 int32 dr = (dy) ? (c1.red - c0.red) / dy : 0;
510 int32 dg = (dy) ? (c1.green - c0.green) / dy : 0;
511 int32 db = (dy) ? (c1.blue - c0.blue) / dy : 0;
512
513 uint32 offset = y * pitch + (x << 2);
514
515 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
516 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
517 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
518 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
519 }
520 while (y < y1) {
521 r = (uint8)(r + dr);
522 g = (uint8)(g + dg);
523 b = (uint8)(b + db);
524
525 offset += pitch;
526 y++;
527 if (d <= 0) {
528 d += ince;
529 } else {
530 d += incne;
531 x++;
532 offset += 4;
533 }
534 if ((x >= 0) && (x < surface_width) && (y >= 0) && (y < surface_height)) {
535 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
536 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
537 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
538 }
539 }
540 } else {
541 addTo = x0;
542 x0 = 0;
543 x1 = (int16)(x1 - addTo);
544 x1 = (int16)-x1;
545 dx = x1 - x0;
546
547 d = 2 * dx - dy;
548 ince = 2 * dx;
549 incne = 2 * (dx - dy);
550 x = x0;
551 y = y0;
552
553 uint8 r = c0.red;
554 uint8 g = c0.green;
555 uint8 b = c0.blue;
556 int32 dr = (dy) ? (c1.red - c0.red) / dy : 0;
557 int32 dg = (dy) ? (c1.green - c0.green) / dy : 0;
558 int32 db = (dy) ? (c1.blue - c0.blue) / dy : 0;
559
560 uint32 offset = y * pitch + ((addTo - x) << 2);
561
562 if ((addTo - x >= 0) && (addTo - x < surface_width) && (y >= 0) && (y < surface_height)) {
563 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
564 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
565 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
566 }
567
568 while (y < y1) {
569 r = (uint8)(r + dr);
570 g = (uint8)(g + dg);
571 b = (uint8)(b + db);
572
573 offset += pitch;
574 y++;
575 if (d <= 0) {
576 d += ince;
577
578 } else {
579 d += incne;
580 x += 1;
581 offset -= 4;
582 }
583 if ((addTo - x >= 0) && (addTo - x < surface_width) && (y >= 0) && (y < surface_height)) {
584 surface[offset] = ((surface[offset] + b) > 255) ? (uint8)255 : (uint8)(surface[offset] + b);
585 surface[offset + 1] = ((surface[offset] + g) > 255) ? (uint8)255 : (uint8)(surface[offset + 1] + g);
586 surface[offset + 2] = ((surface[offset] + r) > 255) ? (uint8)255 : (uint8)(surface[offset + 2] + r);
587 }
588 }
589 }
590 }
591
592 surface_manager->Unlock_surface(surface_id);
593 }
594
BlendedLine(int32 x0,int32 y0,int32 x1,int32 y1,_rgb c,uint32 surface_id)595 void BlendedLine(int32 x0, int32 y0, int32 x1, int32 y1, _rgb c, uint32 surface_id) {
596 uint8 *surface = (uint8 *)surface_manager->Lock_surface(surface_id);
597 uint32 pitch = surface_manager->Get_pitch(surface_id);
598 int32 surface_width = surface_manager->Get_width(surface_id);
599 int32 surface_height = surface_manager->Get_height(surface_id);
600
601 BlendedLine(x0, y0, x1, y1, c, surface_width, surface_height, pitch, surface);
602
603 surface_manager->Unlock_surface(surface_id);
604 }
605
BlendedLine(int32 x0,int32 y0,int32 x1,int32 y1,_rgb c,int32 surface_width,int32 surface_height,uint32 pitch,uint8 * surface)606 void BlendedLine(int32 x0, int32 y0, int32 x1, int32 y1, _rgb c, int32 surface_width, int32 surface_height, uint32 pitch, uint8 *surface) {
607 // Uses Bressnham's incremental algorithm!
608 // We have a start colour and an end colour
609 int32 dx, dy;
610 int32 dxmod, dymod;
611 int32 ince, incne;
612 int32 d;
613 int32 x, y;
614 int32 addTo;
615
616 // Make sure we're going from left to right
617 if (x1 < x0) {
618 x = x1;
619 x1 = x0;
620 x0 = (int16)x;
621 y = y1;
622 y1 = y0;
623 y0 = (int16)y;
624 }
625 dx = x1 - x0;
626 dy = y1 - y0;
627
628 if (dx < 0)
629 dxmod = -dx;
630 else
631 dxmod = dx;
632
633 if (dy < 0)
634 dymod = -dy;
635 else
636 dymod = dy;
637
638 if (dxmod >= dymod) {
639 if (dy > 0) {
640 d = 2 * dy - dx;
641 ince = 2 * dy;
642 incne = 2 * (dy - dx);
643 x = x0;
644 y = y0;
645 uint8 r = c.red;
646 uint8 g = c.green;
647 uint8 b = c.blue;
648 uint32 offset = y * pitch + (x << 2);
649
650 while (x < 0 || y < 0) {
651 offset += 4;
652 x++;
653
654 if (d <= 0) {
655 d += ince;
656 } else {
657 d += incne;
658 y++;
659 offset += pitch;
660 }
661 }
662
663 if (x1 >= surface_width)
664 x1 = surface_width - 1;
665
666 while (x < x1) {
667 offset += 4;
668 x++;
669
670 if (d <= 0) {
671 d += ince;
672 } else {
673 d += incne;
674 y++;
675 offset += pitch;
676 }
677 if (y < surface_height) {
678 surface[offset] = (uint8)((surface[offset] + b) >> 1);
679 surface[offset + 1] = (uint8)((surface[offset + 1] + g) >> 1);
680 surface[offset + 2] = (uint8)((surface[offset + 2] + r) >> 1);
681 }
682 }
683 } else {
684 addTo = y0;
685 y0 = 0;
686 y1 = (int16)(y1 - addTo);
687 y1 = (int16)-y1;
688 dy = y1 - y0;
689
690 d = 2 * dy - dx;
691 ince = 2 * dy;
692 incne = 2 * (dy - dx);
693 x = x0;
694 y = y0;
695 uint8 r = c.red;
696 uint8 g = c.green;
697 uint8 b = c.blue;
698
699 uint32 offset = (addTo - y) * pitch + (x << 2);
700
701 while ((x < 0) || ((addTo - y) >= surface_height)) {
702 x++;
703 offset += 4;
704 if (d <= 0) {
705 d += ince;
706 } else {
707 d += incne;
708 y++;
709 offset -= pitch;
710 }
711 }
712
713 if (x1 >= surface_width)
714 x1 = surface_width - 1;
715
716 while (x < x1) {
717 x++;
718 offset += 4;
719 if (d <= 0) {
720 d += ince;
721 } else {
722 d += incne;
723 y++;
724 offset -= pitch;
725 }
726 if ((addTo - y) >= 0) {
727 surface[offset] = (uint8)((surface[offset] + b) >> 1);
728 surface[offset + 1] = (uint8)((surface[offset + 1] + g) >> 1);
729 surface[offset + 2] = (uint8)((surface[offset + 2] + r) >> 1);
730 }
731 }
732 }
733 } else {
734 // OK, y is now going to be the single increment.
735 // Ensure the line is going top to bottom
736 if (y1 < y0) {
737 x = x1;
738 x1 = x0;
739 x0 = (int16)x;
740 y = y1;
741 y1 = y0;
742 y0 = (int16)y;
743 }
744 dx = x1 - x0;
745 dy = y1 - y0;
746
747 if (dx > 0) {
748 d = 2 * dx - dy;
749 ince = 2 * dx;
750 incne = 2 * (dx - dy);
751 x = x0;
752 y = y0;
753
754 uint8 r = c.red;
755 uint8 g = c.green;
756 uint8 b = c.blue;
757 uint32 offset = y * pitch + (x << 2);
758
759 while ((y < 0) || (x < 0)) {
760 offset += pitch;
761 ++y;
762 if (d <= 0) {
763 d += ince;
764 } else {
765 d += incne;
766 ++x;
767 offset += 4;
768 }
769 }
770
771 if (y1 >= surface_height)
772 y1 = surface_height - 1;
773
774 while (y < y1) {
775 offset += pitch;
776 ++y;
777 if (d <= 0) {
778 d += ince;
779 } else {
780 d += incne;
781 ++x;
782 offset += 4;
783 }
784 if (x < surface_width) {
785 surface[offset] = (uint8)((surface[offset] + b) >> 1);
786 surface[offset + 1] = (uint8)((surface[offset + 1] + g) >> 1);
787 surface[offset + 2] = (uint8)((surface[offset + 2] + r) >> 1);
788 }
789 }
790 } else {
791 addTo = x0;
792 x0 = 0;
793 x1 = (int16)(x1 - addTo);
794 x1 = (int16)-x1;
795 dx = x1 - x0;
796
797 d = 2 * dx - dy;
798 ince = 2 * dx;
799 incne = 2 * (dx - dy);
800 x = x0;
801 y = y0;
802
803 uint8 r = c.red;
804 uint8 g = c.green;
805 uint8 b = c.blue;
806 uint32 offset = y * pitch + ((addTo - x) << 2);
807
808 while ((y < 0) || (addTo - x >= surface_width)) {
809 offset += pitch;
810 ++y;
811 if (d <= 0) {
812 d += ince;
813
814 } else {
815 d += incne;
816 ++x;
817 offset -= 4;
818 }
819 }
820
821 if (y1 >= surface_height)
822 y1 = surface_height - 1;
823
824 while (y < y1) {
825 offset += pitch;
826 y++;
827 if (d <= 0) {
828 d += ince;
829
830 } else {
831 d += incne;
832 x += 1;
833 offset -= 4;
834 }
835 if ((addTo - x) >= 0) {
836 surface[offset] = (uint8)((surface[offset] + b) >> 1);
837 surface[offset + 1] = (uint8)((surface[offset + 1] + g) >> 1);
838 surface[offset + 2] = (uint8)((surface[offset + 2] + r) >> 1);
839 }
840 }
841 }
842 }
843 }
844
SpriteFrameDraw(uint8 * pSurfaceBitmap,uint32 nPitch,uint32 nSurfaceWidth,uint32 nSurfaceHeight,_pxBitmap * pBitmap,uint32 nFrameNumber,uint32 * pnTransparencyRef,uint8 nOpacity)845 void SpriteFrameDraw(uint8 *pSurfaceBitmap, // IN: Pointer to the surface's drawing area.
846 uint32 nPitch, // IN: Pitch for the surface.
847 uint32 nSurfaceWidth, // IN: Width of the surface.
848 uint32 nSurfaceHeight, // IN: Height of the surface.
849 _pxBitmap *pBitmap, // IN: Pointer to the bitmap to render.
850 uint32 nFrameNumber, // IN: Frame to draw.
851 uint32 *pnTransparencyRef, // IN: Colour to use for transparency.
852 uint8 nOpacity // IN: Opacity 0-255 to draw sprite into surface.
853 ) {
854 uint8 *pPalette;
855 _pxSprite *pSprite;
856
857 // Get to the sprite frame.
858 pSprite = pBitmap->Fetch_item_by_number(nFrameNumber);
859
860 // Get the palette pointer.
861 pPalette = pBitmap->Fetch_palette_pointer();
862
863 // Now do the actual drawing.
864 RawSpriteDraw(pSurfaceBitmap, nPitch, nSurfaceWidth, nSurfaceHeight, pSprite, pPalette, pSprite->x, pSprite->y, pnTransparencyRef, nOpacity);
865 }
866
SpriteXYFrameDraw(uint8 * pSurfaceBitmap,uint32 nPitch,uint32 nSurfaceWidth,uint32 nSurfaceHeight,_pxBitmap * pBitmap,int32 nX,int32 nY,uint32 nFrameNumber,bool8 bCenter,uint32 * pnTransparencyRef,uint8 nOpacity)867 void SpriteXYFrameDraw(uint8 *pSurfaceBitmap, // IN: Pointer to the surface's drawing area.
868 uint32 nPitch, // IN: Pitch for the surface.
869 uint32 nSurfaceWidth, // IN: Width of the surface.
870 uint32 nSurfaceHeight, // IN: Height of the surface.
871 _pxBitmap *pBitmap, // IN: Pointer to the bitmap to render.
872 int32 nX, // IN: X-position to draw sprite at (relative to the surface).
873 int32 nY, // IN: Y-position to draw sprite at (relative to the surface).
874 uint32 nFrameNumber, // IN: Frame to draw.
875 bool8 bCenter, // IN: If true, centre the sprite.
876 uint32 *pnTransparencyRef, // IN: Colour to use for transparency.
877 uint8 nOpacity // IN: Opacity 0-255 to draw sprite into surface.
878 ) {
879 uint8 *pPalette;
880 _pxSprite *pSprite;
881
882 // Get to the sprite frame.
883 pSprite = pBitmap->Fetch_item_by_number(nFrameNumber);
884
885 // Work out a new plotting position if it is to be centred.
886 if (bCenter) {
887 nX -= (pSprite->width >> 1);
888 nY -= (pSprite->height >> 1);
889 }
890
891 // Get the palette pointer.
892 pPalette = pBitmap->Fetch_palette_pointer();
893
894 // Now do the actual drawing.
895 RawSpriteDraw(pSurfaceBitmap, nPitch, nSurfaceWidth, nSurfaceHeight, pSprite, pPalette, nX, nY, pnTransparencyRef, nOpacity);
896 }
897
RawSpriteDraw(uint8 * pSurfaceBitmap,uint32 nPitch,uint32 nSurfaceWidth,uint32 nSurfaceHeight,_pxSprite * pSprite,uint8 * pPalette,int32 nX,int32 nY,uint32 * pnTransparentRef,uint8 nOpacity)898 void RawSpriteDraw(uint8 *pSurfaceBitmap, // IN: Pointer to the surface's drawing area.
899 uint32 nPitch, // IN: Pitch for the surface.
900 uint32 nSurfaceWidth, // IN: Width of surface in pixels.
901 uint32 nSurfaceHeight, // IN: Height of surface in pixels.
902 _pxSprite *pSprite, // IN: Pointer to one frame of a sprite.
903 uint8 *pPalette, // IN: Pointer to the palette.
904 int32 nX, // IN: X-position to draw sprite at (relative to the surface).
905 int32 nY, // IN: Y-position to draw sprite at (relative to the surface).
906 uint32 *pnTransparentRef, // IN: Colour to use for transparency.
907 uint8 nOpacity // IN: If true, pixels are blended into the surface.
908 ) {
909 uint32 x, y;
910 uint32 *pSurfaceRowStart32;
911 uint8 *pSurfaceRowStart8;
912 uint8 *pSpriteData;
913 uint8 *pPaletteEntry;
914 int32 nSpriteTop, nSpriteLeft;
915 int32 nSurfaceTop, nSurfaceLeft;
916 uint32 nNumRowsToRender, nNumColumnsToRender;
917 uint32 nSurfaceSkipToNextRow, nSpriteSkipToNextRow;
918 uint32 nSpriteRowStart;
919 uint8 nExistingB, nExistingG, nExistingR;
920 uint8 nNewB, nNewG, nNewR;
921
922 // This used to be variable; now it's fixed.
923 const uint32 nBytesPerPixel = 4;
924
925 // If the start position of the sprite is below the bottom row of the surface or its end position
926 // is before the first row of the surface, there can be nothing to display.
927 if ((nY >= (int32)nSurfaceHeight) || ((nY + (int32)pSprite->height) <= 0))
928 return;
929
930 // Now do the same check in the horizontal direction.
931 if ((nX >= (int32)nSurfaceWidth) || ((nX + (int32)pSprite->width) <= 0))
932 return;
933
934 // First work out what proportion of the height of the sprite we have to copy allowing
935 // for clipping it where it overlaps the edges of the surface.
936 nNumRowsToRender = pSprite->height;
937
938 if (nY < 0) {
939 nSurfaceTop = 0;
940 nSpriteTop = abs(nY);
941 nNumRowsToRender -= nSpriteTop;
942 } else {
943 nSurfaceTop = nY;
944 nSpriteTop = 0;
945 }
946
947 if ((nY + pSprite->height) > nSurfaceHeight)
948 nNumRowsToRender -= ((nY + pSprite->height) - nSurfaceHeight);
949
950 // Now do the same in the horizontal direction.
951 nNumColumnsToRender = pSprite->width;
952
953 if (nX < 0) {
954 nSurfaceLeft = 0;
955 nSpriteLeft = abs(nX);
956 nNumColumnsToRender -= nSpriteLeft;
957 } else {
958 nSurfaceLeft = nX;
959 nSpriteLeft = 0;
960 }
961
962 if ((nX + pSprite->width) > nSurfaceWidth)
963 nNumColumnsToRender -= ((nX + pSprite->width) - nSurfaceWidth);
964
965 // Get to the sprite data.
966 pSpriteData = pSprite->data;
967
968 // Work out the byte in the surface to start drawing at.
969 pSurfaceRowStart32 = (uint32 *)(pSurfaceBitmap + (nSurfaceTop * nPitch) + (nBytesPerPixel * nSurfaceLeft));
970 nSurfaceSkipToNextRow = (nPitch - (nBytesPerPixel * nNumColumnsToRender)) >> 2;
971
972 // Work out the pixel to start drawing and how much we need to jump when we get to the end of a row.
973 nSpriteRowStart = nSpriteTop * pSprite->width + nSpriteLeft;
974 nSpriteSkipToNextRow = pSprite->width - nNumColumnsToRender;
975
976 // Check if transparency support is required.
977 if (pnTransparentRef) {
978 // Check if pixel blending is required.
979 if (nOpacity != 255) {
980 for (y = 0; y < nNumRowsToRender; ++y) {
981 // Now loop for one row of the image.
982 for (x = 0; x < nNumColumnsToRender; ++x) {
983 // Get the palette index for this pixel of the sprite.
984 pPaletteEntry = pPalette + (pSpriteData[nSpriteRowStart++] << 2);
985
986 // Don't print anything if the pixel is transparent.
987 if (*((uint32 *)pPaletteEntry) != *pnTransparentRef) {
988 // We are doing pixel merging.
989 pSurfaceRowStart8 = (uint8 *)pSurfaceRowStart32;
990
991 // Get the existing RGB in the surface.
992 nExistingB = *pSurfaceRowStart8;
993 nExistingG = *(pSurfaceRowStart8 + 1);
994 nExistingR = *(pSurfaceRowStart8 + 2);
995
996 // Get the new RGB.
997 nNewB = *pPaletteEntry;
998 nNewG = *(pPaletteEntry + 1);
999 nNewR = *(pPaletteEntry + 2);
1000
1001 // Merge the pixels.
1002 nNewB = (uint8)((((nNewB - nExistingB) * nOpacity) >> 8) + nExistingB);
1003 nNewG = (uint8)((((nNewG - nExistingG) * nOpacity) >> 8) + nExistingG);
1004 nNewR = (uint8)((((nNewR - nExistingR) * nOpacity) >> 8) + nExistingR);
1005
1006 // Write the new colour back to the surface.
1007 *pSurfaceRowStart8 = (uint8)nNewB;
1008 *(pSurfaceRowStart8 + 1) = (uint8)nNewG;
1009 *(pSurfaceRowStart8 + 2) = (uint8)nNewR;
1010 }
1011
1012 ++pSurfaceRowStart32;
1013 }
1014
1015 // We have completed a row; need to jump to the start of the next one.
1016 pSurfaceRowStart32 += nSurfaceSkipToNextRow;
1017 nSpriteRowStart += nSpriteSkipToNextRow;
1018 }
1019 } else {
1020 for (y = 0; y < nNumRowsToRender; ++y) {
1021 // Now loop for one row of the image.
1022 for (x = 0; x < nNumColumnsToRender; ++x) {
1023 // Get the palette index for this pixel of the sprite.
1024 pPaletteEntry = pPalette + (pSpriteData[nSpriteRowStart++] << 2);
1025
1026 // Don't print anything if the pixel is transparent.
1027 if (*((uint32 *)pPaletteEntry) != *pnTransparentRef)
1028 *pSurfaceRowStart32 = *((uint32 *)pPaletteEntry);
1029
1030 ++pSurfaceRowStart32;
1031 }
1032
1033 // We have completed a row; need to jump to the start of the next one.
1034 pSurfaceRowStart32 += nSurfaceSkipToNextRow;
1035 nSpriteRowStart += nSpriteSkipToNextRow;
1036 }
1037 }
1038 } else {
1039 // No transparency support required. Check if pixel blending is required.
1040 if (nOpacity != 255) {
1041 // Pixel blending required.
1042 for (y = 0; y < nNumRowsToRender; ++y) {
1043 // Now loop for one row of the image.
1044 for (x = 0; x < nNumColumnsToRender; ++x) {
1045 // Get the palette index for this pixel of the sprite.
1046 pPaletteEntry = pPalette + (pSpriteData[nSpriteRowStart++] << 2);
1047
1048 // We are doing pixel merging.
1049 pSurfaceRowStart8 = (uint8 *)pSurfaceRowStart32;
1050
1051 // Get the existing RGB in the surface.
1052 nExistingB = *pSurfaceRowStart8;
1053 nExistingG = *(pSurfaceRowStart8 + 1);
1054 nExistingR = *(pSurfaceRowStart8 + 2);
1055
1056 // Get the new RGB.
1057 nNewB = *pPaletteEntry;
1058 nNewG = *(pPaletteEntry + 1);
1059 nNewR = *(pPaletteEntry + 2);
1060
1061 // Merge the pixels.
1062 nNewB = (uint8)((((nNewB - nExistingB) * nOpacity) >> 8) + nExistingB);
1063 nNewG = (uint8)((((nNewG - nExistingG) * nOpacity) >> 8) + nExistingG);
1064 nNewR = (uint8)((((nNewR - nExistingR) * nOpacity) >> 8) + nExistingR);
1065
1066 // Write the new colour back to the surface.
1067 *pSurfaceRowStart8 = (uint8)nNewB;
1068 *(pSurfaceRowStart8 + 1) = (uint8)nNewG;
1069 *(pSurfaceRowStart8 + 2) = (uint8)nNewR;
1070
1071 ++pSurfaceRowStart32;
1072 }
1073
1074 // We have completed a row; need to jump to the start of the next one.
1075 pSurfaceRowStart32 += nSurfaceSkipToNextRow;
1076 nSpriteRowStart += nSpriteSkipToNextRow;
1077 }
1078 } else {
1079 // No pixel blending required - just a straight opaque copy.
1080 for (y = 0; y < nNumRowsToRender; ++y) {
1081 // Now loop for one row of the image.
1082 for (x = 0; x < nNumColumnsToRender; ++x) {
1083 // Get the palette index for this pixel of the sprite.
1084 pPaletteEntry = pPalette + (pSpriteData[nSpriteRowStart++] << 2);
1085
1086 // 32-bit opaque copy is a straight assignment.
1087 *pSurfaceRowStart32++ = *((uint32 *)pPaletteEntry);
1088 }
1089
1090 // We have completed a row; need to jump to the start of the next one.
1091 pSurfaceRowStart32 += nSurfaceSkipToNextRow;
1092 nSpriteRowStart += nSpriteSkipToNextRow;
1093 }
1094 }
1095 }
1096 }
1097
ConvertPxBitmapRectToRECT(const _PxBitmapRect & sBitmapRect)1098 LRECT ConvertPxBitmapRectToRECT(const _PxBitmapRect &sBitmapRect) {
1099 LRECT sRect;
1100
1101 sRect.left = sBitmapRect.nX;
1102 sRect.right = (sBitmapRect.nX + sBitmapRect.nWidth) - 1;
1103 sRect.top = sBitmapRect.nY;
1104 sRect.bottom = (sBitmapRect.nY + sBitmapRect.nHeight) - 1;
1105
1106 return sRect;
1107 }
1108
General_poly_draw_24_32(_point * pVerts,int32 nNumVerts,_rgb sColour,bool8 bFill,uint8 * pSurface,int32 nPitch,int32,int32)1109 void General_poly_draw_24_32(_point *pVerts, int32 nNumVerts, _rgb sColour, bool8 bFill, uint8 *pSurface, int32 nPitch, int32 /*nSurfaceWidth*/, int32 /*nSurfaceHeight*/) {
1110 int32 i, j;
1111 int32 x, y;
1112 int32 nTopVert, nBottomVert, nLeftVert, nRightVert;
1113 int32 nNextVert;
1114 int32 nTopY, nBottomY, nSlope, nSpanTopY, nSpanBottomY;
1115 int32 nX;
1116 int32 nCount;
1117 PXreal fTopY, fBottomY, fSlope, fHeight, fWidth, fPrestep;
1118 Span pSpans[SCREEN_DEPTH];
1119 Span *pSpan;
1120 int32 nBytesPerPixel;
1121 uint8 *pSurfaceAddress;
1122
1123 nTopVert = 0;
1124 nBottomVert = 0;
1125 nX = 0;
1126
1127 // Some initialisation.
1128 nBytesPerPixel = 4;
1129 fTopY = 999999.0f;
1130 fBottomY = -999999.0f;
1131
1132 // Find the top and bottom vertices.
1133 for (i = 0; i < (int32)nNumVerts; ++i) {
1134 if (pVerts[i].z < fTopY) {
1135 fTopY = pVerts[i].z;
1136 nTopVert = i;
1137 }
1138
1139 if (pVerts[i].z > fBottomY) {
1140 fBottomY = pVerts[i].z;
1141 nBottomVert = i;
1142 }
1143 }
1144
1145 nTopY = (int32)ceil(fTopY);
1146 nBottomY = (int32)ceil(fBottomY);
1147
1148 // Polygon has to have a height to be drawn.
1149 if (nBottomY == nTopY)
1150 return;
1151
1152 // Scan out the left edge.
1153 pSpan = pSpans;
1154 nLeftVert = nTopVert;
1155
1156 do {
1157 nNextVert = nLeftVert - 1;
1158
1159 if (nNextVert < 0)
1160 nNextVert = nNumVerts - 1;
1161
1162 nSpanTopY = (int32)ceil(pVerts[nLeftVert].z);
1163 nSpanBottomY = (int32)ceil(pVerts[nNextVert].z);
1164
1165 if (nSpanTopY < nSpanBottomY) {
1166 fHeight = pVerts[nNextVert].z - pVerts[nLeftVert].z;
1167 fWidth = pVerts[nNextVert].x - pVerts[nLeftVert].x;
1168 fSlope = fWidth / fHeight;
1169 fPrestep = nSpanTopY - pVerts[nLeftVert].z;
1170 nX = (int32)((pVerts[nLeftVert].x + (fSlope * fPrestep)) * 65536.0f) + ((1 << 16) - 1);
1171 nSlope = (int32)(fSlope * 65536.0f);
1172
1173 for (j = nSpanTopY; j < nSpanBottomY; ++j) {
1174 pSpan->nX = nX >> 16;
1175 nX += nSlope;
1176 ++pSpan;
1177 }
1178 }
1179
1180 --nLeftVert;
1181 if (nLeftVert < 0)
1182 nLeftVert = nNumVerts - 1;
1183
1184 } while (nLeftVert != nBottomVert);
1185
1186 // Scan out the right edge
1187 pSpan = pSpans;
1188 nRightVert = nTopVert;
1189
1190 do {
1191 nNextVert = (nRightVert + 1) % nNumVerts;
1192
1193 nSpanTopY = (int32)ceil(pVerts[nRightVert].z);
1194 nSpanBottomY = (int32)ceil(pVerts[nNextVert].z);
1195
1196 if (nSpanTopY < nSpanBottomY) {
1197 fHeight = pVerts[nNextVert].z - pVerts[nRightVert].z;
1198 fWidth = pVerts[nNextVert].x - pVerts[nRightVert].x;
1199 fSlope = fWidth / fHeight;
1200 fPrestep = nSpanTopY - pVerts[nRightVert].z;
1201 nX = (int32)((pVerts[nRightVert].x + (fSlope * fPrestep)) * 65536.0f) + ((1 << 16) - 1);
1202 nSlope = (int32)(fSlope * 65536.0f);
1203
1204 for (j = nSpanTopY; j < nSpanBottomY; ++j) {
1205 pSpan->nY = nX >> 16;
1206 nX += nSlope;
1207 ++pSpan;
1208 }
1209 }
1210
1211 nRightVert = (nRightVert + 1) % nNumVerts;
1212
1213 } while (nRightVert != nBottomVert);
1214
1215 // Draw the spans
1216 pSpan = pSpans;
1217
1218 // How we draw depends on the bitmap.
1219 // Drawing in 32-bit colour depth. Fill or just outline?
1220 if (bFill) {
1221 // Fill the polygon (32-bit colour).
1222 for (x = nTopY; x < nBottomY; ++x) {
1223 // Work out the width of the line at this point in the height.
1224 nCount = pSpan->nY - pSpan->nX;
1225
1226 if (nCount > 0) {
1227 // Work out the start address of the row in our target surface.
1228 pSurfaceAddress = pSurface + nPitch * x;
1229
1230 // Loop along the row.
1231 for (y = 0; y < nCount; ++y) {
1232 // Look up the actual colour.
1233 *pSurfaceAddress++ = sColour.red;
1234 *pSurfaceAddress++ = sColour.green;
1235 *pSurfaceAddress++ = sColour.blue;
1236 *pSurfaceAddress = 0x00;
1237 }
1238 }
1239
1240 // Move on to the next span we've stored.
1241 ++pSpan;
1242 }
1243 } else {
1244 // Just draw outline (32-bit colour).
1245 for (x = nTopY; x < nBottomY; ++x) {
1246 // Work out the width of the line at this point in the height.
1247 nCount = pSpan->nY - pSpan->nX;
1248
1249 if (nCount > 0) {
1250 // Draw left edge.
1251 pSurfaceAddress = pSurface + nPitch * x;
1252 *pSurfaceAddress++ = sColour.red;
1253 *pSurfaceAddress++ = sColour.green;
1254 *pSurfaceAddress++ = sColour.blue;
1255 *pSurfaceAddress = 0x00;
1256
1257 // Draw right edge.
1258 pSurfaceAddress = (pSurface + nPitch * x) + ((nCount - 1) * nBytesPerPixel);
1259 *pSurfaceAddress++ = sColour.red;
1260 *pSurfaceAddress++ = sColour.green;
1261 *pSurfaceAddress++ = sColour.blue;
1262 *pSurfaceAddress = 0x00;
1263 }
1264
1265 // Move on to the next span we've stored.
1266 ++pSpan;
1267 }
1268 }
1269 }
1270
1271 } // End of namespace ICB
1272