correct font handling

Signed-off-by: SergeySlice <sergey.slice@gmail.com>
This commit is contained in:
SergeySlice 2020-03-29 10:14:14 +03:00
parent e59f205afc
commit 38319f70bc
4 changed files with 82 additions and 112 deletions

View File

@ -48,22 +48,25 @@ extern VOID
WaitForKeyPress(CHAR16 *Message); WaitForKeyPress(CHAR16 *Message);
extern void DumpFloat2 (CONST char* s, float* t, int N); extern void DumpFloat2 (CONST char* s, float* t, int N);
#if !USE_XTHEME
extern EG_IMAGE *BackgroundImage; extern EG_IMAGE *BackgroundImage;
extern EG_IMAGE *Banner; extern EG_IMAGE *Banner;
extern EG_IMAGE *BigBack; extern EG_IMAGE *BigBack;
extern INTN BanHeight; extern INTN BanHeight;
extern INTN row0TileSize; extern INTN row0TileSize;
extern INTN row1TileSize; extern INTN row1TileSize;
extern INTN FontWidth; //extern INTN FontWidth;
#endif
extern UINTN NumFrames; extern UINTN NumFrames;
extern UINTN FrameTime; extern UINTN FrameTime;
extern BOOLEAN DayLight; extern BOOLEAN DayLight;
textFaces textFace[4]; //0-help 1-message 2-menu 3-test
textFaces textFace[4]; //0-help 1-message 2-menu 3-test, far future it will be infinite list with id
NSVGparser *mainParser = NULL; //it must be global variable NSVGparser *mainParser = NULL; //it must be global variable
#if USE_XTHEME #if USE_XTHEME
EFI_STATUS ParseSVGXIcon(NSVGparser *p, INTN Id, CONST CHAR8 *IconName, float Scale, OUT XImage& Image) EFI_STATUS ParseSVGXIcon(NSVGparser *p, INTN Id, XString& IconNameX, float Scale, OUT XImage& Image)
{ {
EFI_STATUS Status = EFI_NOT_FOUND; EFI_STATUS Status = EFI_NOT_FOUND;
NSVGimage *SVGimage; NSVGimage *SVGimage;
@ -73,6 +76,7 @@ EFI_STATUS ParseSVGXIcon(NSVGparser *p, INTN Id, CONST CHAR8 *IconName, float S
NSVGgroup *group; NSVGgroup *group;
NSVGimage *IconImage; NSVGimage *IconImage;
NSVGshape *shapeNext, *shapesTail = NULL, *shapePrev; NSVGshape *shapeNext, *shapesTail = NULL, *shapePrev;
CONST CHAR8 *IconName = IconNameX.c_str();
NSVGparser* p2 = nsvg__createParser(); NSVGparser* p2 = nsvg__createParser();
IconImage = p2->image; IconImage = p2->image;
@ -719,102 +723,6 @@ EG_IMAGE * LoadSvgFrame(INTN i)
return Frame; return Frame;
} }
#if 0
VOID RenderSVGfont(NSVGfont *fontSVG, UINT32 color)
{
// EFI_STATUS Status;
float FontScale;
NSVGparser *p;
NSVGrasterizer *rast;
INTN i;
if (!fontSVG) {
return;
}
//free old font
if (FontImage != NULL) {
egFreeImage (FontImage);
FontImage = NULL;
}
INTN Height = FontHeight + 4;
// DBG("load font %s\n", fontSVG->fontFamily);
if (fontSVG->unitsPerEm < 1.f) {
fontSVG->unitsPerEm = 1000.f;
}
float fH = fontSVG->bbox[3] - fontSVG->bbox[1];
if (fH == 0.f) {
fH = fontSVG->unitsPerEm;
}
FontScale = (float)FontHeight / fH;
DBG("font scale %ls\n", FontScale);
FontWidth = (int)(fontSVG->horizAdvX * FontScale);
INTN Width = FontWidth * (AsciiPageSize + GlobalConfig.CodepageSize);
FontImage = egCreateImage(Width, Height, TRUE);
p = nsvg__createParser();
if (!p) {
return;
}
// p->font = fontSVG;
p->image->height = (float)Height;
p->image->width = (float)Width;
NSVGtext* text = (NSVGtext*)AllocateZeroPool(sizeof(NSVGtext));
if (!text) {
return;
}
text->fontSize = (float)FontHeight;
text->font = fontSVG;
text->fontColor = color;
// DBG("RenderSVGfont: fontID=%s\n", text->font->id);
// DBG("RenderSVGfont: family=%s\n", text->font->fontFamily);
//add to head
text->next = p->text;
p->text = text;
//for each letter rasterize glyph into FontImage
//0..0xC0 == AsciiPageSize
// cyrillic 0x410..0x450 at 0xC0
float x = 0.f;
float y = fontSVG->bbox[1] * FontScale;; //(float)Height;
p->isText = TRUE;
for (i = 0; i < AsciiPageSize; i++) {
addLetter(p, i, x, y, FontScale, color);
x += (float)FontWidth;
}
x = AsciiPageSize * FontWidth;
for (i = GlobalConfig.Codepage; i < GlobalConfig.Codepage+GlobalConfig.CodepageSize; i++) {
addLetter(p, i, x, y, FontScale, color);
x += (float)FontWidth;
}
p->image->realBounds[0] = fontSVG->bbox[0] * FontScale;
p->image->realBounds[1] = fontSVG->bbox[1] * FontScale;
p->image->realBounds[2] = fontSVG->bbox[2] * FontScale + x; //last bound
p->image->realBounds[3] = fontSVG->bbox[3] * FontScale;
//We made an image, then rasterize it
rast = nsvgCreateRasterizer();
nsvgRasterize(rast, p->image, 0, 0, 1.0f, 1.0f, (UINT8*)FontImage->PixelData, (int)Width, (int)Height, (int)(Width*4));
#if 0 //DEBUG_FONT
//save font as png yyyyy
UINT8 *FileData = NULL;
UINTN FileDataLength = 0U;
EFI_UGA_PIXEL *ImagePNG = (EFI_UGA_PIXEL *)FontImage->PixelData;
unsigned lode_return =
eglodepng_encode(&FileData, &FileDataLength, (CONST UINT8*)ImagePNG, (UINTN)FontImage->Width, (UINTN)FontImage->Height);
if (!lode_return) {
egSaveFile(SelfRootDir, L"\\FontSVG.png", FileData, FileDataLength);
}
#endif
nsvgDeleteRasterizer(rast);
// nsvg__deleteParser(p);
return;
}
#endif
// it is not draw, it is render and mainly used in egRenderText // it is not draw, it is render and mainly used in egRenderText
// which is used in icns.cpp as an icon rplacement if no image found, looks like not used // which is used in icns.cpp as an icon rplacement if no image found, looks like not used
// in menu.cpp 3 places // in menu.cpp 3 places

View File

@ -37,7 +37,7 @@
#ifndef __LIBEG_LIBEG_H__ #ifndef __LIBEG_LIBEG_H__
#define __LIBEG_LIBEG_H__ #define __LIBEG_LIBEG_H__
#define USE_XTHEME 0 #define USE_XTHEME 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -56,7 +56,7 @@
EG_IMAGE *FontImage = NULL; EG_IMAGE *FontImage = NULL;
INTN FontWidth = 9; INTN FontWidth = 9; //local variable
INTN FontHeight = 18; INTN FontHeight = 18;
INTN TextHeight = 19; INTN TextHeight = 19;
NSVGfontChain *fontsDB = NULL; NSVGfontChain *fontsDB = NULL;
@ -89,6 +89,7 @@ VOID egMeasureText(IN CONST CHAR16 *Text, OUT INTN *Width, OUT INTN *Height)
} }
#endif #endif
//should be rewritten to use XImage and XStringW
EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols) EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
{ {
EG_IMAGE *NewImage = NULL, *NewFontImage; EG_IMAGE *NewImage = NULL, *NewFontImage;
@ -96,12 +97,21 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
EG_PIXEL *PixelPtr, FirstPixel; EG_PIXEL *PixelPtr, FirstPixel;
BOOLEAN isKorean = (gLanguage == korean); BOOLEAN isKorean = (gLanguage == korean);
CHAR16 *fontFilePath = NULL; CHAR16 *fontFilePath = NULL;
CONST CHAR16 *commonFontDir = L"EFI\\CLOVER\\font"; CONST CHAR16 *commonFontDir = L"EFI\\CLOVER\\font";
if (IsEmbeddedTheme() && !isKorean) { //or initial screen before theme init if (IsEmbeddedTheme() && !isKorean) { //or initial screen before theme init
NewImage = egDecodePNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data), TRUE); NewImage = egDecodePNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data), TRUE);
MsgLog("Using embedded font: %s\n", NewImage ? "Success" : "Error"); MsgLog("Using embedded font: %s\n", NewImage ? "Success" : "Error");
} else { } else {
#if USE_XTHEME
if (!ThemeX.TypeSVG) {
NewImage = egLoadImage(ThemeDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data(), TRUE);
MsgLog("Loading font from ThemeDir: %s\n", NewImage ? "Success" : "Error");
} else {
MsgLog("Using SVG font\n");
return FontImage;
}
#else
if (!GlobalConfig.TypeSVG) { if (!GlobalConfig.TypeSVG) {
NewImage = egLoadImage(ThemeDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName, TRUE); NewImage = egLoadImage(ThemeDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName, TRUE);
MsgLog("Loading font from ThemeDir: %s\n", NewImage ? "Success" : "Error"); MsgLog("Loading font from ThemeDir: %s\n", NewImage ? "Success" : "Error");
@ -109,11 +119,17 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
MsgLog("Using SVG font\n"); MsgLog("Using SVG font\n");
return FontImage; return FontImage;
} }
#endif
} }
if (!NewImage) { if (!NewImage) {
//then take from common font folder //then take from common font folder
#if USE_XTHEME
fontFilePath = PoolPrint(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data());
#else
fontFilePath = PoolPrint(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName); fontFilePath = PoolPrint(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName);
#endif
NewImage = egLoadImage(SelfRootDir, fontFilePath, TRUE); NewImage = egLoadImage(SelfRootDir, fontFilePath, TRUE);
//else use embedded //else use embedded
if (!NewImage) { if (!NewImage) {
@ -145,7 +161,12 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
FontWidth = ImageWidth / Cols; FontWidth = ImageWidth / Cols;
FontHeight = ImageHeight / Rows; FontHeight = ImageHeight / Rows;
#if USE_XTHEME
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * ThemeX.Scale);
#else
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale); TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale);
#endif
FirstPixel = *PixelPtr; FirstPixel = *PixelPtr;
for (y = 0; y < Rows; y++) { for (y = 0; y < Rows; y++) {
for (j = 0; j < FontHeight; j++) { for (j = 0; j < FontHeight; j++) {
@ -158,8 +179,13 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
(PixelPtr->r == FirstPixel.r) (PixelPtr->r == FirstPixel.r)
) { ) {
PixelPtr->a = 0; PixelPtr->a = 0;
#if USE_XTHEME
} else if (ThemeX.DarkEmbedded) {
*PixelPtr = SemiWhitePixel;
#else
} else if (GlobalConfig.DarkEmbedded) { } else if (GlobalConfig.DarkEmbedded) {
*PixelPtr = SemiWhitePixel; *PixelPtr = SemiWhitePixel;
#endif
} }
NewFontImage->PixelData[Ypos + x] = *PixelPtr++; NewFontImage->PixelData[Ypos + x] = *PixelPtr++;
} }
@ -175,12 +201,18 @@ VOID PrepareFont()
{ {
EG_PIXEL *p; EG_PIXEL *p;
INTN Width, Height; INTN Width, Height;
#if USE_XTHEME
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale); TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * ThemeX.Scale);
if (GlobalConfig.TypeSVG) { if (ThemeX.TypeSVG) {
// FontImage = RenderSVGfont();
return; return;
} }
#else
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale);
if (GlobalConfig.TypeSVG) {
// FontImage = RenderSVGfont();
return;
}
#endif
if (FontImage) { if (FontImage) {
egFreeImage(FontImage); egFreeImage(FontImage);
@ -190,10 +222,12 @@ VOID PrepareFont()
if (gLanguage == korean) { if (gLanguage == korean) {
FontImage = egLoadFontImage(FALSE, 10, 28); FontImage = egLoadFontImage(FALSE, 10, 28);
if (FontImage) { if (FontImage) {
// FontHeight = 16; //delete? #if USE_XTHEME
ThemeX.CharWidth = 22;
#else
GlobalConfig.CharWidth = 22; GlobalConfig.CharWidth = 22;
// FontWidth = GlobalConfig.CharWidth; //delete? #endif
// TextHeight = FontHeight + TEXT_YMARGIN * 2;
MsgLog("Using Korean font matrix\n"); MsgLog("Using Korean font matrix\n");
return; return;
} else { } else {
@ -209,6 +243,20 @@ VOID PrepareFont()
} }
if (FontImage) { if (FontImage) {
#if USE_XTHEME
if (ThemeX.Font == FONT_GRAY) {
//invert the font. embedded is dark
p = FontImage->PixelData;
for (Height = 0; Height < FontImage->Height; Height++){
for (Width = 0; Width < FontImage->Width; Width++, p++){
p->b ^= 0xFF;
p->g ^= 0xFF;
p->r ^= 0xFF;
//p->a = 0xFF; //huh!
}
}
}
#else
if (GlobalConfig.Font == FONT_GRAY) { if (GlobalConfig.Font == FONT_GRAY) {
//invert the font. embedded is dark //invert the font. embedded is dark
p = FontImage->PixelData; p = FontImage->PixelData;
@ -221,6 +269,7 @@ VOID PrepareFont()
} }
} }
} }
#endif
// TextHeight = FontHeight + TEXT_YMARGIN * 2; // TextHeight = FontHeight + TEXT_YMARGIN * 2;
DBG("Font %d prepared WxH=%lldx%lld CharWidth=%lld\n", GlobalConfig.Font, FontWidth, FontHeight, GlobalConfig.CharWidth); DBG("Font %d prepared WxH=%lldx%lld CharWidth=%lld\n", GlobalConfig.Font, FontWidth, FontHeight, GlobalConfig.CharWidth);
@ -297,7 +346,12 @@ INTN egRenderText(IN CONST CHAR16 *Text, IN OUT EG_IMAGE *CompImage,
// clip the text // clip the text
#if USE_XTHEME
TextLength = Text.size();
#else
TextLength = StrLen(Text); TextLength = StrLen(Text);
#endif
if (!FontImage) { if (!FontImage) {
// GlobalConfig.Font = FONT_ALFA; // GlobalConfig.Font = FONT_ALFA;
PrepareFont(); PrepareFont();
@ -332,10 +386,17 @@ INTN egRenderText(IN CONST CHAR16 *Text, IN OUT EG_IMAGE *CompImage,
c = Text[i]; c = Text[i];
#endif #endif
if (gLanguage != korean) { if (gLanguage != korean) {
c1 = (((c >= GlobalConfig.Codepage) ? (c - (GlobalConfig.Codepage - AsciiPageSize)) : c) & 0xff); //International letters #if USE_XTHEME
c1 = (((c >= ThemeX.Codepage) ? (c - (ThemeX.Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1; c = c1;
if (ThemeX.Proportional) {
#else
c1 = (((c >= GlobalConfig.Codepage) ? (c - (GlobalConfig.Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1;
if (GlobalConfig.Proportional) { if (GlobalConfig.Proportional) {
#endif
if (c0 <= 0x20) { // space before or at buffer edge if (c0 <= 0x20) { // space before or at buffer edge
LeftSpace = 2; LeftSpace = 2;
} else { } else {

View File

@ -504,8 +504,9 @@ EFI_STATUS InitializeUnicodeCollationProtocol (VOID);
#define LAYOUT_X_EDGE (20) #define LAYOUT_X_EDGE (20)
#define BAR_WIDTH (16) #define BAR_WIDTH (16)
extern INTN FontWidth; // local variables
extern INTN FontHeight; //extern INTN FontWidth;
//extern INTN FontHeight;
extern INTN TextHeight; extern INTN TextHeight;
extern INTN row0TileSize; extern INTN row0TileSize;
extern INTN row1TileSize; extern INTN row1TileSize;