BizHawk/EMU7800/Core/FontRenderer.cs

171 lines
5.4 KiB
C#

/*
* FontRenderer
*
* A simple font renderer for displaying text during emulation. Font data and
* rendering algorithm courtesy of Bradford W. Mott's Stella source.
*
* Copyright © 2004 Mike Murphy
*
*/
using System;
namespace EMU7800.Core
{
/// <summary>
/// A simple font renderer for displaying text during emulation.
/// </summary>
public class FontRenderer
{
static readonly uint[] AlphaFontData =
{
0x699f999, // A
0xe99e99e, // B
0x6988896, // C
0xe99999e, // D
0xf88e88f, // E
0xf88e888, // F
0x698b996, // G
0x999f999, // H
0x7222227, // I
0x72222a4, // J
0x9accaa9, // K
0x888888f, // L
0x9ff9999, // M
0x9ddbb99, // N
0x6999996, // O
0xe99e888, // P
0x69999b7, // Q
0xe99ea99, // R
0x6986196, // S
0x7222222, // T
0x9999996, // U
0x9999966, // V
0x9999ff9, // W
0x99fff99, // X
0x9996244, // Y
0xf12488f // Z
};
static readonly uint[] DigitFontData =
{
0x69bd996, // 0
0x2622227, // 1
0x691248f, // 2
0x6916196, // 3
0xaaaf222, // 4
0xf88e11e, // 5
0x698e996, // 6
0xf112244, // 7
0x6996996, // 8
0x6997196 // 9
};
/// <summary>
/// Draw specified text at specified position using the specified foreground and background colors.
/// </summary>
/// <param name="frameBuffer"></param>
/// <param name="text"></param>
/// <param name="xoffset"></param>
/// <param name="yoffset"></param>
/// <param name="fore"></param>
/// <param name="back"></param>
/// <exception cref="ArgumentNullException">text must be non-null.</exception>
public void DrawText(FrameBuffer frameBuffer, string text, int xoffset, int yoffset, byte fore, byte back)
{
if (text == null)
throw new ArgumentNullException("text");
var textchars = text.ToUpper().ToCharArray();
for (var i = 0; i < text.Length + 1; i++)
{
for (var j = 0; j < 9; j++)
{
var pos = (j + yoffset) * frameBuffer.VisiblePitch + i * 5;
for (var k = 0; k < 5; k++)
{
while (pos >= frameBuffer.VideoBufferByteLength)
{
pos -= frameBuffer.VideoBufferByteLength;
}
while (pos < 0)
{
pos += frameBuffer.VideoBufferByteLength;
}
frameBuffer.VideoBuffer[pos++] = back;
}
}
}
for (var i = 0; i < text.Length; i++)
{
var c = textchars[i];
uint fdata;
switch (c)
{
case '/':
case '\\':
fdata = 0x0122448;
break;
case '(':
fdata = 0x2488842;
break;
case ')':
fdata = 0x4211124;
break;
case '.':
fdata = 0x0000066;
break;
case ':':
fdata = 0x0660660;
break;
case '-':
fdata = 0x0007000;
break;
default:
if (c >= 'A' && c <= 'Z')
{
fdata = AlphaFontData[c - 'A'];
}
else if (c >= '0' && c <= '9')
{
fdata = DigitFontData[c - '0'];
}
else
{
fdata = 0;
}
break;
}
var ypos = 8;
for (var j = 0; j < 32; j++)
{
var xpos = j & 3;
if (xpos == 0)
{
ypos--;
}
var pos = (ypos + yoffset) * frameBuffer.VisiblePitch + (4 - xpos) + xoffset;
while (pos >= frameBuffer.VideoBufferByteLength)
{
pos -= frameBuffer.VideoBufferByteLength;
}
while (pos < 0)
{
pos += frameBuffer.VideoBufferByteLength;
}
if (((fdata >> j) & 1) != 0)
{
frameBuffer.VideoBuffer[pos] = fore;
}
}
xoffset += 5;
}
}
}
}