paulo@0: /* paulo@0: Variable width font drawing library for DS (and GBA) paulo@0: paulo@0: Copyright 2007-2008 Damian Yerrick paulo@0: paulo@0: This work is provided 'as-is', without any express or implied paulo@0: warranty. In no event will the authors be held liable for any paulo@0: damages arising from the use of this work. paulo@0: paulo@0: Permission is granted to anyone to use this work for any purpose, paulo@0: including commercial applications, and to alter it and redistribute paulo@0: it freely, subject to the following restrictions: paulo@0: paulo@0: 1. The origin of this work must not be misrepresented; you must paulo@0: not claim that you wrote the original work. If you use paulo@0: this work in a product, an acknowledgment in the product paulo@0: documentation would be appreciated but is not required. paulo@0: 2. Altered source versions must be plainly marked as such, and must paulo@0: not be misrepresented as being the original work. paulo@0: 3. This notice may not be removed or altered from any source paulo@0: distribution. paulo@0: paulo@0: "Source" is the preferred form of a work for making changes to it. paulo@0: paulo@0: */ paulo@0: /* paulo@0: paulo@0: Set FONTDRAW_SPLIT_COMPILE when compiling the time-sensitve parts paulo@0: into a separate file to be placed in "fast" memory. paulo@0: paulo@0: */ paulo@0: paulo@0: paulo@0: #ifdef FONTDRAW_SPLIT_COMPILE paulo@0: typedef unsigned int u32; paulo@0: extern const unsigned char vwfont_bin[]; paulo@0: paulo@0: typedef struct GlyphRec { paulo@0: unsigned short dataOffset; paulo@0: unsigned char glyphWidth; paulo@0: unsigned char reserved; paulo@0: } GlyphRec; paulo@0: #endif paulo@0: paulo@0: unsigned int fontdraw_putchar(u32 *dst, unsigned int colStride, int wid, int x, int glyph) { paulo@0: glyph &= 0xFF; paulo@0: if (glyph < vwfont_bin[1]) { paulo@0: return 0; paulo@0: } paulo@0: glyph -= vwfont_bin[1]; paulo@0: if (vwfont_bin[2] != 0 && glyph >= vwfont_bin[2]) { paulo@0: return 0; paulo@0: } paulo@0: const GlyphRec *glyphRec = paulo@0: ((const GlyphRec *)(vwfont_bin + vwfont_bin[0])) + glyph; paulo@0: const unsigned char *data = vwfont_bin + glyphRec->dataOffset; paulo@0: unsigned int dataShift = 2; paulo@0: unsigned int dataBits = *data++; paulo@0: unsigned int pixelCode = dataBits & 0x03; paulo@0: paulo@0: // Convert x to tile column address and bit address within tile paulo@0: dst += colStride * (x >> 3); paulo@0: x = (x & 0x07) << 2; paulo@0: paulo@0: if (dataShift >= 8) { paulo@0: dataShift = 2; paulo@0: dataBits = *data++; paulo@0: } paulo@0: paulo@0: for (unsigned int height = vwfont_bin[3]; paulo@0: height > 0; paulo@0: --height, ++dst) { paulo@0: int eol = 0; paulo@0: int xLine = x; paulo@0: int widLeft = wid; paulo@0: u32 *dstLine = dst; paulo@0: u32 dstBits = *dstLine; paulo@0: while (!eol) { paulo@0: paulo@0: // Process a pixel instruction paulo@0: if (pixelCode == 0) { paulo@0: eol = 1; paulo@0: } else if (widLeft > 0) { paulo@0: paulo@0: // Change pixel and move to next pixel paulo@0: if (pixelCode > 1) { paulo@0: //dstBits &= ~(0x0F << xLine); paulo@0: dstBits |= (pixelCode - 1) << xLine; paulo@0: } paulo@0: xLine += 4; paulo@0: --widLeft; paulo@0: } paulo@0: paulo@0: // If finished with this tile, write back changed bits paulo@0: if (xLine >= 32) { paulo@0: xLine = 0; paulo@0: *dstLine = dstBits; paulo@0: dstLine += colStride; paulo@0: dstBits = *dstLine; paulo@0: } paulo@0: paulo@0: // Decode next pixel instruction paulo@0: if (dataShift >= 8) { paulo@0: dataShift = 0; paulo@0: dataBits = *data++; paulo@0: } paulo@0: paulo@0: // Decode a byte into pixel instructions paulo@0: pixelCode = (dataBits >> dataShift) & 0x03; paulo@0: dataShift += 2; paulo@0: } paulo@0: paulo@0: // Write back changed bits paulo@0: if (xLine > 0) { paulo@0: *dstLine = dstBits; paulo@0: } paulo@0: } paulo@0: return glyphRec->glyphWidth; paulo@0: } paulo@0: paulo@0: void vwfRectfillColumn(u32 *dst, unsigned int colStride, paulo@0: unsigned int l, unsigned int t, paulo@0: unsigned int r, unsigned int b, paulo@0: unsigned int c) paulo@0: { paulo@0: u32 mask = 0xffffffffU << (4 * l); paulo@0: mask &= 0xffffffffU >> (4 * (8 - r)); paulo@0: c &= mask; paulo@0: mask = ~mask; paulo@0: paulo@0: for (; t < b; t++) { paulo@0: dst[t] = (dst[t] & mask) | c; paulo@0: } paulo@0: } paulo@0: