152 lines
2.8 KiB
C
152 lines
2.8 KiB
C
#include <string.h>
|
|
#include <alloca.h>
|
|
#include "wintype.h"
|
|
#include "log.h"
|
|
#include "fbinit.h"
|
|
#include "fontengine.h"
|
|
#include "fbprimitive.h"
|
|
|
|
inline static PUINT16 loc_from_coords(INT32 x, INT32 y)
|
|
{
|
|
return Fb_Ptr + (y * Fb_Info->width) + x;
|
|
}
|
|
|
|
UINT16 Fb_setpixel(INT32 x, INT32 y, UINT16 color, BOOL xor)
|
|
{
|
|
UINT16 rc;
|
|
PUINT16 loc = loc_from_coords(x, y);
|
|
|
|
rc = *loc;
|
|
if (xor)
|
|
*loc ^= color;
|
|
else
|
|
*loc = color;
|
|
return rc;
|
|
}
|
|
|
|
void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor)
|
|
{
|
|
INT32 tmp;
|
|
INT32 dx = x2 - x1;
|
|
INT32 dy = y2 - y1;
|
|
|
|
/* uses Bresenham's line algorithm with fixed-point arithmetic */
|
|
if (ABS(dx) < ABS(dy))
|
|
{
|
|
if (y1 > y2)
|
|
{
|
|
tmp = x1;
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
tmp = y1;
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
dx = -dx;
|
|
dy = -dy;
|
|
}
|
|
x1 <<= 16;
|
|
dx = (dx << 16) / dy;
|
|
while (y1 <= y2)
|
|
{
|
|
Fb_setpixel(x1 >> 16, y1, color, xor);
|
|
x1 += dx;
|
|
y1++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (x1 > x2)
|
|
{
|
|
tmp = x1;
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
tmp = y1;
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
dx = -dx;
|
|
dy = -dy;
|
|
}
|
|
y1 <<= 16;
|
|
dy = dx ? (dy << 16) / dx : 0;
|
|
while (x1 <= x2)
|
|
{
|
|
Fb_setpixel(x1, y1 >> 16, color, xor);
|
|
y1 += dy;
|
|
x1++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fb_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor)
|
|
{
|
|
Fb_line(x1, y1, x2, y1, color, xor);
|
|
Fb_line(x2, y1 + 1, x2, y2 - 1, color, xor);
|
|
Fb_line(x1, y2, x2, y2, color, xor);
|
|
Fb_line(x1, y1 + 1, x1, y2 - 1, color, xor);
|
|
}
|
|
|
|
void Fb_filled_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor)
|
|
{
|
|
INT32 tmp;
|
|
PUINT16 ps, p;
|
|
|
|
if (x1 > x2)
|
|
{
|
|
tmp = x1;
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
}
|
|
if (y1 > y2)
|
|
{
|
|
tmp = y1;
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
}
|
|
|
|
ps = loc_from_coords(x1, y1);
|
|
for (; y1 <= y2; y1++)
|
|
{
|
|
p = ps;
|
|
for (tmp = x1; tmp <= x2; tmp++)
|
|
{
|
|
if (xor)
|
|
*p++ ^= color;
|
|
else
|
|
*p++ = color;
|
|
}
|
|
ps += Fb_Info->width;
|
|
}
|
|
}
|
|
|
|
static void internal_textout(INT32 x, INT32 y, INT32 width, INT32 height, PBYTE gsbits)
|
|
{
|
|
INT32 i, j;
|
|
BYTE b;
|
|
PUINT16 dptr, lbuf;
|
|
|
|
if ((width == 0) && (height == 0))
|
|
return; /* must be drawing a space */
|
|
if (((x + width) >= Fb_Info->width) || ((y + height) >= Fb_Info->height))
|
|
return;
|
|
dptr = loc_from_coords(x, y);
|
|
lbuf = (PUINT16)alloca(width * sizeof(UINT16));
|
|
for (i=0; i<height; i++)
|
|
{
|
|
for (j=0; j<width; j++)
|
|
{
|
|
b = *gsbits++;
|
|
lbuf[j] = ((UINT16)(b >> 3) & 0x1F) << 11;
|
|
lbuf[j] |= ((UINT16)(b >> 2) & 0x3F) << 5;
|
|
lbuf[j] |= ((UINT16)(b >> 3) & 0x1F);
|
|
}
|
|
|
|
memcpy(dptr, lbuf, width * sizeof(UINT16));
|
|
dptr += Fb_Info->width;
|
|
}
|
|
}
|
|
|
|
void Fb_textout(INT32 x, INT32 y, PCSTR pstr)
|
|
{
|
|
FontEng_do_text_out(x, y, pstr, internal_textout);
|
|
}
|