[kandinsky] Move to KDFont

This commit is contained in:
Romain Goyet
2018-10-09 16:41:24 +02:00
committed by LeaNumworks
parent 29882768bd
commit f8beae3b86
149 changed files with 564 additions and 610 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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);
}
*/