mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 01:59:59 +01:00
69 lines
2.6 KiB
C++
69 lines
2.6 KiB
C++
#include <assert.h>
|
|
#include <kandinsky/font.h>
|
|
#include <ion.h>
|
|
|
|
constexpr static int k_tabCharacterWidth = 4;
|
|
|
|
KDSize KDFont::stringSize(const char * text) const {
|
|
if (text == nullptr) {
|
|
return KDSizeZero;
|
|
}
|
|
KDSize stringSize = KDSize(0, m_glyphSize.height());
|
|
while (*text != 0) {
|
|
KDSize cSize = KDSize(m_glyphSize.width(), 0);
|
|
if (*text == '\t') {
|
|
cSize = KDSize(k_tabCharacterWidth*m_glyphSize.width(), 0);
|
|
}
|
|
if (*text == '\n') {
|
|
cSize = KDSize(0, m_glyphSize.height());
|
|
}
|
|
stringSize = KDSize(stringSize.width()+cSize.width(), stringSize.height()+cSize.height());
|
|
text++;
|
|
}
|
|
return stringSize;
|
|
}
|
|
|
|
void KDFont::fetchGreyscaleGlyphForChar(char c, uint8_t * greyscaleBuffer) const {
|
|
Ion::decompress(
|
|
compressedGlyphData(c),
|
|
greyscaleBuffer,
|
|
compressedGlyphDataSize(c),
|
|
m_glyphSize.width() * m_glyphSize.height() * k_bitsPerPixel/8
|
|
);
|
|
}
|
|
|
|
void KDFont::fetchGlyphForChar(char c, const KDFont::RenderPalette * renderPalette, KDColor * pixelBuffer) const {
|
|
int pixelCount = m_glyphSize.width() * m_glyphSize.height() - 1;
|
|
int charIndex = signedCharAsIndex(c);
|
|
if (charIndex < 0 || charIndex >= k_numberOfGlyphs) {
|
|
// There is no data for this glyph
|
|
for (int i = 0; i < pixelCount; i++) {
|
|
pixelBuffer[i] = KDColorBlack;
|
|
}
|
|
return;
|
|
}
|
|
/* Since a greyscale value is smaller than a color value (see assertion), we
|
|
* can store the temporary greyscale values in the output pixel buffer.
|
|
* What's great is that now, if we fill the pixel buffer right-to-left with
|
|
* colors derived from the temporary greyscale values, we will never overwrite
|
|
* the remaining grayscale values since those are smaller. So we can avoid a
|
|
* separate buffer for the temporary greyscale values. */
|
|
assert(k_bitsPerPixel < 8*sizeof(KDColor));
|
|
uint8_t * greyscaleBuffer = reinterpret_cast<uint8_t *>(pixelBuffer);
|
|
fetchGreyscaleGlyphForChar(c, greyscaleBuffer);
|
|
|
|
uint8_t mask = (0xFF >> (8-k_bitsPerPixel));
|
|
int pixelIndex = pixelCount; // Let's start at the final pixel
|
|
int greyscaleByteIndex = pixelIndex * k_bitsPerPixel / 8;
|
|
while (pixelIndex >= 0) {
|
|
assert(greyscaleByteIndex == pixelIndex * k_bitsPerPixel / 8);
|
|
uint8_t greyscaleByte = greyscaleBuffer[greyscaleByteIndex--]; // We consume a greyscale byte...
|
|
for (int j=0; j<8/k_bitsPerPixel; j++) { // .. and we'll output 8/k_bits pixels
|
|
uint8_t greyscale = greyscaleByte & mask;
|
|
greyscaleByte = greyscaleByte >> k_bitsPerPixel;
|
|
assert(pixelIndex >= 0);
|
|
pixelBuffer[pixelIndex--] = renderPalette->colorAtIndex(greyscale);
|
|
}
|
|
}
|
|
}
|