Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3011 lines
63 KiB
C++
3011 lines
63 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "l4vb8.h"
|
|
|
|
//########################################################################
|
|
//######################### Video8BitBuffered ###########################
|
|
//########################################################################
|
|
//
|
|
//NOTE: the application assumes that the origin is in the lower left
|
|
// corner of the display, and all parameters passed to these routines
|
|
// use the application's coordinate system.
|
|
//
|
|
// All of the methods here convert these values to the SCREEN
|
|
// coordinate system, with the origin in the UPPER LEFT corner of
|
|
// the display.
|
|
//
|
|
|
|
//===================================================================
|
|
// Creator
|
|
//===================================================================
|
|
Video8BitBuffered::Video8BitBuffered(int x, int y):
|
|
GraphicsDisplay(x, y)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::Video8BitBuffered()\n"
|
|
);
|
|
# endif
|
|
int
|
|
i;
|
|
Word
|
|
*line_dest;
|
|
|
|
pixelBuffer = new PixelMap8(x, y);
|
|
Check(pixelBuffer);
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
Register_Object(pixelBuffer);
|
|
createdPixelmap = True;
|
|
|
|
height = y;
|
|
width = x;
|
|
|
|
maximumY = height-1;
|
|
maximumX = width-1;
|
|
//---------------------------------------------------------
|
|
// Create 'changedLine' array
|
|
//---------------------------------------------------------
|
|
changedLine = new Word[height];
|
|
Register_Pointer(changedLine);
|
|
valid = True;
|
|
|
|
//---------------------------------------------------------
|
|
// Clear the 'changedLine' array
|
|
//---------------------------------------------------------
|
|
for (i=height,line_dest=changedLine; i>0; --i,++line_dest)
|
|
{
|
|
*line_dest = 0;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
Video8BitBuffered::Video8BitBuffered(PixelMap8 *pixel_buffer):
|
|
GraphicsDisplay(pixel_buffer->Data.Size.x, pixel_buffer->Data.Size.y)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::Video8BitBuffered()\n"
|
|
);
|
|
# endif
|
|
int
|
|
i;
|
|
Word
|
|
*line_dest;
|
|
|
|
pixelBuffer = pixel_buffer;
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
createdPixelmap = False;
|
|
|
|
height = pixelBuffer->Data.Size.y;
|
|
width = pixelBuffer->Data.Size.x;
|
|
|
|
maximumY = height-1;
|
|
maximumX = width-1;
|
|
//---------------------------------------------------------
|
|
// Create 'changedLine' array
|
|
//---------------------------------------------------------
|
|
changedLine = new Word[height];
|
|
Register_Pointer(changedLine);
|
|
|
|
# if defined(DEBUG)
|
|
Tell("changedLine=" << changedLine << "\n");
|
|
# endif
|
|
|
|
if (changedLine == NULL)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("INVALID!\n");
|
|
# endif
|
|
valid = False;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
Register_Pointer(changedLine);
|
|
valid = True;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Clear the 'changedLine' array
|
|
//---------------------------------------------------------
|
|
for (i=height,line_dest=changedLine; i>0; --i,++line_dest)
|
|
{
|
|
*line_dest = 0;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// Destructor
|
|
//===================================================================
|
|
Video8BitBuffered::~Video8BitBuffered()
|
|
{
|
|
Check(this);
|
|
|
|
if (changedLine != NULL)
|
|
{
|
|
Unregister_Pointer(changedLine);
|
|
delete changedLine;
|
|
changedLine = NULL;
|
|
}
|
|
|
|
if (createdPixelmap)
|
|
{
|
|
if (pixelBuffer != NULL)
|
|
{
|
|
Check(pixelBuffer);
|
|
Unregister_Object(pixelBuffer);
|
|
delete pixelBuffer;
|
|
pixelBuffer = NULL;
|
|
}
|
|
createdPixelmap = False;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//===================================================================
|
|
// TestInstance
|
|
//===================================================================
|
|
Logical
|
|
Video8BitBuffered::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
//===================================================================
|
|
// ShowInstance
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::ShowInstance(
|
|
char *indent
|
|
)
|
|
{
|
|
std::cout << indent << "Video8BitBuffered:\n";
|
|
|
|
Check(this);
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "width =" << width << "\n";
|
|
std::cout << temp << "height =" << height << "\n";
|
|
std::cout << temp << "maximumX =" << maximumX << "\n";
|
|
std::cout << temp << "maximumY =" << maximumY << "\n";
|
|
std::cout << temp << "changedLine=" << changedLine << "\n";
|
|
|
|
pixelBuffer->ShowInstance(temp);
|
|
GraphicsDisplay::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//===================================================================
|
|
// buildDestPointer
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::buildDestPointer(
|
|
int screenX,
|
|
int screenY,
|
|
Byte **pixel_pointer
|
|
)
|
|
{
|
|
Verify(valid);
|
|
|
|
Verify(pixel_pointer != NULL);
|
|
|
|
Verify(screenX >= 0);
|
|
Verify(screenX < width);
|
|
Verify(screenY >= 0);
|
|
Verify(screenY < height);
|
|
|
|
*pixel_pointer = pixelBuffer->Data.MapPointer +
|
|
screenX +
|
|
(screenY * width);
|
|
Verify(*pixel_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(*pixel_pointer < &pixelBuffer->Data.MapPointer[height*width]);
|
|
|
|
Check_Fpu();
|
|
}
|
|
#define LEFT_DEST(pointer) --pointer
|
|
#define RIGHT_DEST(pointer) ++pointer
|
|
#define UP_DEST(pointer) pointer -= width
|
|
#define DOWN_DEST(pointer) pointer += width
|
|
|
|
#define LEFT_SOURCE(pointer,map) --pointer
|
|
#define RIGHT_SOURCE(pointer,map) ++pointer
|
|
#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x
|
|
#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x
|
|
|
|
#define LEFT_BITMAP(pointer,bits) \
|
|
bits <<= 1; \
|
|
if (bits == 0) { --pointer; bits=0x0001; }
|
|
|
|
#define RIGHT_BITMAP(pointer, bits) \
|
|
bits >>= 1; \
|
|
if (bits == 0) { ++pointer; bits=0x8000; }
|
|
|
|
#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords
|
|
#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords
|
|
|
|
#define WRITEPIXEL(dest_pointer, operation, color) \
|
|
switch (operation) \
|
|
{\
|
|
case GraphicsDisplay::Replace:\
|
|
*dest_pointer = (Byte)color;\
|
|
break;\
|
|
case GraphicsDisplay::And:\
|
|
*dest_pointer &= (Byte) color;\
|
|
break;\
|
|
case GraphicsDisplay::Or:\
|
|
*dest_pointer |= (Byte) color;\
|
|
break;\
|
|
case GraphicsDisplay::Xor:\
|
|
*dest_pointer ^= (Byte) color;\
|
|
break;\
|
|
}
|
|
|
|
//===================================================================
|
|
// MarkChangedLines
|
|
//===================================================================
|
|
//
|
|
// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner!
|
|
//
|
|
void
|
|
Video8BitBuffered::MarkChangedLines(
|
|
int start,
|
|
int stop
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::MarkChangedLines(" << start << ", " << stop <<
|
|
")\n"
|
|
);
|
|
# endif
|
|
Check(this);
|
|
|
|
if (start > stop)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("MarkChangedLines FLIPPING\n");
|
|
# endif
|
|
int temp;
|
|
|
|
temp = start;
|
|
start = stop;
|
|
stop = temp;
|
|
}
|
|
|
|
Verify(start >= 0);
|
|
Verify(start <= maximumY);
|
|
Verify(stop >= 0);
|
|
Verify(stop <= maximumY);
|
|
|
|
++changedLine[start];
|
|
|
|
//
|
|
// Always include at least one line
|
|
//
|
|
if (stop < maximumY)
|
|
{
|
|
--changedLine[stop+1];
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawPoint
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawPoint(
|
|
int color,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int x, int y
|
|
)
|
|
{
|
|
Check(this);
|
|
Verify(x >= bounds.bottomLeft.x);
|
|
Verify(x <= bounds.topRight.x);
|
|
Verify(y >= bounds.bottomLeft.y);
|
|
Verify(y <= bounds.topRight.y);
|
|
|
|
Byte
|
|
*dest_pointer;
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y = maximumY - y;
|
|
|
|
# if defined(DEBUG)
|
|
Tell("x=" << x << ", y=" << y << "\n");
|
|
# endif
|
|
|
|
Verify(x >= 0);
|
|
Verify(x < width);
|
|
Verify(y >= 0);
|
|
Verify(y < height);
|
|
//---------------------------------------------------------
|
|
// Update changedLine array
|
|
//---------------------------------------------------------
|
|
MarkChangedLines(y, y);
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Create pointers
|
|
//---------------------------------------------------------
|
|
buildDestPointer(
|
|
x, y,
|
|
&dest_pointer
|
|
);
|
|
//---------------------------------------------------------
|
|
// Write the point
|
|
//---------------------------------------------------------
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawLine
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawLine(
|
|
int color,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
Logical include_last_pixel
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::DrawLine(" << color <<
|
|
", " << bitmask <<
|
|
", " << operation <<
|
|
", " << x1 << "," << y1 << "," << x2 << "," << y2 <<
|
|
", " << include_last_pixel <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
|
|
Check(this);
|
|
|
|
Verify(x1 >= bounds.bottomLeft.x);
|
|
Verify(x1 <= bounds.topRight.x);
|
|
Verify(y1 >= bounds.bottomLeft.y);
|
|
Verify(y1 <= bounds.topRight.y);
|
|
|
|
Verify(x2 >= bounds.bottomLeft.x);
|
|
Verify(x2 <= bounds.topRight.x);
|
|
Verify(y2 >= bounds.bottomLeft.y);
|
|
Verify(y2 <= bounds.topRight.y);
|
|
|
|
enum
|
|
{
|
|
negative_delta_x = 1,
|
|
negative_delta_y = 2,
|
|
delta_y_greater = 0,
|
|
delta_x_greater = 4
|
|
};
|
|
|
|
long
|
|
length,
|
|
rate,
|
|
accumulator;
|
|
|
|
int
|
|
octant,
|
|
delta_x,
|
|
delta_y;
|
|
|
|
Byte
|
|
*dest_pointer;
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Route to DrawPoint if single pixel
|
|
//---------------------------------------------------------
|
|
if (x1 == x2 && y1 == y2)
|
|
{
|
|
if (include_last_pixel)
|
|
{
|
|
DrawPoint(color, 0 /*bitmask*/, operation, x1, y1);
|
|
}
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y1 = maximumY - y1;
|
|
y2 = maximumY - y2;
|
|
//---------------------------------------------------------
|
|
// Ensure that endpoints are legitimate
|
|
//---------------------------------------------------------
|
|
Verify(x1 >= 0);
|
|
Verify(x1 < width);
|
|
Verify(x2 >= 0);
|
|
Verify(x2 < width);
|
|
|
|
Verify(y1 >= 0);
|
|
Verify(y1 < height);
|
|
Verify(y2 >= 0);
|
|
Verify(y2 < height);
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Transformed coordinates=" << x1 << "," << y1 <<
|
|
"," << x2 << "," << y2 <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
//---------------------------------------------------------
|
|
// Update changedLine array
|
|
//---------------------------------------------------------
|
|
MarkChangedLines(y1, y2);
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Determine which octant to use
|
|
//---------------------------------------------------------
|
|
octant = 0;
|
|
|
|
delta_x = x2 - x1;
|
|
if (delta_x < 0)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("negative dx\n");
|
|
# endif
|
|
octant |= negative_delta_x;
|
|
delta_x = - delta_x;
|
|
}
|
|
|
|
delta_y = y2 - y1;
|
|
if (delta_y < 0)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("negative dy\n");
|
|
# endif
|
|
octant |= negative_delta_y;
|
|
delta_y = - delta_y;
|
|
}
|
|
|
|
if (delta_x > delta_y)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("dx > dy\n");
|
|
# endif
|
|
octant |= delta_x_greater;
|
|
}
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"dx=" << delta_x <<
|
|
", dy=" << delta_y <<
|
|
", octant=" << octant <<
|
|
", color=" << color <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
//---------------------------------------------------------
|
|
// Prepare to draw line
|
|
//---------------------------------------------------------
|
|
buildDestPointer(
|
|
x1, y1,
|
|
&dest_pointer
|
|
);
|
|
|
|
accumulator = 1024L; // preset accumulator to 1/2 full
|
|
//---------------------------------------------------------
|
|
// Draw the line!
|
|
//---------------------------------------------------------
|
|
switch (octant)
|
|
{
|
|
case delta_y_greater:
|
|
//-------------------------------------
|
|
// delta y greater
|
|
// positive delta x
|
|
// positive delta y
|
|
//
|
|
// +
|
|
// \ &
|
|
// \ &
|
|
//-------------------------------------
|
|
length = delta_y;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
|
|
Verify(delta_y > 0);
|
|
rate = (delta_x*2048L)/delta_y;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_y_greater, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
DOWN_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_y_greater+negative_delta_x:
|
|
//-------------------------------------
|
|
// delta y greater
|
|
// negative delta x
|
|
// positive delta y
|
|
//
|
|
// +
|
|
// /
|
|
// /
|
|
//-------------------------------------
|
|
length = delta_y;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_x*2048L)/delta_y;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_y_greater+negative_delta_x, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
DOWN_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_y_greater+negative_delta_y:
|
|
//-------------------------------------
|
|
// delta y greater
|
|
// positive delta x
|
|
// negative delta y
|
|
//
|
|
// /
|
|
// /
|
|
// +
|
|
//-------------------------------------
|
|
length = delta_y;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_x*2048L)/delta_y;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_y_greater+negative_delta_y, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
UP_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_y_greater+negative_delta_x+negative_delta_y:
|
|
//-------------------------------------
|
|
// delta y greater
|
|
// negative delta x
|
|
// negative delta y
|
|
//
|
|
// \ &
|
|
// \ &
|
|
// +
|
|
//-------------------------------------
|
|
length = delta_y;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_x*2048L)/delta_y;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_y_greater+negative_delta_x+negative_delta_y, length=" <<
|
|
length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
UP_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_x_greater:
|
|
//-------------------------------------
|
|
// delta x greater
|
|
// positive delta x
|
|
// positive delta y
|
|
//
|
|
// +---___
|
|
//
|
|
//
|
|
//-------------------------------------
|
|
length = delta_x;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_y*2048L)/delta_x;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_x_greater, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
RIGHT_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_x_greater+negative_delta_x:
|
|
//-------------------------------------
|
|
// delta x greater
|
|
// negative delta x
|
|
// positive delta y
|
|
//
|
|
// ___---+
|
|
//
|
|
//
|
|
//-------------------------------------
|
|
length = delta_x;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_y*2048L)/delta_x;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_x_greater+negative_delta_x, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
LEFT_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_x_greater+negative_delta_y:
|
|
//-------------------------------------
|
|
// delta x greater
|
|
// positive delta x
|
|
// negative delta y
|
|
//
|
|
// +___---
|
|
//
|
|
//
|
|
//-------------------------------------
|
|
length = delta_x;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_y*2048L)/delta_x;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_x_greater+negative_delta_y, length=" << length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
RIGHT_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case delta_x_greater+negative_delta_x+negative_delta_y:
|
|
//-------------------------------------
|
|
// delta x greater
|
|
// negative delta x
|
|
// negative delta y
|
|
//
|
|
// ---___+
|
|
//
|
|
//
|
|
//-------------------------------------
|
|
length = delta_x;
|
|
if (!include_last_pixel)
|
|
{
|
|
-- length;
|
|
}
|
|
rate = (delta_y*2048L)/delta_x;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"delta_x_greater+negative_delta_x+negative_delta_y, length=" <<
|
|
length <<
|
|
", rate=" << rate <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
Verify(rate >= 0L);
|
|
Verify(rate <= 2048L);
|
|
Verify(length >= 0);
|
|
for ( ; length>0; --length)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
length <<
|
|
", accum=" << accumulator <<
|
|
", dest_pointer=" << dest_pointer <<
|
|
"\n"
|
|
);
|
|
# endif
|
|
LEFT_DEST(dest_pointer);
|
|
|
|
accumulator += rate;
|
|
if (accumulator > 2048L)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("OVERFLOW\n");
|
|
# endif
|
|
accumulator -= 2048L;
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawFilledRectangle
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawFilledRectangle(
|
|
int color,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("Video8BitBuffered::DrawFilledRectangle(" <<
|
|
color << ", " <<
|
|
std::hex << bitmask << ", " << std::dec <<
|
|
operation << ", " <<
|
|
x1 << ", " <<
|
|
y1 << ", " <<
|
|
x2 << ", " <<
|
|
y2 << ", " <<
|
|
")\n");
|
|
# endif
|
|
Check(this);
|
|
Verify(x1 >= bounds.bottomLeft.x);
|
|
Verify(x1 <= bounds.topRight.x);
|
|
Verify(y1 >= bounds.bottomLeft.y);
|
|
Verify(y1 <= bounds.topRight.y);
|
|
|
|
Verify(x2 >= bounds.bottomLeft.x);
|
|
Verify(x2 <= bounds.topRight.x);
|
|
Verify(y2 >= bounds.bottomLeft.y);
|
|
Verify(y2 <= bounds.topRight.y);
|
|
|
|
Byte
|
|
*dest_pointer;
|
|
int
|
|
x,
|
|
dest_fixup,
|
|
rect_width,
|
|
rect_height;
|
|
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y1 = maximumY - y1;
|
|
y2 = maximumY - y2;
|
|
//---------------------------------------------------------
|
|
// Ensure that rectangle is properly specified
|
|
//---------------------------------------------------------
|
|
if (x2 < x1)
|
|
{
|
|
int temp;
|
|
|
|
temp = x1;
|
|
x1 = x2;
|
|
x2 = temp;
|
|
}
|
|
|
|
if (y2 < y1)
|
|
{
|
|
int temp;
|
|
|
|
temp = y1;
|
|
y1 = y2;
|
|
y2 = temp;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Verify that values are legitimate
|
|
//---------------------------------------------------------
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
|
|
Verify(x1 >= 0);
|
|
Verify(x1 <= x2);
|
|
Verify(x2 < width);
|
|
|
|
Verify(y1 >= 0);
|
|
Verify(y1 <= y2);
|
|
Verify(y2 < height);
|
|
//---------------------------------------------------------
|
|
// Update changedLine array
|
|
//---------------------------------------------------------
|
|
MarkChangedLines(y1, y2);
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Prepare to fill
|
|
//---------------------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"x1=" << x1 << ", " << "y1=" << y1 << "\n" <<
|
|
"x2=" << x2 << ", " << "y2=" << y2 << "\n" <<
|
|
std::flush
|
|
);
|
|
# endif
|
|
buildDestPointer(x1, y1, &dest_pointer);
|
|
|
|
rect_height = y2 - y1 + 1;
|
|
rect_width = x2 - x1 + 1;
|
|
dest_fixup = width - rect_width;
|
|
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"rect_height=" << rect_height << "\n" <<
|
|
"rect_width=" << rect_width << "\n" <<
|
|
"dest_fixup=" << dest_fixup << "\n" <<
|
|
std::flush
|
|
);
|
|
# endif
|
|
//---------------------------------------------------------
|
|
// Fill the rectangle
|
|
//---------------------------------------------------------
|
|
switch(operation)
|
|
{
|
|
case GraphicsDisplay::Replace:
|
|
for( ; rect_height>0; --rect_height)
|
|
{
|
|
for(x=rect_width; x>0; --x)
|
|
{
|
|
*dest_pointer = (Byte) color;
|
|
dest_pointer++;
|
|
}
|
|
dest_pointer += dest_fixup;
|
|
}
|
|
break;
|
|
|
|
case GraphicsDisplay::And:
|
|
for( ; rect_height>0; --rect_height)
|
|
{
|
|
for(x=rect_width; x>0; --x)
|
|
{
|
|
*dest_pointer++ &= (Byte) color;
|
|
}
|
|
dest_pointer += dest_fixup;
|
|
}
|
|
break;
|
|
|
|
case GraphicsDisplay::Or:
|
|
for( ; rect_height>0; --rect_height)
|
|
{
|
|
for(x=rect_width; x>0; --x)
|
|
{
|
|
*dest_pointer++ |= (Byte) color;
|
|
}
|
|
dest_pointer += dest_fixup;
|
|
}
|
|
break;
|
|
|
|
case GraphicsDisplay::Xor:
|
|
for( ; rect_height>0; --rect_height)
|
|
{
|
|
for(x=rect_width; x>0; --x)
|
|
{
|
|
*dest_pointer++ ^= (Byte) color;
|
|
}
|
|
dest_pointer += dest_fixup;
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
void
|
|
Video8BitBuffered::DrawText(
|
|
int /*color*/,
|
|
int /*bitmask*/,
|
|
Enumeration /*operation*/,
|
|
Logical /*opaque*/,
|
|
int /*rotation*/,
|
|
Enumeration /*fontNumber*/,
|
|
Logical /*vertical*/,
|
|
GraphicsDisplay::Justification /*justification*/,
|
|
Rectangle2D */*clippingRectanglepointer*/,
|
|
char */*stringPointer*/
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell("Video8BitBuffered::DrawText()\n");
|
|
# endif
|
|
Check(this);
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
Check_Fpu();
|
|
if (!valid)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawBitMap
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawBitMap(
|
|
int color,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::DrawBitMap(<" <<
|
|
x << ", " <<
|
|
y << ">,<" <<
|
|
sLeft << ", " <<
|
|
sBottom << ", " <<
|
|
sRight << ", " <<
|
|
sTop << ">" <<
|
|
")\n"
|
|
);
|
|
# endif
|
|
Check(this);
|
|
Verify(x >= bounds.bottomLeft.x);
|
|
Verify(x <= bounds.topRight.x);
|
|
Verify(y >= bounds.bottomLeft.y);
|
|
Verify(y <= bounds.topRight.y);
|
|
|
|
int
|
|
map_width,
|
|
map_height,
|
|
map_max_y,
|
|
bits,
|
|
bit_test,
|
|
first_bit_test;
|
|
|
|
Word
|
|
*source_pointer_begin,
|
|
*source_pointer;
|
|
Byte
|
|
*dest_pointer_begin,
|
|
*dest_pointer;
|
|
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Ensure that source rectangle is properly specified
|
|
//---------------------------------------------------------
|
|
Verify(bitmap != NULL);
|
|
|
|
Verify(sLeft >= 0);
|
|
Verify(sLeft <= sRight);
|
|
Verify(sRight < bitmap->Data.Size.x);
|
|
|
|
Verify(sBottom >= 0);
|
|
Verify(sBottom <= sTop);
|
|
Verify(sTop < bitmap->Data.Size.y);
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y = maximumY - y;
|
|
|
|
map_max_y = bitmap->Data.Size.y-1;
|
|
sTop = map_max_y - sTop;
|
|
sBottom = map_max_y - sBottom;
|
|
|
|
map_width = sRight - sLeft + 1;
|
|
map_height = sBottom - sTop + 1;
|
|
|
|
# if defined(DEBUG)
|
|
Tell("x=" << x << ", y=" << y << "\n");
|
|
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
|
|
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
|
|
# endif
|
|
|
|
Verify(map_width > 0);
|
|
Verify(map_width <= bitmap->Data.Size.x);
|
|
Verify(map_height > 0);
|
|
Verify(map_height <= bitmap->Data.Size.y);
|
|
|
|
Verify(x >= 0);
|
|
Verify(x < width);
|
|
Verify(y >= 0);
|
|
Verify(y < height);
|
|
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Prepare to draw bitmap
|
|
//---------------------------------------------------------
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
|
|
source_pointer_begin =
|
|
bitmap->Data.MapPointer +
|
|
(sLeft >> 4) +
|
|
(sBottom * bitmap->Data.WidthInWords);
|
|
|
|
first_bit_test = 1 << (15-(sLeft & 15));
|
|
|
|
buildDestPointer(
|
|
x, y,
|
|
&dest_pointer_begin
|
|
);
|
|
|
|
switch (rotation)
|
|
{
|
|
default:
|
|
//--------------------------------------------
|
|
// transparent bitmap, zero degrees
|
|
// .-----.
|
|
// | |
|
|
// | |
|
|
// Y |
|
|
// #X----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("zero: xp=" << (x+map_width-1) << ", yp=" << (y-map_height+1) << "\n");
|
|
# endif
|
|
Verify(x+map_width-1 >= 0);
|
|
Verify(x+map_width-1 < width);
|
|
Verify(y-map_height+1 >= 0);
|
|
Verify(y-map_height+1 < height);
|
|
|
|
MarkChangedLines(y-map_height+1, y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
UP_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 90:
|
|
//--------------------------------------------
|
|
// Transparent bitmap, 90 degrees
|
|
// #Y----.
|
|
// X |
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n");
|
|
# endif
|
|
Verify(x+map_height >= 0);
|
|
Verify(x+map_height < width);
|
|
Verify(y+map_width >= 0);
|
|
Verify(y+map_width < height);
|
|
|
|
MarkChangedLines(y, y+map_width);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
RIGHT_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
//--------------------------------------------
|
|
// Transparent bitmap, 180 degrees
|
|
// .----X#
|
|
// | Y
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n");
|
|
# endif
|
|
Verify(x-map_width+1 >= 0);
|
|
Verify(x-map_width+1 < width);
|
|
Verify(y+map_height >= 0);
|
|
Verify(y+map_height < height);
|
|
|
|
MarkChangedLines(y, y+map_height);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
DOWN_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
//--------------------------------------------
|
|
// Transparent bitmap, 270 degrees
|
|
// .-----.
|
|
// | |
|
|
// | X
|
|
// | |
|
|
// .--Y--#
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n");
|
|
# endif
|
|
|
|
Verify(x-map_height >= 0);
|
|
Verify(x-map_height < width);
|
|
Verify(y-(map_width-1) >= 0);
|
|
Verify(y-(map_width-1) < height);
|
|
|
|
MarkChangedLines(y-(map_width-1), y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
LEFT_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawBitMapOpaque
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawBitMapOpaque(
|
|
int foreground,
|
|
int background,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::DrawBitMapOpaque(<" <<
|
|
x << ", " <<
|
|
y << ">,<" <<
|
|
sLeft << ", " <<
|
|
sBottom << ", " <<
|
|
sRight << ", " <<
|
|
sTop << ">" <<
|
|
")\n"
|
|
);
|
|
# endif
|
|
Check(this);
|
|
Verify(x >= bounds.bottomLeft.x);
|
|
Verify(x <= bounds.topRight.x);
|
|
Verify(y >= bounds.bottomLeft.y);
|
|
Verify(y <= bounds.topRight.y);
|
|
|
|
int
|
|
map_width,
|
|
map_height,
|
|
map_max_y,
|
|
bits,
|
|
bit_test,
|
|
first_bit_test;
|
|
|
|
Word
|
|
*source_pointer_begin,
|
|
*source_pointer;
|
|
Byte
|
|
*dest_pointer_begin,
|
|
*dest_pointer;
|
|
Byte
|
|
color;
|
|
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Ensure that source rectangle is properly specified
|
|
//---------------------------------------------------------
|
|
Verify(bitmap != NULL);
|
|
|
|
Verify(sLeft >= 0);
|
|
Verify(sLeft <= sRight);
|
|
Verify(sRight < bitmap->Data.Size.x);
|
|
|
|
Verify(sBottom >= 0);
|
|
Verify(sBottom <= sTop);
|
|
Verify(sTop < bitmap->Data.Size.y);
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y = maximumY - y;
|
|
|
|
map_max_y = bitmap->Data.Size.y-1;
|
|
sTop = map_max_y - sTop;
|
|
sBottom = map_max_y - sBottom;
|
|
|
|
map_width = sRight - sLeft + 1;
|
|
map_height = sBottom - sTop + 1;
|
|
|
|
# if defined(DEBUG)
|
|
Tell("x=" << x << ", y=" << y << "\n");
|
|
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
|
|
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
|
|
# endif
|
|
|
|
Verify(map_width > 0);
|
|
Verify(map_width <= bitmap->Data.Size.x);
|
|
Verify(map_height > 0);
|
|
Verify(map_height <= bitmap->Data.Size.y);
|
|
|
|
Verify(x >= 0);
|
|
Verify(x < width);
|
|
Verify(y >= 0);
|
|
Verify(y < height);
|
|
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Prepare to draw bitmap
|
|
//---------------------------------------------------------
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
|
|
source_pointer_begin =
|
|
bitmap->Data.MapPointer +
|
|
(sLeft >> 4) +
|
|
(sBottom * bitmap->Data.WidthInWords);
|
|
|
|
first_bit_test = 1 << (15-(sLeft & 15));
|
|
|
|
buildDestPointer(
|
|
x, y,
|
|
&dest_pointer_begin
|
|
);
|
|
|
|
switch (rotation)
|
|
{
|
|
default:
|
|
//--------------------------------------------
|
|
// opaque bitmap, zero degrees
|
|
// .-----.
|
|
// | |
|
|
// | |
|
|
// Y |
|
|
// #X----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n");
|
|
# endif
|
|
Verify(x+map_width >= 0);
|
|
Verify(x+map_width <= width); // HACK? <, or <=?
|
|
Verify(y-map_height+1 >= 0);
|
|
Verify(y-map_height+1 < height);
|
|
|
|
MarkChangedLines(y-map_height+1, y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
UP_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
color = (Byte) foreground;
|
|
}
|
|
else
|
|
{
|
|
color = (Byte) background;
|
|
}
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 90:
|
|
//--------------------------------------------
|
|
// opaque bitmap, 90 degrees
|
|
// #Y----.
|
|
// X |
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n");
|
|
# endif
|
|
Verify(x+map_height >= 0);
|
|
Verify(x+map_height < width);
|
|
Verify(y+map_width >= 0);
|
|
Verify(y+map_width < height);
|
|
|
|
MarkChangedLines(y, y+map_width);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
RIGHT_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
color = (Byte) foreground;
|
|
}
|
|
else
|
|
{
|
|
color = (Byte) background;
|
|
}
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
//--------------------------------------------
|
|
// opaque bitmap, 180 degrees
|
|
// .----X#
|
|
// | Y
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n");
|
|
# endif
|
|
Verify(x-map_width+1 >= 0);
|
|
Verify(x-map_width+1 < width);
|
|
Verify(y+map_height >= 0);
|
|
Verify(y+map_height < height);
|
|
|
|
MarkChangedLines(y, y+map_height);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
DOWN_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
color = (Byte) foreground;
|
|
}
|
|
else
|
|
{
|
|
color = (Byte) background;
|
|
}
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
//--------------------------------------------
|
|
// opaque bitmap, 270 degrees
|
|
// .-----.
|
|
// | |
|
|
// | X
|
|
// | |
|
|
// .--Y--#
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("xp=" << (x-map_height+1) << ", yp=" << (y-(map_width-1)) << "\n");
|
|
# endif
|
|
|
|
Verify(x-map_height >= 0);
|
|
Verify(x-map_height < width);
|
|
Verify(y-(map_width-1) >= 0);
|
|
Verify(y-(map_width-1) < height);
|
|
|
|
MarkChangedLines(y-(map_width-1), y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_BITMAP(source_pointer_begin, bitmap);
|
|
LEFT_DEST(dest_pointer_begin);
|
|
|
|
bit_test = first_bit_test;
|
|
bits = *source_pointer++;
|
|
|
|
for(x=map_width; x>0; --x,bit_test>>=1)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
if (bit_test == 0)
|
|
{
|
|
bit_test = 0x8000;
|
|
bits = *source_pointer++;
|
|
}
|
|
|
|
if (bits & bit_test)
|
|
{
|
|
color = (Byte) foreground;
|
|
}
|
|
else
|
|
{
|
|
color = (Byte) background;
|
|
}
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawPixelMap8
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawPixelMap8(
|
|
int */*translation_table*/,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::DrawPixelMap8(<" <<
|
|
x << ", " <<
|
|
y << ">,<" <<
|
|
sLeft << ", " <<
|
|
sBottom << ", " <<
|
|
sRight << ", " <<
|
|
sTop << ">" <<
|
|
")\n"
|
|
);
|
|
# endif
|
|
Check(this);
|
|
Verify(x >= bounds.bottomLeft.x);
|
|
Verify(x <= bounds.topRight.x);
|
|
Verify(y >= bounds.bottomLeft.y);
|
|
Verify(y <= bounds.topRight.y);
|
|
|
|
int
|
|
map_width,
|
|
map_height,
|
|
map_max_y;
|
|
|
|
Byte
|
|
color,
|
|
*source_pointer_begin,
|
|
*source_pointer,
|
|
*dest_pointer_begin,
|
|
*dest_pointer;
|
|
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Ensure that source rectangle is properly specified
|
|
//---------------------------------------------------------
|
|
Verify(pixelmap != NULL);
|
|
|
|
Verify(sLeft >= 0);
|
|
Verify(sLeft <= sRight);
|
|
Verify(sRight < pixelmap->Data.Size.x);
|
|
|
|
Verify(sBottom >= 0);
|
|
Verify(sBottom <= sTop);
|
|
Verify(sTop < pixelmap->Data.Size.y);
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y = maximumY - y;
|
|
|
|
map_max_y = pixelmap->Data.Size.y-1;
|
|
sTop = map_max_y - sTop;
|
|
sBottom = map_max_y - sBottom;
|
|
|
|
map_width = sRight - sLeft + 1;
|
|
map_height = sBottom - sTop + 1;
|
|
|
|
# if defined(DEBUG)
|
|
Tell("x=" << x << ", y=" << y << "\n");
|
|
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
|
|
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
|
|
# endif
|
|
|
|
Verify(map_width > 0);
|
|
Verify(map_width <= pixelmap->Data.Size.x);
|
|
Verify(map_height > 0);
|
|
Verify(map_height <= pixelmap->Data.Size.y);
|
|
|
|
Verify(x >= 0);
|
|
Verify(x < width);
|
|
Verify(y >= 0);
|
|
Verify(y < height);
|
|
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Prepare to draw bitmap
|
|
//---------------------------------------------------------
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
|
|
source_pointer_begin =
|
|
pixelmap->Data.MapPointer +
|
|
sLeft +
|
|
(sBottom * pixelmap->Data.Size.x);
|
|
|
|
buildDestPointer(
|
|
x, y,
|
|
&dest_pointer_begin
|
|
);
|
|
|
|
if (opaque)
|
|
{
|
|
switch (rotation)
|
|
{
|
|
default:
|
|
//--------------------------------------------
|
|
// Opaque pixelmap, zero degrees
|
|
// .-----.
|
|
// | |
|
|
// | |
|
|
// Y |
|
|
// #X----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Opaque zero: xp=" << (x+map_width) <<
|
|
", yp=" << (y-map_height+1) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_width >= 0);
|
|
Verify(x+map_width < width);
|
|
Verify(y-map_height+1 >= 0);
|
|
Verify(y-map_height+1 < height);
|
|
|
|
MarkChangedLines(y-map_height+1, y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
UP_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 90:
|
|
//--------------------------------------------
|
|
// Opaque pixelmap, 90 degrees
|
|
// #Y----.
|
|
// X |
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Opaque 90: xp=" << (x+map_height) <<
|
|
", yp=" << (y+map_width) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_height >= 0);
|
|
Verify(x+map_height < width);
|
|
Verify(y+map_width >= 0);
|
|
Verify(y+map_width < height);
|
|
|
|
MarkChangedLines(y, y+map_width);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
RIGHT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
//--------------------------------------------
|
|
// Opaque pixelmap, 180 degrees
|
|
// .----X#
|
|
// | Y
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Opaque 180: xp=" << (x-map_width+1) <<
|
|
", yp=" << (y+map_height) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x-map_width+1 >= 0);
|
|
Verify(x-map_width+1 < width);
|
|
Verify(y+map_height >= 0);
|
|
Verify(y+map_height < height);
|
|
|
|
MarkChangedLines(y, y+map_height);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
DOWN_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
//--------------------------------------------
|
|
// Opaque pixelmap, 270 degrees
|
|
// .-----.
|
|
// | |
|
|
// | X
|
|
// | |
|
|
// .--Y--#
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("Opaque 270: x=" << x << ", y=" << y << "\n");
|
|
Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n");
|
|
# endif
|
|
Verify(x-map_height >= 0);
|
|
Verify(x-map_height < width);
|
|
Verify(y-(map_width-1) >= 0);
|
|
Verify(y-(map_width-1) < height);
|
|
|
|
MarkChangedLines(y-(map_width-1), y);
|
|
|
|
for(y=map_height ; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
LEFT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (rotation)
|
|
{
|
|
default:
|
|
//--------------------------------------------
|
|
// Transparent pixelmap, zero degrees
|
|
// .-----.
|
|
// | |
|
|
// | |
|
|
// Y |
|
|
// #X----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"transparent zero: xp=" << (x+map_width) <<
|
|
", yp=" << (y-map_height+1) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_width >= 0);
|
|
Verify(x+map_width < width);
|
|
Verify(y-map_height+1 >= 0);
|
|
Verify(y-map_height+1 < height);
|
|
|
|
MarkChangedLines(y-map_height+1, y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
UP_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
if (color)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 90:
|
|
//--------------------------------------------
|
|
// Transparent pixelmap, 90 degrees
|
|
// #Y----.
|
|
// X |
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"transparent 90: xp=" << (x+map_height) <<
|
|
", yp=" << (y+map_width) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_height >= 0);
|
|
Verify(x+map_height < width);
|
|
Verify(y+map_width >= 0);
|
|
Verify(y+map_width < height);
|
|
|
|
MarkChangedLines(y, y+map_width);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
RIGHT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
if (color)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
//--------------------------------------------
|
|
// Transparent pixelmap, 180 degrees
|
|
// .----X#
|
|
// | Y
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"transparent 180: xp=" << (x-map_width+1) <<
|
|
", yp=" << (y+map_height) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x-map_width+1 >= 0);
|
|
Verify(x-map_width+1 < width);
|
|
Verify(y+map_height >= 0);
|
|
Verify(y+map_height < height);
|
|
|
|
MarkChangedLines(y, y+map_height);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
DOWN_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
if (color)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
//--------------------------------------------
|
|
// Transparent pixelmap, 270 degrees
|
|
// .-----.
|
|
// | |
|
|
// | X
|
|
// | |
|
|
// .--Y--#
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("transparent 270: x=" << x << ", y=" << y << "\n");
|
|
Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n");
|
|
# endif
|
|
Verify(x-map_height >= 0);
|
|
Verify(x-map_height < width);
|
|
Verify(y-(map_width-1) >= 0);
|
|
Verify(y-(map_width-1) < height);
|
|
|
|
MarkChangedLines(y-(map_width-1), y);
|
|
|
|
for(y=map_height ; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
LEFT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
color = *source_pointer++; //SOURCE_RIGHT
|
|
if (color)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===================================================================
|
|
// DrawPixelMap8SingleColor
|
|
//===================================================================
|
|
void
|
|
Video8BitBuffered::DrawPixelMap8SingleColor(
|
|
int color,
|
|
int /*bitmask*/,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Video8BitBuffered::DrawPixelMap8SingleColor(<" <<
|
|
x << ", " <<
|
|
y << ">,<" <<
|
|
sLeft << ", " <<
|
|
sBottom << ", " <<
|
|
sRight << ", " <<
|
|
sTop << ">" <<
|
|
")\n"
|
|
);
|
|
# endif
|
|
Check(this);
|
|
Verify(x >= bounds.bottomLeft.x);
|
|
Verify(x <= bounds.topRight.x);
|
|
Verify(y >= bounds.bottomLeft.y);
|
|
Verify(y <= bounds.topRight.y);
|
|
|
|
int
|
|
map_width,
|
|
map_height,
|
|
map_max_y;
|
|
|
|
Byte
|
|
source_data,
|
|
*source_pointer_begin,
|
|
*source_pointer,
|
|
*dest_pointer_begin,
|
|
*dest_pointer;
|
|
|
|
//---------------------------------------------------------
|
|
// If pixelbuffer is invalid, do nothing
|
|
//---------------------------------------------------------
|
|
if (!valid)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//---------------------------------------------------------
|
|
// Ensure that source rectangle is properly specified
|
|
//---------------------------------------------------------
|
|
Verify(pixelmap != NULL);
|
|
|
|
Verify(sLeft >= 0);
|
|
Verify(sLeft <= sRight);
|
|
Verify(sRight < pixelmap->Data.Size.x);
|
|
|
|
Verify(sBottom >= 0);
|
|
Verify(sBottom <= sTop);
|
|
Verify(sTop < pixelmap->Data.Size.y);
|
|
//---------------------------------------------------------
|
|
// Convert to screen co-ordinates
|
|
//---------------------------------------------------------
|
|
y = maximumY - y;
|
|
|
|
map_max_y = pixelmap->Data.Size.y-1;
|
|
sTop = map_max_y - sTop;
|
|
sBottom = map_max_y - sBottom;
|
|
|
|
map_width = sRight - sLeft + 1;
|
|
map_height = sBottom - sTop + 1;
|
|
|
|
# if defined(DEBUG)
|
|
Tell("x=" << x << ", y=" << y << "\n");
|
|
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
|
|
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
|
|
# endif
|
|
|
|
Verify(map_width > 0);
|
|
Verify(map_width <= pixelmap->Data.Size.x);
|
|
Verify(map_height > 0);
|
|
Verify(map_height <= pixelmap->Data.Size.y);
|
|
|
|
Verify(x >= 0);
|
|
Verify(x < width);
|
|
Verify(y >= 0);
|
|
Verify(y < height);
|
|
|
|
//---------------------------------------------------------
|
|
// We really need inverse bitmap here
|
|
//---------------------------------------------------------
|
|
// bitmask = ~bitmask;
|
|
//---------------------------------------------------------
|
|
// Prepare to draw bitmap
|
|
//---------------------------------------------------------
|
|
Verify(pixelBuffer->Data.MapPointer != NULL);
|
|
|
|
source_pointer_begin =
|
|
pixelmap->Data.MapPointer +
|
|
sLeft +
|
|
(sBottom * pixelmap->Data.Size.x);
|
|
|
|
buildDestPointer(
|
|
x, y,
|
|
&dest_pointer_begin
|
|
);
|
|
|
|
{
|
|
switch (rotation)
|
|
{
|
|
default:
|
|
//--------------------------------------------
|
|
// Single-color pixelmap, zero degrees
|
|
// .-----.
|
|
// | |
|
|
// | |
|
|
// Y |
|
|
// #X----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Single-color zero: xp=" << (x+map_width) <<
|
|
", yp=" << (y-map_height+1) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_width >= 0);
|
|
Verify(x+map_width < width);
|
|
Verify(y-map_height+1 >= 0);
|
|
Verify(y-map_height+1 < height);
|
|
|
|
MarkChangedLines(y-map_height+1, y);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
UP_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
source_data = *source_pointer++; //SOURCE_RIGHT
|
|
if (source_data)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
RIGHT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 90:
|
|
//--------------------------------------------
|
|
// Single-color pixelmap, 90 degrees
|
|
// #Y----.
|
|
// X |
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Single-color 90: xp=" << (x+map_height) <<
|
|
", yp=" << (y+map_width) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x+map_height >= 0);
|
|
Verify(x+map_height < width);
|
|
Verify(y+map_width >= 0);
|
|
Verify(y+map_width < height);
|
|
|
|
MarkChangedLines(y, y+map_width);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
RIGHT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
source_data = *source_pointer++; //SOURCE_RIGHT
|
|
if (source_data)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
DOWN_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
//--------------------------------------------
|
|
// Single-color pixelmap, 180 degrees
|
|
// .----X#
|
|
// | Y
|
|
// | |
|
|
// | |
|
|
// .-----.
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell(
|
|
"Single-color 180: xp=" << (x-map_width+1) <<
|
|
", yp=" << (y+map_height) << "\n"
|
|
);
|
|
# endif
|
|
Verify(x-map_width+1 >= 0);
|
|
Verify(x-map_width+1 < width);
|
|
Verify(y+map_height >= 0);
|
|
Verify(y+map_height < height);
|
|
|
|
MarkChangedLines(y, y+map_height);
|
|
|
|
for(y=map_height; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
DOWN_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
source_data = *source_pointer++; //SOURCE_RIGHT
|
|
if (source_data)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
LEFT_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
//--------------------------------------------
|
|
// Single-color pixelmap, 270 degrees
|
|
// .-----.
|
|
// | |
|
|
// | X
|
|
// | |
|
|
// .--Y--#
|
|
//--------------------------------------------
|
|
# if defined(DEBUG)
|
|
Tell("Single-color 270: x=" << x << ", y=" << y << "\n");
|
|
Tell("xp=" << x-map_height << ", yp=" << y-map_width << "\n");
|
|
# endif
|
|
Verify(x-map_height >= 0);
|
|
Verify(x-map_height < width);
|
|
Verify(y-map_width >= 0);
|
|
Verify(y-map_width < height);
|
|
|
|
MarkChangedLines(y-map_width, y);
|
|
|
|
for(y=map_height ; y>0; --y)
|
|
{
|
|
source_pointer = source_pointer_begin;
|
|
dest_pointer = dest_pointer_begin;
|
|
|
|
UP_SOURCE(source_pointer_begin, pixelmap);
|
|
LEFT_DEST(dest_pointer_begin);
|
|
|
|
for(x=map_width; x>0; --x)
|
|
{
|
|
Verify(dest_pointer >= pixelBuffer->Data.MapPointer);
|
|
Verify(dest_pointer < pixelBuffer->Data.MapPointer+
|
|
(width*height));
|
|
|
|
source_data = *source_pointer++; //SOURCE_RIGHT
|
|
if (source_data)
|
|
{
|
|
WRITEPIXEL(dest_pointer, operation, color)
|
|
}
|
|
UP_DEST(dest_pointer);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//########################################################################
|
|
//########################### L4BytePort #############################
|
|
//########################################################################
|
|
|
|
L4BytePort::L4BytePort(
|
|
Video8BitBuffered *graphics_display,
|
|
const char *name,
|
|
int rotation
|
|
):GraphicsPort(graphics_display, name)
|
|
{
|
|
//
|
|
// Save the base rotation value
|
|
//
|
|
baseRotation = rotation;
|
|
//
|
|
// Initialize conversion constants
|
|
//
|
|
maximumX = bounds.topRight.x - bounds.bottomLeft.x;
|
|
maximumY = bounds.topRight.y - bounds.bottomLeft.y;
|
|
//
|
|
// Overwrite the GraphicsPort::bounds data with rotated values
|
|
// for GraphView's benefit
|
|
//
|
|
switch(baseRotation)
|
|
{
|
|
default:
|
|
// do nothing
|
|
break;
|
|
|
|
case 90:
|
|
case 270:
|
|
if (graphics_display != NULL)
|
|
{
|
|
Check(graphics_display);
|
|
bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y;
|
|
bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x;
|
|
bounds.topRight.x = graphics_display->bounds.topRight.y;
|
|
bounds.topRight.y = graphics_display->bounds.topRight.x;
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
L4BytePort::~L4BytePort()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
L4BytePort::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
void
|
|
L4BytePort::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "L4BytePort:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "baseRotation =" << baseRotation << "\n";
|
|
std::cout << temp << "maximumX =" << maximumX << "\n";
|
|
std::cout << temp << "maximumY =" << maximumY << "\n";
|
|
std::cout << temp << "bounds =" << bounds << "\n";
|
|
std::cout << std::flush;
|
|
GraphicsPort::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawPoint(
|
|
int color,
|
|
Enumeration operation,
|
|
int x, int y
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
int
|
|
xp, yp;
|
|
|
|
convertPortPair(&xp, &yp, x, y);
|
|
|
|
graphicsDisplay->
|
|
DrawPoint(
|
|
color,
|
|
0,
|
|
operation,
|
|
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawLine(
|
|
int color,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
Logical include_last_pixel
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
int
|
|
x1p, y1p,
|
|
x2p, y2p;
|
|
|
|
convertPortPair(&x1p, &y1p, x1, y1);
|
|
convertPortPair(&x2p, &y2p, x2, y2);
|
|
|
|
graphicsDisplay->
|
|
DrawLine(
|
|
color,
|
|
0,
|
|
operation,
|
|
x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y,
|
|
x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y,
|
|
include_last_pixel
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawFilledRectangle(
|
|
int color,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
int
|
|
x1p, y1p,
|
|
x2p, y2p;
|
|
|
|
convertPortPair(&x1p, &y1p, x1, y1);
|
|
convertPortPair(&x2p, &y2p, x2, y2);
|
|
|
|
graphicsDisplay->
|
|
DrawFilledRectangle(
|
|
color,
|
|
0,
|
|
operation,
|
|
x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y,
|
|
x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawText(
|
|
int /*color*/,
|
|
Enumeration /*operation*/,
|
|
Logical /*opaque*/,
|
|
int /*rotation*/,
|
|
Enumeration /*fontNumber*/,
|
|
Logical /*vertical*/,
|
|
GraphicsDisplay::Justification /*justification*/,
|
|
Rectangle2D */*clippingRectanglepointer*/,
|
|
char */*stringPointer*/
|
|
)
|
|
{
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawBitMap(
|
|
int color,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
if (bitmap == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
if (bitmap->Data.MapPointer == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(bitmap);
|
|
|
|
int
|
|
xp, yp;
|
|
|
|
convertPortPair(&xp, &yp, x, y);
|
|
|
|
rotation += baseRotation;
|
|
while (rotation < 0) { rotation += 360; }
|
|
while (rotation >= 360) { rotation -= 360; }
|
|
|
|
graphicsDisplay->
|
|
DrawBitMap(
|
|
color,
|
|
0,
|
|
operation,
|
|
rotation,
|
|
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
|
|
bitmap,
|
|
sLeft, sBottom, sRight, sTop
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawBitMapOpaque(
|
|
int color,
|
|
int background,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
if (bitmap == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
if (bitmap->Data.MapPointer == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(bitmap);
|
|
|
|
int
|
|
xp, yp;
|
|
|
|
convertPortPair(&xp, &yp, x, y);
|
|
|
|
rotation += baseRotation;
|
|
while (rotation < 0) { rotation += 360; }
|
|
while (rotation >= 360) { rotation -= 360; }
|
|
|
|
graphicsDisplay->
|
|
DrawBitMapOpaque(
|
|
color,
|
|
background,
|
|
0,
|
|
operation,
|
|
rotation,
|
|
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
|
|
bitmap,
|
|
sLeft, sBottom, sRight, sTop
|
|
);
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawPixelMap8(
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
if (pixelmap == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
if (pixelmap->Data.MapPointer == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(pixelmap);
|
|
|
|
int
|
|
xp, yp;
|
|
|
|
convertPortPair(&xp, &yp, x, y);
|
|
|
|
rotation += baseRotation;
|
|
while (rotation < 0) { rotation += 360; }
|
|
while (rotation >= 360) { rotation -= 360; }
|
|
|
|
graphicsDisplay->
|
|
DrawPixelMap8(
|
|
NULL,
|
|
0,
|
|
operation,
|
|
opaque,
|
|
rotation,
|
|
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
|
|
pixelmap,
|
|
sLeft, sBottom, sRight, sTop
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::DrawPixelMap8SingleColor(
|
|
int color,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sLeft, int sBottom, int sRight, int sTop
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
if (graphicsDisplay == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(graphicsDisplay);
|
|
|
|
if (pixelmap == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
if (pixelmap->Data.MapPointer == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(pixelmap);
|
|
|
|
int
|
|
xp, yp;
|
|
|
|
convertPortPair(&xp, &yp, x, y);
|
|
|
|
rotation += baseRotation;
|
|
while (rotation < 0) { rotation += 360; }
|
|
while (rotation >= 360) { rotation -= 360; }
|
|
|
|
graphicsDisplay->
|
|
DrawPixelMap8SingleColor(
|
|
color,
|
|
0,
|
|
operation,
|
|
rotation,
|
|
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
|
|
pixelmap,
|
|
sLeft, sBottom, sRight, sTop
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4BytePort::convertPortPair(
|
|
int *xp,
|
|
int *yp,
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
switch(baseRotation)
|
|
{
|
|
default:
|
|
*xp = x;
|
|
*yp = y;
|
|
break;
|
|
|
|
case 90:
|
|
*xp = y;
|
|
*yp = maximumY - x;
|
|
break;
|
|
|
|
case 180:
|
|
*xp = maximumX - x;
|
|
*yp = maximumY - y;
|
|
break;
|
|
|
|
case 270:
|
|
*xp = maximumX - y;
|
|
*yp = x;
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|