Newer
Older
Import / research / embedded / src / library / font.c
/*
Copyright (c) 2007-2013, John Ryland
*/
#include <oslayer.h>
#include <font.h>


// XXX quick fix to get it working
// fsMap should be a drop in replacement for mmap but seems to not be working now
//#define fsMmap		mmap


Font openFont(const char *mapableFont)
{
	int fd = fsOpen(mapableFont, O_RDONLY);
	unsigned int *d = (unsigned int *)fsMmap(0, 16, PROT_READ, MAP_PRIVATE, fd, 0);
	unsigned char *c;
	Font data;
	data.fd = fd;
	data.bits_per_pixel = d[0];
	data.pixel_size = d[1];
	data.map_size = d[2];
/*
	strPrint("data.bits_per_pixel: ");
	strPrint(strInteger(data.bits_per_pixel, 10));
	strPrint("\ndata.pixel_size: ");
	strPrint(strInteger(data.pixel_size, 10));
	strPrint("\ndata.map_size: ");
	strPrint(strInteger(data.map_size, 10));
	strPrint("\n");
*/
	fsMunmap(d, 16);
	c = (unsigned char *)fsMmap(0, data.map_size, PROT_READ, MAP_PRIVATE, fd, 0);
	data.glyphs = (Glyph *)(c + 16);
	data.pixel_data = (unsigned char *)(c + 16 + sizeof(Glyph)*256);
	return data;
}

void closeFont(Font font)
{
	fsClose(font.fd);
}

void drawChar(Image *image, int x, int y, unsigned char *data, int w, int h)
{
	int i, j;
	unsigned int col = 0xFFFF;
	for (j = 0; j < h; j++) {
		if ( (y + j >= 0) && (y + j < image->height) ) { 
			unsigned short *row = (unsigned short *)&image->pixel_data[((y+j)*image->width+x)*2];
			for (i = 0; i < w; i++) {
				if ( (x + i >= 0) && (x + i < image->width) ) { 
					int alpha = data[j*w+i];
					if (alpha == 0) {
						// nothing
					} else if (alpha == 255) {
						row[i] = col;
					} else {
						unsigned int r, g, b;
						alpha = 255 - alpha;
						r = alpha * ((row[i] >> 11) & 0x1F);
						g = alpha * ((row[i] >>  5) & 0x3F);
						b = alpha * ((row[i] >>  0) & 0x1F);
						alpha = 255 - alpha;
						r += alpha * ((col >> 11) & 0x1F);
						g += alpha * ((col >>  5) & 0x3F);
						b += alpha * ((col >>  0) & 0x1F);
						r >>= 8;
						g >>= 8;
						b >>= 8;
						row[i] = ((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F);
					}
				}
			}
		}
	}
}

void drawText(Image *image, int x1, int y1, Font font, const char *text)
{
	int i = 0;
	int x = x1;
	int ch;
	while ((ch = text[i]) != 0) {
		int xPos = x;
		/* don't add bitmap_left on first char */
		if ( i != 0 )
			xPos += font.glyphs[ch].left;
		drawChar(image, xPos, y1 + 16 - font.glyphs[ch].top,
				font.pixel_data + font.glyphs[ch].pixel_data_offset,
				font.glyphs[ch].width, font.glyphs[ch].height);
		/* correct for not adding bitmap_left on first char */
		if ( i == 0 )
			x -= font.glyphs[ch].left;
		x += font.glyphs[ch].horiAdvance;
		i++;
	}
}