mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[kandinsky] Move to KDFont
This commit is contained in:
committed by
LeaNumworks
parent
29882768bd
commit
f8beae3b86
@@ -196,7 +196,7 @@ int main(int argc, char * argv[]) {
|
||||
#if NEW_FORMAT
|
||||
|
||||
fprintf(sourceFile, "/* This file is auto-generated by the rasterizer */\n\n");
|
||||
fprintf(sourceFile, "#include \"font.h\"\n\n");
|
||||
fprintf(sourceFile, "#include <kandinsky/font.h>\n\n");
|
||||
fprintf(sourceFile, "static constexpr KDCoordinate glyphWidth = %d;\n\n", glyph_width);
|
||||
fprintf(sourceFile, "static constexpr KDCoordinate glyphHeight = %d;\n\n", glyph_height);
|
||||
|
||||
@@ -264,8 +264,7 @@ int main(int argc, char * argv[]) {
|
||||
free(glyphData);
|
||||
free(uncompressedGlyphBuffer);
|
||||
|
||||
fprintf(sourceFile, "constexpr KDFont font(glyphWidth, glyphHeight, glyphDataOffset, glyphData);\n\n");
|
||||
fprintf(sourceFile, "const KDFont * KDFont::%s = &font;\n", font_name);
|
||||
fprintf(sourceFile, "const KDFont KDFont::private%s(glyphWidth, glyphHeight, glyphDataOffset, glyphData);\n", font_name);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
#include <kandinsky/color.h>
|
||||
#include <kandinsky/coordinate.h>
|
||||
#include <kandinsky/context.h>
|
||||
#include <kandinsky/font.h>
|
||||
#include <kandinsky/framebuffer.h>
|
||||
#include <kandinsky/framebuffer_context.h>
|
||||
#include <kandinsky/ion_context.h>
|
||||
#include <kandinsky/point.h>
|
||||
#include <kandinsky/rect.h>
|
||||
#include <kandinsky/size.h>
|
||||
#include <kandinsky/text.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <kandinsky/color.h>
|
||||
#include <kandinsky/rect.h>
|
||||
#include <kandinsky/text.h>
|
||||
#include <kandinsky/font.h>
|
||||
|
||||
class KDContext {
|
||||
public:
|
||||
@@ -15,8 +15,7 @@ public:
|
||||
KDColor getPixel(KDPoint p);
|
||||
|
||||
// Text
|
||||
KDPoint drawString(const char * text, KDPoint p, KDText::FontSize size = KDText::FontSize::Large, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite, int maxLength = -1);
|
||||
KDPoint blendString(const char * text, KDPoint p, KDText::FontSize size, KDColor textColor = KDColorBlack);
|
||||
KDPoint drawString(const char * text, KDPoint p, const KDFont * font = KDFont::LargeFont, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite, int maxLength = -1);
|
||||
|
||||
// Line. Not anti-aliased.
|
||||
void drawLine(KDPoint p1, KDPoint p2, KDColor c);
|
||||
@@ -33,8 +32,6 @@ protected:
|
||||
virtual void pullRect(KDRect rect, KDColor * pixels) = 0;
|
||||
private:
|
||||
KDRect absoluteFillRect(KDRect rect);
|
||||
KDPoint writeString(const char * text, KDPoint p, KDText::FontSize size, KDColor textColor, KDColor backgroundColor, int maxLength, bool transparentBackground);
|
||||
void writeChar(char character, KDPoint p, KDText::FontSize size, KDColor textColor, KDColor backgroundColor, bool transparentBackground);
|
||||
KDPoint m_origin;
|
||||
KDRect m_clippingRect;
|
||||
};
|
||||
|
||||
@@ -2,26 +2,30 @@
|
||||
#define KANDINSKY_FONT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <kandinsky/size.h>
|
||||
#include <kandinsky/coordinate.h>
|
||||
#include "palette.h"
|
||||
|
||||
class KDFont {
|
||||
private:
|
||||
static constexpr int k_bitsPerPixel = 4;
|
||||
static const KDFont privateLargeFont;
|
||||
static const KDFont privateSmallFont;
|
||||
public:
|
||||
static const KDFont * LargeFont;
|
||||
static const KDFont * SmallFont;
|
||||
static constexpr const KDFont * LargeFont = &privateLargeFont;
|
||||
static constexpr const KDFont * SmallFont = &privateSmallFont;
|
||||
|
||||
KDSize stringSize(const char * text) const;
|
||||
|
||||
using RenderPalette = KDPalette<(1<<k_bitsPerPixel)>;
|
||||
void fetchGlyphForChar(char c, const RenderPalette & renderPalette, KDColor * pixelBuffer) const;
|
||||
void fetchGlyphForChar(char c, const RenderPalette * renderPalette, KDColor * pixelBuffer) const;
|
||||
RenderPalette renderPalette(KDColor textColor, KDColor backgroundColor) const {
|
||||
return RenderPalette::Gradient(textColor, backgroundColor);
|
||||
}
|
||||
KDCoordinate glyphWidth() const { return m_glyphWidth; }
|
||||
KDCoordinate glyphHeight() const { return m_glyphHeight; }
|
||||
KDSize glyphSize() const { return m_glyphSize; }
|
||||
|
||||
constexpr KDFont(KDCoordinate glyphWidth, KDCoordinate glyphHeight, const uint16_t * glyphDataOffset, const uint8_t * data) :
|
||||
m_glyphWidth(glyphWidth), m_glyphHeight(glyphHeight), m_glyphDataOffset(glyphDataOffset), m_data(data) { }
|
||||
m_glyphSize(glyphWidth, glyphHeight), m_glyphDataOffset(glyphDataOffset), m_data(data) { }
|
||||
private:
|
||||
void fetchGreyscaleGlyphForChar(char c, uint8_t * greyscaleBuffer) const;
|
||||
|
||||
@@ -37,8 +41,7 @@ private:
|
||||
// FIXME: 0x20 is a magic value...
|
||||
}
|
||||
|
||||
KDCoordinate m_glyphWidth;
|
||||
KDCoordinate m_glyphHeight;
|
||||
KDSize m_glyphSize;
|
||||
const uint16_t * m_glyphDataOffset;
|
||||
const uint8_t * m_data;
|
||||
};
|
||||
@@ -1,96 +1,33 @@
|
||||
#include <kandinsky/context.h>
|
||||
#include <kandinsky/text.h>
|
||||
#include "small_font.h"
|
||||
#include "large_font.h"
|
||||
#include "font.h"
|
||||
#include <assert.h>
|
||||
#include <kandinsky/context.h>
|
||||
#include <kandinsky/font.h>
|
||||
|
||||
constexpr int maxGlyphPixelCount = 180;
|
||||
constexpr static int k_tabCharacterWidth = 4;
|
||||
|
||||
KDPoint KDContext::drawString(const char * text, KDPoint p, KDText::FontSize size, KDColor textColor, KDColor backgroundColor, int maxLength) {
|
||||
#define NEW_VERSION 1
|
||||
#if NEW_VERSION
|
||||
const KDFont * font = KDFont::LargeFont;
|
||||
KDPoint KDContext::drawString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxLength) {
|
||||
|
||||
KDPoint position = p;
|
||||
KDSize glyphSize = font->glyphSize();
|
||||
KDFont::RenderPalette palette = font->renderPalette(textColor, backgroundColor);
|
||||
|
||||
assert(maxGlyphPixelCount >= font->glyphWidth() * font->glyphHeight());
|
||||
KDColor glyph[maxGlyphPixelCount];
|
||||
|
||||
const char * c = text;
|
||||
while(*c != 0) {
|
||||
KDColor glyph[maxGlyphPixelCount];
|
||||
font->fetchGlyphForChar(*c, palette, glyph);
|
||||
|
||||
KDRect absoluteRect = absoluteFillRect(KDRect(p, font->glyphWidth(), font->glyphHeight()));
|
||||
pushRect(absoluteRect, glyph);
|
||||
p = p.translatedBy(KDPoint(font->glyphWidth(), 0));
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return KDPointZero;
|
||||
#else
|
||||
return writeString(text, p, size, textColor, backgroundColor, maxLength, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
KDPoint KDContext::blendString(const char * text, KDPoint p, KDText::FontSize size, KDColor textColor) {
|
||||
return writeString(text, p, size, textColor, KDColorWhite, -1, true);
|
||||
}
|
||||
|
||||
KDPoint KDContext::writeString(const char * text, KDPoint p, KDText::FontSize size, KDColor textColor, KDColor backgroundColor, int maxLength, bool transparentBackground) {
|
||||
KDPoint position = p;
|
||||
int characterWidth = size == KDText::FontSize::Large ? BITMAP_LargeFont_CHARACTER_WIDTH : BITMAP_SmallFont_CHARACTER_WIDTH;
|
||||
int characterHeight = size == KDText::FontSize::Large ? BITMAP_LargeFont_CHARACTER_HEIGHT: BITMAP_SmallFont_CHARACTER_HEIGHT;
|
||||
KDPoint characterSize(characterWidth, 0);
|
||||
|
||||
const char * end = text+maxLength;
|
||||
const char * end = text + maxLength;
|
||||
while(*text != 0 && text != end) {
|
||||
writeChar(*text, position, size, textColor, backgroundColor, transparentBackground);
|
||||
if (*text == '\n') {
|
||||
position = KDPoint(0, position.y()+characterHeight);
|
||||
position = KDPoint(0, position.y() + glyphSize.height());
|
||||
} else if (*text == '\t') {
|
||||
position = position.translatedBy(KDPoint(KDText::k_tabCharacterWidth*characterWidth, 0));
|
||||
position = position.translatedBy(KDPoint(k_tabCharacterWidth * glyphSize.width(), 0));
|
||||
} else {
|
||||
position = position.translatedBy(characterSize);
|
||||
// Fetch and draw glyph for current char
|
||||
font->fetchGlyphForChar(*text, &palette, glyph);
|
||||
KDRect absoluteRect = absoluteFillRect(KDRect(position, glyphSize.width(), glyphSize.height()));
|
||||
pushRect(absoluteRect, glyph);
|
||||
|
||||
position = position.translatedBy(KDPoint(glyphSize.width(), 0));
|
||||
}
|
||||
text++;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
void KDContext::writeChar(char character, KDPoint p, KDText::FontSize size, KDColor textColor, KDColor backgroundColor, bool transparentBackground) {
|
||||
if (character == '\n' || character == '\t') {
|
||||
return;
|
||||
}
|
||||
char firstCharacter = size == KDText::FontSize::Large ? BITMAP_LargeFont_FIRST_CHARACTER : BITMAP_SmallFont_FIRST_CHARACTER;
|
||||
int characterHeight = size == KDText::FontSize::Large ? BITMAP_LargeFont_CHARACTER_HEIGHT : BITMAP_SmallFont_CHARACTER_HEIGHT;
|
||||
int characterWidth = size == KDText::FontSize::Large ? BITMAP_LargeFont_CHARACTER_WIDTH : BITMAP_SmallFont_CHARACTER_WIDTH;
|
||||
|
||||
KDColor * characterBuffer = size == KDText::FontSize::Large ? largeCharacterBuffer : smallCharacterBuffer;
|
||||
|
||||
KDRect absoluteRect = absoluteFillRect(KDRect(p, characterWidth, characterHeight));
|
||||
if (transparentBackground) {
|
||||
pullRect(absoluteRect, characterBuffer);
|
||||
}
|
||||
KDCoordinate startingI = m_clippingRect.x() - p.translatedBy(m_origin).x();
|
||||
KDCoordinate startingJ = m_clippingRect.y() - p.translatedBy(m_origin).y();
|
||||
startingI = startingI < 0 ? 0 : startingI;
|
||||
startingJ = startingJ < 0 ? 0 : startingJ;
|
||||
|
||||
for (KDCoordinate j=0; j<absoluteRect.height(); j++) {
|
||||
for (KDCoordinate i=0; i<absoluteRect.width(); i++) {
|
||||
KDColor * currentPixelAdress = characterBuffer + i + absoluteRect.width()*j; uint8_t intensity = 0;
|
||||
if (size == KDText::FontSize::Large) {
|
||||
intensity = bitmapLargeFont[(uint8_t)character-(uint8_t)firstCharacter][j + startingJ][i +startingI];
|
||||
} else {
|
||||
intensity = bitmapSmallFont[(uint8_t)character-(uint8_t)firstCharacter][j + startingJ][i +startingI];
|
||||
}
|
||||
KDColor backColor = transparentBackground ? *currentPixelAdress : backgroundColor;
|
||||
*currentPixelAdress = KDColor::blend(textColor, backColor, intensity);
|
||||
}
|
||||
}
|
||||
pushRect(absoluteRect, characterBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,19 +1,40 @@
|
||||
#include "font.h"
|
||||
#include <assert.h>
|
||||
#include <kandinsky/font.h>
|
||||
#include "external/lz4/lz4.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 {
|
||||
//TODO: If debug, use LZ4_decompress_safe, otherwise LZ4_decompress_fast
|
||||
int resultSize = LZ4_decompress_safe(
|
||||
reinterpret_cast<const char *>(compressedGlyphData(c)),
|
||||
reinterpret_cast<char *>(greyscaleBuffer),
|
||||
compressedGlyphDataSize(c),
|
||||
m_glyphWidth * m_glyphHeight * k_bitsPerPixel/8
|
||||
m_glyphSize.width() * m_glyphSize.height() * k_bitsPerPixel/8
|
||||
);
|
||||
assert(resultSize == m_glyphWidth * m_glyphHeight * k_bitsPerPixel/8);
|
||||
assert(resultSize == m_glyphSize.width() * m_glyphSize.height() * k_bitsPerPixel/8);
|
||||
}
|
||||
|
||||
void KDFont::fetchGlyphForChar(char c, const KDFont::RenderPalette & renderPalette, KDColor * pixelBuffer) const {
|
||||
void KDFont::fetchGlyphForChar(char c, const KDFont::RenderPalette * renderPalette, KDColor * pixelBuffer) const {
|
||||
/* 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
|
||||
@@ -25,7 +46,7 @@ void KDFont::fetchGlyphForChar(char c, const KDFont::RenderPalette & renderPalet
|
||||
fetchGreyscaleGlyphForChar(c, greyscaleBuffer);
|
||||
|
||||
uint8_t mask = (0xFF >> (8-k_bitsPerPixel));
|
||||
int pixelIndex = m_glyphWidth * m_glyphHeight - 1; // Let's start at the final pixel
|
||||
int pixelIndex = m_glyphSize.width() * m_glyphSize.height() - 1; // Let's start at the final pixel
|
||||
int greyscaleByteIndex = pixelIndex * k_bitsPerPixel / 8;
|
||||
while (pixelIndex >= 0) {
|
||||
assert(greyscaleByteIndex == pixelIndex * k_bitsPerPixel / 8);
|
||||
@@ -34,25 +55,7 @@ void KDFont::fetchGlyphForChar(char c, const KDFont::RenderPalette & renderPalet
|
||||
uint8_t greyscale = greyscaleByte & mask;
|
||||
greyscaleByte = greyscaleByte >> k_bitsPerPixel;
|
||||
assert(pixelIndex >= 0);
|
||||
pixelBuffer[pixelIndex--] = renderPalette.colorAtIndex(greyscale);
|
||||
pixelBuffer[pixelIndex--] = renderPalette->colorAtIndex(greyscale);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
constexpr int glyphPixelCount = 12;
|
||||
|
||||
void drawString(const char * text, KDColor textColor, KDColor backgroundColor) {
|
||||
const KDFont * font = KDFont::LargeFont;
|
||||
KDFont::RenderPalette palette = font->renderPalette(textColor, backgroundColor);
|
||||
|
||||
assert(glyphPixelCount >= font->glyphWidth() * font->glyphHeight());
|
||||
|
||||
char c;
|
||||
do {
|
||||
char c = text[0];
|
||||
KDColor glyph[glyphPixelCount];
|
||||
font->fetchGlyphForChar(c, palette, glyph);
|
||||
} while (c != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user