]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
MdeModulePkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Font.c
1 /** @file
2 Implementation for EFI_HII_FONT_PROTOCOL.
3
4
5 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include "HiiDatabase.h"
12
13 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mHiiEfiColors[16] = {
14 //
15 // B G R
16 //
17 {0x00, 0x00, 0x00, 0x00}, // BLACK
18 {0x98, 0x00, 0x00, 0x00}, // BLUE
19 {0x00, 0x98, 0x00, 0x00}, // GREEN
20 {0x98, 0x98, 0x00, 0x00}, // CYAN
21 {0x00, 0x00, 0x98, 0x00}, // RED
22 {0x98, 0x00, 0x98, 0x00}, // MAGENTA
23 {0x00, 0x98, 0x98, 0x00}, // BROWN
24 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
25 {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK
26 {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE
27 {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN
28 {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN
29 {0x00, 0x00, 0xff, 0x00}, // LIGHTRED
30 {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA
31 {0x00, 0xff, 0xff, 0x00}, // YELLOW
32 {0xff, 0xff, 0xff, 0x00}, // WHITE
33 };
34
35
36 /**
37 Insert a character cell information to the list specified by GlyphInfoList.
38
39 This is a internal function.
40
41 @param CharValue Unicode character value, which identifies a glyph
42 block.
43 @param GlyphInfoList HII_GLYPH_INFO list head.
44 @param Cell Incoming character cell information.
45
46 @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
47 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
48 task.
49
50 **/
51 EFI_STATUS
52 NewCell (
53 IN CHAR16 CharValue,
54 IN LIST_ENTRY *GlyphInfoList,
55 IN EFI_HII_GLYPH_INFO *Cell
56 )
57 {
58 HII_GLYPH_INFO *GlyphInfo;
59
60 ASSERT (Cell != NULL && GlyphInfoList != NULL);
61
62 GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO));
63 if (GlyphInfo == NULL) {
64 return EFI_OUT_OF_RESOURCES;
65 }
66
67 //
68 // GlyphInfoList stores a list of default character cell information, each is
69 // identified by "CharId".
70 //
71 GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;
72 GlyphInfo->CharId = CharValue;
73 if (Cell->AdvanceX == 0) {
74 Cell->AdvanceX = Cell->Width;
75 }
76 CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));
77 InsertTailList (GlyphInfoList, &GlyphInfo->Entry);
78
79 return EFI_SUCCESS;
80 }
81
82
83 /**
84 Get a character cell information from the list specified by GlyphInfoList.
85
86 This is a internal function.
87
88 @param CharValue Unicode character value, which identifies a glyph
89 block.
90 @param GlyphInfoList HII_GLYPH_INFO list head.
91 @param Cell Buffer which stores output character cell
92 information.
93
94 @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
95 @retval EFI_NOT_FOUND The character info specified by CharValue does
96 not exist.
97
98 **/
99 EFI_STATUS
100 GetCell (
101 IN CHAR16 CharValue,
102 IN LIST_ENTRY *GlyphInfoList,
103 OUT EFI_HII_GLYPH_INFO *Cell
104 )
105 {
106 HII_GLYPH_INFO *GlyphInfo;
107 LIST_ENTRY *Link;
108
109 ASSERT (Cell != NULL && GlyphInfoList != NULL);
110
111 //
112 // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,
113 // the value of "CharId" of a default character cell which is used for a
114 // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be
115 // less or equal to the value of "CharValueCurrent" of this default block.
116 //
117 // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph
118 // with CharValue equals "7" uses the GlyphInfo with CharId = 7;
119 // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.
120 //
121 for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {
122 GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);
123 if (GlyphInfo->CharId <= CharValue) {
124 CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));
125 return EFI_SUCCESS;
126 }
127 }
128
129 return EFI_NOT_FOUND;
130 }
131
132
133 /**
134 Convert the glyph for a single character into a bitmap.
135
136 This is a internal function.
137
138 @param Private HII database driver private data.
139 @param Char Character to retrieve.
140 @param StringInfo Points to the string font and color information
141 or NULL if the string should use the default
142 system font and color.
143 @param GlyphBuffer Buffer to store the retrieved bitmap data.
144 @param Cell Points to EFI_HII_GLYPH_INFO structure.
145 @param Attributes If not NULL, output the glyph attributes if any.
146
147 @retval EFI_SUCCESS Glyph bitmap outputted.
148 @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer.
149 @retval EFI_NOT_FOUND The glyph was unknown can not be found.
150 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
151
152 **/
153 EFI_STATUS
154 GetGlyphBuffer (
155 IN HII_DATABASE_PRIVATE_DATA *Private,
156 IN CHAR16 Char,
157 IN EFI_FONT_INFO *StringInfo,
158 OUT UINT8 **GlyphBuffer,
159 OUT EFI_HII_GLYPH_INFO *Cell,
160 OUT UINT8 *Attributes OPTIONAL
161 )
162 {
163 HII_DATABASE_RECORD *Node;
164 LIST_ENTRY *Link;
165 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont;
166 LIST_ENTRY *Link1;
167 UINT16 Index;
168 EFI_NARROW_GLYPH Narrow;
169 EFI_WIDE_GLYPH Wide;
170 HII_GLOBAL_FONT_INFO *GlobalFont;
171 UINTN HeaderSize;
172 EFI_NARROW_GLYPH *NarrowPtr;
173 EFI_WIDE_GLYPH *WidePtr;
174
175 if (GlyphBuffer == NULL || Cell == NULL) {
176 return EFI_INVALID_PARAMETER;
177 }
178 if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
179 return EFI_INVALID_PARAMETER;
180 }
181
182 ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));
183
184 //
185 // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather
186 // than system default font and color.
187 // If NULL, try to find the character in simplified font packages since
188 // default system font is the fixed font (narrow or wide glyph).
189 //
190 if (StringInfo != NULL) {
191 if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {
192 return EFI_INVALID_PARAMETER;
193 }
194 if (Attributes != NULL) {
195 *Attributes = PROPORTIONAL_GLYPH;
196 }
197 return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);
198 } else {
199 HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);
200
201 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
202 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
203 for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;
204 Link1 != &Node->PackageList->SimpleFontPkgHdr;
205 Link1 = Link1->ForwardLink
206 ) {
207 SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
208 //
209 // Search the narrow glyph array
210 //
211 NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize);
212 for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {
213 CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH));
214 if (Narrow.UnicodeWeight == Char) {
215 *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT);
216 if (*GlyphBuffer == NULL) {
217 return EFI_OUT_OF_RESOURCES;
218 }
219 Cell->Width = EFI_GLYPH_WIDTH;
220 Cell->Height = EFI_GLYPH_HEIGHT;
221 Cell->AdvanceX = Cell->Width;
222 CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);
223 if (Attributes != NULL) {
224 *Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH);
225 }
226 return EFI_SUCCESS;
227 }
228 }
229 //
230 // Search the wide glyph array
231 //
232 WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);
233 for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {
234 CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));
235 if (Wide.UnicodeWeight == Char) {
236 *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);
237 if (*GlyphBuffer == NULL) {
238 return EFI_OUT_OF_RESOURCES;
239 }
240 Cell->Width = EFI_GLYPH_WIDTH * 2;
241 Cell->Height = EFI_GLYPH_HEIGHT;
242 Cell->AdvanceX = Cell->Width;
243 CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);
244 CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);
245 if (Attributes != NULL) {
246 *Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE);
247 }
248 return EFI_SUCCESS;
249 }
250 }
251 }
252 }
253 }
254
255 return EFI_NOT_FOUND;
256 }
257
258 /**
259 Convert bitmap data of the glyph to blt structure.
260
261 This is a internal function.
262
263 @param GlyphBuffer Buffer points to bitmap data of glyph.
264 @param Foreground The color of the "on" pixels in the glyph in the
265 bitmap.
266 @param Background The color of the "off" pixels in the glyph in the
267 bitmap.
268 @param ImageWidth Width of the whole image in pixels.
269 @param RowWidth The width of the text on the line, in pixels.
270 @param RowHeight The height of the line, in pixels.
271 @param Transparent If TRUE, the Background color is ignored and all
272 "off" pixels in the character's drawn will use the
273 pixel value from BltBuffer.
274 @param Origin On input, points to the origin of the to be
275 displayed character, on output, points to the
276 next glyph's origin.
277
278 **/
279 VOID
280 NarrowGlyphToBlt (
281 IN UINT8 *GlyphBuffer,
282 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
283 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
284 IN UINT16 ImageWidth,
285 IN UINTN RowWidth,
286 IN UINTN RowHeight,
287 IN BOOLEAN Transparent,
288 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
289 )
290 {
291 UINT8 Xpos;
292 UINT8 Ypos;
293 UINT8 Height;
294 UINT8 Width;
295 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
296
297 ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
298
299 Height = EFI_GLYPH_HEIGHT;
300 Width = EFI_GLYPH_WIDTH;
301
302 //
303 // Move position to the left-top corner of char.
304 //
305 Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth;
306
307 //
308 // Char may be partially displayed when CLIP_X or CLIP_Y is not set.
309 //
310 if (RowHeight < Height) {
311 Height = (UINT8) RowHeight;
312 }
313 if (RowWidth < Width) {
314 Width = (UINT8) RowWidth;
315 }
316
317 for (Ypos = 0; Ypos < Height; Ypos++) {
318 for (Xpos = 0; Xpos < Width; Xpos++) {
319 if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) {
320 Buffer[Ypos * ImageWidth + Xpos] = Foreground;
321 } else {
322 if (!Transparent) {
323 Buffer[Ypos * ImageWidth + Xpos] = Background;
324 }
325 }
326 }
327 }
328
329 *Origin = *Origin + EFI_GLYPH_WIDTH;
330 }
331
332
333 /**
334 Convert bitmap data of the glyph to blt structure.
335
336 This is a internal function.
337
338 @param GlyphBuffer Buffer points to bitmap data of glyph.
339 @param Foreground The color of the "on" pixels in the glyph in the
340 bitmap.
341 @param Background The color of the "off" pixels in the glyph in the
342 bitmap.
343 @param ImageWidth Width of the whole image in pixels.
344 @param BaseLine BaseLine in the line.
345 @param RowWidth The width of the text on the line, in pixels.
346 @param RowHeight The height of the line, in pixels.
347 @param Transparent If TRUE, the Background color is ignored and all
348 "off" pixels in the character's drawn will use the
349 pixel value from BltBuffer.
350 @param Cell Points to EFI_HII_GLYPH_INFO structure.
351 @param Attributes The attribute of incoming glyph in GlyphBuffer.
352 @param Origin On input, points to the origin of the to be
353 displayed character, on output, points to the
354 next glyph's origin.
355
356
357 **/
358 VOID
359 GlyphToBlt (
360 IN UINT8 *GlyphBuffer,
361 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
362 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
363 IN UINT16 ImageWidth,
364 IN UINT16 BaseLine,
365 IN UINTN RowWidth,
366 IN UINTN RowHeight,
367 IN BOOLEAN Transparent,
368 IN CONST EFI_HII_GLYPH_INFO *Cell,
369 IN UINT8 Attributes,
370 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
371 )
372 {
373 UINT16 Xpos;
374 UINT16 Ypos;
375 UINT8 Data;
376 UINT16 Index;
377 UINT16 YposOffset;
378 UINTN OffsetY;
379 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
380
381 ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
382
383 //
384 // Only adjust origin position if char has no bitmap.
385 //
386 if (GlyphBuffer == NULL) {
387 *Origin = *Origin + Cell->AdvanceX;
388 return;
389 }
390 //
391 // Move position to the left-top corner of char.
392 //
393 BltBuffer = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth;
394 YposOffset = (UINT16) (BaseLine - (Cell->OffsetY + Cell->Height));
395
396 //
397 // Since non-spacing key will be printed OR'd with the previous glyph, don't
398 // write 0.
399 //
400 if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
401 Transparent = TRUE;
402 }
403
404 //
405 // The glyph's upper left hand corner pixel is the most significant bit of the
406 // first bitmap byte.
407 //
408 for (Ypos = 0; Ypos < Cell->Height && (((UINT32) Ypos + YposOffset) < RowHeight); Ypos++) {
409 OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos);
410
411 //
412 // All bits in these bytes are meaningful.
413 //
414 for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) {
415 Data = *(GlyphBuffer + OffsetY + Xpos);
416 for (Index = 0; Index < 8 && (((UINT32) Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
417 if ((Data & (1 << (8 - Index - 1))) != 0) {
418 BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
419 } else {
420 if (!Transparent) {
421 BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
422 }
423 }
424 }
425 }
426
427 if (Cell->Width % 8 != 0) {
428 //
429 // There are some padding bits in this byte. Ignore them.
430 //
431 Data = *(GlyphBuffer + OffsetY + Xpos);
432 for (Index = 0; Index < Cell->Width % 8 && (((UINT32) Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
433 if ((Data & (1 << (8 - Index - 1))) != 0) {
434 BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
435 } else {
436 if (!Transparent) {
437 BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
438 }
439 }
440 }
441 } // end of if (Width % 8...)
442
443 } // end of for (Ypos=0...)
444
445 *Origin = *Origin + Cell->AdvanceX;
446 }
447
448
449 /**
450 Convert bitmap data of the glyph to blt structure.
451
452 This is a internal function.
453
454 @param GlyphBuffer Buffer points to bitmap data of glyph.
455 @param Foreground The color of the "on" pixels in the glyph in the
456 bitmap.
457 @param Background The color of the "off" pixels in the glyph in the
458 bitmap.
459 @param ImageWidth Width of the whole image in pixels.
460 @param BaseLine BaseLine in the line.
461 @param RowWidth The width of the text on the line, in pixels.
462 @param RowHeight The height of the line, in pixels.
463 @param Transparent If TRUE, the Background color is ignored and all
464 "off" pixels in the character's drawn will use the
465 pixel value from BltBuffer.
466 @param Cell Points to EFI_HII_GLYPH_INFO structure.
467 @param Attributes The attribute of incoming glyph in GlyphBuffer.
468 @param Origin On input, points to the origin of the to be
469 displayed character, on output, points to the
470 next glyph's origin.
471
472 @return Points to the address of next origin node in BltBuffer.
473
474 **/
475 VOID
476 GlyphToImage (
477 IN UINT8 *GlyphBuffer,
478 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
479 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
480 IN UINT16 ImageWidth,
481 IN UINT16 BaseLine,
482 IN UINTN RowWidth,
483 IN UINTN RowHeight,
484 IN BOOLEAN Transparent,
485 IN CONST EFI_HII_GLYPH_INFO *Cell,
486 IN UINT8 Attributes,
487 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
488 )
489 {
490 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
491
492 ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
493
494 Buffer = *Origin;
495
496 if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
497 //
498 // This character is a non-spacing key, print it OR'd with the previous glyph.
499 // without advancing cursor.
500 //
501 Buffer -= Cell->AdvanceX;
502 GlyphToBlt (
503 GlyphBuffer,
504 Foreground,
505 Background,
506 ImageWidth,
507 BaseLine,
508 RowWidth,
509 RowHeight,
510 Transparent,
511 Cell,
512 Attributes,
513 &Buffer
514 );
515
516 } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {
517 //
518 // This character is wide glyph, i.e. 16 pixels * 19 pixels.
519 // Draw it as two narrow glyphs.
520 //
521 NarrowGlyphToBlt (
522 GlyphBuffer,
523 Foreground,
524 Background,
525 ImageWidth,
526 RowWidth,
527 RowHeight,
528 Transparent,
529 Origin
530 );
531
532 NarrowGlyphToBlt (
533 GlyphBuffer + EFI_GLYPH_HEIGHT,
534 Foreground,
535 Background,
536 ImageWidth,
537 RowWidth,
538 RowHeight,
539 Transparent,
540 Origin
541 );
542
543 } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {
544 //
545 // This character is narrow glyph, i.e. 8 pixels * 19 pixels.
546 //
547 NarrowGlyphToBlt (
548 GlyphBuffer,
549 Foreground,
550 Background,
551 ImageWidth,
552 RowWidth,
553 RowHeight,
554 Transparent,
555 Origin
556 );
557
558 } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {
559 //
560 // This character is proportional glyph, i.e. Cell->Width * Cell->Height pixels.
561 //
562 GlyphToBlt (
563 GlyphBuffer,
564 Foreground,
565 Background,
566 ImageWidth,
567 BaseLine,
568 RowWidth,
569 RowHeight,
570 Transparent,
571 Cell,
572 Attributes,
573 Origin
574 );
575 }
576 }
577
578
579 /**
580 Write the output parameters of FindGlyphBlock().
581
582 This is a internal function.
583
584 @param BufferIn Buffer which stores the bitmap data of the found
585 block.
586 @param BufferLen Length of BufferIn.
587 @param InputCell Buffer which stores cell information of the
588 encoded bitmap.
589 @param GlyphBuffer Output the corresponding bitmap data of the found
590 block. It is the caller's responsibility to free
591 this buffer.
592 @param Cell Output cell information of the encoded bitmap.
593 @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
594
595 @retval EFI_SUCCESS The operation is performed successfully.
596 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
597 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
598 task.
599
600 **/
601 EFI_STATUS
602 WriteOutputParam (
603 IN UINT8 *BufferIn,
604 IN UINTN BufferLen,
605 IN EFI_HII_GLYPH_INFO *InputCell,
606 OUT UINT8 **GlyphBuffer OPTIONAL,
607 OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
608 OUT UINTN *GlyphBufferLen OPTIONAL
609 )
610 {
611 if (BufferIn == NULL || InputCell == NULL) {
612 return EFI_INVALID_PARAMETER;
613 }
614
615 if (Cell != NULL) {
616 CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
617 }
618
619 if (GlyphBuffer != NULL && BufferLen > 0) {
620 *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);
621 if (*GlyphBuffer == NULL) {
622 return EFI_OUT_OF_RESOURCES;
623 }
624 CopyMem (*GlyphBuffer, BufferIn, BufferLen);
625 }
626
627 if (GlyphBufferLen != NULL) {
628 *GlyphBufferLen = BufferLen;
629 }
630
631 return EFI_SUCCESS;
632 }
633
634
635 /**
636 Parse all glyph blocks to find a glyph block specified by CharValue.
637 If CharValue = (CHAR16) (-1), collect all default character cell information
638 within this font package and backup its information.
639
640 @param FontPackage Hii string package instance.
641 @param CharValue Unicode character value, which identifies a glyph
642 block.
643 @param GlyphBuffer Output the corresponding bitmap data of the found
644 block. It is the caller's responsibility to free
645 this buffer.
646 @param Cell Output cell information of the encoded bitmap.
647 @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
648
649 @retval EFI_SUCCESS The bitmap data is retrieved successfully.
650 @retval EFI_NOT_FOUND The specified CharValue does not exist in current
651 database.
652 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
653 task.
654
655 **/
656 EFI_STATUS
657 FindGlyphBlock (
658 IN HII_FONT_PACKAGE_INSTANCE *FontPackage,
659 IN CHAR16 CharValue,
660 OUT UINT8 **GlyphBuffer OPTIONAL,
661 OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
662 OUT UINTN *GlyphBufferLen OPTIONAL
663 )
664 {
665 EFI_STATUS Status;
666 UINT8 *BlockPtr;
667 UINT16 CharCurrent;
668 UINT16 Length16;
669 UINT32 Length32;
670 EFI_HII_GIBT_GLYPHS_BLOCK Glyphs;
671 UINTN BufferLen;
672 UINT16 Index;
673 EFI_HII_GLYPH_INFO DefaultCell;
674 EFI_HII_GLYPH_INFO LocalCell;
675 INT16 MinOffsetY;
676 UINT16 BaseLine;
677
678 ASSERT (FontPackage != NULL);
679 ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
680 BaseLine = 0;
681 MinOffsetY = 0;
682
683 if (CharValue == (CHAR16) (-1)) {
684 //
685 // Collect the cell information specified in font package fixed header.
686 // Use CharValue =0 to represent this particular cell.
687 //
688 Status = NewCell (
689 0,
690 &FontPackage->GlyphInfoList,
691 (EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32))
692 );
693 if (EFI_ERROR (Status)) {
694 return Status;
695 }
696 CopyMem (
697 &LocalCell,
698 (UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32),
699 sizeof (EFI_HII_GLYPH_INFO)
700 );
701 }
702
703 BlockPtr = FontPackage->GlyphBlock;
704 CharCurrent = 1;
705 BufferLen = 0;
706
707 while (*BlockPtr != EFI_HII_GIBT_END) {
708 switch (*BlockPtr) {
709 case EFI_HII_GIBT_DEFAULTS:
710 //
711 // Collect all default character cell information specified by
712 // EFI_HII_GIBT_DEFAULTS.
713 //
714 if (CharValue == (CHAR16) (-1)) {
715 Status = NewCell (
716 CharCurrent,
717 &FontPackage->GlyphInfoList,
718 (EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))
719 );
720 if (EFI_ERROR (Status)) {
721 return Status;
722 }
723 CopyMem (
724 &LocalCell,
725 BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
726 sizeof (EFI_HII_GLYPH_INFO)
727 );
728 if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
729 BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);
730 }
731 if (MinOffsetY > LocalCell.OffsetY) {
732 MinOffsetY = LocalCell.OffsetY;
733 }
734 }
735 BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);
736 break;
737
738 case EFI_HII_GIBT_DUPLICATE:
739 if (CharCurrent == CharValue) {
740 CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));
741 CharCurrent = 1;
742 BlockPtr = FontPackage->GlyphBlock;
743 continue;
744 }
745 CharCurrent++;
746 BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);
747 break;
748
749 case EFI_HII_GIBT_EXT1:
750 BlockPtr += *(UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
751 break;
752 case EFI_HII_GIBT_EXT2:
753 CopyMem (
754 &Length16,
755 (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
756 sizeof (UINT16)
757 );
758 BlockPtr += Length16;
759 break;
760 case EFI_HII_GIBT_EXT4:
761 CopyMem (
762 &Length32,
763 (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
764 sizeof (UINT32)
765 );
766 BlockPtr += Length32;
767 break;
768
769 case EFI_HII_GIBT_GLYPH:
770 CopyMem (
771 &LocalCell,
772 BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
773 sizeof (EFI_HII_GLYPH_INFO)
774 );
775 if (CharValue == (CHAR16) (-1)) {
776 if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
777 BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);
778 }
779 if (MinOffsetY > LocalCell.OffsetY) {
780 MinOffsetY = LocalCell.OffsetY;
781 }
782 }
783 BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
784 if (CharCurrent == CharValue) {
785 return WriteOutputParam (
786 (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8)),
787 BufferLen,
788 &LocalCell,
789 GlyphBuffer,
790 Cell,
791 GlyphBufferLen
792 );
793 }
794 CharCurrent++;
795 BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;
796 break;
797
798 case EFI_HII_GIBT_GLYPHS:
799 BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);
800 CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));
801 BlockPtr += sizeof (EFI_HII_GLYPH_INFO);
802 CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));
803 BlockPtr += sizeof (UINT16);
804
805 if (CharValue == (CHAR16) (-1)) {
806 if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) {
807 BaseLine = (UINT16) (Glyphs.Cell.Height + Glyphs.Cell.OffsetY);
808 }
809 if (MinOffsetY > Glyphs.Cell.OffsetY) {
810 MinOffsetY = Glyphs.Cell.OffsetY;
811 }
812 }
813
814 BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);
815 for (Index = 0; Index < Glyphs.Count; Index++) {
816 if (CharCurrent + Index == CharValue) {
817 return WriteOutputParam (
818 BlockPtr,
819 BufferLen,
820 &Glyphs.Cell,
821 GlyphBuffer,
822 Cell,
823 GlyphBufferLen
824 );
825 }
826 BlockPtr += BufferLen;
827 }
828 CharCurrent = (UINT16) (CharCurrent + Glyphs.Count);
829 break;
830
831 case EFI_HII_GIBT_GLYPH_DEFAULT:
832 Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
833 if (EFI_ERROR (Status)) {
834 return Status;
835 }
836 if (CharValue == (CHAR16) (-1)) {
837 if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
838 BaseLine = (UINT16) (DefaultCell.Height + DefaultCell.OffsetY);
839 }
840 if (MinOffsetY > DefaultCell.OffsetY) {
841 MinOffsetY = DefaultCell.OffsetY;
842 }
843 }
844 BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
845
846 if (CharCurrent == CharValue) {
847 return WriteOutputParam (
848 BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
849 BufferLen,
850 &DefaultCell,
851 GlyphBuffer,
852 Cell,
853 GlyphBufferLen
854 );
855 }
856 CharCurrent++;
857 BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;
858 break;
859
860 case EFI_HII_GIBT_GLYPHS_DEFAULT:
861 CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
862 Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
863 if (EFI_ERROR (Status)) {
864 return Status;
865 }
866 if (CharValue == (CHAR16) (-1)) {
867 if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
868 BaseLine = (UINT16) (DefaultCell.Height + DefaultCell.OffsetY);
869 }
870 if (MinOffsetY > DefaultCell.OffsetY) {
871 MinOffsetY = DefaultCell.OffsetY;
872 }
873 }
874 BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
875 BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);
876 for (Index = 0; Index < Length16; Index++) {
877 if (CharCurrent + Index == CharValue) {
878 return WriteOutputParam (
879 BlockPtr,
880 BufferLen,
881 &DefaultCell,
882 GlyphBuffer,
883 Cell,
884 GlyphBufferLen
885 );
886 }
887 BlockPtr += BufferLen;
888 }
889 CharCurrent = (UINT16) (CharCurrent + Length16);
890 break;
891
892 case EFI_HII_GIBT_SKIP1:
893 CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));
894 BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);
895 break;
896 case EFI_HII_GIBT_SKIP2:
897 CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
898 CharCurrent = (UINT16) (CharCurrent + Length16);
899 BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);
900 break;
901 default:
902 ASSERT (FALSE);
903 break;
904 }
905
906 if (CharValue < CharCurrent) {
907 return EFI_NOT_FOUND;
908 }
909 }
910
911 if (CharValue == (CHAR16) (-1)) {
912 FontPackage->BaseLine = BaseLine;
913 FontPackage->Height = (UINT16) (BaseLine - MinOffsetY);
914 return EFI_SUCCESS;
915 }
916
917 return EFI_NOT_FOUND;
918 }
919
920
921 /**
922 Copy a Font Name to a new created EFI_FONT_INFO structure.
923
924 This is a internal function.
925
926 @param FontName NULL-terminated string.
927 @param FontInfo a new EFI_FONT_INFO which stores the FontName.
928 It's caller's responsibility to free this buffer.
929
930 @retval EFI_SUCCESS FontInfo is allocated and copied with FontName.
931 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
932 task.
933
934 **/
935 EFI_STATUS
936 SaveFontName (
937 IN EFI_STRING FontName,
938 OUT EFI_FONT_INFO **FontInfo
939 )
940 {
941 UINTN FontInfoLen;
942 UINTN NameSize;
943
944 ASSERT (FontName != NULL && FontInfo != NULL);
945
946 NameSize = StrSize (FontName);
947 FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;
948 *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);
949 if (*FontInfo == NULL) {
950 return EFI_OUT_OF_RESOURCES;
951 }
952
953 StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), FontName);
954 return EFI_SUCCESS;
955 }
956
957
958 /**
959 Retrieve system default font and color.
960
961 @param Private HII database driver private data.
962 @param FontInfo Points to system default font output-related
963 information. It's caller's responsibility to free
964 this buffer.
965 @param FontInfoSize If not NULL, output the size of buffer FontInfo.
966
967 @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
968 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
969 task.
970 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
971
972 **/
973 EFI_STATUS
974 GetSystemFont (
975 IN HII_DATABASE_PRIVATE_DATA *Private,
976 OUT EFI_FONT_DISPLAY_INFO **FontInfo,
977 OUT UINTN *FontInfoSize OPTIONAL
978 )
979 {
980 EFI_FONT_DISPLAY_INFO *Info;
981 UINTN InfoSize;
982 UINTN NameSize;
983
984 if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
985 return EFI_INVALID_PARAMETER;
986 }
987 if (FontInfo == NULL) {
988 return EFI_INVALID_PARAMETER;
989 }
990
991 //
992 // The standard font always has the name "sysdefault".
993 //
994 NameSize = StrSize (L"sysdefault");
995 InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
996 Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);
997 if (Info == NULL) {
998 return EFI_OUT_OF_RESOURCES;
999 }
1000
1001 Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f];
1002 ASSERT ((Private->Attribute >> 4) < 8);
1003 Info->BackgroundColor = mHiiEfiColors[Private->Attribute >> 4];
1004 Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
1005 Info->FontInfo.FontStyle = 0;
1006 Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT;
1007 StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");
1008
1009 *FontInfo = Info;
1010 if (FontInfoSize != NULL) {
1011 *FontInfoSize = InfoSize;
1012 }
1013 return EFI_SUCCESS;
1014 }
1015
1016
1017 /**
1018 Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or
1019 returns the system default according to the optional inputs.
1020
1021 This is a internal function.
1022
1023 @param Private HII database driver private data.
1024 @param StringInfo Points to the string output information,
1025 including the color and font.
1026 @param SystemInfo If not NULL, points to system default font and color.
1027
1028 @param SystemInfoLen If not NULL, output the length of default system
1029 info.
1030
1031 @retval TRUE Yes, it points to system default.
1032 @retval FALSE No.
1033
1034 **/
1035 BOOLEAN
1036 IsSystemFontInfo (
1037 IN HII_DATABASE_PRIVATE_DATA *Private,
1038 IN EFI_FONT_DISPLAY_INFO *StringInfo,
1039 OUT EFI_FONT_DISPLAY_INFO **SystemInfo OPTIONAL,
1040 OUT UINTN *SystemInfoLen OPTIONAL
1041 )
1042 {
1043 EFI_STATUS Status;
1044 EFI_FONT_DISPLAY_INFO *SystemDefault;
1045 UINTN DefaultLen;
1046 BOOLEAN Flag;
1047
1048 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1049
1050 if (StringInfo == NULL && SystemInfo == NULL) {
1051 return TRUE;
1052 }
1053
1054 SystemDefault = NULL;
1055 DefaultLen = 0;
1056
1057 Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
1058 ASSERT_EFI_ERROR (Status);
1059 ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
1060
1061 //
1062 // Record the system default info.
1063 //
1064 if (SystemInfo != NULL) {
1065 *SystemInfo = SystemDefault;
1066 }
1067
1068 if (SystemInfoLen != NULL) {
1069 *SystemInfoLen = DefaultLen;
1070 }
1071
1072 if (StringInfo == NULL) {
1073 return TRUE;
1074 }
1075
1076 Flag = FALSE;
1077 //
1078 // Check the FontInfoMask to see whether it is retrieving system info.
1079 //
1080 if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) {
1081 if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) {
1082 goto Exit;
1083 }
1084 }
1085 if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) {
1086 if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) {
1087 goto Exit;
1088 }
1089 }
1090 if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) {
1091 if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) {
1092 goto Exit;
1093 }
1094 }
1095 if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) {
1096 if (CompareMem (
1097 &StringInfo->ForegroundColor,
1098 &SystemDefault->ForegroundColor,
1099 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1100 ) != 0) {
1101 goto Exit;
1102 }
1103 }
1104 if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) {
1105 if (CompareMem (
1106 &StringInfo->BackgroundColor,
1107 &SystemDefault->BackgroundColor,
1108 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1109 ) != 0) {
1110 goto Exit;
1111 }
1112 }
1113
1114 Flag = TRUE;
1115
1116 Exit:
1117 if (SystemInfo == NULL) {
1118 if (SystemDefault != NULL) {
1119 FreePool (SystemDefault);
1120 }
1121 }
1122 return Flag;
1123 }
1124
1125
1126 /**
1127 This function checks whether EFI_FONT_INFO exists in current database. If
1128 FontInfoMask is specified, check what options can be used to make a match.
1129 Note that the masks relate to where the system default should be supplied
1130 are ignored by this function.
1131
1132 @param Private Hii database private structure.
1133 @param FontInfo Points to EFI_FONT_INFO structure.
1134 @param FontInfoMask If not NULL, describes what options can be used
1135 to make a match between the font requested and
1136 the font available. The caller must guarantee
1137 this mask is valid.
1138 @param FontHandle On entry, Points to the font handle returned by a
1139 previous call to GetFontInfo() or NULL to start
1140 with the first font.
1141 @param GlobalFontInfo If not NULL, output the corresponding global font
1142 info.
1143
1144 @retval TRUE Existed
1145 @retval FALSE Not existed
1146
1147 **/
1148 BOOLEAN
1149 IsFontInfoExisted (
1150 IN HII_DATABASE_PRIVATE_DATA *Private,
1151 IN EFI_FONT_INFO *FontInfo,
1152 IN EFI_FONT_INFO_MASK *FontInfoMask OPTIONAL,
1153 IN EFI_FONT_HANDLE FontHandle OPTIONAL,
1154 OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL
1155 )
1156 {
1157 HII_GLOBAL_FONT_INFO *GlobalFont;
1158 HII_GLOBAL_FONT_INFO *GlobalFontBackup1;
1159 HII_GLOBAL_FONT_INFO *GlobalFontBackup2;
1160 LIST_ENTRY *Link;
1161 EFI_FONT_INFO_MASK Mask;
1162 BOOLEAN Matched;
1163 BOOLEAN VagueMatched1;
1164 BOOLEAN VagueMatched2;
1165
1166 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1167 ASSERT (FontInfo != NULL);
1168
1169 //
1170 // Matched flag represents an exactly match; VagueMatched1 represents a RESIZE
1171 // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
1172 //
1173 Matched = FALSE;
1174 VagueMatched1 = FALSE;
1175 VagueMatched2 = FALSE;
1176
1177 Mask = 0;
1178 GlobalFontBackup1 = NULL;
1179 GlobalFontBackup2 = NULL;
1180
1181 // The process of where the system default should be supplied instead of
1182 // the specified font info beyonds this function's scope.
1183 //
1184 if (FontInfoMask != NULL) {
1185 Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
1186 }
1187
1188 //
1189 // If not NULL, FontHandle points to the next node of the last searched font
1190 // node by previous call.
1191 //
1192 if (FontHandle == NULL) {
1193 Link = Private->FontInfoList.ForwardLink;
1194 } else {
1195 Link = (LIST_ENTRY *) FontHandle;
1196 }
1197
1198 for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
1199 GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
1200 if (FontInfoMask == NULL) {
1201 if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
1202 if (GlobalFontInfo != NULL) {
1203 *GlobalFontInfo = GlobalFont;
1204 }
1205 return TRUE;
1206 }
1207 } else {
1208 //
1209 // Check which options could be used to make a match.
1210 //
1211 switch (Mask) {
1212 case EFI_FONT_INFO_ANY_FONT:
1213 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&
1214 GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1215 Matched = TRUE;
1216 }
1217 break;
1218 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
1219 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1220 Matched = TRUE;
1221 }
1222 break;
1223 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
1224 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1225 Matched = TRUE;
1226 }
1227 break;
1228 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
1229 Matched = TRUE;
1230 break;
1231 //
1232 // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
1233 // remove some of the specified styles to meet the style requested.
1234 //
1235 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
1236 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1237 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1238 Matched = TRUE;
1239 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1240 VagueMatched1 = TRUE;
1241 GlobalFontBackup1 = GlobalFont;
1242 }
1243 }
1244 break;
1245 //
1246 // If EFI_FONT_INFO_RESIZE is specified, then the system may attempt to
1247 // stretch or shrink a font to meet the size requested.
1248 //
1249 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
1250 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1251 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1252 Matched = TRUE;
1253 } else {
1254 VagueMatched1 = TRUE;
1255 GlobalFontBackup1 = GlobalFont;
1256 }
1257 }
1258 break;
1259 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
1260 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1261 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1262 Matched = TRUE;
1263 } else {
1264 VagueMatched1 = TRUE;
1265 GlobalFontBackup1 = GlobalFont;
1266 }
1267 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1268 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1269 VagueMatched1 = TRUE;
1270 GlobalFontBackup1 = GlobalFont;
1271 } else {
1272 VagueMatched2 = TRUE;
1273 GlobalFontBackup2 = GlobalFont;
1274 }
1275 }
1276 break;
1277 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1278 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1279 Matched = TRUE;
1280 } else {
1281 VagueMatched1 = TRUE;
1282 GlobalFontBackup1 = GlobalFont;
1283 }
1284 break;
1285 case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1286 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1287 Matched = TRUE;
1288 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1289 VagueMatched1 = TRUE;
1290 GlobalFontBackup1 = GlobalFont;
1291 }
1292 break;
1293 case EFI_FONT_INFO_ANY_STYLE:
1294 if ((CompareMem (
1295 GlobalFont->FontInfo->FontName,
1296 FontInfo->FontName,
1297 StrSize (FontInfo->FontName)
1298 ) == 0) &&
1299 GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1300 Matched = TRUE;
1301 }
1302 break;
1303 case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
1304 if (CompareMem (
1305 GlobalFont->FontInfo->FontName,
1306 FontInfo->FontName,
1307 StrSize (FontInfo->FontName)
1308 ) == 0) {
1309 Matched = TRUE;
1310 }
1311 break;
1312 case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1313 if (CompareMem (
1314 GlobalFont->FontInfo->FontName,
1315 FontInfo->FontName,
1316 StrSize (FontInfo->FontName)
1317 ) == 0) {
1318 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1319 Matched = TRUE;
1320 } else {
1321 VagueMatched1 = TRUE;
1322 GlobalFontBackup1 = GlobalFont;
1323 }
1324 }
1325 break;
1326 case EFI_FONT_INFO_ANY_SIZE:
1327 if ((CompareMem (
1328 GlobalFont->FontInfo->FontName,
1329 FontInfo->FontName,
1330 StrSize (FontInfo->FontName)
1331 ) == 0) &&
1332 GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1333 Matched = TRUE;
1334 }
1335 break;
1336 case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1337 if (CompareMem (
1338 GlobalFont->FontInfo->FontName,
1339 FontInfo->FontName,
1340 StrSize (FontInfo->FontName)
1341 ) == 0) {
1342 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1343 Matched = TRUE;
1344 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1345 VagueMatched1 = TRUE;
1346 GlobalFontBackup1 = GlobalFont;
1347 }
1348 }
1349 break;
1350 case EFI_FONT_INFO_RESTYLE:
1351 if ((CompareMem (
1352 GlobalFont->FontInfo->FontName,
1353 FontInfo->FontName,
1354 StrSize (FontInfo->FontName)
1355 ) == 0) &&
1356 GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1357
1358 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1359 Matched = TRUE;
1360 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1361 VagueMatched1 = TRUE;
1362 GlobalFontBackup1 = GlobalFont;
1363 }
1364 }
1365 break;
1366 case EFI_FONT_INFO_RESIZE:
1367 if ((CompareMem (
1368 GlobalFont->FontInfo->FontName,
1369 FontInfo->FontName,
1370 StrSize (FontInfo->FontName)
1371 ) == 0) &&
1372 GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1373
1374 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1375 Matched = TRUE;
1376 } else {
1377 VagueMatched1 = TRUE;
1378 GlobalFontBackup1 = GlobalFont;
1379 }
1380 }
1381 break;
1382 case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
1383 if (CompareMem (
1384 GlobalFont->FontInfo->FontName,
1385 FontInfo->FontName,
1386 StrSize (FontInfo->FontName)
1387 ) == 0) {
1388 if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1389 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1390 Matched = TRUE;
1391 } else {
1392 VagueMatched1 = TRUE;
1393 GlobalFontBackup1 = GlobalFont;
1394 }
1395 } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1396 if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1397 VagueMatched1 = TRUE;
1398 GlobalFontBackup1 = GlobalFont;
1399 } else {
1400 VagueMatched2 = TRUE;
1401 GlobalFontBackup2 = GlobalFont;
1402 }
1403 }
1404 }
1405 break;
1406 default:
1407 break;
1408 }
1409
1410 if (Matched) {
1411 if (GlobalFontInfo != NULL) {
1412 *GlobalFontInfo = GlobalFont;
1413 }
1414 return TRUE;
1415 }
1416 }
1417 }
1418
1419 if (VagueMatched1) {
1420 if (GlobalFontInfo != NULL) {
1421 *GlobalFontInfo = GlobalFontBackup1;
1422 }
1423 return TRUE;
1424 } else if (VagueMatched2) {
1425 if (GlobalFontInfo != NULL) {
1426 *GlobalFontInfo = GlobalFontBackup2;
1427 }
1428 return TRUE;
1429 }
1430
1431 return FALSE;
1432 }
1433
1434
1435 /**
1436 Check whether the unicode represents a line break or not.
1437
1438 This is a internal function. Please see Section 27.2.6 of the UEFI Specification
1439 for a description of the supported string format.
1440
1441 @param Char Unicode character
1442
1443 @retval 0 Yes, it forces a line break.
1444 @retval 1 Yes, it presents a line break opportunity
1445 @retval 2 Yes, it requires a line break happen before and after it.
1446 @retval -1 No, it is not a link break.
1447
1448 **/
1449 INT8
1450 IsLineBreak (
1451 IN CHAR16 Char
1452 )
1453 {
1454 switch (Char) {
1455 //
1456 // Mandatory line break characters, which force a line-break
1457 //
1458 case 0x000A:
1459 case 0x000C:
1460 case 0x000D:
1461 case 0x2028:
1462 case 0x2029:
1463 return 0;
1464 //
1465 // Space characters, which is taken as a line-break opportunity
1466 //
1467 case 0x0020:
1468 case 0x1680:
1469 case 0x2000:
1470 case 0x2001:
1471 case 0x2002:
1472 case 0x2003:
1473 case 0x2004:
1474 case 0x2005:
1475 case 0x2006:
1476 case 0x2008:
1477 case 0x2009:
1478 case 0x200A:
1479 case 0x205F:
1480 //
1481 // In-Word Break Opportunities
1482 //
1483 case 0x200B:
1484 return 1;
1485 //
1486 // A space which is not a line-break opportunity
1487 //
1488 case 0x00A0:
1489 case 0x202F:
1490 //
1491 // A hyphen which is not a line-break opportunity
1492 //
1493 case 0x2011:
1494 return -1;
1495 //
1496 // Hyphen characters which describe line break opportunities after the character
1497 //
1498 case 0x058A:
1499 case 0x2010:
1500 case 0x2012:
1501 case 0x2013:
1502 case 0x0F0B:
1503 case 0x1361:
1504 case 0x17D5:
1505 return 1;
1506 //
1507 // A hyphen which describes line break opportunities before and after them, but not between a pair of them
1508 //
1509 case 0x2014:
1510 return 2;
1511 }
1512 return -1;
1513 }
1514
1515
1516 /**
1517 Renders a string to a bitmap or to the display.
1518
1519 @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
1520 @param Flags Describes how the string is to be drawn.
1521 @param String Points to the null-terminated string to be
1522 displayed.
1523 @param StringInfo Points to the string output information,
1524 including the color and font. If NULL, then the
1525 string will be output in the default system font
1526 and color.
1527 @param Blt If this points to a non-NULL on entry, this
1528 points to the image, which is Width pixels wide
1529 and Height pixels high. The string will be drawn
1530 onto this image and
1531 EFI_HII_OUT_FLAG_CLIP is implied. If this points
1532 to a NULL on entry, then a buffer
1533 will be allocated to hold the generated image and
1534 the pointer updated on exit. It is the caller's
1535 responsibility to free this buffer.
1536 @param BltX Specifies the offset from the left and top edge
1537 of the image of the first character cell in the
1538 image.
1539 @param BltY Specifies the offset from the left and top edge
1540 of the image of the first character cell in the
1541 image.
1542 @param RowInfoArray If this is non-NULL on entry, then on exit, this
1543 will point to an allocated buffer containing
1544 row information and RowInfoArraySize will be
1545 updated to contain the number of elements.
1546 This array describes the characters which were at
1547 least partially drawn and the heights of the
1548 rows. It is the caller's responsibility to free
1549 this buffer.
1550 @param RowInfoArraySize If this is non-NULL on entry, then on exit it
1551 contains the number of elements in RowInfoArray.
1552 @param ColumnInfoArray If this is non-NULL, then on return it will be
1553 filled with the horizontal offset for each
1554 character in the string on the row where it is
1555 displayed. Non-printing characters will have
1556 the offset ~0. The caller is responsible to
1557 allocate a buffer large enough so that there
1558 is one entry for each character in the string,
1559 not including the null-terminator. It is possible
1560 when character display is normalized that some
1561 character cells overlap.
1562
1563 @retval EFI_SUCCESS The string was successfully rendered.
1564 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
1565 RowInfoArray or Blt.
1566 @retval EFI_INVALID_PARAMETER The String or Blt was NULL.
1567 @retval EFI_INVALID_PARAMETER Flags were invalid combination..
1568
1569 **/
1570 EFI_STATUS
1571 EFIAPI
1572 HiiStringToImage (
1573 IN CONST EFI_HII_FONT_PROTOCOL *This,
1574 IN EFI_HII_OUT_FLAGS Flags,
1575 IN CONST EFI_STRING String,
1576 IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
1577 IN OUT EFI_IMAGE_OUTPUT **Blt,
1578 IN UINTN BltX,
1579 IN UINTN BltY,
1580 OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
1581 OUT UINTN *RowInfoArraySize OPTIONAL,
1582 OUT UINTN *ColumnInfoArray OPTIONAL
1583 )
1584 {
1585 EFI_STATUS Status;
1586 HII_DATABASE_PRIVATE_DATA *Private;
1587 UINT8 **GlyphBuf;
1588 EFI_HII_GLYPH_INFO *Cell;
1589 UINT8 *Attributes;
1590 EFI_IMAGE_OUTPUT *Image;
1591 EFI_STRING StringPtr;
1592 EFI_STRING StringTmp;
1593 EFI_HII_ROW_INFO *RowInfo;
1594 UINTN LineWidth;
1595 UINTN LineHeight;
1596 UINTN LineOffset;
1597 UINTN LastLineHeight;
1598 UINTN BaseLineOffset;
1599 UINT16 MaxRowNum;
1600 UINT16 RowIndex;
1601 UINTN Index;
1602 UINTN NextIndex;
1603 UINTN Index1;
1604 EFI_FONT_DISPLAY_INFO *StringInfoOut;
1605 EFI_FONT_DISPLAY_INFO *SystemDefault;
1606 EFI_FONT_HANDLE FontHandle;
1607 EFI_STRING StringIn;
1608 EFI_STRING StringIn2;
1609 UINT16 Height;
1610 UINT16 BaseLine;
1611 EFI_FONT_INFO *FontInfo;
1612 BOOLEAN SysFontFlag;
1613 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1614 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1615 BOOLEAN Transparent;
1616 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
1617 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
1618 UINTN RowInfoSize;
1619 BOOLEAN LineBreak;
1620 UINTN StrLength;
1621 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *RowBufferPtr;
1622 HII_GLOBAL_FONT_INFO *GlobalFont;
1623 UINT32 PreInitBkgnd;
1624
1625 //
1626 // Check incoming parameters.
1627 //
1628
1629 if (This == NULL || String == NULL || Blt == NULL) {
1630 return EFI_INVALID_PARAMETER;
1631 }
1632 if (*Blt == NULL) {
1633 //
1634 // These two flag cannot be used if Blt is NULL upon entry.
1635 //
1636 if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
1637 return EFI_INVALID_PARAMETER;
1638 }
1639 if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
1640 return EFI_INVALID_PARAMETER;
1641 }
1642 }
1643 //
1644 // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
1645 //
1646 if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X) {
1647 return EFI_INVALID_PARAMETER;
1648 }
1649 if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {
1650 return EFI_INVALID_PARAMETER;
1651 }
1652 //
1653 // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
1654 //
1655 if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) {
1656 return EFI_INVALID_PARAMETER;
1657 }
1658
1659 if (*Blt == NULL) {
1660 //
1661 // Create a new bitmap and draw the string onto this image.
1662 //
1663 Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1664 if (Image == NULL) {
1665 return EFI_OUT_OF_RESOURCES;
1666 }
1667 Image->Width = 800;
1668 Image->Height = 600;
1669 Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1670 if (Image->Image.Bitmap == NULL) {
1671 FreePool (Image);
1672 return EFI_OUT_OF_RESOURCES;
1673 }
1674
1675 //
1676 // Other flags are not permitted when Blt is NULL.
1677 //
1678 Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
1679 *Blt = Image;
1680 }
1681
1682 StrLength = StrLen(String);
1683 GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *));
1684 ASSERT (GlyphBuf != NULL);
1685 Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
1686 ASSERT (Cell != NULL);
1687 Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8));
1688 ASSERT (Attributes != NULL);
1689
1690 RowInfo = NULL;
1691 Status = EFI_SUCCESS;
1692 StringIn2 = NULL;
1693 SystemDefault = NULL;
1694 StringIn = NULL;
1695
1696 //
1697 // Calculate the string output information, including specified color and font .
1698 // If StringInfo does not points to system font info, it must indicate an existing
1699 // EFI_FONT_INFO.
1700 //
1701 StringInfoOut = NULL;
1702 FontHandle = NULL;
1703 Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1704 SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
1705
1706 if (SysFontFlag) {
1707 ASSERT (SystemDefault != NULL);
1708 FontInfo = NULL;
1709 Height = SystemDefault->FontInfo.FontSize;
1710 BaseLine = SystemDefault->FontInfo.FontSize;
1711 Foreground = SystemDefault->ForegroundColor;
1712 Background = SystemDefault->BackgroundColor;
1713
1714 } else {
1715 //
1716 // StringInfo must not be NULL if it is not system info.
1717 //
1718 ASSERT (StringInfo != NULL);
1719 Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);
1720 if (Status == EFI_NOT_FOUND) {
1721 //
1722 // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
1723 // Use the system font instead. Still use the color specified by StringInfo.
1724 //
1725 SysFontFlag = TRUE;
1726 FontInfo = NULL;
1727 Height = SystemDefault->FontInfo.FontSize;
1728 BaseLine = SystemDefault->FontInfo.FontSize;
1729 Foreground = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;
1730 Background = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;
1731
1732 } else if (Status == EFI_SUCCESS) {
1733 FontInfo = &StringInfoOut->FontInfo;
1734 IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont);
1735 Height = GlobalFont->FontPackage->Height;
1736 BaseLine = GlobalFont->FontPackage->BaseLine;
1737 Foreground = StringInfoOut->ForegroundColor;
1738 Background = StringInfoOut->BackgroundColor;
1739 } else {
1740 goto Exit;
1741 }
1742 }
1743
1744 //
1745 // Use the maximum height of font as the base line.
1746 // And, use the maximum height as line height.
1747 //
1748 LineHeight = Height;
1749 LastLineHeight = Height;
1750 BaseLineOffset = Height - BaseLine;
1751
1752 //
1753 // Parse the string to be displayed to drop some ignored characters.
1754 //
1755
1756 StringPtr = String;
1757
1758 //
1759 // Ignore line-break characters only. Hyphens or dash character will be displayed
1760 // without line-break opportunity.
1761 //
1762 if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
1763 StringIn = AllocateZeroPool (StrSize (StringPtr));
1764 if (StringIn == NULL) {
1765 Status = EFI_OUT_OF_RESOURCES;
1766 goto Exit;
1767 }
1768 StringTmp = StringIn;
1769 while (*StringPtr != 0) {
1770 if (IsLineBreak (*StringPtr) == 0) {
1771 StringPtr++;
1772 } else {
1773 *StringTmp++ = *StringPtr++;
1774 }
1775 }
1776 *StringTmp = 0;
1777 StringPtr = StringIn;
1778 }
1779 //
1780 // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
1781 // are not drawn. Otherwise they are replaced with Unicode character 0xFFFD.
1782 //
1783 StringIn2 = AllocateZeroPool (StrSize (StringPtr));
1784 if (StringIn2 == NULL) {
1785 Status = EFI_OUT_OF_RESOURCES;
1786 goto Exit;
1787 }
1788 Index = 0;
1789 StringTmp = StringIn2;
1790 StrLength = StrLen(StringPtr);
1791 while (*StringPtr != 0 && Index < StrLength) {
1792 if (IsLineBreak (*StringPtr) == 0) {
1793 *StringTmp++ = *StringPtr++;
1794 Index++;
1795 continue;
1796 }
1797
1798 Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
1799 if (Status == EFI_NOT_FOUND) {
1800 if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
1801 GlyphBuf[Index] = NULL;
1802 ZeroMem (&Cell[Index], sizeof (Cell[Index]));
1803 Status = EFI_SUCCESS;
1804 } else {
1805 //
1806 // Unicode 0xFFFD must exist in current hii database if this flag is not set.
1807 //
1808 Status = GetGlyphBuffer (
1809 Private,
1810 REPLACE_UNKNOWN_GLYPH,
1811 FontInfo,
1812 &GlyphBuf[Index],
1813 &Cell[Index],
1814 &Attributes[Index]
1815 );
1816 if (EFI_ERROR (Status)) {
1817 Status = EFI_INVALID_PARAMETER;
1818 }
1819 }
1820 }
1821
1822 if (EFI_ERROR (Status)) {
1823 goto Exit;
1824 }
1825
1826 *StringTmp++ = *StringPtr++;
1827 Index++;
1828 }
1829 *StringTmp = 0;
1830 StringPtr = StringIn2;
1831
1832 //
1833 // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
1834 // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
1835 // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
1836 // Otherwise render this string to a new allocated image and output it.
1837 //
1838 Image = *Blt;
1839 BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
1840 if (Image->Height < BltY) {
1841 //
1842 // the top edge of the image should be in Image resolution scope.
1843 //
1844 Status = EFI_INVALID_PARAMETER;
1845 goto Exit;
1846 }
1847 MaxRowNum = (UINT16) ((Image->Height - BltY) / Height);
1848 if ((Image->Height - BltY) % Height != 0) {
1849 LastLineHeight = (Image->Height - BltY) % Height;
1850 MaxRowNum++;
1851 }
1852
1853 RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
1854 if (RowInfo == NULL) {
1855 Status = EFI_OUT_OF_RESOURCES;
1856 goto Exit;
1857 }
1858
1859 //
1860 // Format the glyph buffer according to flags.
1861 //
1862 Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
1863
1864 for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
1865 LineWidth = 0;
1866 LineBreak = FALSE;
1867
1868 //
1869 // Clip the final row if the row's bottom-most on pixel cannot fit when
1870 // EFI_HII_OUT_FLAG_CLEAN_Y is set.
1871 //
1872 if (RowIndex == MaxRowNum - 1) {
1873 if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y && LastLineHeight < LineHeight ) {
1874 //
1875 // Don't draw at all if the row's bottom-most on pixel cannot fit.
1876 //
1877 break;
1878 }
1879 LineHeight = LastLineHeight;
1880 }
1881
1882 //
1883 // Calculate how many characters there are in a row.
1884 //
1885 RowInfo[RowIndex].StartIndex = Index;
1886
1887 while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
1888 if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
1889 IsLineBreak (StringPtr[Index]) == 0) {
1890 //
1891 // It forces a line break that ends this row.
1892 //
1893 Index++;
1894 LineBreak = TRUE;
1895 break;
1896 }
1897
1898 //
1899 // If the glyph of the character is existing, then accumulate the actual printed width
1900 //
1901 LineWidth += (UINTN) Cell[Index].AdvanceX;
1902
1903 Index++;
1904 }
1905
1906 //
1907 // Record index of next char.
1908 //
1909 NextIndex = Index;
1910 //
1911 // Return to the previous char.
1912 //
1913 Index--;
1914 if (LineBreak && Index > 0 ) {
1915 //
1916 // Return the previous non line break char.
1917 //
1918 Index --;
1919 }
1920
1921 //
1922 // If this character is the last character of a row, we need not
1923 // draw its (AdvanceX - Width - OffsetX) for next character.
1924 //
1925 LineWidth -= (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);
1926
1927 //
1928 // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
1929 //
1930 if (LineWidth + BltX <= Image->Width ||
1931 (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) {
1932 //
1933 // Record right-most character in RowInfo even if it is partially displayed.
1934 //
1935 RowInfo[RowIndex].EndIndex = Index;
1936 RowInfo[RowIndex].LineWidth = LineWidth;
1937 RowInfo[RowIndex].LineHeight = LineHeight;
1938 RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1939 } else {
1940 //
1941 // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
1942 // if its right-most on pixel cannot fit.
1943 //
1944 if (Index > RowInfo[RowIndex].StartIndex) {
1945 //
1946 // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
1947 //
1948 LineWidth -= (Cell[Index].Width + Cell[Index].OffsetX);
1949 LineWidth -= (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);
1950 RowInfo[RowIndex].EndIndex = Index - 1;
1951 RowInfo[RowIndex].LineWidth = LineWidth;
1952 RowInfo[RowIndex].LineHeight = LineHeight;
1953 RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1954 } else {
1955 //
1956 // There is no enough column to draw any character, so set current line width to zero.
1957 // And go to draw Next line if LineBreak is set.
1958 //
1959 RowInfo[RowIndex].LineWidth = 0;
1960 goto NextLine;
1961 }
1962 }
1963
1964 //
1965 // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
1966 // opportunity prior to a character whose right-most extent would exceed Width.
1967 // Search the right-most line-break opportunity here.
1968 //
1969 if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP &&
1970 (RowInfo[RowIndex].LineWidth + BltX > Image->Width || StringPtr[NextIndex] != 0) &&
1971 !LineBreak) {
1972 if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
1973 LineWidth = RowInfo[RowIndex].LineWidth;
1974 for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
1975 if (Index1 == RowInfo[RowIndex].EndIndex) {
1976 LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
1977 } else {
1978 LineWidth -= Cell[Index1].AdvanceX;
1979 }
1980 if (IsLineBreak (StringPtr[Index1]) > 0) {
1981 LineBreak = TRUE;
1982 if (Index1 > RowInfo[RowIndex].StartIndex) {
1983 RowInfo[RowIndex].EndIndex = Index1 - 1;
1984 }
1985 //
1986 // relocate to the character after the right-most line break opportunity of this line
1987 //
1988 NextIndex = Index1 + 1;
1989 break;
1990 }
1991 //
1992 // If don't find a line break opportunity from EndIndex to StartIndex,
1993 // then jump out.
1994 //
1995 if (Index1 == RowInfo[RowIndex].StartIndex)
1996 break;
1997 }
1998
1999 //
2000 // Update LineWidth to the real width
2001 //
2002 if (IsLineBreak (StringPtr[Index1]) > 0) {
2003 if (Index1 == RowInfo[RowIndex].StartIndex) {
2004 LineWidth = 0;
2005 } else {
2006 LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2007 }
2008 RowInfo[RowIndex].LineWidth = LineWidth;
2009 }
2010 }
2011 //
2012 // If no line-break opportunity can be found, then the text will
2013 // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
2014 //
2015 if (!LineBreak) {
2016 LineWidth = RowInfo[RowIndex].LineWidth;
2017 Index1 = RowInfo[RowIndex].EndIndex;
2018 if (LineWidth + BltX > Image->Width) {
2019 if (Index1 > RowInfo[RowIndex].StartIndex) {
2020 //
2021 // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
2022 //
2023 LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
2024 LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2025 RowInfo[RowIndex].EndIndex = Index1 - 1;
2026 RowInfo[RowIndex].LineWidth = LineWidth;
2027 } else {
2028 //
2029 // There is no enough column to draw any character, so set current line width to zero.
2030 // And go to draw Next line if LineBreak is set.
2031 //
2032 RowInfo[RowIndex].LineWidth = 0;
2033 goto NextLine;
2034 }
2035 }
2036 }
2037 }
2038
2039 //
2040 // LineWidth can't exceed Image width.
2041 //
2042 if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {
2043 RowInfo[RowIndex].LineWidth = Image->Width - BltX;
2044 }
2045
2046 //
2047 // Draw it to screen or existing bitmap depending on whether
2048 // EFI_HII_DIRECT_TO_SCREEN is set.
2049 //
2050 LineOffset = 0;
2051 if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
2052 BltBuffer = NULL;
2053 if (RowInfo[RowIndex].LineWidth != 0) {
2054 BltBuffer = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2055 if (BltBuffer == NULL) {
2056 Status = EFI_OUT_OF_RESOURCES;
2057 goto Exit;
2058 }
2059 //
2060 // Initialize the background color.
2061 //
2062 PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
2063 SetMem32 (BltBuffer,RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),PreInitBkgnd);
2064 //
2065 // Set BufferPtr to Origin by adding baseline to the starting position.
2066 //
2067 BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;
2068 }
2069 for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2070 if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2071 //
2072 // Only BLT these character which have corresponding glyph in font database.
2073 //
2074 GlyphToImage (
2075 GlyphBuf[Index1],
2076 Foreground,
2077 Background,
2078 (UINT16) RowInfo[RowIndex].LineWidth,
2079 BaseLine,
2080 RowInfo[RowIndex].LineWidth - LineOffset,
2081 RowInfo[RowIndex].LineHeight,
2082 Transparent,
2083 &Cell[Index1],
2084 Attributes[Index1],
2085 &BufferPtr
2086 );
2087 }
2088 if (ColumnInfoArray != NULL) {
2089 if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2090 || RowInfo[RowIndex].LineWidth == 0) {
2091 *ColumnInfoArray = (UINTN) ~0;
2092 } else {
2093 *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2094 }
2095 ColumnInfoArray++;
2096 }
2097 LineOffset += Cell[Index1].AdvanceX;
2098 }
2099
2100 if (BltBuffer != NULL) {
2101 Status = Image->Image.Screen->Blt (
2102 Image->Image.Screen,
2103 BltBuffer,
2104 EfiBltBufferToVideo,
2105 0,
2106 0,
2107 BltX,
2108 BltY,
2109 RowInfo[RowIndex].LineWidth,
2110 RowInfo[RowIndex].LineHeight,
2111 0
2112 );
2113 if (EFI_ERROR (Status)) {
2114 FreePool (BltBuffer);
2115 goto Exit;
2116 }
2117
2118 FreePool (BltBuffer);
2119 }
2120 } else {
2121 //
2122 // Save the starting position for calculate the starting position of next row.
2123 //
2124 RowBufferPtr = BufferPtr;
2125 //
2126 // Set BufferPtr to Origin by adding baseline to the starting position.
2127 //
2128 BufferPtr = BufferPtr + BaseLine * Image->Width;
2129 for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2130 if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2131 //
2132 // Only BLT these character which have corresponding glyph in font database.
2133 //
2134 GlyphToImage (
2135 GlyphBuf[Index1],
2136 Foreground,
2137 Background,
2138 Image->Width,
2139 BaseLine,
2140 RowInfo[RowIndex].LineWidth - LineOffset,
2141 RowInfo[RowIndex].LineHeight,
2142 Transparent,
2143 &Cell[Index1],
2144 Attributes[Index1],
2145 &BufferPtr
2146 );
2147 }
2148 if (ColumnInfoArray != NULL) {
2149 if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2150 || RowInfo[RowIndex].LineWidth == 0) {
2151 *ColumnInfoArray = (UINTN) ~0;
2152 } else {
2153 *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2154 }
2155 ColumnInfoArray++;
2156 }
2157 LineOffset += Cell[Index1].AdvanceX;
2158 }
2159
2160 //
2161 // Jump to starting position of next row.
2162 //
2163 if (RowIndex == 0) {
2164 BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;
2165 } else {
2166 BufferPtr = RowBufferPtr + LineHeight * Image->Width;
2167 }
2168 }
2169
2170 NextLine:
2171 //
2172 // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down
2173 //
2174 BltY += RowInfo[RowIndex].LineHeight;
2175
2176 RowIndex++;
2177 Index = NextIndex;
2178
2179 if (!LineBreak) {
2180 //
2181 // If there is not a mandatory line break or line break opportunity, only render one line to image
2182 //
2183 break;
2184 }
2185 }
2186
2187 //
2188 // Write output parameters.
2189 //
2190 RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
2191 if (RowInfoArray != NULL) {
2192 if (RowInfoSize > 0) {
2193 *RowInfoArray = AllocateZeroPool (RowInfoSize);
2194 if (*RowInfoArray == NULL) {
2195 Status = EFI_OUT_OF_RESOURCES;
2196 goto Exit;
2197 }
2198 CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
2199 } else {
2200 *RowInfoArray = NULL;
2201 }
2202 }
2203 if (RowInfoArraySize != NULL) {
2204 *RowInfoArraySize = RowIndex;
2205 }
2206
2207 Status = EFI_SUCCESS;
2208
2209 Exit:
2210
2211 for (Index = 0; Index < StrLength; Index++) {
2212 if (GlyphBuf[Index] != NULL) {
2213 FreePool (GlyphBuf[Index]);
2214 }
2215 }
2216 if (StringIn != NULL) {
2217 FreePool (StringIn);
2218 }
2219 if (StringIn2 != NULL) {
2220 FreePool (StringIn2);
2221 }
2222 if (StringInfoOut != NULL) {
2223 FreePool (StringInfoOut);
2224 }
2225 if (RowInfo != NULL) {
2226 FreePool (RowInfo);
2227 }
2228 if (SystemDefault != NULL) {
2229 FreePool (SystemDefault);
2230 }
2231 if (GlyphBuf != NULL) {
2232 FreePool (GlyphBuf);
2233 }
2234 if (Cell != NULL) {
2235 FreePool (Cell);
2236 }
2237 if (Attributes != NULL) {
2238 FreePool (Attributes);
2239 }
2240
2241 return Status;
2242 }
2243
2244
2245 /**
2246 Render a string to a bitmap or the screen containing the contents of the specified string.
2247
2248 @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
2249 @param Flags Describes how the string is to be drawn.
2250 @param PackageList The package list in the HII database to search
2251 for the specified string.
2252 @param StringId The string's id, which is unique within
2253 PackageList.
2254 @param Language Points to the language for the retrieved string.
2255 If NULL, then the current system language is
2256 used.
2257 @param StringInfo Points to the string output information,
2258 including the color and font. If NULL, then the
2259 string will be output in the default system font
2260 and color.
2261 @param Blt If this points to a non-NULL on entry, this
2262 points to the image, which is Width pixels wide
2263 and Height pixels high. The string will be drawn
2264 onto this image and
2265 EFI_HII_OUT_FLAG_CLIP is implied. If this points
2266 to a NULL on entry, then a buffer
2267 will be allocated to hold the generated image and
2268 the pointer updated on exit. It is the caller's
2269 responsibility to free this buffer.
2270 @param BltX Specifies the offset from the left and top edge
2271 of the image of the first character cell in the
2272 image.
2273 @param BltY Specifies the offset from the left and top edge
2274 of the image of the first character cell in the
2275 image.
2276 @param RowInfoArray If this is non-NULL on entry, then on exit, this
2277 will point to an allocated buffer containing
2278 row information and RowInfoArraySize will be
2279 updated to contain the number of elements.
2280 This array describes the characters which were at
2281 least partially drawn and the heights of the
2282 rows. It is the caller's responsibility to free
2283 this buffer.
2284 @param RowInfoArraySize If this is non-NULL on entry, then on exit it
2285 contains the number of elements in RowInfoArray.
2286 @param ColumnInfoArray If this is non-NULL, then on return it will be
2287 filled with the horizontal offset for each
2288 character in the string on the row where it is
2289 displayed. Non-printing characters will have
2290 the offset ~0. The caller is responsible to
2291 allocate a buffer large enough so that there
2292 is one entry for each character in the string,
2293 not including the null-terminator. It is possible
2294 when character display is normalized that some
2295 character cells overlap.
2296
2297 @retval EFI_SUCCESS The string was successfully rendered.
2298 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
2299 RowInfoArray or Blt.
2300 @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL.
2301 @retval EFI_INVALID_PARAMETER Flags were invalid combination.
2302 @retval EFI_NOT_FOUND The specified PackageList is not in the Database or the string id is not
2303 in the specified PackageList.
2304
2305 **/
2306 EFI_STATUS
2307 EFIAPI
2308 HiiStringIdToImage (
2309 IN CONST EFI_HII_FONT_PROTOCOL *This,
2310 IN EFI_HII_OUT_FLAGS Flags,
2311 IN EFI_HII_HANDLE PackageList,
2312 IN EFI_STRING_ID StringId,
2313 IN CONST CHAR8* Language,
2314 IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
2315 IN OUT EFI_IMAGE_OUTPUT **Blt,
2316 IN UINTN BltX,
2317 IN UINTN BltY,
2318 OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
2319 OUT UINTN *RowInfoArraySize OPTIONAL,
2320 OUT UINTN *ColumnInfoArray OPTIONAL
2321 )
2322 {
2323 EFI_STATUS Status;
2324 HII_DATABASE_PRIVATE_DATA *Private;
2325 EFI_HII_STRING_PROTOCOL *HiiString;
2326 EFI_STRING String;
2327 UINTN StringSize;
2328 UINTN FontLen;
2329 UINTN NameSize;
2330 EFI_FONT_INFO *StringFontInfo;
2331 EFI_FONT_DISPLAY_INFO *NewStringInfo;
2332 CHAR8 TempSupportedLanguages;
2333 CHAR8 *SupportedLanguages;
2334 UINTN SupportedLanguagesSize;
2335 CHAR8 *CurrentLanguage;
2336 CHAR8 *BestLanguage;
2337
2338 if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
2339 return EFI_INVALID_PARAMETER;
2340 }
2341
2342 if (!IsHiiHandleValid (PackageList)) {
2343 return EFI_NOT_FOUND;
2344 }
2345
2346 //
2347 // Initialize string pointers to be NULL
2348 //
2349 SupportedLanguages = NULL;
2350 CurrentLanguage = NULL;
2351 BestLanguage = NULL;
2352 String = NULL;
2353 StringFontInfo = NULL;
2354 NewStringInfo = NULL;
2355
2356 //
2357 // Get the string to be displayed.
2358 //
2359 Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2360 HiiString = &Private->HiiString;
2361
2362 //
2363 // Get the size of supported language.
2364 //
2365 SupportedLanguagesSize = 0;
2366 Status = HiiString->GetLanguages (
2367 HiiString,
2368 PackageList,
2369 &TempSupportedLanguages,
2370 &SupportedLanguagesSize
2371 );
2372 if (Status != EFI_BUFFER_TOO_SMALL) {
2373 return Status;
2374 }
2375
2376 SupportedLanguages = AllocatePool (SupportedLanguagesSize);
2377 if (SupportedLanguages == NULL) {
2378 return EFI_OUT_OF_RESOURCES;
2379 }
2380
2381 Status = HiiString->GetLanguages (
2382 HiiString,
2383 PackageList,
2384 SupportedLanguages,
2385 &SupportedLanguagesSize
2386 );
2387 if (EFI_ERROR (Status)) {
2388 goto Exit;
2389 }
2390
2391 if (Language == NULL) {
2392 Language = "";
2393 }
2394 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLanguage, NULL);
2395 BestLanguage = GetBestLanguage (
2396 SupportedLanguages,
2397 FALSE,
2398 Language,
2399 (CurrentLanguage == NULL) ? CurrentLanguage : "",
2400 (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
2401 NULL
2402 );
2403 if (BestLanguage == NULL) {
2404 Status = EFI_NOT_FOUND;
2405 goto Exit;
2406 }
2407
2408 StringSize = MAX_STRING_LENGTH;
2409 String = (EFI_STRING) AllocateZeroPool (StringSize);
2410 if (String == NULL) {
2411 Status = EFI_OUT_OF_RESOURCES;
2412 goto Exit;
2413 }
2414
2415 Status = HiiString->GetString (
2416 HiiString,
2417 BestLanguage,
2418 PackageList,
2419 StringId,
2420 String,
2421 &StringSize,
2422 &StringFontInfo
2423 );
2424 if (Status == EFI_BUFFER_TOO_SMALL) {
2425 FreePool (String);
2426 String = (EFI_STRING) AllocateZeroPool (StringSize);
2427 if (String == NULL) {
2428 Status = EFI_OUT_OF_RESOURCES;
2429 goto Exit;
2430 }
2431 Status = HiiString->GetString (
2432 HiiString,
2433 BestLanguage,
2434 PackageList,
2435 StringId,
2436 String,
2437 &StringSize,
2438 NULL
2439 );
2440 }
2441
2442 if (EFI_ERROR (Status)) {
2443 goto Exit;
2444 }
2445
2446 //
2447 // When StringInfo specifies that string will be output in the system default font and color,
2448 // use particular stringfontinfo described in string package instead if exists.
2449 // StringFontInfo equals NULL means system default font attaches with the string block.
2450 //
2451 if (StringFontInfo != NULL && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, NULL, NULL)) {
2452 NameSize = StrSize (StringFontInfo->FontName);
2453 FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
2454 NewStringInfo = AllocateZeroPool (FontLen);
2455 if (NewStringInfo == NULL) {
2456 Status = EFI_OUT_OF_RESOURCES;
2457 goto Exit;
2458 }
2459 NewStringInfo->FontInfoMask = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;
2460 NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;
2461 NewStringInfo->FontInfo.FontSize = StringFontInfo->FontSize;
2462 StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);
2463
2464 Status = HiiStringToImage (
2465 This,
2466 Flags,
2467 String,
2468 NewStringInfo,
2469 Blt,
2470 BltX,
2471 BltY,
2472 RowInfoArray,
2473 RowInfoArraySize,
2474 ColumnInfoArray
2475 );
2476 goto Exit;
2477 }
2478
2479 Status = HiiStringToImage (
2480 This,
2481 Flags,
2482 String,
2483 StringInfo,
2484 Blt,
2485 BltX,
2486 BltY,
2487 RowInfoArray,
2488 RowInfoArraySize,
2489 ColumnInfoArray
2490 );
2491
2492 Exit:
2493 if (SupportedLanguages != NULL) {
2494 FreePool (SupportedLanguages);
2495 }
2496 if (CurrentLanguage != NULL) {
2497 FreePool (CurrentLanguage);
2498 }
2499 if (BestLanguage != NULL) {
2500 FreePool (BestLanguage);
2501 }
2502 if (String != NULL) {
2503 FreePool (String);
2504 }
2505 if (StringFontInfo != NULL) {
2506 FreePool (StringFontInfo);
2507 }
2508 if (NewStringInfo != NULL) {
2509 FreePool (NewStringInfo);
2510 }
2511
2512 return Status;
2513 }
2514
2515
2516 /**
2517 Convert the glyph for a single character into a bitmap.
2518
2519 @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
2520 @param Char Character to retrieve.
2521 @param StringInfo Points to the string font and color information
2522 or NULL if the string should use the default
2523 system font and color.
2524 @param Blt Thus must point to a NULL on entry. A buffer will
2525 be allocated to hold the output and the pointer
2526 updated on exit. It is the caller's
2527 responsibility to free this buffer.
2528 @param Baseline Number of pixels from the bottom of the bitmap to
2529 the baseline.
2530
2531 @retval EFI_SUCCESS Glyph bitmap created.
2532 @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.
2533 @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the
2534 glyph for Unicode character 0xFFFD.
2535 @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.
2536
2537 **/
2538 EFI_STATUS
2539 EFIAPI
2540 HiiGetGlyph (
2541 IN CONST EFI_HII_FONT_PROTOCOL *This,
2542 IN CHAR16 Char,
2543 IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
2544 OUT EFI_IMAGE_OUTPUT **Blt,
2545 OUT UINTN *Baseline OPTIONAL
2546 )
2547 {
2548 EFI_STATUS Status;
2549 HII_DATABASE_PRIVATE_DATA *Private;
2550 EFI_IMAGE_OUTPUT *Image;
2551 UINT8 *GlyphBuffer;
2552 EFI_FONT_DISPLAY_INFO *SystemDefault;
2553 EFI_FONT_DISPLAY_INFO *StringInfoOut;
2554 BOOLEAN Default;
2555 EFI_FONT_HANDLE FontHandle;
2556 EFI_STRING String;
2557 EFI_HII_GLYPH_INFO Cell;
2558 EFI_FONT_INFO *FontInfo;
2559 UINT8 Attributes;
2560 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
2561 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
2562 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
2563 UINT16 BaseLine;
2564
2565 if (This == NULL || Blt == NULL || *Blt != NULL) {
2566 return EFI_INVALID_PARAMETER;
2567 }
2568
2569 Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2570
2571 Default = FALSE;
2572 Image = NULL;
2573 SystemDefault = NULL;
2574 FontHandle = NULL;
2575 String = NULL;
2576 GlyphBuffer = NULL;
2577 StringInfoOut = NULL;
2578 FontInfo = NULL;
2579
2580 ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2581 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2582
2583 Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
2584
2585 if (!Default) {
2586 //
2587 // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
2588 // the specified color and font.
2589 //
2590 String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);
2591 if (String == NULL) {
2592 Status = EFI_OUT_OF_RESOURCES;
2593 goto Exit;
2594 }
2595 *String = Char;
2596 *(String + 1) = 0;
2597
2598 Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
2599 if (EFI_ERROR (Status)) {
2600 goto Exit;
2601 }
2602 ASSERT (StringInfoOut != NULL);
2603 FontInfo = &StringInfoOut->FontInfo;
2604 Foreground = StringInfoOut->ForegroundColor;
2605 Background = StringInfoOut->BackgroundColor;
2606 } else {
2607 ASSERT (SystemDefault != NULL);
2608 Foreground = SystemDefault->ForegroundColor;
2609 Background = SystemDefault->BackgroundColor;
2610 }
2611
2612 Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
2613 if (EFI_ERROR (Status)) {
2614 goto Exit;
2615 }
2616
2617 Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
2618 if (Image == NULL) {
2619 Status = EFI_OUT_OF_RESOURCES;
2620 goto Exit;
2621 }
2622 Image->Width = Cell.Width;
2623 Image->Height = Cell.Height;
2624
2625 if (Image->Width * Image->Height > 0) {
2626 Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2627 if (Image->Image.Bitmap == NULL) {
2628 FreePool (Image);
2629 Status = EFI_OUT_OF_RESOURCES;
2630 goto Exit;
2631 }
2632
2633 //
2634 // Set BaseLine to the char height.
2635 //
2636 BaseLine = (UINT16) (Cell.Height + Cell.OffsetY);
2637 //
2638 // Set BltBuffer to the position of Origin.
2639 //
2640 BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;
2641 GlyphToImage (
2642 GlyphBuffer,
2643 Foreground,
2644 Background,
2645 Image->Width,
2646 BaseLine,
2647 Cell.Width + Cell.OffsetX,
2648 BaseLine - Cell.OffsetY,
2649 FALSE,
2650 &Cell,
2651 Attributes,
2652 &BltBuffer
2653 );
2654 }
2655
2656 *Blt = Image;
2657 if (Baseline != NULL) {
2658 *Baseline = Cell.OffsetY;
2659 }
2660
2661 Status = EFI_SUCCESS;
2662
2663 Exit:
2664
2665 if (Status == EFI_NOT_FOUND) {
2666 //
2667 // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
2668 //
2669 if (Char != REPLACE_UNKNOWN_GLYPH) {
2670 Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
2671 if (!EFI_ERROR (Status)) {
2672 Status = EFI_WARN_UNKNOWN_GLYPH;
2673 }
2674 } else {
2675 Status = EFI_WARN_UNKNOWN_GLYPH;
2676 }
2677 }
2678
2679 if (SystemDefault != NULL) {
2680 FreePool (SystemDefault);
2681 }
2682 if (StringInfoOut != NULL) {
2683 FreePool (StringInfoOut);
2684 }
2685 if (String != NULL) {
2686 FreePool (String);
2687 }
2688 if (GlyphBuffer != NULL) {
2689 FreePool (GlyphBuffer);
2690 }
2691
2692 return Status;
2693 }
2694
2695
2696 /**
2697 This function iterates through fonts which match the specified font, using
2698 the specified criteria. If String is non-NULL, then all of the characters in
2699 the string must exist in order for a candidate font to be returned.
2700
2701 @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
2702 @param FontHandle On entry, points to the font handle returned by a
2703 previous call to GetFontInfo() or NULL to start
2704 with the first font. On return, points to the
2705 returned font handle or points to NULL if there
2706 are no more matching fonts.
2707 @param StringInfoIn Upon entry, points to the font to return information
2708 about. If NULL, then the information about the system
2709 default font will be returned.
2710 @param StringInfoOut Upon return, contains the matching font's information.
2711 If NULL, then no information is returned. This buffer
2712 is allocated with a call to the Boot Service AllocatePool().
2713 It is the caller's responsibility to call the Boot
2714 Service FreePool() when the caller no longer requires
2715 the contents of StringInfoOut.
2716 @param String Points to the string which will be tested to
2717 determine if all characters are available. If
2718 NULL, then any font is acceptable.
2719
2720 @retval EFI_SUCCESS Matching font returned successfully.
2721 @retval EFI_NOT_FOUND No matching font was found.
2722 @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
2723 @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
2724 request.
2725
2726 **/
2727 EFI_STATUS
2728 EFIAPI
2729 HiiGetFontInfo (
2730 IN CONST EFI_HII_FONT_PROTOCOL *This,
2731 IN OUT EFI_FONT_HANDLE *FontHandle,
2732 IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn OPTIONAL,
2733 OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
2734 IN CONST EFI_STRING String OPTIONAL
2735 )
2736 {
2737 HII_DATABASE_PRIVATE_DATA *Private;
2738 EFI_STATUS Status;
2739 EFI_FONT_DISPLAY_INFO *SystemDefault;
2740 EFI_FONT_DISPLAY_INFO InfoOut;
2741 UINTN StringInfoOutLen;
2742 EFI_FONT_INFO *FontInfo;
2743 HII_GLOBAL_FONT_INFO *GlobalFont;
2744 EFI_STRING StringIn;
2745 EFI_FONT_HANDLE LocalFontHandle;
2746
2747 if (This == NULL) {
2748 return EFI_INVALID_PARAMETER;
2749 }
2750
2751 StringInfoOutLen = 0;
2752 FontInfo = NULL;
2753 SystemDefault = NULL;
2754 LocalFontHandle = NULL;
2755 if (FontHandle != NULL) {
2756 LocalFontHandle = *FontHandle;
2757 }
2758
2759 Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2760
2761 //
2762 // Already searched to the end of the whole list, return directly.
2763 //
2764 if (LocalFontHandle == &Private->FontInfoList) {
2765 LocalFontHandle = NULL;
2766 Status = EFI_NOT_FOUND;
2767 goto Exit;
2768 }
2769
2770 //
2771 // Get default system display info, if StringInfoIn points to
2772 // system display info, return it directly.
2773 //
2774 if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
2775 //
2776 // System font is the first node. When handle is not NULL, system font can not
2777 // be found any more.
2778 //
2779 if (LocalFontHandle == NULL) {
2780 if (StringInfoOut != NULL) {
2781 *StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault);
2782 if (*StringInfoOut == NULL) {
2783 Status = EFI_OUT_OF_RESOURCES;
2784 LocalFontHandle = NULL;
2785 goto Exit;
2786 }
2787 }
2788
2789 LocalFontHandle = Private->FontInfoList.ForwardLink;
2790 Status = EFI_SUCCESS;
2791 goto Exit;
2792 } else {
2793 LocalFontHandle = NULL;
2794 Status = EFI_NOT_FOUND;
2795 goto Exit;
2796 }
2797 }
2798
2799 //
2800 // StringInfoIn must not be NULL if it is not system default font info.
2801 //
2802 ASSERT (StringInfoIn != NULL);
2803 //
2804 // Check the font information mask to make sure it is valid.
2805 //
2806 if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==
2807 (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||
2808 ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==
2809 (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||
2810 ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
2811 (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
2812 ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==
2813 (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||
2814 ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==
2815 (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {
2816 return EFI_INVALID_PARAMETER;
2817 }
2818
2819 //
2820 // Parse the font information mask to find a matching font.
2821 //
2822
2823 CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
2824
2825 if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
2826 Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
2827 } else {
2828 Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);
2829 }
2830 if (EFI_ERROR (Status)) {
2831 goto Exit;
2832 }
2833
2834 if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
2835 InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
2836 }
2837 if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
2838 InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
2839 }
2840 if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
2841 InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
2842 }
2843 if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
2844 InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
2845 }
2846
2847 ASSERT (FontInfo != NULL);
2848 FontInfo->FontSize = InfoOut.FontInfo.FontSize;
2849 FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
2850
2851 if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
2852 //
2853 // Test to guarantee all characters are available in the found font.
2854 //
2855 if (String != NULL) {
2856 StringIn = String;
2857 while (*StringIn != 0) {
2858 Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
2859 if (EFI_ERROR (Status)) {
2860 LocalFontHandle = NULL;
2861 goto Exit;
2862 }
2863 StringIn++;
2864 }
2865 }
2866 //
2867 // Write to output parameter
2868 //
2869 if (StringInfoOut != NULL) {
2870 StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
2871 *StringInfoOut = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);
2872 if (*StringInfoOut == NULL) {
2873 Status = EFI_OUT_OF_RESOURCES;
2874 LocalFontHandle = NULL;
2875 goto Exit;
2876 }
2877
2878 CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
2879 CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
2880 }
2881
2882 LocalFontHandle = GlobalFont->Entry.ForwardLink;
2883 Status = EFI_SUCCESS;
2884 goto Exit;
2885 }
2886
2887 Status = EFI_NOT_FOUND;
2888
2889 Exit:
2890
2891 if (FontHandle != NULL) {
2892 *FontHandle = LocalFontHandle;
2893 }
2894
2895 if (SystemDefault != NULL) {
2896 FreePool (SystemDefault);
2897 }
2898 if (FontInfo != NULL) {
2899 FreePool (FontInfo);
2900 }
2901 return Status;
2902 }