upiwin/src/fbprimitive.c

171 lines
3.7 KiB
C

/*
* UPIWIN - Micro Pi Windowing Framework Kernel
* Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*-------------------------------------------------------------------------
*/
#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);
}