repaired font handling

Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
This commit is contained in:
Sergey Isakov 2020-04-09 16:04:12 +03:00
parent 790fedbdc6
commit 97d1d23eb0
9 changed files with 142 additions and 121 deletions

View File

@ -95,8 +95,6 @@
A570FB0D240D626D0057F26D /* XPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A570FB0B240D626C0057F26D /* XPointer.cpp */; };
A5716F83235968BE000CEC60 /* Nasm.inc in Sources */ = {isa = PBXBuildFile; fileRef = A5716F82235968BE000CEC60 /* Nasm.inc */; };
A571C28D240574DA00B6A2C5 /* XImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A571C28B240574D900B6A2C5 /* XImage.cpp */; };
A57CF7B52419F4F9006DE51E /* XUINTN.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B32419F4F8006DE51E /* XUINTN.cpp */; };
A57CF7B82419F51B006DE51E /* XUINTN_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */; };
A57CF7BB241A8A13006DE51E /* XTheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B9241A8A12006DE51E /* XTheme.cpp */; };
A57CF7C6241BE0A4006DE51E /* strcmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7BF241BE0A4006DE51E /* strcmp.cpp */; };
A57CF7C8241BE0A4006DE51E /* strlen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7C3241BE0A4006DE51E /* strlen.cpp */; };
@ -2508,10 +2506,6 @@
A571C28A240574BB00B6A2C5 /* remove_ref.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = remove_ref.h; sourceTree = "<group>"; };
A571C28B240574D900B6A2C5 /* XImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XImage.cpp; sourceTree = "<group>"; };
A571C28C240574D900B6A2C5 /* XImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XImage.h; sourceTree = "<group>"; };
A57CF7B32419F4F8006DE51E /* XUINTN.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XUINTN.cpp; sourceTree = "<group>"; };
A57CF7B42419F4F8006DE51E /* XUINTN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XUINTN.h; sourceTree = "<group>"; };
A57CF7B62419F51A006DE51E /* XUINTN_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XUINTN_test.h; sourceTree = "<group>"; };
A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XUINTN_test.cpp; sourceTree = "<group>"; };
A57CF7B9241A8A12006DE51E /* XTheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XTheme.cpp; sourceTree = "<group>"; };
A57CF7BA241A8A13006DE51E /* XTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XTheme.h; sourceTree = "<group>"; };
A57CF7BD241BE0A4006DE51E /* stdlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdlib.h; sourceTree = "<group>"; };
@ -8307,8 +8301,6 @@
A5D12C35243A0BE500DFA98A /* XStringWP.h */,
A571C2772405749900B6A2C5 /* XToolsCommon.cpp */,
A571C2702405749900B6A2C5 /* XToolsCommon.h */,
A57CF7B32419F4F8006DE51E /* XUINTN.cpp */,
A57CF7B42419F4F8006DE51E /* XUINTN.h */,
);
path = cpp_foundation;
sourceTree = "<group>";
@ -8349,8 +8341,6 @@
A571C27F240574A100B6A2C5 /* XStringWArray_test.cpp */,
A571C283240574A100B6A2C5 /* XStringW_test.h */,
A571C289240574A100B6A2C5 /* XStringW_test.cpp */,
A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */,
A57CF7B62419F51A006DE51E /* XUINTN_test.h */,
);
path = cpp_unit_test;
sourceTree = "<group>";
@ -16607,7 +16597,6 @@
A5AAFBC6237F13B3009CD413 /* Variable.c in Sources */,
A5AAFB3A237F13B3009CD413 /* SmramProfileRecord.c in Sources */,
A5AA0571237F13C1009CD413 /* WriteMsr64.c in Sources */,
A57CF7B52419F4F9006DE51E /* XUINTN.cpp in Sources */,
A5AAFC37237F13B3009CD413 /* Vtutf8.c in Sources */,
A5AAFD2D237F13B4009CD413 /* DebugAgentLibNull.c in Sources */,
A5816DED24180F4D003BA66C /* panic.cpp in Sources */,
@ -17096,7 +17085,6 @@
A5AAFC1A237F13B3009CD413 /* X64Entry.c in Sources */,
A5AAFB33237F13B3009CD413 /* Page.c in Sources */,
A5AA06D4237F13C2009CD413 /* SmmPeriodicSmiLib.c in Sources */,
A57CF7B82419F51B006DE51E /* XUINTN_test.cpp in Sources */,
A5AAFC45237F13B3009CD413 /* SdHci.c in Sources */,
A5AAFC0C237F13B3009CD413 /* Database.c in Sources */,
A5AAFC5D237F13B3009CD413 /* PciIo.c in Sources */,

View File

@ -4239,27 +4239,14 @@ XTheme::GetThemeTagSettings (void* DictP)
FontFileName.takeValueFrom(Dict2->string);
}
}
#if USE_XTHEME
Dict2 = GetProperty (Dict, "CharWidth");
ThemeX.CharWidth = (UINTN)GetPropertyInteger (Dict2, ThemeX.CharWidth);
if (ThemeX.CharWidth & 1) {
MsgLog("Warning! Character width %lld should be even!\n", ThemeX.CharWidth);
}
Dict2 = GetProperty (Dict, "Proportional");
ThemeX.Proportional = IsPropertyTrue (Dict2);
#else
Dict2 = GetProperty (Dict, "CharWidth");
CharWidth = (UINTN)GetPropertyInteger (Dict2, CharWidth);
if (GlobalConfig.CharWidth & 1) {
if (CharWidth & 1) {
MsgLog("Warning! Character width %lld should be even!\n", CharWidth);
}
Dict2 = GetProperty (Dict, "Proportional");
GlobalConfig.Proportional = IsPropertyTrue (Dict2);
#endif
Proportional = IsPropertyTrue (Dict2);
}

View File

@ -1498,7 +1498,7 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
* so make a place to be large enoungh
*/
ThemeX.MeasureText(Text, &TextWidth, NULL); //NULL means we already know Height
// DBG("drawXY=%ls width=%lld\n", Text.wc_str(), TextWidth);
if (XAlign == X_IS_LEFT) {
TextWidth = UGAWidth - XPos - 1;
XText = XPos;
@ -2563,20 +2563,20 @@ VOID REFIT_MENU_SCREEN::DrawTextCorner(UINTN TextC, UINT8 Align)
// Display Clover boot volume
if (SelfVolume->VolLabel && SelfVolume->VolLabel[0] != L'#') {
// Text = PoolPrint(L"%s, booted from %s", gFirmwareRevision, SelfVolume->VolLabel);
Text = XStringW() + gFirmwareRevision + L", booted from " + SelfVolume->VolLabel;
Text = XStringW() + gFirmwareRevision + L", booted from "_XSW + SelfVolume->VolLabel;
}
if (Text.isEmpty()) {
Text = XStringW() + gFirmwareRevision + L" " + SelfVolume->VolName;
Text = XStringW() + gFirmwareRevision + L" "_XSW + SelfVolume->VolName;
}
break;
case TEXT_CORNER_HELP:
Text = XStringW() + L"F1:Help";
Text = L"F1:Help"_XSW;
break;
case TEXT_CORNER_OPTIMUS:
if (gGraphics[0].Vendor != Intel) {
Text = XStringW() + L"Discrete";
Text = L"Discrete"_XSW;
} else {
Text = XStringW() + L"Intel";
Text = L"Intel"_XSW;
}
// Text = (NGFX == 2)?L"Intel":L"Discrete";
break;
@ -3171,10 +3171,13 @@ VOID REFIT_MENU_SCREEN::MainMenuStyle(IN UINTN Function, IN CONST CHAR16 *ParamT
DrawMainMenuLabel(Entries[ScrollState.CurrentSelection].Title,
(UGAWidth >> 1), textPosY);
}
// DBG("draw TEXT_CORNER_HELP\n");
DrawTextCorner(TEXT_CORNER_HELP, X_IS_LEFT);
// DBG("draw TEXT_CORNER_OPTIMUS\n");
DrawTextCorner(TEXT_CORNER_OPTIMUS, X_IS_CENTER);
// DBG("draw TEXT_CORNER_REVISION\n");
DrawTextCorner(TEXT_CORNER_REVISION, X_IS_RIGHT);
// DBG("MouseBirth\n");
Status = MouseBirth();
if(EFI_ERROR(Status)) {
DBG("can't bear mouse at all! Status=%s\n", strerror(Status));

View File

@ -7,3 +7,8 @@
//
#include "XCinema.h"
void FILM::Advance()
{
CurrentFrame = ++CurrentFrame % Count;
}

View File

@ -25,23 +25,30 @@ typedef struct FRAME {
class FILM
{
public:
bool RunOnce;
protected:
INTN Id; //enumeration value but keep it to be int for extensibility
INTN FrameTime; //usually 50, 100, 200 ms
XString Path; //user defined name for folder and files Path/Path_002.png etc
XArray<FRAME> Frames;
INTN Count; // it is not Frames.size(), it is last index
XObjArray<FRAME> Frames; //Frames can be not sorted
INTN LastIndex; // it is not Frames.size(), it is last index inclusive, so frames 0,1,2,5,8 be LastIndex = 8
EG_RECT FilmPlace;
INTN CurrentFrame; // like a static value will be increase between 0..LastIndex
public:
FILM();
FILM(INTN Id);
FILM(INTN Id) : RunOnce(false), Id(Id), FrameTime(0), Path(), Frames(),
LastIndex(0), FilmPlace(), CurrentFrame(0) {};
~FILM();
const XImage& GetImage(INTN Index);
void AddImage(const XImage& Image, INTN Index);
void AddFrame(const FRAME& Frame, INTN Index);
size_t Size() { return Frames.size(); }
INTN LastFrame() { return Count; }
INTN LastFrame() { return LastIndex; }
void GetFilm(const XStringW& Path); //read from Theme
void SetPlace(const EG_RECT& Rect);
void Advance() { ++CurrentFrame %= (LastIndex + 1); }
};
@ -55,11 +62,17 @@ public:
// Each Screen contains a pointer to FILM. And moreover titleFilm, or BackgroundFilm or even entryFilm
// Next problem is a timeout between frames.
// A theme contains images with indexes 1,2,5,6 for one Id.
// This Id contains fixed timeout between frames
// This Id contains fixed timeout between frames. Then next updateAnime Index will be compared with current tick
// if yes then update. Static index?
//
// in the far future I'll plan to make dynamic SVG: parse SVGIcon with a variable argument
// and then rasterize it. Real SVG contains constants only so it will be dynamicSVG.
// then Entry->Image should be reparsed each time it created or contains flag to update every frameTime
class XCinema
{
protected:
XArray<FILM> Cinema;
XObjArray<FILM> Cinema;
public:

View File

@ -277,43 +277,45 @@ void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
Area.YPos = 0;
Area.Width = TopImage.GetWidth();
Area.Height = TopImage.GetHeight();
Compose(OutPlace, Area, TopImage, Lowest);
Compose(OutPlace, Area, TopImage, Lowest, 0.f);
}
void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XImage& TopImage, bool Lowest)
// TopScale is for scaling TopImage. = 0.f means no scale or = 1.f
// InPlace is a place in TopImage before scaling
void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XImage& TopImage, bool Lowest, float TopScale)
{
//sample
/*
INTN Dx = OwnPlace.XPos - InputRect.XPos;
INTN Dy = OwnPlace.YPos - InputRect.YPos;
INTN W = MIN(OwnPlace.Width, InputRect.Width);
INTN H = MIN(OwnPlace.Height, InputRect.Height);
for (INTN y = OwnPlace.YPos; y - OwnPlace.YPos < H && y < GetHeight() && (y - Dy) < Image.GetHeight(); ++y) {
for (INTN x = OwnPlace.XPos; x - OwnPlace.XPos < W && x < GetWidth() && (x - Dx) < Image.GetWidth(); ++x) {
PixelData[y * Width + x] = Image.GetPixel(x - Dx, y - Dy);
}
}
*/
INTN PosX = InPlace.XPos;
INTN PosY = InPlace.YPos;
INTN WArea = InPlace.Width;
INTN HArea = InPlace.Height;
XImage Top2;
if (TopScale != 0.f && TopScale != 1.f) {
Top2.setSizeInPixels((UINTN)(TopImage.GetWidth() * TopScale), (UINTN)(TopImage.GetHeight() * TopScale));
Top2.CopyScaled(TopImage, TopScale);
PosX = (int)(PosX * TopScale);
PosY = (int)(PosY * TopScale);
WArea = (int)(WArea * TopScale);
HArea = (int)(HArea * TopScale);
}
const XImage& Top = (TopScale != 0.f && TopScale != 1.f) ? Top2 : TopImage; //this is a link, not copy
//assumed Area.Width == OutPlace.Width
// if not choose min
INTN WArea = MIN(InPlace.Width, OutPlace.Width);
WArea = MIN(WArea, OutPlace.Width);
if (OutPlace.XPos + WArea > GetWidth()) { //coordinate in this image - OutPlace
WArea = GetWidth() - OutPlace.XPos;
}
INTN HArea = MIN(InPlace.Height, OutPlace.Height);
HArea = MIN(HArea, OutPlace.Height);
if (OutPlace.YPos + HArea > GetHeight()) {
HArea = GetHeight() - OutPlace.YPos;
}
//change only affected pixels
for (INTN y = 0; y < HArea && (y + PosY) < TopImage.GetHeight(); ++y) {
for (INTN y = 0; y < HArea && (y + PosY) < Top.GetHeight(); ++y) {
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL& CompPtr = *GetPixelPtr(PosX, y); // I assign a ref to avoid the operator ->. Compiler will produce the same anyway.
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* CompPtr = GetPixelPtr(OutPlace.XPos, OutPlace.YPos + y);
for (INTN x = 0; x < WArea && (x + PosX) < TopImage.GetWidth(); ++x) {
for (INTN x = 0; x < WArea && (x + PosX) < Top.GetWidth(); ++x) {
//------
// test compAlpha = 255; TopAlpha = 0 -> only Comp, TopAplha = 255 -> only Top
UINT32 TopAlpha = TopImage.GetPixel(x + PosX, y + PosY).Reserved & 0xFF; //0, 255
UINT32 TopAlpha = Top.GetPixel(x + PosX, y + PosY).Reserved & 0xFF; //0, 255
UINT32 CompAlpha = CompPtr->Reserved & 0xFF; //255
UINT32 RevAlpha = 255 - TopAlpha; //2<<8; 255, 0
UINT32 TempAlpha = CompAlpha * RevAlpha; //2<<16; 255*255, 0
@ -322,13 +324,13 @@ void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XIma
//final alpha =(1-(1-x)*(1-y)) =(255*255-(255-topA)*(255-compA))/255 = topA+compA*(1-topA)
if (FinalAlpha != 0) {
UINT32 Temp = (CompPtr->Blue * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Blue * TopAlpha);
UINT32 Temp = (CompPtr->Blue * TempAlpha) + (Top.GetPixel(x + PosX, y + PosY).Blue * TopAlpha);
CompPtr->Blue = (UINT8)(Temp / FinalAlpha);
Temp = (CompPtr->Green * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Green * TopAlpha);
Temp = (CompPtr->Green * TempAlpha) + (Top.GetPixel(x + PosX, y + PosY).Green * TopAlpha);
CompPtr->Green = (UINT8)(Temp / FinalAlpha);
Temp = (CompPtr->Red * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Red * TopAlpha);
Temp = (CompPtr->Red * TempAlpha) + (Top.GetPixel(x + PosX, y + PosY).Red * TopAlpha);
CompPtr->Red = (UINT8)(Temp / FinalAlpha);
}

View File

@ -88,7 +88,7 @@ public:
void CopyScaled(const XImage& Image, float scale);
void CopyRect(const XImage& Image, INTN X, INTN Y);
void CopyRect(const XImage& Image, const EG_RECT& OwnPlace, const EG_RECT& InputRect);
void Compose(const EG_RECT& OwnPlace, const EG_RECT& InputRect, const XImage& TopImage, bool Lowest);
void Compose(const EG_RECT& OwnPlace, const EG_RECT& InputRect, const XImage& TopImage, bool Lowest, float TopScale = 0.f);
void Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest); //instead of compose we often can Back.Draw(...) + Top.Draw(...)
void FlipRB();
EFI_STATUS FromPNG(const UINT8 * Data, UINTN Lenght);

View File

@ -132,10 +132,10 @@ public:
void PrepareFont();
INTN GetEmpty(const XImage& Buffer, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL& FirstPixel, INTN Start, INTN Step);
INTN RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale = 0.f);
//overload for UTF8 text
INTN RenderText(IN const XString& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale = 0.f);
VOID MeasureText(IN const XStringW& Text, OUT INTN *Width, OUT INTN *Height);

View File

@ -84,11 +84,16 @@ NSVGfontChain *fontsDB = NULL;
// so one more parameter is TextStyle
VOID XTheme::MeasureText(IN const XStringW& Text, OUT INTN *Width, OUT INTN *Height)
{
INTN ScaledWidth = (INTN)(CharWidth * Scale);
INTN ScaledWidth = CharWidth;
INTN ScaledHeight = FontHeight;
if (Scale != 0.f) {
ScaledWidth = (INTN)(CharWidth * Scale);
ScaledHeight = (INTN)(FontHeight * Scale);
}
if (Width != NULL)
*Width = Text.length() * ((FontWidth > ScaledWidth) ? FontWidth : ScaledWidth);
*Width = StrLen(Text.wc_str()) * ((FontWidth > ScaledWidth) ? FontWidth : ScaledWidth);
if (Height != NULL)
*Height = FontHeight;
*Height = ScaledHeight;
}
#else
@ -118,31 +123,38 @@ void XTheme::LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
const XStringW& commonFontDir = L"EFI\\CLOVER\\font"_XSW;
if (IsEmbeddedTheme() && !isKorean) { //or initial screen before theme init
NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data)); //always success
Status = NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data)); //always success
MsgLog("Using embedded font\n");
} else if (isKorean){
Status = NewImage.LoadXImage(ThemeDir, L"FontKorean.png"_XSW);
MsgLog("Loading korean font from ThemeDir: %s\n", strerror(Status));
if (EFI_ERROR(Status)) {
//no korean font, use common
if (!EFI_ERROR(Status)) {
CharWidth = 22; //standard for korean
} else {
MsgLog("...using english\n");
gLanguage = english;
Rows = 16; //standard for english
Cols = 16;
Status = NewImage.LoadXImage(ThemeDir, FontFileName);
} else {
CharWidth = 22; //standard for korean
}
}
if (NewImage.isEmpty()) {
if (EFI_ERROR(Status)) {
//not loaded, use common
Rows = 16; //standard for english
Cols = 16;
Status = NewImage.LoadXImage(ThemeDir, FontFileName);
}
if (EFI_ERROR(Status)) {
//then take from common font folder
// fontFilePath = SWPrintf(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data());
fontFilePath = commonFontDir + FontFileName;
Status = NewImage.LoadXImage(SelfRootDir, fontFilePath);
//else use embedded
//else use embedded even if it is not embedded
if (EFI_ERROR(Status)) {
NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data));
Status = NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data));
}
if (EFI_ERROR(Status)) {
MsgLog("No font found!\n");
return;
}
}
@ -158,9 +170,9 @@ void XTheme::LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
FontWidth = ImageWidth / Cols;
FontHeight = ImageHeight / Rows;
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * Scale);
if (!isKorean) {
CharWidth = FontWidth;
}
// if (!isKorean) {
// CharWidth = FontWidth; //there is default value anyway
// }
FirstPixel = *PixelPtr;
for (INTN y = 0; y < Rows; y++) {
@ -447,53 +459,62 @@ INTN GetEmpty(EG_PIXEL *Ptr, EG_PIXEL *FirstPixel, INTN MaxWidth, INTN Step, INT
#if USE_XTHEME
INTN XTheme::RenderText(IN const XString& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale)
{
const XStringW& UTF16Text = XStringW().takeValueFrom(Text.c_str());
return RenderText(UTF16Text, CompImage_ptr, PosX, PosY, Cursor, textType);
return RenderText(UTF16Text, CompImage_ptr, PosX, PosY, Cursor, textType, textScale);
}
INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale)
{
XImage& CompImage = *CompImage_ptr;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FontPixel;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FirstPixel;
INTN TextLength;
INTN Shift = 0;
UINTN Cho = 0, Jong = 0, Joong = 0;
INTN TextLength;
UINTN Cho = 0, Jong = 0, Joong = 0;
INTN LeftSpace, RightSpace;
INTN RealWidth = 0;
if (TypeSVG) {
return renderSVGtext(&CompImage, PosX, PosY, textType, Text, Cursor);
}
if (textScale == 0.f) {
textScale = 1.f;
}
INTN CharScaledWidth = (INTN)(CharWidth * textScale);
INTN FontScaledWidth = (INTN)(FontWidth * textScale); //FontWidth should be scaled as well?
// clip the text
TextLength = Text.size();
DBG("text to render %ls length %lld\n", Text.wc_str(), Text.size());
// TextLength = StrLenInWChar(Text.wc_str()); //it must be UTF16 length
TextLength = StrLen(Text.wc_str());
DBG("text to render %ls length %lld\n", Text.wc_str(), TextLength);
if (FontImage.isEmpty()) {
PrepareFont(); //at the boot screen there is embedded font
}
// DBG("TextLength =%d PosX=%d PosY=%d\n", TextLength, PosX, PosY);
DBG("TextLength =%lld PosX=%lld PosY=%lld\n", TextLength, PosX, PosY);
FirstPixel = CompImage.GetPixel(0,0);
FontPixel = FontImage.GetPixel(0,0);
UINT16 c0 = 0;
RealWidth = CharWidth;
UINT16 c0 = 0x20;
INTN RealWidth = CharScaledWidth;
INTN Shift = (FontScaledWidth - CharScaledWidth) / 2;
if (Shift < 0) {
Shift = 0;
}
DBG("FontWidth=%lld, CharWidth=%lld\n", FontWidth, RealWidth);
EG_RECT Area;
EG_RECT Area; //area is scaled
Area.YPos = PosY; // not sure
Area.Height = FontHeight;
EG_RECT Bukva;
Area.Height = TextHeight;
EG_RECT Bukva; //bukva is not scaled place
Bukva.YPos = 0;
Bukva.Width = FontWidth;
Bukva.Height = FontHeight;
DBG("codepage=%llx, asciiPage=%x\n", GlobalConfig.Codepage, AsciiPageSize);
for (INTN i = 0; i < TextLength; i++) {
UINT16 c = Text[i];
// DBG("initial char to render 0x%x\n", c); //good
for (INTN i = 0; i < TextLength && c0 != 0; i++) {
UINT16 c = Text[i]; //including UTF8 -> UTF16 conversion
DBG("initial char to render 0x%x\n", c); //good
if (gLanguage != korean) { //russian Codepage = 0x410
if (c >= 0x410 && c < 0x450) {
//we have russian raster fonts with chars at 0xC0
@ -512,39 +533,41 @@ INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
}
if (c <= 0x20) { //new space will be half font width
RightSpace = 1;
RealWidth = (FontWidth >> 1) + 1;
RealWidth = (CharScaledWidth >> 1) + 1;
} else {
RightSpace = GetEmpty(FontImage, FontPixel, c * FontWidth, 1);
RightSpace = GetEmpty(FontImage, FontPixel, c * FontWidth, 1); //not scaled yet
if (RightSpace >= FontWidth) {
RightSpace = 0; //empty place for invisible characters
}
RealWidth = FontWidth - RightSpace; //a part of char
RealWidth = CharScaledWidth - (int)(RightSpace * textScale); //a part of char
}
} else {
LeftSpace = 2;
RightSpace = 0;
RightSpace = Shift;
}
// DBG(" RealWidth = %lld LeftSpace = %lld RightSpace = %lld\n", RealWidth, LeftSpace, RightSpace);
c0 = c; //old value
LeftSpace = (int)(LeftSpace * textScale); //was not scaled yet
//RightSpace will not be scaled
// RealWidth are scaled now
DBG(" RealWidth = %lld LeftSpace = %lld RightSpace = %lld\n", RealWidth, LeftSpace, RightSpace);
c0 = c; //remember old value
if (PosX + RealWidth > CompImage.GetWidth()) {
//no more place for character
DBG("no more place for character\n");
break;
}
Area.XPos = PosX + 2 - LeftSpace;
Area.Width = RealWidth;
Bukva.XPos = c * FontWidth + RightSpace;
// DBG("place [%lld,%lld,%lld,%lld], bukva [%lld,%lld,%lld,%lld]\n",
// Area.XPos, Area.YPos, Area.Width, Area.Height,
// Bukva.XPos, Bukva.YPos, Bukva.Width, Bukva.Height);
// Bukva.YPos
CompImage.Compose(Area, Bukva, FontImage, false);
DBG("place [%lld,%lld,%lld,%lld], bukva [%lld,%lld,%lld,%lld]\n",
Area.XPos, Area.YPos, Area.Width, Area.Height,
Bukva.XPos, Bukva.YPos, Bukva.Width, Bukva.Height);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
// CompImage.CopyRect(FontImage, Area, Bukva);
if (i == Cursor) {
c = 0x5F;
Bukva.XPos = c * FontWidth + RightSpace;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
}
PosX += RealWidth - LeftSpace + 2; //next char position
} else {
@ -581,29 +604,29 @@ INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
if (Shift == 18) {
Bukva.XPos = Cho * FontWidth + 4;
Bukva.YPos = 1;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
} else {
Area.YPos = PosY + 3;
Bukva.XPos = Cho * FontWidth + 2;
Bukva.YPos = 0;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
}
if (i == Cursor) {
c = 99;
Bukva.XPos = c * FontWidth + 2;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
}
if (Shift == 18) {
Area.XPos = PosX + 9;
Area.YPos = PosY;
Bukva.XPos = Joong * FontWidth + 6;
Bukva.YPos = 0;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
Area.XPos = PosX;
Area.YPos = PosY + 9;
Bukva.XPos = Jong * FontWidth + 1;
CompImage.Compose(Area, Bukva, FontImage, false);
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
}
PosX += CharWidth; //Shift;