/* $Id: render.c,v 1.3 2002/03/05 16:10:42 pavlovskii Exp $ */
#include "mgl.h"
#include "render.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <os/syscall.h>
#undef __FTERRORS_H__
#define FT_ERRORDEF( e, v, s ) { e, s },
#define FT_ERROR_START_LIST {
#define FT_ERROR_END_LIST { 0, 0 } };
const struct
{
int err_code;
const char* err_msg;
} ft_errors[] =
#include FT_ERRORS_H
#define vidAddToQueue(q, s) QueueAppend(q, s, sizeof(*s))
bool vidFlushQueue(queue_t *queue, addr_t video)
{
if (queue->length > 0)
{
params_vid_t params;
fileop_t op;
params.vid_draw.shapes = QUEUE_DATA(*queue);
params.vid_draw.length = queue->length;
if (FsRequestSync(video, VID_DRAW, ¶ms, sizeof(params), &op))
op.result = 0;
QueueClear(queue);
if (op.result != 0)
{
errno = op.result;
return false;
}
else
return true;
}
else
return true;
}
const char *mgliGetFtError(int error)
{
unsigned i;
static char str[20];
for (i = 0; i < _countof(ft_errors); i++)
if (ft_errors[i].err_code == error)
return ft_errors[i].err_msg;
sprintf(str, "unknown 0x%d", error);
return str;
}
void swap_MGLreal(MGLreal *a, MGLreal *b)
{
MGLreal temp = *b;
*b = *a;
*a = temp;
}
bool vidFillRect(queue_t *queue, point_t topLeft, point_t bottomRight,
colour_t colour)
{
vid_shape_t shape;
shape.shape = VID_SHAPE_FILLRECT;
shape.s.rect.rect.left = topLeft.x;
shape.s.rect.rect.top = topLeft.y;
shape.s.rect.rect.right = bottomRight.x;
shape.s.rect.rect.bottom = bottomRight.y;
shape.s.rect.colour = colour;
return vidAddToQueue(queue, &shape) != NULL;
}
bool vidVLine(queue_t *queue, int x, int y1, int y2, colour_t colour)
{
vid_shape_t shape;
shape.shape = VID_SHAPE_VLINE;
shape.s.line.a.x = shape.s.line.b.x = x;
shape.s.line.a.y = y1;
shape.s.line.b.y = y2;
shape.s.line.colour = colour;
return vidAddToQueue(queue, &shape) != NULL;
}
bool vidHLine(queue_t *queue, int x1, int x2, int y, colour_t colour)
{
vid_shape_t shape;
shape.shape = VID_SHAPE_HLINE;
shape.s.line.a.x = x1;
shape.s.line.b.x = x2;
shape.s.line.a.y = shape.s.line.b.y = y;
shape.s.line.colour = colour;
return vidAddToQueue(queue, &shape) != NULL;
}
bool vidLine(queue_t *queue, point_t from, point_t to, colour_t colour)
{
vid_shape_t shape;
shape.shape = VID_SHAPE_LINE;
shape.s.line.a = from;
shape.s.line.b = to;
shape.s.line.colour = colour;
return vidAddToQueue(queue, &shape) != NULL;
}
bool vidPutPixel(queue_t *queue, int x, int y, colour_t colour)
{
vid_shape_t shape;
shape.shape = VID_SHAPE_PUTPIXEL;
shape.s.pix.point.x = x;
shape.s.pix.point.y = y;
shape.s.pix.colour = colour;
return vidAddToQueue(queue, &shape) != NULL;
}
void glFillRect(MGLreal left, MGLreal top, MGLreal right, MGLreal bottom)
{
point_t topLeft, bottomRight;
CCV;
if (right < left)
swap_MGLreal(&left, &right);
if (bottom < top)
swap_MGLreal(&top, &bottom);
if (!mgliMapToSurface(left, top, &topLeft) ||
!mgliMapToSurface(right, bottom, &bottomRight))
return;
vidFillRect(¤t->render_queue, topLeft, bottomRight, current->colour);
}
void glClear(void)
{
point_t topLeft, bottomRight;
FT_UInt glyph_index;
int x, y;
FT_Error error;
CCV;
topLeft.x = topLeft.y = 0;
bottomRight.x = current->surf_width;
bottomRight.y = current->surf_height;
vidFillRect(¤t->render_queue, topLeft, bottomRight, current->clear_colour);
/*FT_Set_Pixel_Sizes(current->ft_face, 0, 20);
glyph_index = FT_Get_Char_Index(current->ft_face, 'a');
wprintf(L"glyph_index = %d\n", glyph_index);
error = FT_Load_Glyph(current->ft_face, glyph_index, FT_LOAD_DEFAULT);
if (error)
wprintf(L"FT_Load_Glyph: %S\n", mgliGetFtError(error));
else
{
FT_GlyphSlot slot = current->ft_face->glyph;
error = FT_Render_Glyph(current->ft_face->glyph, 0);
if (error)
wprintf(L"FT_Render_Glyph: %S\n", mgliGetFtError(error));
else
{
for (x = 0; x < slot->bitmap.rows; x++)
for (y = 0; y < slot->bitmap.width; y++)
vidPutPixel(current->video, x, y,
slot->bitmap.buffer[x + y * slot->bitmap.width]);
}
}*/
}
void glMoveTo(MGLreal x, MGLreal y)
{
CCV;
current->pos.x = x;
current->pos.y = y;
}
void glLineTo(MGLreal x, MGLreal y)
{
point_t to, from;
CCV;
mgliMapToSurface(x, y, &to);
mgliMapToSurface(current->pos.x, current->pos.y, &from);
if (from.x == to.x)
vidVLine(¤t->render_queue, from.x, from.y, to.y, current->colour);
else if (from.y == to.y)
vidHLine(¤t->render_queue, from.x, to.x, from.y, current->colour);
else
vidLine(¤t->render_queue, from, to, current->colour);
current->pos.x = x;
current->pos.y = y;
}
void glRectangle(MGLreal left, MGLreal top, MGLreal right, MGLreal bottom)
{
point_t topLeft, bottomRight;
CCV;
if (right < left)
swap_MGLreal(&left, &right);
if (bottom < top)
swap_MGLreal(&top, &bottom);
if (!mgliMapToSurface(left, top, &topLeft) ||
!mgliMapToSurface(right, bottom, &bottomRight))
return;
vidHLine(¤t->render_queue,
topLeft.x, bottomRight.x, topLeft.y, current->colour);
vidHLine(¤t->render_queue,
topLeft.x, bottomRight.x, bottomRight.y, current->colour);
vidVLine(¤t->render_queue,
topLeft.x, topLeft.y, bottomRight.y, current->colour);
vidVLine(¤t->render_queue,
bottomRight.x, topLeft.y, bottomRight.y, current->colour);
}
void glPutPixel(MGLreal x, MGLreal y)
{
point_t pt;
CCV;
mgliMapToSurface(x, y, &pt);
vidPutPixel(¤t->render_queue, pt.x, pt.y, current->colour);
}