MHEG-5  19.3.0
MHEG-5 Documentation
mg_hkfont.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2012 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
38 /*---includes for this file--------------------------------------------------*/
39 #include <stdio.h>
40 #ifdef HK_PROFILE
41 #include <string.h>
42 
43 #include <ft2build.h>
44 #include FT_FREETYPE_H
45 
46 #include "mg_drawtext.h"
47 #include "mg_hkfont.h"
48 #include "glue_memory.h"
49 #include "glue_debug.h"
50 #include "mg_ctxt.h"
51 #include "mg_osd.h"
52 #include "osd_utils.h"
53 #include "stb_osd.h"
54 
55 #include "dvb_font.h"
56 
57 /*---constant definitions for this file--------------------------------------*/
58 
59 /* Unicode control characters: non-printable */
60 #define U_CTRL_NULL 0x00
61 #define U_CTRL_A 0x01
62 #define U_CTRL_B 0x02
63 #define U_CTRL_C 0x03
64 #define U_CTRL_D 0x04
65 #define U_CTRL_E 0x05
66 #define U_CTRL_F 0x06
67 #define U_CTRL_G 0x07
68 #define U_CTRL_H 0x08
69 #define U_CTRL_K 0x0B
70 #define U_CTRL_L 0x0C
71 #define U_CTRL_N 0x0E
72 #define U_CTRL_O 0x0F
73 #define U_CTRL_P 0x10
74 #define U_CTRL_Q 0x11
75 #define U_CTRL_R 0x12
76 #define U_CTRL_S 0x13
77 #define U_CTRL_T 0x14
78 #define U_CTRL_U 0x15
79 #define U_CTRL_V 0x16
80 #define U_CTRL_W 0x17
81 #define U_CTRL_X 0x18
82 #define U_CTRL_Y 0x19
83 #define U_CTRL_Z 0x1A
84 #define U_CTRL_FS 0x1C
85 #define U_CTRL_GS 0x1D
86 #define U_CTRL_RS 0x1E
87 #define U_CTRL_US 0x1F
88 
89 
90 /* Unicode character values */
91 #define UNICODE_SPACE (' ')
92 #define UNICODE_TAB ('\t')
93 #define UNICODE_LF (0x0a)
94 #define UNICODE_CR (0x0d)
95 #define UNICODE_ESC (0x1b)
96 #define UNICODE_HARD_SPACE (0xa0)
97 #define UNICODE_FIGURE_SPACE (0x2007)
98 #define UNICODE_APOSTROPHE_N (0x0149)
99 #define UNICODE_HYPER_ANCHOR_START (0x41)
100 #define UNICODE_HYPER_ANCHOR_END (0x61)
101 #define UNICODE_TEXT_COLOUR_START (0x43)
102 #define UNICODE_TEXT_COLOUR_END (0x63)
103 #define UNICODE_HYPER_ATTRIB_START (0x44)
104 #define UNICODE_HYPER_ATTRIB_END (0x64)
105 
106 /* HK profile: dont break after chars */
107 #define UNICODE_QUOTE ('"')
108 #define UNICODE_LEFT_ROUND ('(')
109 #define UNICODE_LEFT_SQUARE ('[')
110 #define UNICODE_LEFT_CURLY ('{')
111 #define UNICODE_LEFT_DQUOTE 0x201C
112 #define UNICODE_LEFT_PANGLE 0x2039
113 #define UNICODE_LEFT_FULL_CURLY 0xFF5B
114 #define UNICODE_LEFT_FULL_ROUND 0xFF08
115 #define UNICODE_LEFT_FULL_SQUARE 0xFF3B
116 #define UNICODE_LEFT_FULL_DROUND 0xFF5F
117 #define UNICODE_LEFT_FULL_DQUOTE 0xFF02
118 
119 /* HK profile: dont break before chars */
120 #define UNICODE_QUOTE ('"')
121 #define UNICODE_RIGHT_ROUND (')')
122 #define UNICODE_RIGHT_SQUARE (']')
123 #define UNICODE_RIGHT_CURLY ('}')
124 #define UNICODE_RIGHT_DQUOTE 0x201D
125 #define UNICODE_RIGHT_PANGLE 0x203A
126 #define UNICODE_RIGHT_FULL_CURLY 0xFF5D
127 #define UNICODE_RIGHT_FULL_ROUND 0xFF09
128 #define UNICODE_RIGHT_FULL_SQUARE 0xFF3D
129 #define UNICODE_RIGHT_FULL_DROUND 0xFF60
130 #define UNICODE_RIGHT_FULL_DQUOTE 0xFF02
131 #define UNICODE_FULL_QUESTIONMARK 0xFF1F
132 #define UNICODE_QUESTIONMARK 0x003F
133 #define UNICODE_EXCLAMATIONMARK 0x0021
134 #define UNICODE_FULL_STOP ('.')
135 #define UNICODE_COMMA (',')
136 #define UNICODE_COMMA_FULL 0xFF0C
137 #define UNICODE_FULL_STOP_FULL 0xFF0E
138 #define UNICODE_COLON (':')
139 #define UNICODE_SEMICOLON (';')
140 #define UNICODE_FULL_SEMICOLON 0xFF1B
141 #define IDEOGRAPHIC_COMMA 0x3001
142 #define IDEOGRAPHIC_FULL_STOP 0x3002
143 
144 #define HIGH_SURROGATE_START 0xD800
145 #define HIGH_SURROGATE_END 0xDBFF
146 #define LOW_SURROGATE_START 0xDC00
147 #define LOW_SURROGATE_END 0xDFFF
148 #define FULL_ADVANCE 1
149 #define HALF_ADVANCE 2
150 #define NO_ADVANCE 3
151 
152 #if 0
153 #define DIV(x, y) ((((x) * 10) / (y) + 5) / 10)
154 #else
155 #define DIV(x, y) ((x) / (y))
156 #endif
157 
158 /* SD-HD scaling function, using the existing mg_context */
159 #define SCALE_X_TO_HD(X) DIV((X * mg_ctxt.osd_x.mlt), mg_ctxt.osd_x.div)
160 #define SCALE_Y_TO_HD(Y) DIV((Y * mg_ctxt.osd_y.mlt), mg_ctxt.osd_y.div)
161 
162 /* checks for breakable whitespace */
163 #define IS_WHITESPACE(X) ((X) == UNICODE_SPACE || (X) == UNICODE_TAB)
164 
165 #define SRC_FORE_MAX 255
166 #define FactorForeAlpha(fore_value, fore_col) fore_value *= (fore_col >> 24)
167 #define NotTransTDColor( col ) ((col >> 12) != 0x0)
168 #define NotOpaqueTDColor( col ) ((col >> 12) != 0xf)
169 
170 
171 /*---local typedef structs for this file-------------------------------------*/
172 
173 
174 typedef struct fontLibrary_s
175 {
176  FT_Library library;
177  FT_Face face;
178 } fontLibrary_t;
179 
180 typedef struct metrics_s
181 {
182  S32BIT fullAdvance;
183  S32BIT halfAdvance;
184  S32BIT xOffsetLeft;
185  S32BIT yMin;
186  S32BIT yMax;
187 } metrics_t;
188 
189 /* a character to be rendered */
190 typedef struct textChar_s
191 {
192  U32BIT uchar; /* The utf-16 character to print*/
193  U16BIT position; /* X position of the origin of the character */
194  U8BIT advanceType; /* whether the advance is full or half width*/
195  U32BIT advance; /* character advance in pixels*/
196  OSDColor colour; /* ARGB colour (per char) */
197  struct textChar_s *next; /* Next char on the line, NULL if last in line */
198  struct textChar_s *previous; /* Previous char on the line, NULL if first in the line */
199 } textChar_t;
200 
201 /* A line of characters */
202 typedef struct textLine_s
203 {
204  textChar_t *firstChar; /* first character item in line*/
205  textChar_t *lastChar; /* last character item in line*/
206  U16BIT fullCharCount; /* number of full-width chars */
207  U16BIT halfCharCount; /* number of half-width chars */
208  U16BIT position; /* Y position of the line */
209  struct textLine_s *next; /* Next line */
210  struct textLine_s *previous; /* previous line */
211  struct textItem_s *parentObject; /* pointer to the text object containing the line */
212 } textLine_t;
213 
214 /* justification function pointer prototype */
215 typedef void (*justify_fn)(struct textItem_s *textObject);
216 
217 /* parsed text data structure*/
218 typedef struct textItem_s
219 {
220  U32BIT boxX, boxY; /* text box dimensions */
221  S_SURFACE *canvas; /* surface and associated data */
222  justify_fn vJustify, hJustify; /* pointers to justification functions */
223  U16BIT *chars; /* original string */
224  U32BIT charsLen; /* length of the chars string */
225  U16BIT lineCount; /* number of lines created (CRs and wrapping) */
226  U16BIT maxLines; /* maximum displayable lines of text */
227  metrics_t *metrics; /* metic table for the required font size*/
228  pDrawTextAttrib attribs; /* attributes of the text object */
229  textLine_t *firstLine; /* pointer to the first line */
230  textLine_t *lastLine; /* pointer to the last line */
231 } textItem_t;
232 
233 /* structure to build a stack of colours for markup */
234 typedef struct colourNode_s
235 {
236  OSDColor colour;
237  struct colourNode_s *previous;
238 } colourNode_t;
239 
240 
241 /*---local (static) variable declarations for this file----------------------*/
242 
243 static fontLibrary_t *font = NULL;
244 static colourNode_t *colourStack = NULL;
245 
246 /*metrics taken from the profile specification*/
247 static metrics_t metrics24Point = {22, 11, 1, -3, 18};
248 static metrics_t metrics26Point = {24, 12, 1, -3, 20};
249 static metrics_t metrics31Point = {28, 14, 1, -4, 23};
250 static metrics_t metrics36Point = {32, 16, 2, -4, 27};
251 
252 static U16BIT overwrite_caret = ENTRY_OVERWRITE_CHAR;
253 static U16BIT insert_caret = ENTRY_INSERT_CHAR;
254 /*---local function definitions----------------------------------------------*/
255 
256 /*---global function definitions---------------------------------------------*/
257 
258 
263 static void DestructColourStack(void)
264 {
265  colourNode_t *previous;
266  while (colourStack != NULL)
267  {
268  previous = colourStack->previous;
269  STB_MemFree(colourStack);
270  colourStack = previous;
271  }
272 }
273 
279 static void InitColourStack(OSDColor colour)
280 {
281  if (colourStack != NULL)
282  {
283  DestructColourStack();
284  }
285  colourStack = STB_MemAlloc(sizeof(colourNode_t));
286  colourStack->previous = NULL;
287  colourStack->colour = colour;
288 }
289 
295 static void PushColour(OSDColor colour)
296 {
297  colourNode_t *new;
298  new = STB_MemAlloc(sizeof(colourNode_t));
299  new->previous = colourStack;
300  new->colour = colour;
301  colourStack = new;
302 }
303 
310 static OSDColor PopColour(void)
311 {
312  colourNode_t *previous;
313  if (colourStack->previous != NULL)
314  {
315  previous = colourStack->previous;
316  STB_MemFree(colourStack);
317  colourStack = previous;
318  }
319  return colourStack->colour;
320 }
321 
328 static U16BIT* ReadHyperAttribs(U16BIT *string, pHyperAttribs ha)
329 {
330  U16BIT tagLength;
331  U16BIT bytesLeft;
332  U16BIT *cursor = string;
333  BOOLEAN linkColourEnabled = FALSE;
334  BOOLEAN activeColourEnabled = FALSE;
335  BOOLEAN visitedColourEnabled = FALSE;
336  if ((ha != NULL))
337  {
338  /*move to the tag length byte*/
339  cursor++;
340  tagLength = *cursor;
341  bytesLeft = tagLength;
342  if (bytesLeft >= 2)
343  {
344  cursor += 2;
345  if (((*cursor) & 0x08) != 0)
346  {
347  ha->anchor_wrap = TRUE;
348  }
349  else
350  {
351  ha->anchor_wrap = FALSE;
352  }
353 
354  if (((*cursor) & 0x40) != 0)
355  {
356  linkColourEnabled = TRUE;
357  }
358  if (((*cursor) & 0x20) != 0)
359  {
360  activeColourEnabled = TRUE;
361  }
362  if (((*cursor) & 0x10) != 0)
363  {
364  visitedColourEnabled = TRUE;
365  }
366  bytesLeft -= 2;
367  }
368  if (bytesLeft >= 4 && linkColourEnabled)
369  {
370  ha->link_colour = RGBT(cursor[0], cursor[1], cursor[2], cursor[3]);
371  cursor += 4;
372  bytesLeft -= 4;
373  }
374  if (bytesLeft >= 4 && activeColourEnabled)
375  {
376  ha->active_colour = RGBT(cursor[0], cursor[1], cursor[2], cursor[3]);
377  cursor += 4;
378  bytesLeft -= 4;
379  }
380  if (bytesLeft >= 4 && visitedColourEnabled)
381  {
382  ha->visit_colour = RGBT(cursor[0], cursor[1], cursor[2], cursor[3]);
383  cursor += 4;
384  bytesLeft -= 4;
385  }
386  }
387  /*return the end position: original + tag length + 1*/
388  return string + tagLength + 1;
389 }
390 
397 static U16BIT* AddHyperAnchor(U16BIT *string, pHyperAttribs ha)
398 {
399  U16BIT *cursor = string;
400  if ((ha != NULL))
401  {
402  ha->number_of_links++;
403  if (ha->markup_state == 0)
404  {
405  ha->markup_state = 2;
406  }
407  else
408  {
409  ha->markup_state++;
410  }
411  if (ha->focus_position == ha->number_of_links)
412  {
413  PushColour(ha->active_colour);
414  }
415  else
416  {
417  PushColour(ha->link_colour);
418  }
419  /*move to the tag length byte*/
420  cursor++;
421  /*move forward [tag length] bytes*/
422  cursor += (*cursor);
423  }
424  return cursor;
425 }
426 
433 static void EndHyperAnchor(U16BIT *string, pHyperAttribs ha)
434 {
435  if ((ha != NULL))
436  {
437  PopColour();
438  }
439 }
440 
447 static void ScaleAllToHD(textItem_t *textObject)
448 {
449  textLine_t *currentLine;
450  textChar_t *currentChar;
451 
452  /*scale the text box dimensions*/
453  textObject->boxX = SCALE_X_TO_HD(textObject->boxX);
454  textObject->boxY = SCALE_Y_TO_HD(textObject->boxY);
455 
456  /*go through each line*/
457  currentLine = textObject->firstLine;
458  while (currentLine != NULL)
459  {
460  /* scale each line position */
461  currentLine->position = SCALE_Y_TO_HD(currentLine->position);
462  /* go through each character */
463  currentChar = currentLine->firstChar;
464  while (currentChar != NULL)
465  {
466  /* scale each character position */
467  currentChar->position = SCALE_X_TO_HD(currentChar->position);
468  currentChar = currentChar->next;
469  }
470  currentLine = currentLine->next;
471  }
472 }
473 
479 static textChar_t* NewCharacter(U32BIT *pCharacter)
480 {
481  textChar_t *newChar;
482  newChar = STB_MemAlloc(sizeof(textChar_t));
483  if (newChar != NULL)
484  {
485  newChar->uchar = *pCharacter;
486  newChar->next = NULL;
487  }
488  return newChar;
489 }
490 
496 static textLine_t* NewLine(textItem_t *parent)
497 {
498  textLine_t *newLine;
499 
500  newLine = STB_MemAlloc(sizeof(textLine_t));
501  if (newLine != NULL)
502  {
503  newLine->firstChar = NULL;
504  newLine->lastChar = NULL;
505  newLine->fullCharCount = 0;
506  newLine->halfCharCount = 0;
507  newLine->next = NULL;
508  newLine->parentObject = parent;
509  /* add the new line to the end of the text object */
510  if (parent->lastLine != NULL)
511  {
512  parent->lastLine->next = newLine;
513  newLine->previous = parent->lastLine;
514  }
515  else
516  {
517  newLine->previous = NULL;
518  }
519  /*set it as the new lastLine in the object*/
520  parent->lastLine = newLine;
521  parent->lineCount++;
522  }
523  return newLine;
524 }
525 
532 static void DeleteChar(textChar_t *pChar, textLine_t *line)
533 {
534  if (pChar->advanceType == FULL_ADVANCE)
535  {
536  line->fullCharCount--;
537  }
538  else if (pChar->advanceType == HALF_ADVANCE)
539  {
540  line->halfCharCount--;
541  }
542  STB_MemFree(pChar);
543 }
544 
551 static void DeleteRemainingChars(textChar_t *pChar, textLine_t *line)
552 {
553  textChar_t *cursor, *next;
554 
555  cursor = pChar;
556  if (pChar->previous != NULL)
557  {
558  pChar->previous->next = NULL;
559  }
560 
561  while (cursor != NULL)
562  {
563  next = cursor->next;
564  DeleteChar(cursor, line);
565  cursor = next;
566  }
567 }
568 
574 static void DestructLine(textLine_t *line)
575 {
576  DeleteRemainingChars(line->firstChar, line);
577  STB_MemFree(line);
578 }
579 
585 static void DestructTextObject(textItem_t *text)
586 {
587  textLine_t *cursor, *next;
588 
589  cursor = text->firstLine;
590  while (cursor != NULL)
591  {
592  next = cursor->next;
593  DestructLine(cursor);
594  cursor = next;
595  }
596  STB_MemFree(text);
597 }
598 
606 static BOOLEAN CharIsPrintable(U16BIT uchar, int characterSet)
607 {
608  BOOLEAN print;
609  /*if we are using the HK character set*/
610  if (characterSet == 12)
611  {
612  /*if the value is higher than the highest value control character
613  it is "printable" (for now)*/
614  if (uchar > U_CTRL_US)
615  {
616  print = TRUE;
617  }
618  else
619  {
620  print = FALSE;
621  }
622  }
623  else /*UK character set*/
624  {
625  /* only allow latin characters*/
626  if (uchar > U_CTRL_US && uchar < 0x2000)
627  {
628  print = TRUE;
629  }
630  else
631  {
632  print = FALSE;
633  }
634  }
635  return print;
636 }
637 
644 static U32BIT PointsToPixels(U32BIT points, pDrawTextAttrib attribs)
645 {
646  U32BIT pixels;
647  switch (attribs->font.fp.style)
648  {
649  case FONT_STYLE_PLAIN:
650  pixels = (points * 45) / 56;
651  break;
652  case FONT_STYLE_SQUARE:
653  pixels = (points * 45) / 64;
654  break;
655  }
656  return pixels;
657 }
658 
664 static U32BIT GetLineLengthPixels(textLine_t *line)
665 {
666  U32BIT lineLengthPts;
667  U32BIT letterSpaces;
668  U32BIT charsWidth;
669  textItem_t *text;
670  U32BIT fullCharCount = line->fullCharCount;
671  U32BIT halfCharCount = line->halfCharCount;
672 
673  text = line->parentObject;
674 
675  letterSpaces = DIV(((fullCharCount + halfCharCount - 1) * text->attribs->letter_space), 255);
676 
677  charsWidth = ((fullCharCount * text->metrics->fullAdvance) + (halfCharCount * text->metrics->halfAdvance));
678 
679  lineLengthPts = charsWidth + letterSpaces + text->metrics->xOffsetLeft;
680 
681  /*test suite converts points to pixels 1:1*/
682 #if 1
683  return lineLengthPts;
684 #else
685  U32BIT lineLengthPixels;
686  lineLengthPixels = PointsToPixels(lineLengthPts, line->parentObject->attribs);
687  return lineLengthPixels;
688 #endif
689 }
690 
697 static BOOLEAN IsBreakable(U16BIT character)
698 {
699  BOOLEAN isBreakable;
700  if (character >= 0xF900 && character <= 0xFAFF)
701  isBreakable = TRUE;
702  else if (character >= 0x3190 && character <= 0x319F)
703  isBreakable = TRUE;
704  else if (character >= 0x4E00 && character <= 0x9FFF)
705  isBreakable = TRUE;
706  else if (character >= 0x3200 && character <= 0x32FF)
707  isBreakable = TRUE;
708  else
709  isBreakable = FALSE;
710  return isBreakable;
711 }
712 
719 static BOOLEAN DontBreakBefore(U16BIT character)
720 {
721  switch (character)
722  {
723  case UNICODE_QUOTE:
724  case UNICODE_RIGHT_ROUND:
725  case UNICODE_RIGHT_SQUARE:
726  case UNICODE_RIGHT_CURLY:
727  case UNICODE_RIGHT_DQUOTE:
728  case UNICODE_RIGHT_PANGLE:
729  case UNICODE_RIGHT_FULL_CURLY:
730  case UNICODE_RIGHT_FULL_ROUND:
731  case UNICODE_RIGHT_FULL_SQUARE:
732  case UNICODE_RIGHT_FULL_DROUND:
733  case UNICODE_RIGHT_FULL_DQUOTE:
734  case UNICODE_QUESTIONMARK:
735  case UNICODE_FULL_QUESTIONMARK:
736  case UNICODE_EXCLAMATIONMARK:
737  case UNICODE_FULL_STOP:
738  case UNICODE_COMMA:
739  case UNICODE_FULL_STOP_FULL:
740  case UNICODE_COMMA_FULL:
741  case UNICODE_COLON:
742  case UNICODE_SEMICOLON:
743  case UNICODE_FULL_SEMICOLON:
744  case UNICODE_HARD_SPACE:
745  case IDEOGRAPHIC_COMMA:
746  case IDEOGRAPHIC_FULL_STOP:
747  return TRUE;
748  default:
749  return FALSE;
750  }
751 }
752 
759 static BOOLEAN DontBreakAfter(U16BIT character)
760 {
761  switch (character)
762  {
763  case UNICODE_QUOTE:
764  case UNICODE_LEFT_ROUND:
765  case UNICODE_LEFT_SQUARE:
766  case UNICODE_LEFT_CURLY:
767  case UNICODE_LEFT_DQUOTE:
768  case UNICODE_LEFT_PANGLE:
769  case UNICODE_LEFT_FULL_CURLY:
770  case UNICODE_LEFT_FULL_ROUND:
771  case UNICODE_LEFT_FULL_SQUARE:
772  case UNICODE_LEFT_FULL_DROUND:
773  case UNICODE_LEFT_FULL_DQUOTE:
774  case UNICODE_HARD_SPACE:
775  case UNICODE_FIGURE_SPACE:
776  return TRUE;
777  default:
778  return FALSE;
779  }
780 }
781 
787 static void DeleteFollowingWhitespace(textLine_t *line)
788 {
789  textChar_t *cursor;
790  cursor = line->lastChar;
791  while (IS_WHITESPACE(cursor->uchar))
792  {
793  cursor = cursor->previous;
794  }
795  if (cursor->next != NULL)
796  {
797  DeleteRemainingChars(cursor->next, line);
798  }
799 }
800 
807 static void DoWrapping(textItem_t *text)
808 {
809  textLine_t *currentLine;
810  textLine_t *newLine;
811  textChar_t *cursor;
812  BOOLEAN breakFound = FALSE;
813 
814  currentLine = text->lastLine;
815 
816  /*if the character goes over the box boundary*/
817  if (GetLineLengthPixels(currentLine) > text->boxX)
818  {
819  cursor = currentLine->lastChar;
820 
821  /*special case where a whitespace char takes the line over the limit*/
822  if (IS_WHITESPACE(cursor->uchar))
823  {
824  currentLine->lastChar = cursor->previous;
825  currentLine->lastChar->next = NULL;
826  DeleteChar(cursor, currentLine);
827  if (text->lineCount < text->maxLines)
828  {
829  NewLine(text);
830  }
831  cursor = NULL;
832  }
833  /*look for a breakpoint*/
834  while (!breakFound && cursor != NULL)
835  {
836  if (IS_WHITESPACE(cursor->uchar))
837  {
838  /*break after the whitespace if possible*/
839  if (cursor->next != NULL)
840  {
841  cursor = cursor->next;
842  }
843  breakFound = TRUE;
844  }
845  /*if current char is DBB or previous char was DBA*/
846  else if (DontBreakBefore(cursor->uchar) || DontBreakAfter(cursor->previous->uchar))
847  {
848  cursor = cursor->previous;
849  }
850  /*if the current or previous character is breakable */
851  else if (IsBreakable(cursor->uchar) || IsBreakable(cursor->previous->uchar))
852  {
853  breakFound = TRUE;
854  }
855  else
856  {
857  cursor = cursor->previous;
858  }
859  }
860 
861  if (breakFound)
862  {
863  /*put the characters after the breakpoint onto a new line*/
864  newLine = NewLine(text);
865  cursor->previous->next = NULL;
866  newLine->lastChar = currentLine->lastChar;
867  currentLine->lastChar = cursor->previous;
868  newLine->firstChar = cursor;
869  newLine->firstChar->previous = NULL;
870 
871  /*go through each character moved to the new line*/
872  for (cursor = newLine->firstChar; cursor != NULL; cursor = cursor->next)
873  {
874  /*move the character count for each onto the new line*/
875  if (cursor->advanceType == FULL_ADVANCE)
876  {
877  currentLine->fullCharCount--;
878  newLine->fullCharCount++;
879  }
880  else if (cursor->advanceType == HALF_ADVANCE)
881  {
882  currentLine->halfCharCount--;
883  newLine->halfCharCount++;
884  }
885  }
886 
887  DeleteFollowingWhitespace(currentLine);
888  }
889  }
890 }
891 
899 static void AddChar(U32BIT *character, textItem_t *text, OSDColor colour)
900 {
901  textLine_t *currentLine;
902  textChar_t *newChar;
903 
904  currentLine = text->lastLine;
905 
906  newChar = NewCharacter(character);
907  if (currentLine->firstChar == NULL)
908  {
909  currentLine->firstChar = newChar;
910  }
911  newChar->previous = currentLine->lastChar;
912  if (currentLine->lastChar != NULL)
913  {
914  currentLine->lastChar->next = newChar;
915  }
916  currentLine->lastChar = newChar;
917  newChar->colour = colour;
918 
919  if (*character < 0x1fff)
920  {
921  currentLine->halfCharCount++;
922  newChar->advanceType = HALF_ADVANCE;
923  newChar->advance = text->metrics->halfAdvance;
924  }
925  else
926  {
927  currentLine->fullCharCount++;
928  newChar->advanceType = FULL_ADVANCE;
929  newChar->advance = text->metrics->fullAdvance;
930  }
931 
932  if (text->attribs->justify & WRAP_WORDS)
933  {
934  DoWrapping(text);
935  }
936 }
937 
943 static void AddCaret(textItem_t *text)
944 {
945  textLine_t *currentLine;
946  textChar_t *newChar;
947  U32BIT *character;
948  currentLine = text->lastLine;
949 
950  /* Make 'character' point at global var */
951  switch (text->attribs->caret)
952  {
953  case ENTRY_INSERT_CHAR:
954  character = (U32BIT *)&insert_caret;
955  break;
956  case ENTRY_OVERWRITE_CHAR:
957  character = (U32BIT *)&overwrite_caret;
958  break;
959  }
960 
961  newChar = NewCharacter(character);
962  if (currentLine->firstChar == NULL)
963  {
964  currentLine->firstChar = newChar;
965  }
966  newChar->previous = currentLine->lastChar;
967  if (currentLine->lastChar != NULL)
968  {
969  currentLine->lastChar->next = newChar;
970  }
971  currentLine->lastChar = newChar;
972  newChar->colour = text->attribs->fore_colour;
973 
974  if (text->attribs->entry_point == text->charsLen)
975  {
976  currentLine->halfCharCount++;
977  newChar->advanceType = HALF_ADVANCE;
978  newChar->advance = text->metrics->halfAdvance;
979  }
980  else
981  {
982  newChar->advanceType = NO_ADVANCE;
983  newChar->advance = 0;
984  }
985 
986  if (text->attribs->justify & WRAP_WORDS)
987  {
988  DoWrapping(text);
989  }
990 }
991 
998 static void GetMaxLines(textItem_t *text)
999 {
1000  S32BIT Ymin, Ymax;
1001 
1002  Ymin = 0 - text->metrics->yMin;
1003  Ymax = text->metrics->yMax;
1004  text->maxLines = ((text->boxY - (Ymax + Ymin)) / text->attribs->line_space) + 1;
1005 
1006  return;
1007 }
1008 
1014 static void FillLines(textItem_t *text)
1015 {
1016  U16BIT *currentChar;
1017  OSDColor markupColour;
1018  U16BIT high_surrogate = 0;
1019  text->firstLine = NewLine(text);
1020  text->lastLine = text->firstLine;
1021 
1022  markupColour = text->attribs->fore_colour;
1023 
1024  /*go through the string and fill up the text object*/
1025  for (currentChar = text->chars; currentChar < text->chars + (text->charsLen); currentChar++)
1026  {
1027  if (*currentChar >= HIGH_SURROGATE_START && *currentChar <= HIGH_SURROGATE_END)
1028  {
1029  high_surrogate = *currentChar;
1030  continue;
1031  }
1032 
1033  if (high_surrogate && *currentChar >= LOW_SURROGATE_START && *currentChar <= LOW_SURROGATE_END)
1034  {
1035  /*following rules found on the unicode.org FAQ*/
1036  U32BIT X, U;
1037  U32BIT unicode_character;
1038 
1039  X = (high_surrogate & 0x3F) << 10 | (*currentChar & 0x3FF);
1040  U = ((high_surrogate >> 6) & 0x1F) + 1;
1041  unicode_character = (U << 16) | X;
1042 
1043  AddChar(&unicode_character, text, markupColour);
1044 
1045  high_surrogate = 0;
1046  continue;
1047  }
1048  else if (high_surrogate)
1049  {
1050  high_surrogate = 0;
1051  continue;
1052  }
1053  /*if the current position is the entry point*/
1054  if (currentChar - text->chars == text->attribs->entry_point)
1055  {
1056  /*add the caret*/
1057  AddCaret(text);
1058  }
1059 
1060  /*On carriage return character*/
1061  if (*currentChar == UNICODE_CR)
1062  {
1063  /*create new line*/
1064  NewLine(text);
1065  }
1066  /*on markup escape character*/
1067  else if (*currentChar == UNICODE_ESC)
1068  {
1069  /*check the markup code*/
1070  currentChar++;
1071  switch (*currentChar)
1072  {
1073  case UNICODE_TEXT_COLOUR_START:
1074  currentChar++;
1075  if (*currentChar == 4)
1076  {
1077  currentChar++;
1078  markupColour = (*currentChar << 16) & 0xff0000;
1079  currentChar++;
1080  markupColour |= (*currentChar << 8) & 0xff00;
1081  currentChar++;
1082  markupColour |= *currentChar & 0xff;
1083  currentChar++;
1084  markupColour |= ((255 - *currentChar) << 24) & 0xff000000;
1085  PushColour(markupColour);
1086  }
1087  break;
1088  case UNICODE_TEXT_COLOUR_END:
1089  markupColour = PopColour();
1090  break;
1091  case UNICODE_HYPER_ATTRIB_START:
1092  currentChar = ReadHyperAttribs(currentChar, text->attribs->p_ha);
1093  break;
1094  case UNICODE_HYPER_ANCHOR_START:
1095  currentChar = AddHyperAnchor(currentChar, text->attribs->p_ha);
1096  markupColour = colourStack->colour;
1097  break;
1098  case UNICODE_HYPER_ANCHOR_END:
1099  EndHyperAnchor(currentChar, text->attribs->p_ha);
1100  markupColour = colourStack->colour;
1101  break;
1102  default:
1103  break;
1104  }
1105  }
1106  else if (CharIsPrintable(*currentChar, text->attribs->character_set))
1107  {
1108  U32BIT unicode_character = *currentChar;
1109  AddChar(&unicode_character, text, markupColour);
1110  }
1111  }
1112  if (text->attribs->entry_point == text->charsLen)
1113  {
1114  AddCaret(text);
1115  }
1116 }
1117 
1121 static void JustifyHStart(textItem_t *textObject)
1122 {
1123  textLine_t *currentLine;
1124  textChar_t *currentChar;
1125  S32BIT cursor;
1126 
1127  currentLine = textObject->firstLine;
1128  while (currentLine != NULL)
1129  {
1130  currentChar = currentLine->firstChar;
1131  cursor = textObject->metrics->xOffsetLeft;
1132 
1133  while (currentChar != NULL)
1134  {
1135  currentChar->position = cursor;
1136  if (cursor + (S32BIT)currentChar->advance > (S32BIT)textObject->boxX)
1137  {
1138  currentLine->lastChar = currentChar->previous;
1139  DeleteRemainingChars(currentChar, currentLine);
1140  currentChar = NULL;
1141  break;
1142  }
1143  else
1144  {
1145  cursor += (S32BIT)currentChar->advance;
1146  currentChar = currentChar->next;
1147  }
1148  }
1149 
1150  currentLine = currentLine->next;
1151  }
1152 }
1153 
1157 static void JustifyHCentre(textItem_t *textObject)
1158 {
1159  textLine_t *currentLine;
1160  textChar_t *currentChar;
1161  S32BIT cursor;
1162  S32BIT lineLength;
1163 
1164  currentLine = textObject->firstLine;
1165  while (currentLine != NULL)
1166  {
1167  lineLength = GetLineLengthPixels(currentLine);
1168  cursor = ((S32BIT)textObject->boxX - lineLength) / 2;
1169  currentChar = currentLine->firstChar;
1170 
1171  while (currentChar != NULL)
1172  {
1173  currentChar->position = cursor;
1174  if (cursor + (S32BIT)currentChar->advance > (S32BIT)textObject->boxX)
1175  {
1176  currentLine->lastChar = currentChar->previous;
1177  DeleteRemainingChars(currentChar, currentLine);
1178  currentChar = NULL;
1179  break;
1180  }
1181  else if (cursor < textObject->metrics->xOffsetLeft)
1182  {
1183  currentLine->firstChar = currentChar->next;
1184  cursor += (S32BIT)currentChar->advance;
1185  DeleteChar(currentChar, currentLine);
1186  currentLine->firstChar->previous = NULL;
1187 
1188  currentChar = currentLine->firstChar;
1189  }
1190  else
1191  {
1192  cursor += (S32BIT)currentChar->advance;
1193  currentChar = currentChar->next;
1194  }
1195  }
1196 
1197  currentLine = currentLine->next;
1198  }
1199 }
1200 
1204 static void JustifyHEnd(textItem_t *textObject)
1205 {
1206  textLine_t *currentLine;
1207  textChar_t *currentChar;
1208  S32BIT cursor;
1209 
1210  currentLine = textObject->lastLine;
1211  while (currentLine != NULL)
1212  {
1213  currentChar = currentLine->lastChar;
1214  cursor = textObject->boxX - (S32BIT)currentChar->advance;
1215 
1216  while (currentChar != NULL)
1217  {
1218  currentChar->position = cursor;
1219  if (cursor < textObject->metrics->xOffsetLeft)
1220  {
1221  /*clever shuffling to delete unneeded chars*/
1222  currentChar = currentChar->next;
1223  currentChar->previous->next = NULL;
1224  DeleteRemainingChars(currentLine->firstChar, currentLine);
1225  currentLine->firstChar = currentChar;
1226  currentChar->previous = NULL;
1227  break;
1228  }
1229  else
1230  {
1231  currentChar = currentChar->previous;
1232  if (currentChar != NULL)
1233  {
1234  cursor -= (S32BIT)currentChar->advance;
1235  }
1236  }
1237  }
1238 
1239  currentLine = currentLine->previous;
1240  }
1241 }
1242 
1247 static void JustifyVStart(textItem_t *textObject)
1248 {
1249  textLine_t *currentLine;
1250  textLine_t *next;
1251  U32BIT cursor;
1252  U32BIT lineCount = 0;
1253  U32BIT yMaxPixels;
1254 
1255  /*calculate positions of lines*/
1256  currentLine = textObject->firstLine;
1257 
1258  yMaxPixels = textObject->metrics->yMax;
1259 
1260  cursor = yMaxPixels;
1261 
1262  /*slight correction for difference between font size and metrics*/
1263  cursor += 2;
1264  while (currentLine != NULL)
1265  {
1266  currentLine->position = cursor;
1267  cursor += textObject->attribs->line_space;
1268  lineCount++;
1269  if (lineCount > textObject->maxLines)
1270  {
1271  break;
1272  }
1273  else
1274  {
1275  currentLine = currentLine->next;
1276  }
1277  }
1278 
1279  if (currentLine != NULL)
1280  {
1281  currentLine->previous->next = NULL;
1282  while (currentLine != NULL)
1283  {
1284  next = currentLine->next;
1285  DestructLine(currentLine);
1286  currentLine = next;
1287  }
1288  }
1289 }
1290 
1295 static void JustifyVCentre(textItem_t *textObject)
1296 {
1297  textLine_t *currentLine;
1298  U32BIT cursor;
1299  U32BIT yMaxPixels, yMinPixels;
1300  U32BIT linesHeight;
1301 
1302  /*calculate positions of lines*/
1303  currentLine = textObject->firstLine;
1304 
1305  yMaxPixels = textObject->metrics->yMax;
1306  yMinPixels = 0 - textObject->metrics->yMin;
1307 
1308  linesHeight = yMaxPixels + yMinPixels + (textObject->attribs->line_space * (textObject->lineCount - 1));
1309  cursor = (textObject->boxY - linesHeight) / 2;
1310  cursor += yMaxPixels;
1311 
1312  while (currentLine != NULL)
1313  {
1314  currentLine->position = cursor;
1315  cursor += textObject->attribs->line_space;
1316  currentLine = currentLine->next;
1317  }
1318 }
1319 
1324 static void JustifyVEnd(textItem_t *textObject)
1325 {
1326  textLine_t *currentLine;
1327  U32BIT cursor;
1328  U32BIT yMinPixels;
1329 
1330  /*calculate positions of lines*/
1331  currentLine = textObject->lastLine;
1332 
1333  yMinPixels = 0 - textObject->metrics->yMin;
1334 
1335  cursor = textObject->boxY - yMinPixels;
1336 
1337  /*slight correction for difference between font size and metrics*/
1338  cursor -= 2;
1339 
1340  while (currentLine != NULL)
1341  {
1342  currentLine->position = cursor;
1343  cursor -= textObject->attribs->line_space;
1344  currentLine = currentLine->previous;
1345  }
1346 }
1347 
1353 static BOOLEAN CreateSurface(textItem_t *textObject)
1354 {
1355  BOOLEAN success = FALSE;
1356 
1357  textObject->canvas = STB_MemAlloc(sizeof(S_SURFACE));
1358  if (textObject->canvas != NULL)
1359  {
1360  IF_COL_DEPTH(COLOUR_FORMAT_ARGB4444)
1361  {
1362  textObject->canvas->hw_handle = STB_OSDMhegCreateSurface(textObject->boxX,
1363  textObject->boxY,
1364  TRUE,
1365  MakeHD2Color(textObject->attribs->back_colour));
1366  }
1367  ELSE IF_COL_DEPTH(COLOUR_FORMAT_ARGB8888)
1368  {
1369  textObject->canvas->hw_handle = STB_OSDMhegCreateSurface(textObject->boxX,
1370  textObject->boxY,
1371  TRUE,
1372  textObject->attribs->back_colour);
1373  }
1374 
1375  if (textObject->canvas->hw_handle != NULL)
1376  {
1377  textObject->canvas->width = textObject->boxX;
1378  textObject->canvas->height = textObject->boxY;
1379  success = TRUE;
1380  }
1381  }
1382 
1383  return success;
1384 }
1385 
1393 static void BlendColours32(OSDColor *pixel, U32BIT fore_value, OSDColor fore_col)
1394 {
1395  U32BIT fa, ba, comp, tmp_c, alpha_c;
1396  ba = *pixel >> 24;
1397 
1398  FactorForeAlpha(fore_value, fore_col);
1399 
1400  alpha_c = ((((255 ^ ba) * fore_value) + 32512) / 65025) + ba;
1401  fa = (U8BIT)(fore_value / SRC_FORE_MAX);
1402  ba = (((255 ^ fa) * ba) + 127) / 255;
1403  tmp_c = alpha_c << 24;
1404  comp = ba * ((*pixel >> 16) & 0xff) + fa * ((fore_col >> 16) & 0xff);
1405  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 16;
1406  comp = ba * ((*pixel >> 8) & 0xff) + fa * ((fore_col >> 8) & 0xff);
1407  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 8;
1408  comp = ba * (*pixel & 0xff) + fa * (fore_col & 0xff);
1409  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c);
1410  *pixel = tmp_c;
1411 }
1412 
1420 static void BlendColours16(HD2Color *pixel, U32BIT fore_value, OSDColor fore_col )
1421 {
1422  U32BIT fa, ba, comp, tmp_c, alpha_c;
1423  HD2Color temp_col = MakeHD2Color(fore_col);
1424 
1425  FactorForeAlpha(fore_value, fore_col);
1426  ba = *pixel >> 12;
1427  comp = ba * 17;
1428  alpha_c = ((((15 - ba) * fore_value) + 1912) / 3825) + comp;
1429  fa = (U8BIT)(fore_value / SRC_FORE_MAX);
1430  ba = (((255 ^ fa) * comp) + 127) / 255;
1431  tmp_c = (alpha_c / 17) << 12;
1432  comp = ba * ((*pixel >> 8) & 0xf) + fa * ((temp_col >> 8) & 0xf);
1433  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 8;
1434  comp = ba * ((*pixel >> 4) & 0xf) + fa * ((temp_col >> 4) & 0xf);
1435  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 4;
1436  comp = ba * (*pixel & 0xf) + fa * (temp_col & 0xf);
1437  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c);
1438  *pixel = tmp_c;
1439 }
1440 
1449 static void RenderChar(FT_GlyphSlot glyph, textLine_t *line, textChar_t *charObject)
1450 {
1451  S_SURFACE *canvas;
1452  U32BIT glyphHeight;
1453  U32BIT row_count;
1454  U32BIT a_point;
1455  U8BIT *src_buffer, *dest_buffer;
1456  S32BIT penX, penY;
1457  OSDColor fore_colour;
1458  U32BIT fore_value;
1459  U8BIT *src_pixel;
1460  OSDColor *dest_pixel;
1461 
1462  canvas = line->parentObject->canvas;
1463 
1464  glyphHeight = glyph->bitmap.rows;
1465 
1466  penX = charObject->position + glyph->bitmap_left;
1467  penY = line->position - glyph->bitmap_top;
1468 
1469  src_buffer = (U8BIT *)glyph->bitmap.buffer;
1470  dest_buffer = (U8BIT *)canvas->col_buff;
1471 
1472  fore_colour = charObject->colour;
1473  if (NotOpaqueTDColor( fore_colour ))
1474  {
1475  canvas->opaque = FALSE;
1476  }
1477  for (row_count = 0; row_count != glyphHeight && penY < canvas->height; row_count++)
1478  {
1479  if (penY < 0)
1480  {
1481  penY++;
1482  continue;
1483  }
1484 
1485  for (a_point = 0; a_point != glyph->bitmap.width && penX < canvas->width; a_point++)
1486  {
1487  if (penX < 0)
1488  {
1489  penX++;
1490  continue;
1491  }
1492  src_pixel = &src_buffer[(row_count * glyph->bitmap.pitch) + a_point];
1493  IF_COL_DEPTH(COLOUR_FORMAT_ARGB4444)
1494  {
1495  dest_pixel = (OSDColor *)&dest_buffer[((penY * canvas->buff_pitch / 2) + (penX)) * 2];
1496  fore_value = *src_pixel;
1497  if (*src_pixel > 0)
1498  {
1499  BlendColours16((HD2Color *)dest_pixel, fore_value, fore_colour );
1500  }
1501  }
1502  ELSE IF_COL_DEPTH(COLOUR_FORMAT_ARGB8888)
1503  {
1504  dest_pixel = (OSDColor *)&dest_buffer[((penY * canvas->buff_pitch / 4) + (penX)) * 4];
1505  fore_value = *src_pixel;
1506  if (*src_pixel > 0)
1507  {
1508  BlendColours32( dest_pixel, fore_value, fore_colour );
1509  }
1510  }
1511 
1512  penX++;
1513  }
1514  penX = charObject->position + glyph->bitmap_left;
1515  penY++;
1516  }
1517 }
1518 
1524 static BOOLEAN Render(textItem_t *textObject)
1525 {
1526  BOOLEAN success;
1527  textLine_t *currentLine;
1528  textChar_t *currentChar;
1529  S_SURFACE *canvas;
1530  FT_Error err;
1531  U32BIT fontWidth;
1532  U32BIT fontHeight;
1533 
1534  fontWidth = PointsToPixels(textObject->attribs->font.fp.size, textObject->attribs);
1535  fontHeight = textObject->attribs->font.fp.size;
1536 
1537  fontWidth = (fontWidth * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div;
1538  fontHeight = (fontHeight * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div;
1539 
1540  success = CreateSurface(textObject);
1541  if (success)
1542  {
1543  canvas = textObject->canvas;
1544  canvas->buff_pitch = textObject->boxX * 4;
1545  canvas->col_buff = STB_OSDMhegLockBuffer( canvas->hw_handle, &canvas->buff_pitch );
1546 
1547  FT_Set_Pixel_Sizes(font->face, fontWidth, fontHeight);
1548  }
1549  currentLine = textObject->firstLine;
1550 
1551  while (currentLine != NULL && success)
1552  {
1553  currentChar = currentLine->firstChar;
1554 
1555  while (currentChar != NULL && success)
1556  {
1557  /*load the required glyph from the font*/
1558  err = FT_Load_Char( font->face, currentChar->uchar, FT_LOAD_RENDER );
1559  if (!err)
1560  {
1561  RenderChar(font->face->glyph, currentLine, currentChar);
1562  }
1563  else
1564  {
1565  success = FALSE;
1566  }
1567  currentChar = currentChar->next;
1568  }
1569  currentLine = currentLine->next;
1570  }
1571  STB_OSDMhegUnlockBuffer( canvas->hw_handle);
1572  return success;
1573 }
1574 
1580 static fontLibrary_t* InitFreetype(pDrawTextAttrib attrib)
1581 {
1582  fontLibrary_t *newFontLibrary;
1583  FT_Error ftErr;
1584  E_MhegErr mhErr = MHERR_INTERNAL;
1585  S_FontData *fontFileData;
1586 
1587  newFontLibrary = STB_MemAlloc(sizeof(fontLibrary_t));
1588  if (newFontLibrary != NULL)
1589  {
1590  ftErr = FT_Init_FreeType( &newFontLibrary->library );
1591 
1592  if (ftErr)
1593  {
1594  STB_MemFree(newFontLibrary);
1595  newFontLibrary = NULL;
1596  }
1597  else
1598  {
1599  mhErr = DVB_MhegGetEmbeddedFont(attrib->font_name.zptr, &fontFileData);
1600  }
1601 
1602  if (mhErr == MHERR_OK && fontFileData != NULL)
1603  {
1604  if (fontFileData->dataType == MHEG5_FONT_FILE_PATH_TTF)
1605  {
1606  ftErr = FT_New_Face( newFontLibrary->library, (char *)fontFileData->data, 0, &newFontLibrary->face );
1607  }
1608  else if (fontFileData->dataType == MHEG5_RAW_FONT_DATA_TTF)
1609  {
1610  ftErr = FT_New_Memory_Face( newFontLibrary->library,
1611  (FT_Byte *)fontFileData->data,
1612  (FT_Long)fontFileData->dataLength,
1613  0,
1614  &newFontLibrary->face );
1615  }
1616  }
1617  else
1618  {
1619  STB_MemFree(newFontLibrary);
1620  newFontLibrary = NULL;
1621  }
1622 
1623  if (ftErr)
1624  {
1625  STB_MemFree(newFontLibrary);
1626  newFontLibrary = NULL;
1627  }
1628  }
1629  return newFontLibrary;
1630 }
1631 
1639 static textItem_t* InitText(const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box)
1640 {
1641  textItem_t *newItem;
1642 
1643  newItem = STB_MemAlloc(sizeof(textItem_t));
1644  if (newItem != NULL)
1645  {
1646  switch (attrib->font.fp.size)
1647  {
1648  case 24:
1649  newItem->metrics = &metrics24Point;
1650  break;
1651  case 26:
1652  newItem->metrics = &metrics26Point;
1653  break;
1654  case 31:
1655  newItem->metrics = &metrics31Point;
1656  break;
1657  case 36:
1658  newItem->metrics = &metrics36Point;
1659  break;
1660  default:
1661  STB_MemFree(newItem);
1662  newItem = NULL;
1663  }
1664  }
1665  if (newItem != NULL)
1666  {
1667  newItem->firstLine = NULL;
1668  newItem->lastLine = NULL;
1669  newItem->lineCount = 0;
1670  newItem->chars = unistr.data;
1671  newItem->charsLen = unistr.len;
1672  newItem->attribs = attrib;
1673  newItem->boxX = txt_box.width;
1674  newItem->boxY = txt_box.height;
1675  /*set horizontal justification function*/
1676  switch (attrib->justify & JFY_HZ_MASK)
1677  {
1678  case JUSTIFY_H_START:
1679  case JUSTIFY_H_JUSTIFIED:
1680  newItem->hJustify = JustifyHStart;
1681  break;
1682  case JUSTIFY_H_END:
1683  newItem->hJustify = JustifyHEnd;
1684  break;
1685  case JUSTIFY_H_CENTRE:
1686  newItem->hJustify = JustifyHCentre;
1687  break;
1688  default:
1689  break;
1690  }
1691 
1692  switch (attrib->justify & JUSTIFY_VERTI_MASK)
1693  {
1694  case JUSTIFY_V_START:
1695  case JUSTIFY_V_JUSTIFIED:
1696  newItem->vJustify = JustifyVStart;
1697  break;
1698  case JUSTIFY_V_END:
1699  newItem->vJustify = JustifyVEnd;
1700  break;
1701  case JUSTIFY_V_CENTRE:
1702  newItem->vJustify = JustifyVCentre;
1703  break;
1704  default:
1705  break;
1706  }
1707  }
1708  return newItem;
1709 }
1710 
1719 void* MG_DrawHKText(const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box)
1720 {
1721  textItem_t *textObject;
1722  S_SURFACE *renderedSurface = NULL;
1723  BOOLEAN success = FALSE;
1724 
1725  textObject = InitText(unistr, attrib, txt_box);
1726  if (font == NULL)
1727  {
1728  font = InitFreetype(attrib);
1729  }
1730 
1731  if (font == NULL)
1732  {
1733  return NULL;
1734  }
1735 
1736  GetMaxLines(textObject);
1737 
1738  InitColourStack(attrib->fore_colour);
1739  if (textObject != NULL)
1740  {
1741  FillLines(textObject);
1742  success = TRUE;
1743  }
1744  DestructColourStack();
1745 
1746  if (textObject != NULL && textObject->hJustify != NULL)
1747  {
1748  textObject->hJustify(textObject);
1749  }
1750  else
1751  {
1752  success = FALSE;
1753  }
1754 
1755  if (textObject != NULL && textObject->vJustify != NULL)
1756  {
1757  textObject->vJustify(textObject);
1758  }
1759  else
1760  {
1761  success = FALSE;
1762  }
1763  #if 0
1764  {
1765  textLine_t *line;
1766  textChar_t *character;
1767 
1768  DBG_PRINTF("debugging lines, justify = %x\n", attrib->justify);
1769  line = textObject->firstLine;
1770  while (line)
1771  {
1772  character = line->firstChar;
1773  while (character)
1774  {
1775  DBG_PRINTF("%x ", *character->uchar);
1776  character = character->next;
1777  }
1778  DBG_PRINTF("\n");
1779  line = line->next;
1780  }
1781  }
1782  #endif
1783 
1784  if (success)
1785  {
1786  ScaleAllToHD(textObject);
1787  success = Render(textObject);
1788  }
1789 
1790  if (success)
1791  {
1792  renderedSurface = textObject->canvas;
1793  }
1794  if (textObject != NULL)
1795  {
1796  DestructTextObject(textObject);
1797  }
1798 
1799  return renderedSurface;
1800 }
1801 
1802 #endif
OSD utility functions.
E_MhegErr DVB_MhegGetEmbeddedFont(const U8BIT *fontName, S_FontData **fontData)
Retrieves the specified embedded font. Depending on the requirements of the platform, it may either pass back:
void STB_MemFree(void *ptr)
Releases previously allocated memory.
Debug tracing.
void * STB_OSDMhegCreateSurface(U16BIT width, U16BIT height, BOOLEAN init, U32BIT colour)
Creates a hardware surface on which MHEG5 engine will draw an individual MHEG object. At its basic the function can just allocate the buffer to be returned by STB_OSDMhegLockBuffer(). It&#39;s size being: (width * height * bytes_per_pixel) Also, when &#39;init&#39; is TRUE, function initialises surface buffer to the specified colour. For pixel colour format of less than four bytes, use least significant bits of &#39;colour&#39;.
Memory functions.
void * STB_MemAlloc(U32BIT memSize)
Allocates the specified number of bytes.
Interface to OSD.
Font loading functions required by MHEG5 engine (Hong Kong profile)
void * STB_OSDMhegLockBuffer(void *surface, U32BIT *pPitch)
Converts hardware surface handle returned by STB_OSDMhegCreateSurface() to buffer address that the en...
Interface to the MHEG text render that uses Freetype font library.
Interface to OSD.
Interface to the MHEG text render that uses Freetype font library.
Graphics functions required by the HD MHEG5 engine. All references to colour used in these functions ...
void STB_OSDMhegUnlockBuffer(void *surface)
This function informs HW that MHEG5 is finished writing to the buffer.