mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[Update] Epsilon 15.3.1
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user