using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Text;
using System.Drawing.Imaging;
namespace SpriteWave
{
public static class DigitImages
{
public const int digitW = 8;
public const int digitH = 16;
public const float fontSize = 12;
// List of pixel maps of numbers 0-9 (black then white)
private static byte[][] _numbersPix;
private const int numBufSize = digitW * digitH * Utils.cLen;
private static void CreateDigitMaps()
{
Font font;
try {
font = new Font(FontFamily.GenericMonospace, fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
}
catch (ArgumentException) {
font = SystemFonts.DefaultFont;
}
Brush[] clrs = {new SolidBrush(Color.Black), new SolidBrush(Color.White)};
// For positioning digit characters inside each image
const float numKernX = -2;
const float numKernY = 1;
var bounds = new RectangleF(
numKernX,
numKernY,
digitW - numKernX,
digitH - numKernY
);
var sizeRect = new Rectangle(
0, 0, digitW, digitH
);
_numbersPix = new byte[10 * 2][];
int idx = 0;
for (int i = 0; i < 2; i++) // 2 colours
{
for (int j = 0; j < 10; j++) // 10 digits
{
// Render text to a bitmap image
var bmp = new Bitmap(digitW, digitH, PixelFormat.Format32bppArgb);
using (var g = Graphics.FromImage(bmp))
{
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.DrawString(j.ToString(), font, clrs[i], bounds);
}
// Extract the pixel data out of the bitmap image
_numbersPix[idx] = new byte[numBufSize];
var data = bmp.LockBits(
sizeRect,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb
);
// Copy the bitmap data directly to our pixel array.
// Each pixel is stored as four bytes - B, G, R, then A.
Marshal.Copy(data.Scan0, _numbersPix[idx], 0, numBufSize);
bmp.UnlockBits(data);
idx++;
}
}
}
public static byte[] Generate(int count)
{
if (count < 2)
return null;
if (_numbersPix == null)
CreateDigitMaps();
// Minus one because maximum value is the last index, not the size
int nDigits = Utils.DigitCount(count - 1);
int[] digits = new int[nDigits];
// x2 is for black and white versions
var numArrayPix = new byte[numBufSize * nDigits * count * 2];
int stride = nDigits * digitW * Utils.cLen;
for (int i = 0; i < count; i++)
{
int dc = Utils.DigitCount(i);
int n = i;
int j;
// Format the digits list such that the number starts from the left side of the row, eg.
// 7 (out of 8) = |7|, 6 (out of 16) = |6 |, 14 (out of 256) = |14 |
for (j = 0; j < nDigits; j++)
{
if (j < dc)
digits[dc-j-1] = n % 10; // placed in reverse, as digit significance goes left->right
else
digits[j] = -1; // -1 means a blank space
n /= 10;
}
for (j = 0; j < digitH; j++)
{
int dstX = 0;
for (int k = 0; k < nDigits; k++)
{
int srcOff = j * digitW * Utils.cLen;
int dstY = i * 2 * digitH + j;
if (digits[k] >= 0)
{
// Copy row from black digit
Buffer.BlockCopy(
_numbersPix[digits[k]],
srcOff,
numArrayPix,
dstY * stride + dstX,
digitW * Utils.cLen
);
// Copy row from white digit
Buffer.BlockCopy(
_numbersPix[10 + digits[k]],
srcOff,
numArrayPix,
(dstY + digitH) * stride + dstX,
digitW * Utils.cLen
);
}
dstX += digitW * Utils.cLen;
}
}
}
return numArrayPix;
}
}
}