Add support for using 4bits mode smooth fonts
By default,the create_font create a 8 bits/pixel fonts,but now it can be transform into 4 bits/pixel and used on ESP8266/ESP32.I have tested it on ESP32,both SPIFFS and flash array. Main modifications : 1. add readInt16() and readInt8() functions; 2. add a flag c4bpp to struct gFont. 3. adjust 4bits mode display. 4. add a tool made by pure C to convert font files. The API is compatible with previous.Compressed font format is described in tools/create_smooth_font/compress_font/readme.md Signed-off-by: Lucy2003 <53362310+Lucy2003@users.noreply.github.com>
This commit is contained in:
parent
58f457ba97
commit
9393f05fdc
|
|
@ -126,7 +126,7 @@ void TFT_eSPI::loadFont(String fontName, bool flash)
|
||||||
gFont.gArray = (const uint8_t*)fontPtr;
|
gFont.gArray = (const uint8_t*)fontPtr;
|
||||||
|
|
||||||
gFont.gCount = (uint16_t)readInt32(); // glyph count in file
|
gFont.gCount = (uint16_t)readInt32(); // glyph count in file
|
||||||
readInt32(); // vlw encoder version - discard
|
gFont.c4bpp = (readInt32() == 0xC); // vlw encoder version,0xC for 4bpp version
|
||||||
gFont.yAdvance = (uint16_t)readInt32(); // Font size in points, not pixels
|
gFont.yAdvance = (uint16_t)readInt32(); // Font size in points, not pixels
|
||||||
readInt32(); // discard
|
readInt32(); // discard
|
||||||
gFont.ascent = (uint16_t)readInt32(); // top of "d"
|
gFont.ascent = (uint16_t)readInt32(); // top of "d"
|
||||||
|
|
@ -154,6 +154,10 @@ void TFT_eSPI::loadMetrics(void)
|
||||||
{
|
{
|
||||||
uint32_t headerPtr = 24;
|
uint32_t headerPtr = 24;
|
||||||
uint32_t bitmapPtr = headerPtr + gFont.gCount * 28;
|
uint32_t bitmapPtr = headerPtr + gFont.gCount * 28;
|
||||||
|
if(gFont.c4bpp)
|
||||||
|
{
|
||||||
|
bitmapPtr = headerPtr + gFont.gCount * 8;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
|
#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
|
||||||
if ( psramFound() )
|
if ( psramFound() )
|
||||||
|
|
@ -191,19 +195,29 @@ void TFT_eSPI::loadMetrics(void)
|
||||||
|
|
||||||
while (gNum < gFont.gCount)
|
while (gNum < gFont.gCount)
|
||||||
{
|
{
|
||||||
gUnicode[gNum] = (uint16_t)readInt32(); // Unicode code point value
|
if(!gFont.c4bpp)
|
||||||
gHeight[gNum] = (uint8_t)readInt32(); // Height of glyph
|
{
|
||||||
gWidth[gNum] = (uint8_t)readInt32(); // Width of glyph
|
gUnicode[gNum] = (uint16_t)readInt32(); // Unicode code point value
|
||||||
gxAdvance[gNum] = (uint8_t)readInt32(); // xAdvance - to move x cursor
|
gHeight[gNum] = (uint8_t)readInt32(); // Height of glyph
|
||||||
gdY[gNum] = (int16_t)readInt32(); // y delta from baseline
|
gWidth[gNum] = (uint8_t)readInt32(); // Width of glyph
|
||||||
gdX[gNum] = (int8_t)readInt32(); // x delta from cursor
|
gxAdvance[gNum] = (uint8_t)readInt32(); // xAdvance - to move x cursor
|
||||||
readInt32(); // ignored
|
gdY[gNum] = (int16_t)readInt32(); // y delta from baseline
|
||||||
|
gdX[gNum] = (int8_t)readInt32(); // x delta from cursor
|
||||||
|
readInt32(); // ignored
|
||||||
|
}else{
|
||||||
|
gUnicode[gNum] = (uint16_t)readInt16(); // Unicode code point value
|
||||||
|
gHeight[gNum] = (uint8_t)readInt8(); // Height of glyph
|
||||||
|
gWidth[gNum] = (uint8_t)readInt8(); // Width of glyph
|
||||||
|
gxAdvance[gNum] = (uint8_t)readInt8(); // xAdvance - to move x cursor
|
||||||
|
gdY[gNum] = (int16_t)readInt16(); // y delta from baseline
|
||||||
|
gdX[gNum] = (int8_t)readInt8(); // x delta from cursor
|
||||||
|
}
|
||||||
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gHeight = "); Serial.println(gHeight[gNum]);
|
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gHeight = "); Serial.println(gHeight[gNum]);
|
||||||
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gWidth = "); Serial.println(gWidth[gNum]);
|
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gWidth = "); Serial.println(gWidth[gNum]);
|
||||||
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gxAdvance = "); Serial.println(gxAdvance[gNum]);
|
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gxAdvance = "); Serial.println(gxAdvance[gNum]);
|
||||||
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdY = "); Serial.println(gdY[gNum]);
|
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdY = "); Serial.println(gdY[gNum]);
|
||||||
|
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdX = "); Serial.println(gdX[gNum]);
|
||||||
|
//Serial.println("");
|
||||||
// Different glyph sets have different ascent values not always based on "d", so we could get
|
// Different glyph sets have different ascent values not always based on "d", so we could get
|
||||||
// the maximum glyph ascent by checking all characters. BUT this method can generate bad values
|
// the maximum glyph ascent by checking all characters. BUT this method can generate bad values
|
||||||
// for non-existant glyphs, so we will reply on processing for the value and disable this code for now...
|
// for non-existant glyphs, so we will reply on processing for the value and disable this code for now...
|
||||||
|
|
@ -229,14 +243,22 @@ void TFT_eSPI::loadMetrics(void)
|
||||||
{
|
{
|
||||||
gFont.maxDescent = gHeight[gNum] - gdY[gNum];
|
gFont.maxDescent = gHeight[gNum] - gdY[gNum];
|
||||||
#ifdef SHOW_ASCENT_DESCENT
|
#ifdef SHOW_ASCENT_DESCENT
|
||||||
Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", maxDescent = "); Serial.println(gHeight[gNum] - gdY[gNum]);
|
Serial.print("Unicode = 0x");
|
||||||
|
Serial.print(gUnicode[gNum], HEX); Serial.print(", maxDescent = ");
|
||||||
|
Serial.println(gHeight[gNum] - gdY[gNum]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gBitmap[gNum] = bitmapPtr;
|
gBitmap[gNum] = bitmapPtr;
|
||||||
|
if(gFont.c4bpp)
|
||||||
bitmapPtr += gWidth[gNum] * gHeight[gNum];
|
{
|
||||||
|
bitmapPtr += ((gWidth[gNum] >> 1) + (gWidth[gNum] & 1)) * gHeight[gNum];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmapPtr += gWidth[gNum] * gHeight[gNum];
|
||||||
|
}
|
||||||
|
|
||||||
gNum++;
|
gNum++;
|
||||||
yield();
|
yield();
|
||||||
|
|
@ -333,6 +355,50 @@ uint32_t TFT_eSPI::readInt32(void)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: readInt16
|
||||||
|
** Description: Get a 16 bit integer from the font file
|
||||||
|
*************************************************************************************x*/
|
||||||
|
uint16_t TFT_eSPI::readInt16(void)
|
||||||
|
{
|
||||||
|
uint16_t val = 0;
|
||||||
|
|
||||||
|
#ifdef FONT_FS_AVAILABLE
|
||||||
|
if (fs_font) {
|
||||||
|
val |= fontFile.read() << 8;
|
||||||
|
val |= fontFile.read();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
val |= pgm_read_byte(fontPtr++) << 8;
|
||||||
|
val |= pgm_read_byte(fontPtr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: readInt8
|
||||||
|
** Description: Get a 8 bit integer from the font file
|
||||||
|
*************************************************************************************x*/
|
||||||
|
uint8_t TFT_eSPI::readInt8(void)
|
||||||
|
{
|
||||||
|
uint8_t val = 0;
|
||||||
|
|
||||||
|
#ifdef FONT_FS_AVAILABLE
|
||||||
|
if (fs_font) {
|
||||||
|
val = fontFile.read();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
val = pgm_read_byte(fontPtr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: getUnicodeIndex
|
** Function name: getUnicodeIndex
|
||||||
|
|
@ -408,7 +474,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
||||||
|
|
||||||
int16_t xs = cx;
|
int16_t xs = cx;
|
||||||
uint32_t dl = 0;
|
uint32_t dl = 0;
|
||||||
uint8_t pixel;
|
uint8_t pixel = 0;
|
||||||
|
uint8_t pixel_before = 0;
|
||||||
|
|
||||||
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
|
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
|
||||||
|
|
||||||
|
|
@ -420,13 +487,27 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
||||||
if (fs_font) {
|
if (fs_font) {
|
||||||
if (spiffs)
|
if (spiffs)
|
||||||
{
|
{
|
||||||
fontFile.read(pbuffer, gWidth[gNum]);
|
if(gFont.c4bpp)
|
||||||
|
{
|
||||||
|
fontFile.read(pbuffer, (gWidth[gNum] >> 1) + (gWidth[gNum] & 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fontFile.read(pbuffer, gWidth[gNum]);
|
||||||
|
}
|
||||||
//Serial.println("SPIFFS");
|
//Serial.println("SPIFFS");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
endWrite(); // Release SPI for SD card transaction
|
endWrite(); // Release SPI for SD card transaction
|
||||||
fontFile.read(pbuffer, gWidth[gNum]);
|
if(gFont.c4bpp)
|
||||||
|
{
|
||||||
|
fontFile.read(pbuffer, (gWidth[gNum] >> 1) + (gWidth[gNum] & 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fontFile.read(pbuffer, gWidth[gNum]);
|
||||||
|
}
|
||||||
startWrite(); // Re-start SPI for TFT transaction
|
startWrite(); // Re-start SPI for TFT transaction
|
||||||
//Serial.println("Not SPIFFS");
|
//Serial.println("Not SPIFFS");
|
||||||
}
|
}
|
||||||
|
|
@ -435,10 +516,26 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
||||||
for (int x = 0; x < gWidth[gNum]; x++)
|
for (int x = 0; x < gWidth[gNum]; x++)
|
||||||
{
|
{
|
||||||
#ifdef FONT_FS_AVAILABLE
|
#ifdef FONT_FS_AVAILABLE
|
||||||
if (fs_font) pixel = pbuffer[x];
|
if (fs_font)
|
||||||
else
|
{
|
||||||
|
pixel = (!gFont.c4bpp ? pbuffer[x] : pbuffer[(x >> 1) + (x & 1)]);
|
||||||
|
pixel_before = (!gFont.c4bpp || x == 0 ? 0 : pbuffer[((x-1) >> 1) + ((x - 1) & 1)]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
#endif
|
#endif
|
||||||
pixel = pgm_read_byte(gPtr + gBitmap[gNum] + x + gWidth[gNum] * y);
|
pixel = (!gFont.c4bpp ? pgm_read_byte(gPtr + gBitmap[gNum] + x + gWidth[gNum] * y)
|
||||||
|
: pgm_read_byte( gPtr + gBitmap[gNum] + (x >> 1) + (x & 1) +
|
||||||
|
((gWidth[gNum] >> 1) + (gWidth[gNum] & 1)) * y));
|
||||||
|
pixel_before = (!gFont.c4bpp || x == 0 ? 0 : pgm_read_byte( gPtr + gBitmap[gNum] + ((x -1) >> 1) +
|
||||||
|
((x -1) & 1) + ((gWidth[gNum] >> 1) + (gWidth[gNum] & 1)) * y));
|
||||||
|
#ifdef FONT_FS_AVAILABLE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//Prepare real pixel data for 4bpp mode
|
||||||
|
if(gFont.c4bpp)
|
||||||
|
{
|
||||||
|
pixel = (!(x & 1) ? (pixel & 0xf0) : ((pixel_before & 0x0f) << 4));
|
||||||
|
}
|
||||||
|
|
||||||
if (pixel)
|
if (pixel)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,10 @@
|
||||||
int16_t descent; // Offset to bottom of 'p', other characters may have a larger descent
|
int16_t descent; // Offset to bottom of 'p', other characters may have a larger descent
|
||||||
uint16_t maxAscent; // Maximum ascent found in font
|
uint16_t maxAscent; // Maximum ascent found in font
|
||||||
uint16_t maxDescent; // Maximum descent found in font
|
uint16_t maxDescent; // Maximum descent found in font
|
||||||
|
bool c4bpp;
|
||||||
} fontMetrics;
|
} fontMetrics;
|
||||||
|
|
||||||
fontMetrics gFont = { nullptr, 0, 0, 0, 0, 0, 0, 0 };
|
fontMetrics gFont = { nullptr, 0, 0, 0, 0, 0, 0, 0 ,false };
|
||||||
|
|
||||||
// These are for the metrics for each individual glyph (so we don't need to seek this in file and waste time)
|
// These are for the metrics for each individual glyph (so we don't need to seek this in file and waste time)
|
||||||
uint16_t* gUnicode = NULL; //UTF-16 code, the codes are searched so do not need to be sequential
|
uint16_t* gUnicode = NULL; //UTF-16 code, the codes are searched so do not need to be sequential
|
||||||
|
|
@ -56,6 +57,8 @@ fontMetrics gFont = { nullptr, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
void loadMetrics(void);
|
void loadMetrics(void);
|
||||||
uint32_t readInt32(void);
|
uint32_t readInt32(void);
|
||||||
|
uint16_t readInt16(void);
|
||||||
|
uint8_t readInt8(void);
|
||||||
|
|
||||||
uint8_t* fontPtr = nullptr;
|
uint8_t* fontPtr = nullptr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
### VLW Compress for TFT_eSPI
|
||||||
|
|
||||||
|
Used to transform 8bit VLW file into 4bit VLW file with no padding support.
|
||||||
|
|
||||||
|
**Advantage**: It will save at least 50% space.
|
||||||
|
**Limitation**: Fonts that height over 255 are not being generated properly.
|
||||||
|
|
||||||
|
To Compile,run the command below:
|
||||||
|
|
||||||
|
Windows(MinGW needed): `gcc vlwcompress.c -o vlwcompress.exe`
|
||||||
|
Linux (GCC needed): `gcc vlwcompress.c -o vlwcompress`
|
||||||
|
|
||||||
|
|
||||||
|
#### Compressed Font format
|
||||||
|
|
||||||
|
Header of vlw file is the same as uncompressed;it comprises 6 uint32_t parameters (24 bytes total):
|
||||||
|
1. The gCount (number of character glyphs)
|
||||||
|
2. A version number (0xB = 11 for uncompressed,0XC = 12 for compressed 4bit)
|
||||||
|
3. The font size (in points, not pixels)
|
||||||
|
4. Deprecated mboxY parameter (typically set to 0)
|
||||||
|
5. Ascent in pixels from baseline to top of "d"
|
||||||
|
6. Descent in pixels from baseline to bottom of "p"
|
||||||
|
|
||||||
|
Next are gCount sets of values for each glyph(8 bytes):
|
||||||
|
1. (16 bits) Glyph Unicode
|
||||||
|
2. (8 bits) Height of bitmap bounding box
|
||||||
|
3. (8 bits) Width of bitmap bounding box
|
||||||
|
4. (8 bits) gxAdvance for cursor (setWidth in Processing)
|
||||||
|
5. (16 bits) dY = distance from cursor baseline to top of glyph bitmap (signed value +ve = up)
|
||||||
|
6. (8 bits) dX = distance from cursor to left side of glyph bitmap (signed value -ve = left)
|
||||||
|
|
||||||
|
The bitmaps start next at 24 + (8 * gCount) bytes from the start of the file.
|
||||||
|
Each pixel is 0.5 byte, an 4 bit Alpha value which represents the transparency from
|
||||||
|
0xF foreground colour, 0x0 background.When a line consist of odd number of pixels,the last byte
|
||||||
|
for the last pixel of the line will be filled with 0 as low 4 bits.
|
||||||
|
4 bits alpha value will be generated to 8 bits before drawing.
|
||||||
|
|
||||||
|
After the bitmaps is (Not modified):
|
||||||
|
1 byte for font name string length (excludes null)
|
||||||
|
a zero terminated character string giving the font name
|
||||||
|
1 byte for Postscript name string length
|
||||||
|
a zero/one terminated character string giving the font name
|
||||||
|
last byte is 0 for non-anti-aliased and 1 for anti-aliased (smoothed)
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
VLW Compress v0.0.1 16/7/21
|
||||||
|
|
||||||
|
Used to transform 8bit VLW file into 4bit VLW file with no padding support.
|
||||||
|
|
||||||
|
Note: The program is made by pure C ;it has no dependence.
|
||||||
|
License:See license in root directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
FILE* fin;
|
||||||
|
FILE* fout;
|
||||||
|
struct {
|
||||||
|
uint32_t gCount;
|
||||||
|
uint32_t gVer; //0xB(11) = unCompressed,0xC(12)=compressed.
|
||||||
|
uint32_t fSize;
|
||||||
|
uint32_t mboxY;
|
||||||
|
uint32_t ascent;
|
||||||
|
uint32_t descent;
|
||||||
|
uint8_t* gX;
|
||||||
|
uint8_t* gY;
|
||||||
|
} fInfo;
|
||||||
|
|
||||||
|
uint32_t readu32(){
|
||||||
|
uint32_t temp=0;
|
||||||
|
uint8_t tmp[4]={0};
|
||||||
|
fread(tmp,1,4,fin);
|
||||||
|
temp |= tmp[0] << 24;
|
||||||
|
temp |= tmp[1] << 16;
|
||||||
|
temp |= tmp[2] << 8;
|
||||||
|
temp |= tmp[3] << 0;
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t readu8(){
|
||||||
|
uint8_t temp[1];
|
||||||
|
fread(temp,1,1,fin);
|
||||||
|
return temp[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeu32(uint32_t in){
|
||||||
|
uint8_t tmp[4]={0};
|
||||||
|
tmp[0]=in>>24;
|
||||||
|
tmp[1]=(in & 0x00ff0000 )>>16;
|
||||||
|
tmp[2]=(in & 0x0000ff00 )>>8;
|
||||||
|
tmp[3]=(in & 0x000000ff );
|
||||||
|
if(fwrite(tmp,1,4,fout)==4){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeu16(uint16_t in){
|
||||||
|
uint8_t tmp[2]={0};
|
||||||
|
tmp[0]=in>>8;
|
||||||
|
tmp[1]=(in & 0x00ff );
|
||||||
|
if(fwrite(tmp,1,2,fout)==2){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeu8(uint8_t in){
|
||||||
|
if(fwrite(&in,1,1,fout)==1){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t combine2u8(uint8_t H,uint8_t L){
|
||||||
|
return (H & 0xf0 ) | (L >> 4); //All get High bits and combine
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getFontInfo(){
|
||||||
|
fInfo.gCount=readu32();
|
||||||
|
fInfo.gVer=readu32();
|
||||||
|
fInfo.fSize=readu32();
|
||||||
|
fInfo.mboxY=readu32();
|
||||||
|
fInfo.ascent=readu32();
|
||||||
|
fInfo.descent=readu32();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeHeader(){
|
||||||
|
writeu32(fInfo.gCount);
|
||||||
|
writeu32(12ULL);
|
||||||
|
writeu32(fInfo.fSize);
|
||||||
|
writeu32(fInfo.mboxY);
|
||||||
|
writeu32(fInfo.ascent);
|
||||||
|
writeu32(fInfo.descent);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int compressCharsTable(){
|
||||||
|
for(uint32_t i=0;i<fInfo.gCount;i++){
|
||||||
|
uint16_t unicode=(uint16_t)readu32();
|
||||||
|
uint8_t bh=(uint8_t)readu32();
|
||||||
|
uint8_t bw=(uint8_t)readu32();
|
||||||
|
uint8_t ga=(uint8_t)readu32();
|
||||||
|
int16_t dy=(int16_t)readu32();
|
||||||
|
int8_t dx=(int8_t)readu32();
|
||||||
|
readu32(); //ignore padding
|
||||||
|
fInfo.gX[i]=bw;
|
||||||
|
fInfo.gY[i]=bh;
|
||||||
|
writeu16(unicode);
|
||||||
|
writeu8(bh);
|
||||||
|
writeu8(bw);
|
||||||
|
writeu8(ga);
|
||||||
|
writeu16(dy);
|
||||||
|
writeu8(dx);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compressCharsBitmap(){
|
||||||
|
for(uint32_t i=0;i<fInfo.gCount;i++){
|
||||||
|
if((fInfo.gX[i] & 1) !=0){//not fix 2
|
||||||
|
for(uint8_t j=0;j<fInfo.gY[i];j++){
|
||||||
|
for(uint8_t k=0;k<fInfo.gX[i]-1;k+=2){
|
||||||
|
uint8_t t1=(uint8_t)readu8();
|
||||||
|
uint8_t t2=(uint8_t)readu8();
|
||||||
|
writeu8(combine2u8(t1,t2));
|
||||||
|
}
|
||||||
|
//process the last pixel of each line with 0 as low bits
|
||||||
|
uint8_t t1=(uint8_t)readu8();
|
||||||
|
writeu8(combine2u8(t1,0));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for(uint16_t j=0;j<fInfo.gX[i] * fInfo.gY[i];j+=2){
|
||||||
|
uint8_t t1=(uint8_t)readu8();
|
||||||
|
uint8_t t2=(uint8_t)readu8();
|
||||||
|
writeu8(combine2u8(t1,t2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc,char* argv[]){
|
||||||
|
printf("\n=== VLWCompress - 4bpp by Lucy2003 v0.0.1 === \n\n");
|
||||||
|
if(argc<=2){
|
||||||
|
printf(" usage: %s [input_path] [output_path]\n\n",argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("Input file: %s\nOutput file: %s\n",argv[1],argv[2]);
|
||||||
|
|
||||||
|
|
||||||
|
fin=fopen(argv[1],"rb");
|
||||||
|
if(fin == NULL){
|
||||||
|
printf("\nError: Can't open input file. \n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fseek(fin,0,SEEK_SET);
|
||||||
|
fout=fopen(argv[2],"w+b");
|
||||||
|
if(fout==NULL){
|
||||||
|
printf("\nError: Can't open output file. \n\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontInfo();
|
||||||
|
printf("Font file info:\n");
|
||||||
|
printf(" Char count: %d\n",fInfo.gCount);
|
||||||
|
printf(" Font version: %d\n",fInfo.gVer);
|
||||||
|
printf(" Font size: %d Bytes\n",fInfo.fSize);
|
||||||
|
printf(" mboxY: %d\n ascent:%d\n descent:%d\n",fInfo.mboxY,fInfo.ascent,fInfo.descent);
|
||||||
|
|
||||||
|
if(fInfo.gVer==12){
|
||||||
|
printf("\nError: Input file already compressed.\n\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fInfo.gVer!=11){
|
||||||
|
printf("\nError: Unsupport font version.\n\n");
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
fInfo.gX=NULL;
|
||||||
|
fInfo.gY=NULL;
|
||||||
|
fInfo.gX=(uint8_t*)calloc(fInfo.gCount,sizeof(uint8_t));
|
||||||
|
fInfo.gY=(uint8_t*)calloc(fInfo.gCount,sizeof(uint8_t));
|
||||||
|
if(fInfo.gX==NULL || fInfo.gY==NULL){
|
||||||
|
printf("\nError: Malloc memory failed.\n\n");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
//Compress
|
||||||
|
writeHeader();
|
||||||
|
compressCharsTable();
|
||||||
|
compressCharsBitmap();
|
||||||
|
|
||||||
|
free(fInfo.gX);
|
||||||
|
free(fInfo.gY);
|
||||||
|
|
||||||
|
while(!feof(fin)){
|
||||||
|
writeu8(readu8());
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fin);
|
||||||
|
fclose(fout);
|
||||||
|
printf("\nCompress Font successfully!\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue