[Update] Epsilon 15.3.1

This commit is contained in:
Joachim LF
2021-01-21 17:27:39 +01:00
700 changed files with 15118 additions and 7297 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -204,10 +204,10 @@ int main(int argc, char * argv[]) {
fprintf(sourceFile, "static constexpr KDCoordinate glyphWidth = %d;\n\n", glyph_width);
fprintf(sourceFile, "static constexpr KDCoordinate glyphHeight = %d;\n\n", glyph_height);
int greyscaleBitsPerPixel = 4;
int grayscaleBitsPerPixel = 4;
int sizeOfUncompressedGlyphBuffer = glyph_width * glyph_height * greyscaleBitsPerPixel/8;
ENSURE(8*sizeOfUncompressedGlyphBuffer == glyph_width * glyph_height * greyscaleBitsPerPixel, "Error: the glyph size (%dx%d@%dbpp) cannot fit in an integral number of bytes", glyph_width, glyph_height, greyscaleBitsPerPixel);
int sizeOfUncompressedGlyphBuffer = glyph_width * glyph_height * grayscaleBitsPerPixel/8;
ENSURE(8*sizeOfUncompressedGlyphBuffer == glyph_width * glyph_height * grayscaleBitsPerPixel, "Error: the glyph size (%dx%d@%dbpp) cannot fit in an integral number of bytes", glyph_width, glyph_height, grayscaleBitsPerPixel);
uint8_t * uncompressedGlyphBuffer = (uint8_t *)malloc(sizeOfUncompressedGlyphBuffer);
uint16_t glyphDataOffset[NumberOfCodePoints+1];
@@ -225,9 +225,9 @@ int main(int argc, char * argv[]) {
for (int x = 0; x < glyph_width; x++) {
pixel_t * pixel = (bitmap_image.pixels + (y+characterY)*bitmap_image.width + (x+characterX));
uint8_t greyscaleValue = (0xFF - pixel->green) >> (8 - greyscaleBitsPerPixel);
accumulator = (accumulator << greyscaleBitsPerPixel) | greyscaleValue;
if (numberOfValuesAccumulated++ == (8/greyscaleBitsPerPixel)-1) {
uint8_t grayscaleValue = (0xFF - pixel->green) >> (8 - grayscaleBitsPerPixel);
accumulator = (accumulator << grayscaleBitsPerPixel) | grayscaleValue;
if (numberOfValuesAccumulated++ == (8/grayscaleBitsPerPixel)-1) {
uncompressedGlyphBuffer[uncompressedGlyphBufferIndex++] = accumulator;
accumulator = 0;
numberOfValuesAccumulated = 0;
@@ -261,7 +261,7 @@ int main(int argc, char * argv[]) {
size_t initialDataSize = NumberOfCodePoints * glyph_width * glyph_height;
fprintf(sourceFile, "/* Rasterized = %5zu bytes (%d glyphs x %d pixels)\n", initialDataSize, NumberOfCodePoints, glyph_width*glyph_height);
fprintf(sourceFile, " * Downsampled = %5lu bytes (1/%d of rasterized)\n", initialDataSize*greyscaleBitsPerPixel/8, 8/greyscaleBitsPerPixel);
fprintf(sourceFile, " * Downsampled = %5lu bytes (1/%d of rasterized)\n", initialDataSize*grayscaleBitsPerPixel/8, 8/grayscaleBitsPerPixel);
fprintf(sourceFile, " * Compressed = %5zu bytes (%.2f%% of rasterized) */\n", finalDataSize, 100.0*finalDataSize/initialDataSize);
fprintf(sourceFile, "static constexpr uint8_t glyphData[%d] = {", lastOffset);

View File

@@ -33,6 +33,8 @@ public:
static constexpr const KDFont * LargeFont = &privateLargeFont;
static constexpr const KDFont * SmallFont = &privateSmallFont;
static bool CanBeWrittenWithGlyphs(const char * text);
KDSize stringSize(const char * text, int textLength = -1) const {
return stringSizeUntil(text, textLength < 0 ? nullptr : text + textLength);
}
@@ -42,10 +44,10 @@ public:
public:
GlyphBuffer() {} // Don't initialize either buffer
KDColor * colorBuffer() { return m_colors; }
uint8_t * greyscaleBuffer() { return m_greyscales; }
uint8_t * secondaryGreyscaleBuffer() { return m_greyscales + k_maxGlyphPixelCount; }
uint8_t * grayscaleBuffer() { return m_grayscales; }
uint8_t * secondaryGrayscaleBuffer() { return m_grayscales + k_maxGlyphPixelCount; }
private:
uint8_t m_greyscales[2*k_maxGlyphPixelCount];
uint8_t m_grayscales[2*k_maxGlyphPixelCount];
KDColor m_colors[k_maxGlyphPixelCount];
};
@@ -62,8 +64,8 @@ public:
static constexpr GlyphIndex IndexForReplacementCharacterCodePoint = 134;
GlyphIndex indexForCodePoint(CodePoint c) const;
void setGlyphGreyscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const;
void accumulateGlyphGreyscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const;
void setGlyphGrayscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const;
void accumulateGlyphGrayscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const;
using RenderPalette = KDPalette<(1<<k_bitsPerPixel)>;
void colorizeGlyphBuffer(const RenderPalette * renderPalette, GlyphBuffer * glyphBuffer) const;
@@ -76,7 +78,7 @@ public:
constexpr KDFont(size_t tableLength, const CodePointIndexPair * table, KDCoordinate glyphWidth, KDCoordinate glyphHeight, const uint16_t * glyphDataOffset, const uint8_t * data) :
m_tableLength(tableLength), m_table(table), m_glyphSize(glyphWidth, glyphHeight), m_glyphDataOffset(glyphDataOffset), m_data(data) { }
private:
void fetchGreyscaleGlyphAtIndex(GlyphIndex index, uint8_t * greyscaleBuffer) const;
void fetchGrayscaleGlyphAtIndex(GlyphIndex index, uint8_t * grayscaleBuffer) const;
const uint8_t * compressedGlyphData(GlyphIndex index) const {
return m_data + m_glyphDataOffset[index];

View File

@@ -28,6 +28,7 @@ KDPoint KDContext::pushOrPullString(const char * text, KDPoint p, const KDFont *
while (codePoint != UCodePointNull && (maxByteLength < 0 || codePointPointer < text + maxByteLength)) {
codePointPointer = decoder.stringPosition();
if (codePoint == UCodePointLineFeed) {
assert(position.y() < KDCOORDINATE_MAX - glyphSize.height());
position = KDPoint(0, position.y() + glyphSize.height());
codePoint = decoder.nextCodePoint();
} else if (codePoint == UCodePointTabulation) {
@@ -35,10 +36,10 @@ KDPoint KDContext::pushOrPullString(const char * text, KDPoint p, const KDFont *
codePoint = decoder.nextCodePoint();
} else {
assert(!codePoint.isCombining());
font->setGlyphGreyscalesForCodePoint(codePoint, &glyphBuffer);
font->setGlyphGrayscalesForCodePoint(codePoint, &glyphBuffer);
codePoint = decoder.nextCodePoint();
while (codePoint.isCombining()) {
font->accumulateGlyphGreyscalesForCodePoint(codePoint, &glyphBuffer);
font->accumulateGlyphGrayscalesForCodePoint(codePoint, &glyphBuffer);
codePointPointer = decoder.stringPosition();
codePoint = decoder.nextCodePoint();
}

View File

@@ -30,54 +30,55 @@ KDSize KDFont::stringSizeUntil(const char * text, const char * limit) const {
currentStringPosition = decoder.stringPosition();
codePoint = decoder.nextCodePoint();
}
assert(stringSize.width() >= 0 && stringSize.height() >= 0);
return stringSize;
}
void KDFont::setGlyphGreyscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const {
fetchGreyscaleGlyphAtIndex(indexForCodePoint(codePoint), glyphBuffer->greyscaleBuffer());
void KDFont::setGlyphGrayscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const {
fetchGrayscaleGlyphAtIndex(indexForCodePoint(codePoint), glyphBuffer->grayscaleBuffer());
}
void KDFont::accumulateGlyphGreyscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const {
uint8_t * greyscaleBuffer = glyphBuffer->greyscaleBuffer();
uint8_t * accumulationGreyscaleBuffer = glyphBuffer->secondaryGreyscaleBuffer();
fetchGreyscaleGlyphAtIndex(indexForCodePoint(codePoint), accumulationGreyscaleBuffer);
void KDFont::accumulateGlyphGrayscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const {
uint8_t * grayscaleBuffer = glyphBuffer->grayscaleBuffer();
uint8_t * accumulationGrayscaleBuffer = glyphBuffer->secondaryGrayscaleBuffer();
fetchGrayscaleGlyphAtIndex(indexForCodePoint(codePoint), accumulationGrayscaleBuffer);
for (int i=0; i<m_glyphSize.width()*m_glyphSize.height(); i++) {
greyscaleBuffer[i] |= accumulationGreyscaleBuffer[i];
grayscaleBuffer[i] |= accumulationGrayscaleBuffer[i];
}
}
void KDFont::fetchGreyscaleGlyphAtIndex(KDFont::GlyphIndex index, uint8_t * greyscaleBuffer) const {
void KDFont::fetchGrayscaleGlyphAtIndex(KDFont::GlyphIndex index, uint8_t * grayscaleBuffer) const {
Ion::decompress(
compressedGlyphData(index),
greyscaleBuffer,
grayscaleBuffer,
compressedGlyphDataSize(index),
m_glyphSize.width() * m_glyphSize.height() * k_bitsPerPixel/8
);
}
void KDFont::colorizeGlyphBuffer(const RenderPalette * renderPalette, GlyphBuffer * glyphBuffer) 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.
/* Since a grayscale value is smaller than a color value (see assertion), we
* can store the temporary grayscale 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
* colors derived from the temporary grayscale 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. */
* separate buffer for the temporary grayscale values. */
assert(k_bitsPerPixel < 8*sizeof(KDColor));
uint8_t * greyscaleBuffer = glyphBuffer->greyscaleBuffer();
uint8_t * grayscaleBuffer = glyphBuffer->grayscaleBuffer();
KDColor * colorBuffer = glyphBuffer->colorBuffer();
uint8_t mask = (0xFF >> (8-k_bitsPerPixel));
int pixelIndex = m_glyphSize.width() * m_glyphSize.height() - 1; // Let's start at the final pixel
int greyscaleByteIndex = pixelIndex * k_bitsPerPixel / 8;
int grayscaleByteIndex = pixelIndex * k_bitsPerPixel / 8;
while (pixelIndex >= 0) {
assert(greyscaleByteIndex == pixelIndex * k_bitsPerPixel / 8);
uint8_t greyscaleByte = greyscaleBuffer[greyscaleByteIndex--]; // We consume a greyscale byte...
assert(grayscaleByteIndex == pixelIndex * k_bitsPerPixel / 8);
uint8_t grayscaleByte = grayscaleBuffer[grayscaleByteIndex--]; // We consume a grayscale 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;
uint8_t grayscale = grayscaleByte & mask;
grayscaleByte = grayscaleByte >> k_bitsPerPixel;
assert(pixelIndex >= 0);
colorBuffer[pixelIndex--] = renderPalette->colorAtIndex(greyscale);
colorBuffer[pixelIndex--] = renderPalette->colorAtIndex(grayscale);
}
}
}
@@ -158,3 +159,17 @@ KDFont::GlyphIndex KDFont::indexForCodePoint(CodePoint c) const {
return IndexForReplacementCharacterCodePoint;
#endif
}
bool KDFont::CanBeWrittenWithGlyphs(const char * text) {
UTF8Decoder decoder(text);
CodePoint cp = decoder.nextCodePoint();
while(cp != UCodePointNull) {
if (LargeFont->indexForCodePoint(cp) == KDFont::IndexForReplacementCharacterCodePoint
|| SmallFont->indexForCodePoint(cp) == KDFont::IndexForReplacementCharacterCodePoint)
{
return false;
}
cp = decoder.nextCodePoint();
}
return true;
}

View File

@@ -1,6 +1,10 @@
#include <kandinsky/point.h>
#include <assert.h>
KDPoint KDPoint::translatedBy(KDPoint other) const {
assert((other.x() >= 0 && m_x <= KDCOORDINATE_MAX - other.x()) || (other.x() < 0 && m_x >= KDCOORDINATE_MIN - other.x()));
assert((other.y() >= 0 && m_y <= KDCOORDINATE_MAX - other.y()) || (other.y() < 0 && m_y >= KDCOORDINATE_MIN - other.y()));
return KDPoint(m_x+other.x(), m_y+other.y());
}