refine the implementation of HiiStringToImage:

1. Remove the limitation of MAX_STRING_LENGTH and according to actual string length to store glyph info
2. fix a issue when print multi-lines, the next line will overlaps the above line. The original implementation doesn't recalculate the start point of X/Y axis.
3. refine the flow to avoid the meaningless recursive call.
4. modify the usage of "Index" to force them 1/1 mapping between glyphbuf and string. So the RowInfoArray and ColumnInfoArray can reflect the actual situation.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8371 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
eric_tian 2009-05-21 09:41:59 +00:00
parent 619e4c06c3
commit 4772ce75e8
1 changed files with 303 additions and 286 deletions

View File

@ -1344,15 +1344,14 @@ IsFontInfoExisted (
/**
Check whether the unicode represents a line break or not.
This is a internal function.
This is a internal function. Please see Section 27.2.6 of the UEFI Specification
for a description of the supported string format.
@param Char Unicode character
@retval 0 Yes, it is a line break.
@retval 1 Yes, it is a hyphen that desires a line break
after this character.
@retval 2 Yes, it is a dash that desires a line break
before and after it.
@retval 0 Yes, it forces a line break.
@retval 1 Yes, it presents a line break opportunity
@retval 2 Yes, it requires a line break happen before and after it.
@retval -1 No, it is not a link break.
**/
@ -1361,61 +1360,63 @@ IsLineBreak (
IN CHAR16 Char
)
{
UINT8 Byte1;
UINT8 Byte2;
//
// In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.
//
Byte1 = *((UINT8 *) (&Char));
Byte2 = *(((UINT8 *) (&Char) + 1));
if (Byte2 == 0x20) {
switch (Byte1) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
case 0x28:
case 0x29:
case 0x5F:
return 0;
case 0x10:
case 0x12:
case 0x13:
return 1;
case 0x14:
//
// BUGBUG: Does it really require line break before it and after it?
//
return 2;
}
} else if (Byte2 == 0x00) {
switch (Byte1) {
case 0x20:
case 0x0C:
case 0x0D:
return 0;
}
}
switch (Char) {
case 0x1680:
//
// Mandatory line break characters, which force a line-break
//
case 0x000C:
case 0x000D:
case 0x2028:
case 0x2029:
return 0;
//
// Space characters, which is taken as a line-break opportunity
//
case 0x0020:
case 0x1680:
case 0x2000:
case 0x2001:
case 0x2002:
case 0x2003:
case 0x2004:
case 0x2005:
case 0x2006:
case 0x2008:
case 0x2009:
case 0x200A:
case 0x205F:
//
// In-Word Break Opportunities
//
case 0x200B:
return 1;
//
// A space which is not a line-break opportunity
//
case 0x00A0:
case 0x202F:
//
// A hyphen which is not a line-break opportunity
//
case 0x2011:
return -1;
//
// Hyphen characters which describe line break opportunities after the character
//
case 0x058A:
case 0x2010:
case 0x2012:
case 0x2013:
case 0x0F0B:
case 0x1361:
case 0x17D5:
return 1;
//
// A hyphen which describes line break opportunities before and after them, but not between a pair of them
//
case 0x2014:
return 2;
}
return -1;
}
@ -1520,6 +1521,7 @@ HiiStringToImage (
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
UINTN RowInfoSize;
BOOLEAN LineBreak;
UINTN StrLength;
//
// Check incoming parameters.
@ -1555,11 +1557,35 @@ HiiStringToImage (
return EFI_INVALID_PARAMETER;
}
GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));
if (*Blt == NULL) {
//
// Create a new bitmap and draw the string onto this image.
//
Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
if (Image == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Image->Width = 800;
Image->Height = 600;
Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
if (Image->Image.Bitmap == NULL) {
FreePool (Image);
return EFI_OUT_OF_RESOURCES;
}
//
// Other flags are not permitted when Blt is NULL.
//
Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
*Blt = Image;
}
StrLength = StrLen(String);
GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *));
ASSERT (GlyphBuf != NULL);
Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));
Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
ASSERT (Cell != NULL);
Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));
Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8));
ASSERT (Attributes != NULL);
RowInfo = NULL;
@ -1649,16 +1675,14 @@ HiiStringToImage (
}
Index = 0;
StringTmp = StringIn2;
while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {
StrLength = StrLen(StringPtr);
while (*StringPtr != 0 && Index < StrLength) {
Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
if (Status == EFI_NOT_FOUND) {
if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
if (GlyphBuf[Index] != NULL) {
FreePool (GlyphBuf[Index]);
}
GlyphBuf[Index] = NULL;
StringPtr++;
*StringTmp++ = *StringPtr++;
Index++;
} else {
//
// Unicode 0xFFFD must exist in current hii database if this flag is not set.
@ -1694,7 +1718,6 @@ HiiStringToImage (
// to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
// Otherwise render this string to a new allocated image and output it.
//
if (*Blt != NULL) {
Image = *Blt;
BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
MaxRowNum = (UINT16) (Image->Height / Height);
@ -1736,19 +1759,24 @@ HiiStringToImage (
RowInfo[RowIndex].StartIndex = Index;
while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
(Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&
IsLineBreak (StringPtr[Index]) == 0) {
//
// It forces a line break that ends this row.
//
Index++;
break;
}
//
// If the glyph of the character is existing, then accumulate the actual printed width
//
if (GlyphBuf[Index] != NULL) {
LineWidth += (UINTN) Cell[Index].AdvanceX;
if (LineHeight < Cell[Index].Height) {
LineHeight = (UINTN) Cell[Index].Height;
}
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
(Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&
IsLineBreak (StringPtr[Index]) > 0) {
//
// It is a line break that ends this row.
//
Index++;
break;
}
Index++;
@ -1763,31 +1791,6 @@ HiiStringToImage (
LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);
}
//
// EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
// opportunity prior to a character whose right-most extent would exceed Width.
// Search the right-most line-break opportunity here.
//
if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
if (IsLineBreak (StringPtr[Index1]) > 0) {
LineBreak = TRUE;
RowInfo[RowIndex].EndIndex = Index1 - 1;
break;
}
}
}
//
// If no line-break opportunity can be found, then the text will
// behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
//
if (!LineBreak) {
Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);
Flags |= EFI_HII_OUT_FLAG_CLIP_CLEAN_X;
}
}
//
// Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
//
@ -1822,6 +1825,35 @@ HiiStringToImage (
}
}
//
// EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
// opportunity prior to a character whose right-most extent would exceed Width.
// Search the right-most line-break opportunity here.
//
if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
if (IsLineBreak (StringPtr[Index1]) > 0) {
LineBreak = TRUE;
RowInfo[RowIndex].EndIndex = Index1 - 1;
//
// relocate to the character after the right-most line break opportunity of this line
//
Index = Index1 + 1;
break;
}
}
}
//
// If no line-break opportunity can be found, then the text will
// behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
//
if (!LineBreak) {
Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);
Flags |= EFI_HII_OUT_FLAG_CLIP_CLEAN_X;
}
}
//
// Clip the final row if the row's bottom-most on pixel cannot fit when
// EFI_HII_OUT_FLAG_CLEAN_Y is set.
@ -1848,6 +1880,10 @@ HiiStringToImage (
}
BufferPtr = BltBuffer;
for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
if (GlyphBuf[Index1] != NULL) {
//
// Only BLT these character which have corrsponding glyph in font basebase.
//
GlyphToImage (
GlyphBuf[Index1],
Foreground,
@ -1859,8 +1895,9 @@ HiiStringToImage (
Attributes[Index1],
&BufferPtr
);
}
if (ColumnInfoArray != NULL) {
if (Index1 == RowInfo[RowIndex].StartIndex) {
if (GlyphBuf[Index1] == NULL) {
*ColumnInfoArray = 0;
} else {
*ColumnInfoArray = Cell[Index1 -1].AdvanceX;
@ -1868,6 +1905,14 @@ HiiStringToImage (
ColumnInfoArray++;
}
}
//
// Recalculate the start point of X/Y axis to draw multi-lines with the order of top-to-down
//
if (RowIndex != 0) {
BltX = 0;
BltY += RowInfo[RowIndex].LineHeight;
}
Status = Image->Image.Screen->Blt (
Image->Image.Screen,
BltBuffer,
@ -1889,6 +1934,10 @@ HiiStringToImage (
} else {
for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
if (GlyphBuf[Index1] != NULL) {
//
// Only BLT these character which have corrsponding glyph in font basebase.
//
GlyphToImage (
GlyphBuf[Index1],
Foreground,
@ -1900,8 +1949,9 @@ HiiStringToImage (
Attributes[Index1],
&BufferPtr
);
}
if (ColumnInfoArray != NULL) {
if (Index1 == RowInfo[RowIndex].StartIndex) {
if (GlyphBuf[Index1] == NULL) {
*ColumnInfoArray = 0;
} else {
*ColumnInfoArray = Cell[Index1 -1].AdvanceX;
@ -1918,6 +1968,12 @@ HiiStringToImage (
Index++;
RowIndex++;
if (Flags & EFI_HII_IGNORE_LINE_BREAK) {
//
// If setting IGNORE_LINE_BREAK attribute, only render one line to image
//
break;
}
}
//
@ -1936,50 +1992,11 @@ HiiStringToImage (
*RowInfoArraySize = RowIndex;
}
} else {
//
// Create a new bitmap and draw the string onto this image.
//
Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
if (Image == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Image->Width = 800;
Image->Height = 600;
Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
if (Image->Image.Bitmap == NULL) {
FreePool (Image);
return EFI_OUT_OF_RESOURCES;
}
//
// Other flags are not permitted when Blt is NULL.
//
Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
Status = HiiStringToImage (
This,
Flags,
String,
StringInfo,
&Image,
BltX,
BltY,
RowInfoArray,
RowInfoArraySize,
ColumnInfoArray
);
if (EFI_ERROR (Status)) {
return Status;
}
*Blt = Image;
}
Status = EFI_SUCCESS;
Exit:
for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {
for (Index = 0; Index < StrLength; Index++) {
if (GlyphBuf[Index] != NULL) {
FreePool (GlyphBuf[Index]);
}