MHEG5  18.9.0
MHEG5 Documentation
mg_drawtext.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2008 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  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "stb_osd.h"
30 #include "mg_font.h"
31 
32 #include "mg_drawtext.h"
33 #include "glue_memory.h"
34 #include "glue_debug.h"
35 #include "mg_osd.h"
36 #include "osd_utils.h" /* for RGBT() */
37 #include "glue_assert.h"
38 #include "glue_debug.h" /* for TRACE */
39 
40 #ifdef HK_PROFILE
41 #include "mg_hkfont.h"
42 #endif
43 
44 /*---constant definitions for this file--------------------------------------*/
45 
46 #define COLOUR_STACK_SIZE 18
47 
48 #ifdef OSD_8_BIT
49  #define TRANSPARENT_COLOUR OFFSET_TRANS
50 #else
51  #define TRANSPARENT_COLOUR 0
52 #endif
53 
54 /* Unicode control characters: non-printable */
55 #define U_CTRL_NULL 0x00
56 #define U_CTRL_A 0x01
57 #define U_CTRL_B 0x02
58 #define U_CTRL_C 0x03
59 #define U_CTRL_D 0x04
60 #define U_CTRL_E 0x05
61 #define U_CTRL_F 0x06
62 #define U_CTRL_G 0x07
63 #define U_CTRL_H 0x08
64 #define U_CTRL_K 0x0B
65 #define U_CTRL_L 0x0C
66 #define U_CTRL_N 0x0E
67 #define U_CTRL_O 0x0F
68 #define U_CTRL_P 0x10
69 #define U_CTRL_Q 0x11
70 #define U_CTRL_R 0x12
71 #define U_CTRL_S 0x13
72 #define U_CTRL_T 0x14
73 #define U_CTRL_U 0x15
74 #define U_CTRL_V 0x16
75 #define U_CTRL_W 0x17
76 #define U_CTRL_X 0x18
77 #define U_CTRL_Y 0x19
78 #define U_CTRL_Z 0x1A
79 #define U_CTRL_FS 0x1C
80 #define U_CTRL_GS 0x1D
81 #define U_CTRL_RS 0x1E
82 #define U_CTRL_US 0x1F
83 
84 /* Unicode character values */
85 #define UNICODE_SPACE (' ')
86 #define UNICODE_TAB ('\t')
87 #define UNICODE_LF (0x0a)
88 #define UNICODE_CR (0x0d)
89 #define UNICODE_ESC (0x1b)
90 #define UNICODE_HARD_SPACE (0xa0)
91 #define UNICODE_FIGURE_SPACE (0x2007)
92 #define UNICODE_APOSTROPHE_N (0x0149)
93 #define UNICODE_HYPER_ANCHOR_START (0x41)
94 #define UNICODE_HYPER_ANCHOR_END (0x61)
95 #define UNICODE_TEXT_COLOUR_START (0x43)
96 #define UNICODE_TEXT_COLOUR_END (0x63)
97 #define UNICODE_HYPER_ATTRIB_START (0x44)
98 #define UNICODE_HYPER_ATTRIB_END (0x64)
99 
100 
101 /**** this ONLY work for ascii chars '!' - '~' (i.e. cached chars)
102  **** in the Tiresias font files ***/
103 #define GLYPH_NDX(x) (x - 30)
104 /****/
105 
106 #define MAX_NUM_LINES 32
107 #define MAX_NUM_CHARS 64
108 
109 #define PNTS_LS_LEN(tls) ((tls + 255) >> 8)
110 #define MTRC_POSN(mll, tls, mr, fsz) mll + (PNTS_LS_LEN(tls) * mr) / fsz
111 
112 /* conversion calculations for local copy of S_PROPERTIES */
113 /* letter spaces plus width of chars - in metric units */
114 #define S_METRIC_POSITION(pp) MTRC_POSN(pp.metric_line_length, pp.total_letter_space, pp.metric_resn, pp.pnts_font_size)
115 /* letter spaces plus width of chars - in points */
116 #define S_POINTS_POSITION(pp) PNTS_LS_LEN(pp.total_letter_space) + ((pp.metric_line_length * pp.pnts_font_size + pp.metric_resn - 1) / pp.metric_resn)
117 /* letter spaces plus width of chars - in SD pixels */
118 #define S_SPIXEL_POSITION(pp) (((((S_POINTS_POSITION(pp)) * 45) + pp.pixel_par_x - 1) / pp.pixel_par_x) + pp.spxl_tab_start)
119 
120 /* conversion calculations for pointer to S_PROPERTIES */
121 /*convert to SD pixels*/
122 #define P_PNTS_2_SPXL(pp, pts) ((((pts) * 45) + pp->pixel_par_x - 1) / pp->pixel_par_x)
123 #define P_MTRC_2_PNTS(pp, mtr) ((mtr) * pp->pnts_font_size + pp->metric_resn - 1) / pp->metric_resn
124 #define P_MTRC_2_SPXL(pp, mtr) P_PNTS_2_SPXL(pp, P_MTRC_2_PNTS(pp, mtr))
125 /* letter spaces plus width of chars - in metric units */
126 #define P_METRIC_POSITION(pp) MTRC_POSN(pp->metric_line_length, pp->total_letter_space, pp->metric_resn, pp->pnts_font_size)
127 /* letter spaces plus width of chars - in points */
128 #define P_POINTS_POSITION(pp) PNTS_LS_LEN(pp->total_letter_space) + ((pp->metric_line_length * pp->pnts_font_size + pp->metric_resn - 1) / pp->metric_resn)
129 /* letter spaces plus width of chars - in SD pixels */
130 #define P_SPIXEL_POSITION(pp) (((((P_POINTS_POSITION(pp)) * 45) + pp->pixel_par_x - 1) / pp->pixel_par_x) + pp->spxl_tab_start)
131 
132 
133 /*---local typedef structs for this file-------------------------------------*/
134 
135 typedef struct _LineLimit
136 {
142 } LineLimit;
143 
144 typedef struct _CharData
145 {
152  #ifdef TRACE
153  S16BIT spxl_end;
154  #endif
156 } CharData;
157 
158 typedef enum
159 {
165 } EBreakState;
166 
167 typedef struct s_properties
168 {
169  S32BIT hpxl_last_tab,
170  hpxl_pen_posn,
171  hpxl_line_end,
172  metric_resn,
173  metric_line_length,
174  spxl_tab_start,
175  pnts_tab_start,
176  hpxl_letter_offset,
178  break_letter_space,
179  metric_break_length,
180  pnts_font_size,
181  pixel_par_x,
182  m_to_pix_mlt,
183  m_to_pix_div;
185  FT_UInt glyph_index,
186  glyph_last;
189  //EBreakState break_state;
190  //CharData* char_data;
192  hpxl_box_width;
194  S8BIT char_adv,
195  char_left;
197 } S_PROPERTIES;
198 
199 /*---local (static) variable declarations for this file----------------------*/
200 
201 /*---local function definitions----------------------------------------------*/
202 
203 #ifdef TRACING
204 
208 static void traceLine( LineLimit *pLine, CharData *chars, U32BIT f_size, U32BIT m_res )
209 {
210  char str[80];
211  CharData *p_chr;
212  U32BIT mposn, sposn;
213  U16BIT nx;
214  char *pch;
215 
216  for (nx = pLine->start_ndx, pch = str; nx != pLine->end_ndx && pch != str + 79; nx++, pch++)
217  {
218  *pch = (char)chars[nx].uni_chr;
219  }
220  *pch = 0;
221  DBG_PRINTF( "Line %d: start=%ld width=%d start=%d end=%d F-Size=%d M-Res=%d\n",
222  pLine->line_num, pLine->position, pLine->l_width, pLine->start_ndx, pLine->end_ndx, f_size, m_res );
223  DBG_PRINTF( "%s\n", str);
224  nx = pLine->start_ndx;
225  p_chr = chars + nx;
226  while (nx != pLine->end_ndx)
227  {
228  //tmp = (p_chr->spxl_end * 45 * mg_ctxt.screen_x_factor) / (mg_ctxt.normal_x_factor * 56);
229  mposn = p_chr->mtrc_position + p_chr->mtrc_advance;
230  sposn = ((mposn * f_size) + m_res - 1) / m_res;
231  sposn = ((sposn * 45) + 55) / 56; // assuming plain text
232  DBG_PRINTF( "(%c,%ld,%d,%d,%d) ", p_chr->uni_chr, p_chr->real_position - pLine->position, p_chr->width, mposn, sposn);
233  nx++;
234  p_chr++;
235  }
236  DBG_PRINTF( "\n");
237 }
238 
243 static void trace_lines( U16BIT total, LineLimit *lines, CharData *chars, U32BIT f_size, U32BIT m_res )
244 {
245  U16BIT line_num = 0;
246  while (line_num != total)
247  {
248  if (line_num == lines->line_num)
249  {
250  traceLine( lines, chars, f_size, m_res );
251  lines++;
252  }
253  line_num++;
254  }
255 }
256 
257 #endif /*TRACING*/
258 
267 static U16BIT ProcessMarkup( U16BIT *data, OSDColor *cStack, U8BIT *cCount, pHyperAttribs ha )
268 {
269  U16BIT mu_length = 0;
270  if ((*data <= 0x5e) && (*data >= 0x40))
271  {
272  mu_length = data[1] + 1; /* add 1 for the 'length' byte itself */
273  }
274  switch (*data)
275  {
277  if ((ha != NULL) && (*cCount < COLOUR_STACK_SIZE))
278  {
279  ha->number_of_links++;
280  if (ha->markup_state == 0)
281  {
282  ha->markup_state = 2;
283  }
284  else
285  {
286  ha->markup_state++;
287  }
288  ha->save_colour = *cCount;
289  (*cCount)++;
290  /*Note: focus_position should be zero when not interacting so no need for testing (ha->interacting)*/
291  if (ha->focus_position == ha->number_of_links)
292  {
293  cStack[*cCount] = ha->active_colour;
294  }
295  else
296  {
297  cStack[*cCount] = ha->link_colour;
298  }
299  }
300  break;
301 
303  if ((mu_length == 5) && (*cCount < COLOUR_STACK_SIZE))
304  {
305  /* correct length byte, so extract the new text colour from the markup */
306  cStack[++(*cCount)] = RGBT( data[2], data[3], data[4], data[5] );
307  }
308  break;
309 
311  if ((ha != NULL) && (mu_length > 1) && (ha->markup_state == 0))
312  {
313  U16BIT mu_lft = mu_length - 2;
314  U16BIT mu_ind = data[2];
315  if (mu_ind & 0x08)
316  {
317  ha->anchor_wrap = TRUE;
318  }
319  else
320  {
321  ha->anchor_wrap = FALSE;
322  }
323  data += 3;
324  if ((mu_ind & 0x40) && (mu_lft > 3))
325  {
326  ha->link_colour = RGBT( data[0], data[1], data[2], data[3] );
327  data += 4;
328  mu_lft -= 4;
329  }
330  if ((mu_ind & 0x20) && (mu_lft > 3))
331  {
332  ha->active_colour = RGBT( data[0], data[1], data[2], data[3] );
333  data += 4;
334  mu_lft -= 4;
335  }
336  if ((mu_ind & 0x10) && (mu_lft > 3))
337  {
338  ha->visit_colour = RGBT( data[0], data[1], data[2], data[3] );
339  }
340  }
341  break;
342 
344  if ((ha != NULL) && (ha->markup_state > 1))
345  {
346  ha->markup_state--;
347  *cCount = ha->save_colour;
348  }
349  break;
350 
352  if ((ha != NULL) && (ha->markup_state > 1))
353  {
354  if (ha->save_colour)
355  ha->save_colour--;
356  }
357  else
358  {
359  if (*cCount > 0)
360  (*cCount)--;
361  }
362  break;
363 
365  default:
366  break;
367  }
368  if ((ha != NULL) && (ha->markup_state == 0))
369  {
370  ha->markup_state = 1;
371  }
372  return mu_length;
373 }
374 
380 static void doExtraKernHD( S_PROPERTIES *pp )
381 {
382  U32BIT fsz = pp->pnts_font_size;
383  switch (pp->glyph_last)
384  {
385  case GLYPH_NDX('f'):
386  if (pp->glyph_index == GLYPH_NDX('t'))
387  {
388  /* Otherwise f and t touch in HD */
389  pp->hpxl_pen_posn++;
390  if (fsz == 36)
391  {
392  pp->hpxl_pen_posn++;
393  }
394  }
395  break;
396 
397  default:;
398  }
399 }
400 
406 static void doExtraKernSD( S_PROPERTIES *pp )
407 {
408  U32BIT fsz = pp->pnts_font_size;
409  switch (pp->glyph_last)
410  {
411  case GLYPH_NDX('a'):
412  switch (pp->glyph_index)
413  {
414  case GLYPH_NDX('f'):
415  /*any screen, test 5.5.9 for "waft"*/
416  pp->hpxl_pen_posn--;
417  break;
418 
419  case GLYPH_NDX('r'):
420  if (fsz == 26)
421  {
422  /*any screen, test 3.12.8 for "mark"*/
423  pp->hpxl_pen_posn--;
424  }
425  default:;
426  }
427  break;
428 
429  case GLYPH_NDX('d'):
430  if (pp->glyph_index == GLYPH_NDX('e'))
431  {
432  /*any screen, test 3.12.7 for "BitmapDecodeOffset test:"*/
433  pp->hpxl_pen_posn--;
434  }
435  break;
436 
437  case GLYPH_NDX('e'):
438  switch (pp->glyph_index)
439  {
440  case GLYPH_NDX('f'):
441  /* SD screen: otherwise test ISO 03 T69 scene 10 'refer' loses 'r' */
442  pp->hpxl_pen_posn -= 2;
443  break;
444  case GLYPH_NDX('l'):
445  /*any screen, test 5.5.9 for "rely"*/
446  pp->hpxl_pen_posn--;
447  break;
448  case GLYPH_NDX('t'):
449  /* just coz SD screen had some over-long words */
450  pp->hpxl_pen_posn--;
451  break;
452  default:;
453  }
454  break;
455 
456  case GLYPH_NDX('f'):
457  if (pp->glyph_index == GLYPH_NDX('t'))
458  {
459  /* Otherwise f and t touch in SD */
460  pp->hpxl_pen_posn++;
461  if (fsz == 36)
462  {
463  pp->hpxl_pen_posn++;
464  }
465  }
466  else if ((pp->glyph_index == GLYPH_NDX('i')) ||
467  (pp->glyph_index == GLYPH_NDX('l')))
468  {
469  if (fsz == 24)
470  {
471  /* Otherwise f and (i or l) touch in SD */
472  pp->hpxl_pen_posn++;
473  }
474  }
475  break;
476 
477  case GLYPH_NDX('i'):
478  if ((pp->glyph_index == GLYPH_NDX('f')) ||
479  (pp->glyph_index == GLYPH_NDX('t'))
480  )
481  {
482  if (fsz == 24)
483  {
484  pp->hpxl_pen_posn--;
485  }
486  }
487  break;
488 
489  case GLYPH_NDX('n'):
490  if (pp->glyph_index == GLYPH_NDX('k'))
491  {
492  /*any screen, in test 5.5.9 for "junk"*/
493  pp->hpxl_pen_posn--;
494  }
495  break;
496 
497  case GLYPH_NDX('o'):
498  switch (pp->glyph_index)
499  {
500  case GLYPH_NDX('c'):
501  /*any screen, test 5.5.6.2 for "octal"*/
502  pp->hpxl_pen_posn--;
503  break;
504 
505  case GLYPH_NDX('f'):
506  /*any screen, coz it looks beter */
507  pp->hpxl_pen_posn--;
508  break;
509  case GLYPH_NDX('m'):
510  /*SD screen, test 5.5.9 for "room" */
511  pp->hpxl_pen_posn--;
512  break;
513  default:;
514  }
515  break;
516 
517  case GLYPH_NDX('p'):
518  if (pp->glyph_index == GLYPH_NDX('D'))
519  {
520  /*SD screen, test 3.12.7 for "BitmapDecodeOffset test:"*/
521  pp->hpxl_pen_posn--;
522  }
523  break;
524 
525  case GLYPH_NDX('r'):
526  switch (pp->glyph_index)
527  {
528  case GLYPH_NDX('e'):
529  /* SD screen: otherwise test ISO 03 T69 scene 10 'refer' loses 'r' */
530  pp->hpxl_pen_posn--;
531  break;
532  case GLYPH_NDX('s'):
533  /* otherwise gap too big */
534  pp->hpxl_pen_posn--;
535  break;
536  default:;
537  }
538  break;
539 
540  case GLYPH_NDX('s'):
541  if (pp->glyph_index == GLYPH_NDX('t'))
542  {
543  /*SD screen, test 3.12.7 for "BitmapDecodeOffset test:"*/
544  pp->hpxl_pen_posn--;
545  }
546  break;
547 
548  case GLYPH_NDX('u'):
549  if (pp->glyph_index == GLYPH_NDX('n'))
550  {
551  /*any screen, in test 5.5.9 for "junk"*/
552  pp->hpxl_pen_posn--;
553  }
554  break;
555 
556  case GLYPH_NDX('w'):
557  if (pp->glyph_index == GLYPH_NDX('a') && (fsz == 31))
558  {
559  /*any screen, test 5.5.9 for "waft"*/
560  pp->hpxl_pen_posn--;
561  }
562  break;
563 
564  case GLYPH_NDX('t'):
565  case GLYPH_NDX('T'):
566  if (pp->glyph_index == GLYPH_NDX('h'))
567  {
568  if (fsz == 24)
569  {
570  pp->hpxl_pen_posn++;
571  }
572  }
573  break;
574 
575  default:;
576  } /*hctiws*/
577 }
578 
579 static void AddLetterSpace(S_PROPERTIES *pp, S32BIT tls)
580 {
581  pp->total_letter_space += tls;
582  if (pp->total_letter_space > 0)
583  {
584  tls = ((pp->m_to_pix_mlt * pp->total_letter_space) + (pp->m_to_pix_div - 1)) / pp->m_to_pix_div;
585  /* according to UK profile sec 5.5.5.2, must do round up for the divide by 256 */
586  tls = (tls + 255) / 256;
587  }
588  else
589  {
590  tls = ((pp->m_to_pix_mlt * pp->total_letter_space) - (pp->m_to_pix_div - 1)) / pp->m_to_pix_div;
591  tls = (tls - 255) / 256;
592  }
593  if (pp->hpxl_letter_offset != tls)
594  {
595  pp->hpxl_pen_posn += tls - pp->hpxl_letter_offset;
596  pp->hpxl_letter_offset = tls;
597  }
598 }
599 
605 static void DoTheKerning( pDrawTextAttrib attrib, S_FontDetails *ftd_ptr, S_PROPERTIES *pp )
606 {
607  FT_Vector kerning;
608 
609  if (pp->glyph_last && attrib->letter_space)
610  {
611  AddLetterSpace(pp,attrib->letter_space);
612  }
613 
614  if (ftd_ptr->face_type == FTYPE_PFR)
615  {
616  if (FT_Get_PFR_Kerning(ftd_ptr->face, pp->glyph_last, pp->glyph_index, &kerning) == 0 &&
617  kerning.x != 0)
618  {
619  pp->metric_line_length += kerning.x;
620  kerning.x *= pp->m_to_pix_mlt * pp->pnts_font_size;
621  kerning.y = ftd_ptr->metric_resolution * pp->m_to_pix_div;
622  if (kerning.x < 0)
623  {
624  kerning.x -= kerning.y >> 1;
625  }
626  else
627  {
628  kerning.x += kerning.y >> 2;
629  }
630  pp->hpxl_pen_posn += kerning.x / kerning.y;
631  }
632  }
633  else if (pp->glyph_last != 0)
634  {
635  if (pp->glyph_last != ftd_ptr->glyph_ndx_space)
636  {
637  if (FT_Get_Kerning(ftd_ptr->face, pp->glyph_last, pp->glyph_index, FT_KERNING_UNSCALED, &kerning) == 0)
638  {
639  /* kerning.x in original font units */
640  if (kerning.x != 0)
641  {
642  pp->metric_line_length += kerning.x;
643  kerning.x *= pp->m_to_pix_mlt * pp->pnts_font_size;
644  kerning.y = ftd_ptr->metric_resolution * pp->m_to_pix_div;
645  if (kerning.x < 0)
646  {
647  kerning.x -= kerning.y >> 1;
648  }
649  else
650  {
651  kerning.x += kerning.y >> 2;
652  }
653  pp->hpxl_pen_posn += kerning.x / kerning.y;
654  }
655  }
656  }
657  }
658  /* extra kerning here, to ensure we pass DTG tests
659  * without making the font smaller than it should be */
660  if (pp->font_style == 0 && /* PLAIN */
661  pp->font_index == BUILT_IN_FONT) /* UK Profile: tiresias font */
662  {
663  if (mg_hd_mode == NORMAL_SD)
664  doExtraKernSD( pp );
665  else
666  doExtraKernHD( pp );
667  }
668  pp->glyph_last = pp->glyph_index;
669 }
670 
676 static BOOLEAN LoadPrintableChar( S_FontDetails *ftd_ptr, S_FontSize *f_sz_data,
677  S_PROPERTIES *pp, U16BIT u_chr, CharData *char_data )
678 {
679  FT_Face the_face = ftd_ptr->face;
680  FT_Int32 load_flags;
681 
682  /* First check that FT is using the right font size */
683  if (ftd_ptr->current_fnt_id != f_sz_data->fnt_id)
684  {
685  if (FT_Set_Char_Size( the_face, f_sz_data->width, f_sz_data->height, 72, 72 ) != 0)
686  {
687  TRACE(TERROR, ("FT_Set_Char_Size FAILED: w=%u, h=%u\n", f_sz_data->width, f_sz_data->height))
688  return FALSE;
689  }
690  ftd_ptr->current_fnt_id = f_sz_data->fnt_id;
691  }
692  if (char_data->mtrc_advance == 0) /* when this has non-zero value, it's cachable char but no room for cache */
693  {
694  if (ftd_ptr->face_type == FTYPE_PFR)
695  {
696  FT_Pos advance;
697 
698  if (FT_Get_PFR_Advance( the_face, pp->glyph_index, &advance ) != 0)
699  {
700  TRACE(TERROR, ("FT_Get_PFR_Advance FAILED: gi=%u\n", pp->glyph_index))
701  return FALSE;
702  }
703  else
704  {
705  char_data->mtrc_advance = (S16BIT)advance;
706  }
707  }
708  else
709  {
710  if (FT_Load_Glyph( the_face, pp->glyph_index, FT_LOAD_NO_SCALE ) != 0)
711  {
712  TRACE(TERROR, ("FT_Load_Glyph FAILED: gi=%u\n", pp->glyph_index))
713  return FALSE;
714  }
715  else
716  {
717  char_data->mtrc_advance = (S16BIT)the_face->glyph->metrics.horiAdvance;
718  }
719  }
720  }
721 
722  load_flags = FT_LOAD_RENDER;
723  /* Special cases to overcome a FreeType bug: for
724  * "Latin Small Letter A With Tilde U+00E3",
725  * "Latin Small Letter N With Tilde U+00F1" and
726  * "Latin Small Letter O With Tilde U+00F5"
727  * the "tilde" is rendered as a macron for small font sizes, when
728  * auto-hinting is enabled. We cannot always control the build options,
729  * so a special case is required.
730  */
731  if (u_chr == 0x00e3 || u_chr == 0x00f1 || u_chr == 0x00f5)
732  {
733  load_flags |= FT_LOAD_NO_AUTOHINT;
734  }
735  if (FT_Load_Glyph( the_face, pp->glyph_index, load_flags ) != 0)
736  {
737  return FALSE;
738  }
739 
740  char_data->uni_chr = u_chr;
741  char_data->gf_ndx = pp->glyph_index;
742  char_data->width = the_face->glyph->bitmap.width;
743  pp->char_left = the_face->glyph->bitmap_left;
744  switch (u_chr)
745  {
746  case 0x2215: /* divide */
747  if (ftd_ptr->font_ndx != BUILT_IN_FONT)
748  {
749  pp->char_adv = (S8BIT)((the_face->glyph->linearHoriAdvance + 0x7fff) >> 16);
750  break;
751  }
752  case 0xd7:
753  case 0xf7:
754  case 0x66b:
755  /* case UNICODE_FIGURE_SPACE: not neccessary */
756  case 0x2212:
757  case 0x2214:
758  /* This is a bit of a cheat for getting through the DTG test "5.10B Monospace chars", but
759  * it is quite reasonable. And it's only way to avoid mucking up the rendering elsewhere.
760  */
761  pp->char_adv = f_sz_data->figure_adv;
762  break;
763 
764  case 0x2713:
765  case 0x2717:
766  if ((the_face->glyph->linearHoriAdvance & 0x8000) &&
767  (ftd_ptr->current_fnt_id & 0xff) == 24 && pp->hpxl_last_tab == pp->hpxl_pen_posn)
768  {
769  pp->char_left--;
770  pp->hpxl_last_tab--;
771  pp->char_adv = (S8BIT)(the_face->glyph->linearHoriAdvance >> 16);
772  break;
773  }
774  default:
775  pp->char_adv = (S8BIT)((the_face->glyph->linearHoriAdvance + 0x7fff) >> 16);
776  }
777  return TRUE;
778 }
779 
785 static void InitialiseProperties( pDrawTextAttrib attrib, S_FontSize *f_sz_data, S_PROPERTIES *pp )
786 {
787  pp->glyph_last = 0;
788  pp->hpxl_line_end = 0;
789  pp->font_style = (U8BIT)((f_sz_data->fnt_id >> 8) & 0xFF);
791  {
792  pp->m_to_pix_mlt = 1;
793  pp->m_to_pix_div = 1;
794  pp->pixel_par_x = 45;
795  }
796  else if ((pp->font_style & FONT_STYLE_SQUARE) && (mg_hd_mode != NORMAL_SD))
797  {
800  pp->pixel_par_x = 64;
801  }
802  else
803  {
804  pp->m_to_pix_mlt = mg_ctxt.osd_x.mlt * 9;
805  pp->m_to_pix_div = mg_ctxt.osd_y.div * 14;
806  pp->pixel_par_x = 56;
807  }
808  if ((attrib->justify & JFY_HZ_MASK) == JUSTIFY_H_START)
809  {
810  pp->hpxl_last_tab = f_sz_data->bound_box.left;
811  pp->pnts_tab_start = f_sz_data->pnts_xleftoffset;
812  pp->spxl_tab_start = f_sz_data->spxl_xleftoffset;
813  }
814  else
815  {
816  pp->hpxl_last_tab = 0;
817  pp->spxl_tab_start = 0;
818  }
819  pp->hpxl_pen_posn = pp->hpxl_last_tab;
820  pp->hpxl_letter_offset = 0;
821  pp->total_letter_space = 0;
822  pp->metric_line_length = 0;
823  pp->metric_break_length = 0;
824  pp->pnts_font_size = (S32BIT)f_sz_data->fnt_id & 0xFF;
825  pp->font_index = f_sz_data->fnt_id >> 16;
826 }
827 
833 static void MoveTabPosition( S_PROPERTIES *pp )
834 {
835  S32BIT new_posn;
836  /* get sd pixels, and add xLeftOffset since
837  * "tab logically advances the rendering of the text by at least the width xOffsetLeft" */
838  new_posn = P_SPIXEL_POSITION(pp) + pp->p_font_size->spxl_xleftoffset;
839  /* round up to new tab position */
840  //TRACE(TTEXT,("new_posn=%d pp->spxl_tab_start=%d pp->metric_line_length=%d", new_posn, pp->spxl_tab_start, pp->metric_line_length ))
841  if ((new_posn % 45) != 0)
842  {
843  new_posn += 45 - (new_posn % 45);
844  }
845  pp->spxl_tab_start = new_posn;
846  /* now that size of chars and letter space been used - zero them */
847  pp->metric_line_length = 0;
848  pp->hpxl_letter_offset = 0;
849  pp->total_letter_space = 0;
850  /* calculate tab position in real pixels */
851  new_posn = ((new_posn * mg_ctxt.osd_x.mlt) + (mg_ctxt.osd_x.div >> 1)) / mg_ctxt.osd_x.div;
852  pp->hpxl_pen_posn = pp->p_current_line->position + new_posn;
853  pp->hpxl_last_tab = pp->hpxl_pen_posn;
854  /* forget previous glyph to prevent kerning across a tab character */
855  pp->glyph_last = 0;
856 }
857 
863 static void AddSpaceRendering( pDrawTextAttrib attrib, S_PROPERTIES *pp, CharData *char_data,
864  FT_UInt mt_adv, S8BIT pxl_adv )
865 {
866  if (pp->glyph_last && attrib->letter_space)
867  {
868  AddLetterSpace(pp,attrib->letter_space);
869  if (pp->hpxl_pen_posn < pp->p_current_line->position)
870  {
872  }
873  }
874  if ((attrib->justify & JFY_HZ_MASK) == JUSTIFY_H_CENTRE)
875  {
876  char_data->mtrc_position = P_METRIC_POSITION(pp);
877  char_data->mtrc_advance = mt_adv;
878  char_data->real_position = pp->hpxl_pen_posn;
879  char_data->colour = TRANSPARENT_COLOUR; /* <- so that rendering function ignors this character data */
880  char_data->width = pxl_adv;
881  }
882  pp->hpxl_pen_posn += pxl_adv;
883  pp->metric_line_length += mt_adv;
884 }
885 
892 static void MinorAdjustOfPenPositionAtSpace( S_PROPERTIES *pp )
893 {
894  S32BIT tmp,psn;
895  psn = P_POINTS_POSITION(pp);
896  tmp = ((pp->m_to_pix_mlt * psn) + (pp->m_to_pix_div >> 1)) / pp->m_to_pix_div;
897  tmp += pp->hpxl_last_tab;
898  if (tmp != pp->hpxl_pen_posn)
899  {
900  TPRINT(TTEXT, ("MAPP(%d,%d,%d,%d,%d)", pp->total_letter_space, pp->metric_line_length, psn, tmp, pp->hpxl_pen_posn));
901  pp->hpxl_pen_posn += (tmp - pp->hpxl_pen_posn) / 2;
902  }
903 }
904 
913 static void ProcessWrappingBreak( S_PROPERTIES *pp, CharData *chars, U16BIT cur_ndx )
914 {
915  S32BIT brk_posn, ndx;
918  TRACE(TTEXT, ("Metric break-posn=%d; After: start=%d 1st-char=0x%x", brk_posn, pp->break_line.start_ndx, chars[pp->break_line.start_ndx].uni_chr))
919  if (brk_posn)
920  {
921  assert( pp->break_line.start_ndx < cur_ndx );
922  for (ndx = pp->break_line.start_ndx; ndx != cur_ndx; ndx++)
923  {
924  assert( chars[ndx].mtrc_position >= brk_posn );
925  chars[ndx].mtrc_position -= brk_posn;
926  }
927  }
928  pp->metric_break_length = 0;
929  pp->break_letter_space = 0;
930 }
931 
939 static void FudgeForHD( S_PROPERTIES *pp, CharData *chars )
940 {
941  CharData *p_start, *p_other, *p_last;
942  LineLimit *line = pp->p_current_line;
943  S32BIT fudge_size, fudge_last;
944 
945  assert(line->end_ndx > line->start_ndx);
946  p_start = chars + line->start_ndx;
947  p_last = chars + line->end_ndx - 1;
948  assert(line->position <= p_start->real_position);
949 
950  /* width of chars visible at HD */
951  fudge_size = p_last->real_position + p_last->width - line->position;
952 
953  /* is char width > box width, and is there more than one char ? */
954  if (fudge_size > pp->hpxl_box_width && p_start != p_last)
955  {
956  /* Ensure SD displayable chars can be seen in HD */
957  fudge_size -= pp->hpxl_box_width;
958  if (line->position < p_start->real_position)
959  {
960  /* attempt to sort it, by moving whole line left by one pixel
961  * Should not do more than one, coz it would be noticable on
962  * multi-line with left margin being jagged */
963  line->position++;
964  fudge_size--;
965  if (fudge_size == 0)
966  {
967  return; /* fudged it ! */
968  }
969  }
970  /* move end char back by required fudge size */
971  p_last->real_position -= fudge_size;
972  /* now loop until fudging is done or cannot do anymore */
973  do
974  {
975  fudge_last = fudge_size; /* save fudge size */
976  p_other = p_last - 1;
977  /* Start from end, and move chars back */
978  while (p_other != p_start)
979  {
980  p_other->real_position -= fudge_size;
981  if (p_other->real_position + p_other->width + 1 < p_last->real_position)
982  {
983  /* still have gap between chars after fudge, so can decrement fudge size
984  * i.e. lose one pixel between them */
985  fudge_size--;
986  p_other->real_position++;
987  if (fudge_size == 0)
988  {
989  return; /* fudged it ! */
990  }
991  }
992  p_last = p_other;
993  p_other--;
994  }
995  assert(p_other == p_start);
996  TRACE(TTEXT, ("More fudging to do %d", fudge_size))
997  /* This time, start from beginning and move them up */
998  p_last = chars + line->end_ndx - 1;
999  p_other++;
1000  while (p_other != p_last)
1001  {
1002  p_other->real_position += fudge_size;
1003  if (p_start->real_position + p_start->width + 1 < p_other->real_position)
1004  {
1005  /* still have gap between chars after fudge, so can decrement fudge size
1006  * i.e. lose one pixel between them */
1007  fudge_size--;
1008  if (fudge_size == 0)
1009  {
1010  return; /* fudged it ! */
1011  }
1012  }
1013  p_start = p_other;
1014  p_other++;
1015  }
1016  assert(p_other == p_last);
1017  p_start = chars + line->start_ndx;
1018  }
1019  while (fudge_size != fudge_last); /*if these are equal it is not possible to do any more */
1020  TRACE(TERROR, ("fudging failed to complete %d", fudge_size))
1021  }
1022  /* else nothing to do */
1023 }
1024 
1033 static void AdjustLineEnding( S_PROPERTIES *pp, CharData *chars )
1034 {
1035  S32BIT len, mtr_end, width;
1036  CharData *p_cd;
1037  LineLimit *line = pp->p_current_line;
1038  U16BIT ndx;
1039 
1040  assert(line->end_ndx > line->start_ndx);
1041  ndx = line->end_ndx - 1;
1042  p_cd = chars + ndx;
1043  mtr_end = p_cd->mtrc_position + p_cd->mtrc_advance;
1044  width = pp->spxl_box_width - pp->p_font_size->spxl_xleftoffset;
1045 
1046  ndx = line->start_ndx;
1047  p_cd = chars + ndx;
1048 
1049  while (ndx != line->end_ndx)
1050  {
1051  len = P_MTRC_2_SPXL(pp, mtr_end - p_cd->mtrc_position);
1052  if (len <= width)
1053  {
1054  break;
1055  }
1056  p_cd++;
1057  ndx++;
1058  }
1059  assert(ndx <= line->end_ndx);
1060  line->start_ndx = ndx;
1061 
1062  /* adjust rending length so that displayable chars are centred properly */
1063  line->l_width -= p_cd->real_position - line->position;
1064  line->position = p_cd->real_position;
1065 }
1066 
1075 static void AdjustLineMiddle( S_PROPERTIES *pp, CharData *chars, U8BIT justify )
1076 {
1077  S32BIT mleft, mhalf, rright, mright, b_wdth;
1078  CharData *p_ecd, *p_scd;
1079  LineLimit *line = pp->p_current_line;
1080  U16BIT e_ndx, s_ndx;
1081 
1082  assert(line->end_ndx > line->start_ndx);
1083  e_ndx = line->end_ndx - 1;
1084  s_ndx = line->start_ndx;
1085  p_ecd = chars + e_ndx;
1086  if (justify & WRAP_WORDS)
1087  {
1088  /*Strip off extra spaces from end of chars array for this line */
1089  while (e_ndx != s_ndx && p_ecd->uni_chr == UNICODE_SPACE)
1090  {
1091  p_ecd--;
1092  e_ndx--;
1093  }
1094  }
1095  mright = p_ecd->mtrc_position + p_ecd->mtrc_advance;
1096  p_scd = chars + s_ndx;
1097  mleft = p_scd->mtrc_position;
1098  rright = pp->break_line.position;
1099 
1100  #ifdef ACCURATE_CENTRE_TRUNCATION
1101 
1102  mhalf = mright >> 1;
1103  b_wdth = pp->spxl_box_width - pp->p_font_size->spxl_xleftoffset;
1104  while ((e_ndx != s_ndx) && (P_MTRC_2_SPXL(pp, mright - mleft) > b_wdth))
1105  {
1106  if (mright - mhalf > mhalf - mleft)
1107  {
1108  rright = p_ecd->real_position;
1109  p_ecd--;
1110  e_ndx--;
1111  mright = p_ecd->mtrc_position + p_ecd->mtrc_advance;
1112  }
1113  else
1114  {
1115  p_scd++;
1116  s_ndx++;
1117  mleft = p_scd->mtrc_position;
1118  }
1119  }
1120 
1121  #else
1122 
1123  mhalf = mright << 1;
1124  b_wdth = pp->spxl_box_width; /* twice width of right half */
1125  while ((e_ndx != s_ndx) && (P_MTRC_2_SPXL(pp, mhalf - mright) > b_wdth))
1126  {
1127  rright = p_ecd->real_position;
1128  p_ecd--;
1129  e_ndx--;
1130  mhalf = (p_ecd->mtrc_position + p_ecd->mtrc_advance) << 1;
1131  }
1132  b_wdth -= pp->p_font_size->spxl_xleftoffset;
1133  while ((e_ndx != s_ndx) && (P_MTRC_2_SPXL(pp, mright - mleft) > b_wdth))
1134  {
1135  p_scd++;
1136  s_ndx++;
1137  mleft = p_scd->mtrc_position << 1;
1138  }
1139 
1140  #endif /*ACCURATE_CENTRE_TRUNCATION*/
1141 
1142  if (s_ndx != line->start_ndx || e_ndx != (line->end_ndx - 1))
1143  {
1144  assert( rright > p_scd->real_position );
1145  if (rright > p_scd->real_position)
1146  {
1147  assert(s_ndx <= (e_ndx + 1));
1148  line->start_ndx = s_ndx;
1149  line->end_ndx = e_ndx + 1;
1150 
1151  /* adjust rending length so that displayable chars are centred properly */
1152  line->position = p_scd->real_position;
1153  line->l_width = p_ecd->real_position + p_ecd->width - p_scd->real_position;
1154  }
1155  }
1156 }
1157 
1163 void ProcessNewLine( S_PROPERTIES *pp, CharData *chars, S_FontSize *f_sz_data, U16BIT line_num, U8BIT justify )
1164 {
1165  TRACE(TTEXT, ("start=%d bk-end=%d", pp->p_current_line->start_ndx, pp->break_line.end_ndx))
1166  if (pp->p_current_line->start_ndx < pp->break_line.end_ndx)
1167  {
1171  pp->hpxl_last_tab = pp->break_line.position;
1172  switch (justify & JFY_HZ_MASK)
1173  {
1174  case JUSTIFY_H_END:
1175  AdjustLineEnding( pp, chars );
1176  break;
1177 
1178  case JUSTIFY_H_CENTRE:
1179  AdjustLineMiddle( pp, chars, justify );
1180  FudgeForHD( pp, chars );
1181  break;
1182 
1183  default: /*JUSTIFY_H_START and JUSTIFY_H_JUSTIFIED*/
1184  FudgeForHD( pp, chars );
1185  pp->spxl_tab_start = f_sz_data->spxl_xleftoffset;
1186  pp->pnts_tab_start = f_sz_data->pnts_xleftoffset;
1187  pp->break_line.position -= f_sz_data->bound_box.left;
1188  break;
1189  }
1190  pp->hpxl_letter_offset = 0;
1191  pp->total_letter_space = 0;
1192  pp->p_current_line++;
1193  }
1194  else
1195  {
1196  if ((justify & JFY_HZ_MASK) == JUSTIFY_H_START)
1197  {
1198  pp->break_line.position -= f_sz_data->bound_box.left;
1199  }
1200  }
1204 }
1205 
1214 static LineLimit* ShuffleUpLines( LineLimit *lines, U16BIT num )
1215 {
1216  U16BIT first = 0;
1217  while (lines[first].line_num < num)
1218  {
1219  first++;
1220  }
1221  num = first;
1222  first = 0;
1223  while (num != MAX_NUM_LINES)
1224  {
1225  lines[first] = lines[num];
1226  first++;
1227  num++;
1228  }
1229  return &lines[first - 1];
1230 }
1231 
1237 static void AddCaretChar( S_PROPERTIES *pp, S_FontDetails *ftd_ptr, S_FontSize *f_sz_data, CharData *char_data,
1238  OSDColor col, U16BIT caret )
1239 {
1240  if (f_sz_data->sbit_cache)
1241  {
1242  CacheSbit *c_sbit = &f_sz_data->sbit_cache[caret - FIRST_CACHE_CHAR];
1243  char_data->width = c_sbit->width;
1244  char_data->real_position = pp->hpxl_pen_posn + c_sbit->left;
1245  char_data->gf_ndx = 0;
1246  }
1247  else
1248  {
1249  FT_Face the_face = ftd_ptr->face;
1250  char_data->gf_ndx = FT_Get_Char_Index( the_face, caret );
1251  if (FT_Load_Glyph( the_face, char_data->gf_ndx, FT_LOAD_RENDER ) == 0)
1252  {
1253  char_data->width = the_face->glyph->bitmap.width;
1254  char_data->real_position = pp->hpxl_pen_posn + the_face->glyph->bitmap_left;
1255  }
1256  }
1257  char_data->mtrc_position = P_METRIC_POSITION(pp);
1258  char_data->mtrc_advance = ftd_ptr->horiz_adv[caret - FIRST_CACHE_CHAR];
1259  char_data->uni_chr = caret;
1260  char_data->colour = col;
1261 }
1262 
1277 static U16BIT PreparePrintableData( const TextString unistr, pDrawTextAttrib attrib, S_FontSize *f_sz_data,
1278  S_FontDetails *ftd_ptr, U16BIT hpxl_box_width, U16BIT spxl_box_width,
1279  U16BIT available_lines, LineLimit *lines, CharData *chars, U16BIT *p_chr_cnt )
1280 {
1281  CharData *char_data = chars;
1282  FT_UInt *hori_advance = ftd_ptr->horiz_adv;
1283  OSDColor colour_stack[COLOUR_STACK_SIZE];
1284  S_PROPERTIES prop;
1285  U16BIT u_chr, uni_pos, char_count;
1286  U16BIT total_lines;
1287  EBreakState break_state;
1288  U8BIT colour_count, hz_justify;
1289  U16BIT spxl_avl_width;
1290 
1291  /* Initialise values, including 'properties' */
1292  lines[0].position = 0;
1293  lines[0].start_ndx = 0;
1294  lines[0].end_ndx = 0;
1295  prop.break_line.start_ndx = 0;
1296  total_lines = 0;
1297  char_count = 0;
1298  colour_count = 0; /* fore colour in 'zero' */
1299  colour_stack[0] = attrib->fore_colour;
1300  break_state = NO_BREAK;
1301  prop.p_font_size = attrib->font.hdl;
1302  prop.p_current_line = lines;
1303  prop.metric_resn = ftd_ptr->metric_resolution;
1304  prop.hpxl_box_width = hpxl_box_width;
1305  prop.spxl_box_width = spxl_box_width;
1306 
1307  InitialiseProperties( attrib, f_sz_data, &prop );
1308 
1309  hz_justify = attrib->justify & JFY_HZ_MASK;
1310  if (hz_justify == JUSTIFY_H_START)
1311  {
1312  spxl_avl_width = spxl_box_width;
1313  }
1314  else
1315  {
1316  spxl_avl_width = spxl_box_width - f_sz_data->spxl_xleftoffset;
1317  }
1318 
1319  /* loop through the string */
1320  for (uni_pos = 0; uni_pos < unistr.len; uni_pos++)
1321  {
1322  if (uni_pos == attrib->entry_point)
1323  {
1324  AddCaretChar( &prop, ftd_ptr, f_sz_data, char_data, colour_stack[colour_count], attrib->caret );
1325  char_count++;
1326  char_data++;
1327  }
1328  u_chr = unistr.data[uni_pos];
1329  switch (u_chr)
1330  {
1331  case UNICODE_LF: case U_CTRL_NULL:
1332  case U_CTRL_A: case U_CTRL_B: case U_CTRL_C: case U_CTRL_D: case U_CTRL_E:
1333  case U_CTRL_F: case U_CTRL_G: case U_CTRL_H: case U_CTRL_K: case U_CTRL_L:
1334  case U_CTRL_N: case U_CTRL_O: case U_CTRL_P: case U_CTRL_Q: case U_CTRL_R:
1335  case U_CTRL_S: case U_CTRL_T: case U_CTRL_U: case U_CTRL_V: case U_CTRL_W:
1336  case U_CTRL_X: case U_CTRL_Y: case U_CTRL_Z: case U_CTRL_FS:
1337  case U_CTRL_GS: case U_CTRL_RS: case U_CTRL_US:
1338  TRACE(TTEXT, ("Ignoring control char 0x%x", u_chr))
1339  break;
1340 
1341  case UNICODE_CR:
1343  if (break_state != OVER_RUN)
1344  {
1345  prop.break_line.end_ndx = char_count;
1346  }
1347  prop.break_line.position = prop.hpxl_pen_posn;
1348  prop.break_line.start_ndx = char_count;
1349  prop.hpxl_last_tab = prop.hpxl_pen_posn; /* last screen of test 5.9 */
1350  if (hz_justify == JUSTIFY_H_START)
1351  {
1352  prop.pnts_tab_start = f_sz_data->pnts_xleftoffset;
1353  prop.spxl_tab_start = f_sz_data->spxl_xleftoffset;
1354  }
1355  prop.metric_line_length = 0;
1356  break_state = NEW_LINE;
1357  break;
1358 
1359  case UNICODE_ESC:
1360  /* process markup's */
1361  uni_pos++;
1362  if (uni_pos != unistr.len)
1363  {
1364  uni_pos += ProcessMarkup( &unistr.data[uni_pos], colour_stack, &colour_count, attrib->p_ha );
1365  }
1366  break;
1367 
1368  case UNICODE_TAB:
1369  if (hz_justify == JUSTIFY_H_START)
1370  {
1371  MoveTabPosition( &prop );
1372  }
1373  else
1374  {
1375  u_chr = UNICODE_SPACE;
1376  }
1377  case UNICODE_SPACE:
1378  if (u_chr == UNICODE_SPACE)
1379  {
1380  AddSpaceRendering( attrib, &prop, char_data, ftd_ptr->space_horiz_adv, f_sz_data->space_adv );
1381  if (hz_justify == JUSTIFY_H_CENTRE)
1382  {
1383  /* for centre justify, AddSpaceRendering adds char data,
1384  * gf_ndx and uni_chr do not really matter, but might as well have something */
1385  char_data->gf_ndx = ftd_ptr->glyph_ndx_space;
1386  char_data->uni_chr = u_chr;
1387  #ifdef TRACE
1388  char_data->spxl_end = (S16BIT)S_SPIXEL_POSITION(prop);
1389  #endif
1390  char_count++;
1391  char_data++;
1392  }
1393  prop.glyph_last = ftd_ptr->glyph_ndx_space;
1394  /* Special case, only for SD resolution */
1395  if (mg_ctxt.out_osd_width == 720)
1396  {
1397  MinorAdjustOfPenPositionAtSpace( &prop );
1398  }
1399  }
1400  if ((break_state != BREAKING) && (attrib->justify & WRAP_WORDS))
1401  {
1403  if (break_state != OVER_RUN)
1404  {
1405  prop.break_line.end_ndx = char_count;
1406  }
1407  if (S_SPIXEL_POSITION(prop) > spxl_avl_width)
1408  {
1409  TRACE(TTEXT, ("Need line break: sdp=%ld, aw=%d", S_SPIXEL_POSITION(prop), spxl_avl_width))
1410  prop.break_line.position = prop.hpxl_pen_posn;
1411  prop.break_line.start_ndx = char_count;
1412  prop.metric_line_length = 0;
1413  break_state = NEW_LINE;
1414  }
1415  else
1416  {
1417  break_state = BREAKING;
1418  }
1419  }
1420  if (hz_justify == JUSTIFY_H_END)
1421  {
1422  if (prop.hpxl_pen_posn > prop.hpxl_line_end)
1423  {
1424  prop.hpxl_line_end = prop.hpxl_pen_posn;
1425  }
1426  }
1427  break;
1428 #if 0
1429  case UNICODE_HARD_SPACE:
1430  AddSpaceRendering( attrib, &prop, char_data, ftd_ptr->space_horiz_adv, f_sz_data->space_adv );
1431  if (hz_justify == JUSTIFY_H_CENTRE)
1432  {
1433  /* for centre justify, AddSpaceRendering adds char data,
1434  * gf_ndx and uni_chr do not really matter, but might as well have something */
1435  char_data->gf_ndx = ftd_ptr->glyph_ndx_space;
1436  char_data->uni_chr = u_chr;
1437  char_count++;
1438  char_data++;
1439  }
1440  prop.glyph_last = ftd_ptr->glyph_ndx_space;
1441  if (prop.hpxl_pen_posn > prop.hpxl_line_end)
1442  {
1443  prop.hpxl_line_end = prop.hpxl_pen_posn;
1444  }
1445  break;
1446 
1447  case UNICODE_FIGURE_SPACE:
1448  AddSpaceRendering( attrib, &prop, char_data, ftd_ptr->fig_horiz_adv, f_sz_data->figure_adv );
1449  if (hz_justify == JUSTIFY_H_CENTRE)
1450  {
1451  /* for centre justify, AddSpaceRendering adds char data,
1452  * gf_ndx and uni_chr do not really matter, but might as well have something */
1453  char_data->gf_ndx = ftd_ptr->glyph_ndx_space;
1454  char_data->uni_chr = u_chr;
1455  char_count++;
1456  char_data++;
1457  }
1458  prop.glyph_last = ftd_ptr->glyph_ndx_space;
1459  if (prop.hpxl_pen_posn > prop.hpxl_line_end)
1460  {
1461  prop.hpxl_line_end = prop.hpxl_pen_posn;
1462  }
1463  break;
1464 #endif
1465  default:
1466  /* PRINTABLE CHARS */
1467  if (u_chr < (FIRST_CACHE_CHAR + CHAR_CACHE_SIZE))
1468  {
1469  assert(u_chr >= FIRST_CACHE_CHAR);
1470  prop.glyph_index = ftd_ptr->glyph_ndx[u_chr - FIRST_CACHE_CHAR];
1471 
1472  char_data->mtrc_advance = (S16BIT)hori_advance[u_chr - FIRST_CACHE_CHAR];
1473 
1474  if (f_sz_data->sbit_cache)
1475  {
1476  CacheSbit *c_sbit = &f_sz_data->sbit_cache[u_chr - FIRST_CACHE_CHAR];
1477  char_data->uni_chr = u_chr;
1478  char_data->gf_ndx = 0;
1479  char_data->width = c_sbit->width;
1480  prop.char_left = c_sbit->left;
1481  prop.char_adv = c_sbit->advance;
1482  }
1483  else
1484  {
1485  if (prop.glyph_index == 0 ||
1486  !LoadPrintableChar( ftd_ptr, f_sz_data, &prop, u_chr, char_data ))
1487  {
1488  break;
1489  }
1490  }
1491  }
1492  else
1493  {
1494  prop.glyph_index = FT_Get_Char_Index( ftd_ptr->face, u_chr );
1495  char_data->mtrc_advance = 0;
1496  if (prop.glyph_index == 0 ||
1497  !LoadPrintableChar( ftd_ptr, f_sz_data, &prop, u_chr, char_data ))
1498  {
1499  TRACE(TTEXT, ("0x%x is not printable\n", u_chr))
1500  break;
1501  }
1502  }
1503  char_data->colour = colour_stack[colour_count];
1504 
1505  if (break_state == BREAKING)
1506  {
1507  prop.break_line.position = prop.hpxl_pen_posn + prop.char_left;
1510  prop.break_line.end_ndx = char_count;
1511  prop.break_line.start_ndx = char_count;
1512  break_state = HAD_BREAK;
1513  }
1514 
1515  DoTheKerning( attrib, ftd_ptr, &prop );
1516 
1517  {
1518  S32BIT tmp_adv = prop.hpxl_pen_posn + prop.char_left;
1519  char_data->real_position = tmp_adv;
1520  if (tmp_adv < prop.p_current_line->position)
1521  {
1522  prop.p_current_line->position = tmp_adv;
1523  }
1524  tmp_adv += char_data->width;
1525  if (tmp_adv > prop.hpxl_line_end)
1526  {
1527  prop.hpxl_line_end = tmp_adv;
1528  }
1529  }
1530 
1531  prop.hpxl_pen_posn += prop.char_adv;
1532  char_data->mtrc_position = S_METRIC_POSITION(prop);
1533  prop.metric_line_length += char_data->mtrc_advance;
1534  if (prop.hpxl_pen_posn > prop.hpxl_line_end)
1535  {
1536  prop.hpxl_line_end = prop.hpxl_pen_posn;
1537  }
1538  #ifdef TRACE
1539  char_data->spxl_end = (S16BIT)S_SPIXEL_POSITION(prop);
1540  #endif
1541  char_count++;
1542  char_data++;
1543 
1544  if (attrib->justify & WRAP_VERTICAL)
1545  {
1546  /* wrap on every char */
1548  prop.break_line.end_ndx = char_count;
1549  prop.break_line.position = prop.hpxl_pen_posn;
1550  prop.metric_line_length = 0;
1551  break_state = NEW_LINE;
1552  }
1553  else
1554  {
1555  if (S_SPIXEL_POSITION(prop) > spxl_avl_width)
1556  {
1557  /* this line now exceeds available width */
1558  TRACE(TTEXT, ("Need line-break: sdp=%ld, aw=%d", S_SPIXEL_POSITION(prop), spxl_avl_width))
1559  #ifdef TRACING
1560  if (TTEXT & mheg_trace_debug)
1561  {
1563  prop.p_current_line->end_ndx = char_count;
1564  prop.p_current_line->line_num = total_lines;
1565  traceLine( prop.p_current_line, chars, prop.pnts_font_size, prop.metric_resn );
1566  }
1567  #endif
1568  switch (break_state)
1569  {
1570  case HAD_BREAK:
1571  /* Need to remove from total_letter_space, the letter space after the breaking space char */
1572  prop.break_letter_space += attrib->letter_space;
1574  ProcessWrappingBreak( &prop, chars, char_count );
1575  break_state = NEW_LINE;
1576  break;
1577  default:
1578  if (hz_justify == JUSTIFY_H_START)
1579  {
1580  TRACE(TTEXT, ("Over run at %d", char_count))
1581  assert(break_state == NO_BREAK);
1582  prop.break_line.end_ndx = char_count - 1;
1583  break_state = OVER_RUN;
1584  }
1585  break;
1586  case OVER_RUN:
1587  break;
1588  }
1589  }
1590  }
1591  } /*end: switch(u_chr)*/
1592 
1593  if (break_state == NEW_LINE)
1594  {
1595  ProcessNewLine( &prop, chars, f_sz_data, total_lines, attrib->justify );
1596 
1597  total_lines++;
1598 
1599  if ((total_lines == available_lines) &&
1601  )
1602  {
1603  /* GOOD! we've done enough - let's exit loop */
1604  break;
1605  }
1606  if (prop.p_current_line == &lines[MAX_NUM_LINES - 1])
1607  {
1608  if ((attrib->justify & JUSTIFY_V_JUSTIFIED) != JUSTIFY_V_END)
1609  {
1610  TRACE(TERROR, ("Run out of line space"))
1611  break; /* eek, cannot do anymore */
1612  }
1613  /* for JUSTIFY_V_END, can shuffle up the lines coz only interested in the last ones */
1614  prop.p_current_line = ShuffleUpLines( lines, total_lines - available_lines );
1615  }
1616  prop.glyph_last = 0;
1617  break_state = NO_BREAK;
1618  }
1619  }
1620 
1621  if (uni_pos == attrib->entry_point)
1622  {
1623  /* add 'caret' in the end position */
1624  AddCaretChar( &prop, ftd_ptr, f_sz_data, char_data, colour_stack[colour_count], attrib->caret );
1625  if ((char_data->real_position + char_data->width) > prop.hpxl_line_end)
1626  {
1627  prop.hpxl_line_end = char_data->real_position + char_data->width;
1628  }
1629  char_count++;
1630  }
1631  /* complete stuff for the last line being processed */
1632  TRACE(TTEXT, ("last line: mt=%ld, rt=%ld", prop.metric_line_length, prop.hpxl_line_end))
1634  prop.p_current_line->line_num = total_lines;
1635  if (break_state == OVER_RUN)
1636  {
1638  }
1639  else
1640  {
1641  prop.p_current_line->end_ndx = char_count;
1642  if (prop.p_current_line->start_ndx < char_count)
1643  { /* there are some visible chars */
1644  prop.break_line.position = prop.hpxl_pen_posn;
1645  switch (attrib->justify & JFY_HZ_MASK)
1646  {
1647  case JUSTIFY_H_END:
1648  AdjustLineEnding( &prop, chars );
1649  break;
1650 
1651  case JUSTIFY_H_CENTRE:
1652  AdjustLineMiddle( &prop, chars, attrib->justify );
1653  FudgeForHD( &prop, chars );
1654  break;
1655 
1656  default: /*JUSTIFY_H_START and JUSTIFY_H_JUSTIFIED*/
1657  FudgeForHD( &prop, chars );
1658  break;
1659  }
1660  }
1661  }
1662  if (prop.p_current_line->l_width)
1663  {
1664  total_lines++;
1665  /* TextDrawFn() requires that there is a terminating lines array element
1666  * with line_num equal to total_lines */
1667  prop.p_current_line++;
1668 
1669  prop.p_current_line->line_num = total_lines;
1670  }
1671  *p_chr_cnt = char_count;
1672  return total_lines;
1673 } /* end of PreparePrintableData */
1674 
1675 #ifdef OSD_8_BIT
1676 
1681 #define TextDrawFn TextDraw8Bit
1682 #define RenderGlyphFn RenderGlyph8Bit
1683 #define TDColor U8BIT
1684 #define MakeTDColor(col) OSD_FindNearestColourIndex( col )
1685 #define GreyValue(val) (val >> 6)
1686 #define SRC_FORE_MAX 3
1687 #define IsOpaqueColor( tcol ) (tcol >= OFFSET_OPAQUE)
1688 #define NotTransparent( fcol ) ((fcol >> 24) > 0x18)
1689 #define CombineAlphaColour(pixel, grey_val, fc, tc) if (grey_val) pixel = aa_8bit_cols[grey_val];
1690 //#define SetColorArrayBack(bck_col) aa_8bit_cols[0] = bck_col;
1691 #define CalcColorArray(for_col) \
1692  if (/*for_col != OFFSET_TRANS &&*/ aa_8bit_cols[3] != for_col) { \
1693  U8BIT fa, ba, bck_col = aa_8bit_cols[0]; \
1694  register U32BIT comp, tmp_c, alpha_c; \
1695  comp = mg_palette[for_col] >> 24; \
1696  ba = (U8BIT)(mg_palette[bck_col] >> 24); \
1697  alpha_c = ((((255 ^ ba) * comp) + 382) / 765) + ba; \
1698  tmp_c = alpha_c << 24; \
1699  fa = (U8BIT)((comp + 1) / 3); \
1700  comp = ba; \
1701  ba = (U8BIT)(((255 ^ fa) * comp) + 127) / 255; \
1702  comp = ba * ((mg_palette[bck_col] >> 16) & 0xff) + fa * ((mg_palette[for_col] >> 16) & 0xff); \
1703  tmp_c |= (comp / alpha_c) << 16; \
1704  comp = ba * ((mg_palette[bck_col] >> 8) & 0xff) + fa * ((mg_palette[for_col] >> 8) & 0xff); \
1705  tmp_c |= (comp / alpha_c) << 8; \
1706  comp = ba * (mg_palette[bck_col] & 0xff) + fa * (mg_palette[for_col] & 0xff); \
1707  tmp_c |= (comp / alpha_c); \
1708  aa_8bit_cols[1] = OSD_FindNearestColourIndex(tmp_c); \
1709  comp = 2 * (mg_palette[for_col] >> 24); \
1710  ba = (U8BIT)(mg_palette[bck_col] >> 24); \
1711  alpha_c = ((((255 ^ ba) * comp) + 382) / 765) + ba; \
1712  tmp_c = alpha_c << 24; \
1713  fa = (U8BIT)((comp + 1) / 3); \
1714  comp = ba; \
1715  ba = (U8BIT)(((255 ^ fa) * comp) + 127) / 255; \
1716  comp = ba * ((mg_palette[bck_col] >> 16) & 0xff) + fa * ((mg_palette[for_col] >> 16) & 0xff); \
1717  tmp_c |= (comp / alpha_c) << 16; \
1718  comp = ba * ((mg_palette[bck_col] >> 8) & 0xff) + fa * ((mg_palette[for_col] >> 8) & 0xff); \
1719  tmp_c |= (comp / alpha_c) << 8; \
1720  comp = ba * (mg_palette[bck_col] & 0xff) + fa * (mg_palette[for_col] & 0xff); \
1721  tmp_c |= (comp / alpha_c); \
1722  aa_8bit_cols[2] = OSD_FindNearestColourIndex(tmp_c); \
1723  aa_8bit_cols[3] = for_col; \
1724  }
1725 
1726 static U8BIT aa_8bit_cols[4] = {OFFSET_TRANS, OFFSET_TRANS, OFFSET_TRANS, OFFSET_TRANS};
1727 
1728 #include "textdrawfn.h"
1729 
1730 #undef TextDrawFn
1731 #undef RenderGlyphFn
1732 #undef TDColor
1733 #undef CalcColorArray
1734 #undef MakeTDColor
1735 #undef GreyValue
1736 #undef SRC_FORE_MAX
1737 #undef IsOpaqueColor
1738 #undef NotTransparent
1739 #undef CombineAlphaColour
1740 
1741 #endif /*OSD_8_BIT*/
1742 
1743 
1744 #ifdef OSD_16_BIT
1745 
1750 #define TextDrawFn TextDraw16Bit
1751 #define RenderGlyphFn RenderGlyph16Bit
1752 #define TDColor HD2Color
1753 #define MakeTDColor(col) MakeHD2Color( col )
1754 #define GreyValue(val) val
1755 #define SRC_FORE_MAX 255
1756 #define IsOpaqueColor( tcol ) ((tcol >> 12) == 0xf)
1757 #define NotTransparent( fcol ) ((fcol >> 28) != 0x0)
1758 #define CombineAlphaColour(pixel, grey_val, full_col, fore_col) \
1759  grey_val *= (full_col >> 24); \
1760  if (grey_val & 0xf000) { pixel = (fore_col & 0x0fff) | (grey_val & 0xf000); }
1761 
1762 #include "textdrawfn.h"
1763 
1764 #undef TextDrawFn
1765 #undef RenderGlyphFn
1766 #undef CombineAlphaColour
1767 
1772 #define TextDrawFn TextDraw16BitBlend
1773 #define RenderGlyphFn RenderGlyph16Blend
1774 #define CombineAlphaColour(pixel, grey_val, full_col, fore_col) \
1775  grey_val *= (full_col >> 24); \
1776  if (grey_val & 0xff00) { \
1777  register U32BIT fa, ba, comp, tmp_c, alpha_c; \
1778  ba = (U8BIT)(pixel >> 12); \
1779  comp = ba * 17; \
1780  alpha_c = ((((15 - ba) *grey_val) + 1912) / 3825) + comp; \
1781  fa = (U8BIT)(grey_val / SRC_FORE_MAX); \
1782  ba = (((255 ^ fa) *comp) + 127) / 255; \
1783  tmp_c = (alpha_c / 17) << 12; \
1784  comp = ba * ((pixel >> 8) & 0xf) + fa * ((fore_col >> 8) & 0xf); \
1785  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 8; \
1786  comp = ba * ((pixel >> 4) & 0xf) + fa * ((fore_col >> 4) & 0xf); \
1787  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 4; \
1788  comp = ba * (pixel & 0xf) + fa * (fore_col & 0xf); \
1789  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c); \
1790  pixel = (U16BIT)tmp_c; \
1791  }
1792 
1793 #include "textdrawfn.h"
1794 
1795 #undef TextDrawFn
1796 #undef RenderGlyphFn
1797 #undef TDColor
1798 #undef MakeTDColor
1799 #undef SRC_FORE_MAX
1800 #undef IsOpaqueColor
1801 #undef NotTransparent
1802 #undef CombineAlphaColour
1803 
1804 #endif /* OSD_16_BIT */
1805 
1806 
1807 #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
1808 
1813 #define TextDrawFn TextDraw32Bit
1814 #define RenderGlyphFn RenderGlyph32Bit
1815 #define TDColor OSDColor
1816 #define GreyValue(val) val
1817 #define MakeTDColor(col) AlphaPlatform(col)
1818 #define SRC_FORE_MAX 255
1819 #define IsOpaqueColor( tcol ) ((tcol >> 24) == MAX_ALPHA)
1820 #define NotTransparent( fcol ) ((fcol >> 24) != 0x00)
1821 #define CombineAlphaColour(pixel, grey_val, full_col, fore_col) \
1822  grey_val *= CalcAlpha(fore_col >> 24); \
1823  if (grey_val > 127) { pixel = (fore_col & 0xffffff) | ((grey_val << 16) & 0xff000000); }
1824 
1825 #include "textdrawfn.h"
1826 
1827 #undef TextDrawFn
1828 #undef RenderGlyphFn
1829 #undef CombineAlphaColour
1830 
1835 #define TextDrawFn TextDraw32BitBlend
1836 #define RenderGlyphFn RenderGlyph32Blend
1837 #define CombineAlphaColour(pixel, grey_val, full_col, fore_col) \
1838  grey_val *= CalcAlpha(fore_col >> 24); \
1839  if (grey_val > 127) { \
1840  register U32BIT fa, ba, comp, tmp_c, alpha_c; \
1841  ba = pixel >> 24; \
1842  alpha_c = ((((MAX_ALPHA - ba) *grey_val) + ((MAX_ALPHA *255) / 2)) / (MAX_ALPHA *255)) + ba; \
1843  fa = (U8BIT)(grey_val / SRC_FORE_MAX); \
1844  ba = (((MAX_ALPHA - fa) *ba) + (MAX_ALPHA / 2)) / MAX_ALPHA; \
1845  tmp_c = alpha_c << 24; \
1846  comp = ba * ((pixel >> 16) & 0xff) + fa * ((fore_col >> 16) & 0xff); \
1847  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 16; \
1848  comp = ba * ((pixel >> 8) & 0xff) + fa * ((fore_col >> 8) & 0xff); \
1849  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c) << 8; \
1850  comp = ba * (pixel & 0xff) + fa * (fore_col & 0xff); \
1851  tmp_c |= ((comp + (alpha_c >> 1)) / alpha_c); \
1852  pixel = tmp_c; \
1853  }
1854 
1855 #include "textdrawfn.h"
1856 
1857 #undef TextDrawFn
1858 #undef RenderGlyphFn
1859 #undef TDColor
1860 #undef MakeTDColor
1861 #undef SRC_FORE_MAX
1862 #undef IsOpaqueColor
1863 #undef NotTransparent
1864 #undef SignificantFore
1865 #undef CombineAlphaColour
1866 
1867 #endif /* OSD_32_BIT */
1868 
1869 
1870 static CharData* GetCharArray( const TextString unistr, pDrawTextAttrib attrib, CharData *chars )
1871 {
1872  U32BIT m_size, glph_count;
1873  CharData *char_data;
1874  if (unistr.len < MAX_NUM_CHARS)
1875  {
1876  char_data = chars;
1877  }
1878  else
1879  {
1880  /* check that the 'chars' array on the stack is big enough,
1881  * if not get some heap space for it */
1882  m_size = 0;
1883  for (glph_count = 0; glph_count != unistr.len; glph_count++)
1884  {
1885  switch (unistr.data[glph_count])
1886  {
1887  case UNICODE_ESC:
1888  if (glph_count + 1 != unistr.len)
1889  {
1890  /*Markup sequence*/
1891  glph_count++;
1892  if ((unistr.data[glph_count] <= 0x5e) &&
1893  (unistr.data[glph_count] >= 0x40) &&
1894  (glph_count + 1 != unistr.len))
1895  {
1896  glph_count++;
1897  if ((glph_count + unistr.data[glph_count]) <= unistr.len)
1898  {
1899  glph_count += unistr.data[glph_count];
1900  }
1901  }
1902  }
1903  break;
1904 
1905  case UNICODE_SPACE:
1906  case UNICODE_TAB:
1907  #if 0
1908  case UNICODE_HARD_SPACE:
1909  case UNICODE_FIGURE_SPACE:
1910  #endif
1911  if ((attrib->justify & JFY_HZ_MASK) == JUSTIFY_H_CENTRE)
1912  {
1913  m_size++;
1914  }
1915  break;
1916 
1917  default:
1918  if (unistr.data[glph_count] > 0x20)
1919  {
1920  /* assume this is a printable char */
1921  m_size++;
1922  }
1923  }
1924  }
1925  if (attrib->entry_point != -1)
1926  {
1927  m_size++;
1928  }
1929  if (m_size > MAX_NUM_CHARS)
1930  {
1931  /* array 'chars' ain't big enough, so allocate buffer for character descriptions */
1932  char_data = (CharData *)OSD_MemAlloc( sizeof(CharData) * m_size );
1933  TRACE(TTEXT, ("malloc char_data array (sz=%d) at 0x%x", m_size, char_data))
1934  }
1935  else
1936  {
1937  char_data = chars;
1938  }
1939  }
1940  return char_data;
1941 }
1942 
1943 /*---global function definitions---------------------------------------------*/
1944 
1953 void* MG_DrawUKText( const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box )
1954 {
1955  S_FontDetails *font_ptr;
1956  S_FontSize *f_szdata;
1957  S_SURFACE *canvas = 0;
1958  CharData *char_data;
1959  CharData chars[MAX_NUM_CHARS];
1960  LineLimit lines[MAX_NUM_LINES + 1];
1961  U16BIT line_count, glph_count;
1962 
1963  assert( attrib );
1964 
1965  TRACE(TTEXT, ("SD box=(%d,%d,%d,%d)", txt_box.left, txt_box.top, txt_box.left + txt_box.width, txt_box.top + txt_box.height))
1966  TRACE_UNIC(TTEXT, unistr.data, unistr.len)
1967 
1968  f_szdata = attrib->font.hdl;
1969 
1970  if ((f_szdata != NULL) &&
1971  (txt_box.width > f_szdata->bb_sd_width) &&
1972  (txt_box.height >= f_szdata->bb_sd_height))
1973  {
1974  U16BIT available_lines;
1975  S_REGION draw;
1976 
1977  TRACE(TTEXT, ("font=%x width=%d, height=%d posn=(%d,%d) ls=%d", attrib->font.hdl->fnt_id,
1978  txt_box.width, txt_box.height, txt_box.left, txt_box.top, attrib->line_space))
1979  /*See MHEG HD spec in DBook section 14.11.3.2 "Bounding box transformation" for scaling of boxes */
1980  draw.left = (S16BIT)((txt_box.left * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div);
1981  draw.top = (S16BIT)((txt_box.top * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div);
1982  draw.right = (S16BIT)txt_box.width;
1983  draw.bottom = (S16BIT)txt_box.height;
1984  draw.right = (S16BIT)(((draw.right + txt_box.left) * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div);
1985  draw.bottom = (S16BIT)(((draw.bottom + txt_box.top) * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div);
1986 
1987  /* box has some size, and may be able to fit some text in */
1988  if (attrib->line_space == 0)
1989  {
1990  /* infinite lines: all on same place! */
1991  available_lines = MAX_NUM_LINES;
1992  }
1993  else
1994  {
1995  available_lines = (U16BIT)(((txt_box.height - f_szdata->bb_sd_height) / attrib->line_space) + 1);
1996  if (available_lines > MAX_NUM_LINES)
1997  {
1998  /* defensive programming */
1999  TRACE(TERROR, ("Num of text lines was restricted from %d to %d", available_lines, MAX_NUM_LINES))
2000  available_lines = MAX_NUM_LINES;
2001  }
2002  }
2003 
2004  MG_CheckCache( f_szdata );
2005 
2006  char_data = GetCharArray( unistr, attrib, chars );
2007  if (char_data == NULL)
2008  {
2009  /*out of memory*/
2010  return 0;
2011  }
2012  font_ptr = MG_FindFont(f_szdata);
2013  line_count = PreparePrintableData( unistr, attrib, f_szdata, font_ptr, draw.right - draw.left,
2014  (U16BIT)txt_box.width, available_lines, lines, char_data, &glph_count );
2015  if (line_count > 0 && glph_count > 0)
2016  {
2017  #ifdef TRACING
2018  TRACE(TTEXT, ("HD box=(%d,%d,%d,%d)", draw.left, draw.top, draw.right, draw.bottom))
2019  TRACE(TTEXT, ("lines(%d,%d) left=%d avl_width=%d", available_lines, line_count, f_szdata->bound_box.left,
2020  txt_box.width - f_szdata->spxl_xleftoffset))
2021  if (TTEXT & mheg_trace_debug)
2022  trace_lines( line_count, lines, char_data, f_szdata->fnt_id & 0xff, font_ptr->metric_resolution );
2023  #endif /*TRACING*/
2024 
2025  canvas = OSD_MemAlloc( sizeof(S_SURFACE));
2026 
2027  if (canvas != NULL)
2028  {
2029  canvas->width = draw.right - draw.left;
2030  canvas->height = draw.bottom - draw.top;
2031  canvas->srf_type = SRF_TYPE_TXT;
2032  TRACE(TTEXT, ("canvas=(%d,%d)", canvas->width, canvas->height))
2033 
2034  if (attrib->line_space == 0)
2035  {
2036  available_lines = line_count;
2037  }
2038 
2040  {
2041  #ifdef OSD_8_BIT
2042  canvas->col_buff = OSD_MemAlloc( canvas->width * canvas->height );
2043  canvas->hw_handle = NULL;
2044  if (canvas->col_buff != NULL)
2045  {
2046  canvas->buff_pitch = canvas->width;
2047  memset( canvas->col_buff,
2048  OSD_FindNearestColourIndex(0x00000000),
2049  canvas->width * canvas->height );
2050 
2051  TextDraw8Bit( lines, char_data, f_szdata, font_ptr->face,
2053  attrib->line_space, txt_box.top, txt_box.height,
2054  line_count, available_lines, canvas );
2055  }
2056  #endif
2057  }
2059  {
2060  #ifdef OSD_16_BIT
2061  canvas->hw_handle = STB_OSDMhegCreateSurface( canvas->width, canvas->height,
2062  TRUE, 0x0000 );
2063  OSD_DbgAddSurf( canvas );
2064  if (canvas->hw_handle != NULL)
2065  {
2066  canvas->buff_pitch = canvas->width << 1;
2067  canvas->col_buff = STB_OSDMhegLockBuffer( canvas->hw_handle, &canvas->buff_pitch );
2068  if (canvas->col_buff)
2069  {
2070  TextDraw16Bit( lines, char_data, f_szdata, font_ptr->face,
2072  attrib->line_space, txt_box.top, txt_box.height,
2073  line_count, available_lines, canvas );
2075  }
2076  }
2077  #endif
2078  }
2079 
2080  ELSE
2081  {
2082  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
2083  canvas->hw_handle = STB_OSDMhegCreateSurface( canvas->width, canvas->height,
2084  TRUE, 0x00000000 );
2085  OSD_DbgAddSurf( canvas );
2086  if (canvas->hw_handle != NULL)
2087  {
2088  canvas->buff_pitch = canvas->width << 2;
2089  canvas->col_buff = STB_OSDMhegLockBuffer( canvas->hw_handle, &canvas->buff_pitch );
2090  if (canvas->col_buff)
2091  {
2092  TextDraw32Bit( lines, char_data, f_szdata, font_ptr->face,
2094  attrib->line_space, txt_box.top, txt_box.height,
2095  line_count, available_lines, canvas );
2097  }
2098  }
2099  #endif
2100  }
2101  }
2102  }
2103 
2104  if (char_data != chars)
2105  {
2106  OSD_MemFree( char_data );
2107  }
2108  }
2109 
2110  TRACE(TTEXT, ("return=0x%x\n", canvas))
2111  return canvas;
2112  /* returning NULL is not necessarily an error. It does that when no actual text to be displayed.
2113  * This code assumes that where an empty box is required (as when box is too small for text),
2114  * the higher level software will draw it.
2115  */
2116 }
2117 
2125 {
2126  CharData *char_data;
2127  CharData chars[MAX_NUM_CHARS];
2128  LineLimit lines[2];
2129  U16BIT line_count, glph_count;
2130  H_FontSize f_sz;
2131 
2132  assert( attrib );
2133 
2134  TRACE_UNIC(TTEXT, unistr.data, unistr.len)
2135 
2136  f_sz = attrib->font.hdl;
2137 
2138  if (f_sz == NULL)
2139  {
2140  TRACE(TERROR, ("f_sz NULL"))
2141  lines[0].l_width = 0;
2142  }
2143  else
2144  {
2145  TRACE(TTEXT, ("font id=%x", f_sz->fnt_id))
2146 
2147  MG_CheckCache( f_sz );
2148 
2149  char_data = GetCharArray( unistr, attrib, chars );
2150  if (char_data != NULL)
2151  {
2152  /* Setting justify to Hz End, means that width of spaces are counted (also tab => space) */
2153  attrib->justify = JUSTIFY_H_END;
2154  line_count = PreparePrintableData( unistr, attrib, f_sz, MG_FindFont(f_sz), mg_ctxt.out_osd_width,
2155  mg_ctxt.out_osd_width, 1, lines, char_data, &glph_count );
2156  if (line_count == 0)
2157  {
2158  lines[0].l_width = 0;
2159  }
2160  if (char_data != chars)
2161  {
2162  OSD_MemFree( char_data );
2163  }
2164  }
2165  }
2166 
2167  TRACE(TTEXT, ("return=%d", lines[0].l_width))
2168  return (S16BIT)lines[0].l_width;
2169 }
2170 
2178 void MG_DrawScreenText( const TextString unistr, pDrawTextAttrib attrib, S_SURFACE *canvas )
2179 {
2180  S_FontDetails *font_ptr;
2181  S_FontSize *f_szdata;
2182  CharData *char_data;
2183  CharData chars[MAX_NUM_CHARS];
2184  LineLimit lines[2];
2185  U16BIT line_count, glph_count;
2186 
2187  assert( attrib );
2188 
2189  TRACE(TTEXT, ("box=%d,%d", canvas->width, canvas->height))
2190  TRACE_UNIC(TTEXT, unistr.data, unistr.len)
2191 
2192  f_szdata = attrib->font.hdl;
2193 
2194  if (f_szdata != NULL && canvas != NULL && canvas->col_buff != NULL &&
2195  (canvas->width > f_szdata->bb_sd_width) &&
2196  (canvas->height >= f_szdata->bb_sd_height))
2197  {
2198  TRACE(TTEXT, ("font=%x ls=%d", attrib->font.hdl->fnt_id, attrib->line_space))
2199 
2200  //MG_CheckCache( f_szdata );
2201 
2202  char_data = GetCharArray( unistr, attrib, chars );
2203  if (char_data != NULL)
2204  {
2205  font_ptr = MG_FindFont(f_szdata);
2206  line_count = PreparePrintableData( unistr, attrib, f_szdata, font_ptr, canvas->width,
2207  canvas->width, 1, lines, char_data, &glph_count );
2208  if (line_count > 0 && glph_count > 0)
2209  {
2210  #ifdef TRACING
2211  TRACE(TTEXT, ("lines(%d,%d)", 1, line_count))
2212  if (TTEXT & mheg_trace_debug)
2213  trace_lines( line_count, lines, char_data, f_szdata->fnt_id & 0xff, font_ptr->metric_resolution );
2214  #endif /*TRACING*/
2215 
2216  if (canvas != NULL)
2217  {
2218  TRACE(TTEXT, ("canvas (buf=%p,%d,%d)", canvas->col_buff, canvas->width, canvas->height))
2219 
2221  {
2222  #ifdef OSD_8_BIT
2223  TextDraw8Bit( lines, char_data, f_szdata, font_ptr->face,
2225  attrib->line_space, 0, canvas->height,
2226  line_count, 1, canvas );
2227  #endif
2228  }
2230  {
2231  #ifdef OSD_16_BIT
2232  TextDraw16BitBlend( lines, char_data, f_szdata, font_ptr->face,
2234  attrib->line_space, 0, canvas->height,
2235  line_count, 1, canvas );
2236  #endif
2237  }
2238 
2239  ELSE
2240  {
2241  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
2242  TextDraw32BitBlend( lines, char_data, f_szdata, font_ptr->face,
2244  attrib->line_space, 0, canvas->height,
2245  line_count, 1, canvas );
2246  #endif
2247  }
2248  }
2249  }
2250 
2251  if (char_data != chars)
2252  {
2253  OSD_MemFree( char_data );
2254  }
2255  }
2256  }
2257  else
2258  {
2259  /* Access often code causes things to end up here - appearance seems ok anyway */
2260  if (f_szdata != NULL && canvas != NULL)
2261  {
2262  TRACE(TTEXT, ("Size too small: (%d < %d)? or (%d < %d)?", canvas->width, f_szdata->bb_sd_width, canvas->height, f_szdata->bb_sd_height));
2263  }
2264  }
2265 }
2266 
2275 void* MG_DrawText( const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box )
2276 {
2277 #ifdef HK_PROFILE
2278  if (attrib->font.fp.index == HK_FNT_MAGIC)
2279  {
2280  return MG_DrawHKText( unistr, attrib, txt_box );
2281  }
2282  else
2283 #endif
2284  {
2285  return MG_DrawUKText( unistr, attrib, txt_box );
2286  }
2287 }
2288 
FT_UInt glyph_ndx_space
Definition: mg_font.h:104
#define TPRINT(t, x)
Definition: glue_debug.h:119
OSD utility functions.
FT_UInt space_horiz_adv
Definition: mg_font.h:105
S16BIT left
Definition: mg_drawtext.h:67
U16BIT height
Definition: mg_font.h:80
U16BIT out_osd_width
Definition: mg_ctxt.h:81
U8BIT bb_sd_height
Definition: mg_font.h:90
#define IF_COL_DEPTH(cd)
Definition: mg_ctxt.h:65
#define TRANSPARENT_COLOUR
Definition: mg_drawtext.c:51
U16BIT font_ndx
Definition: mg_font.h:109
S16BIT letter_space
Definition: mg_drawtext.h:109
U8BIT spxl_xleftoffset
Definition: mg_font.h:93
S32BIT position
Definition: mg_drawtext.c:137
#define RGBT(r, g, b, t)
Definition: tmcolor.h:48
U16BIT start_ndx
Definition: mg_drawtext.c:140
S16BIT index
Definition: mg_drawtext.h:97
#define OSD_MemAlloc
Definition: glue_memory.h:96
U16BIT width
Definition: mg_font.h:81
#define WRAP_VERTICAL
Definition: mg_drawtext.h:44
#define U_CTRL_NULL
Definition: mg_drawtext.c:55
U8BIT width
Definition: mg_font.h:73
#define U_CTRL_P
Definition: mg_drawtext.c:68
void * MG_DrawUKText(const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box)
Create Surface and draw text string on it and terminate freetype library.
Definition: mg_drawtext.c:1953
S32BIT spxl_tab_start
Definition: mg_drawtext.c:169
S16BIT MG_TextWidth(const TextString unistr, pDrawTextAttrib attrib)
Definition: mg_drawtext.c:2124
void MG_DrawScreenText(const TextString unistr, pDrawTextAttrib attrib, S_SURFACE *canvas)
Single line text string drawn on existing Surface.
Definition: mg_drawtext.c:2178
void * col_buff
Definition: mg_osd.h:41
#define MTRC_POSN(mll, tls, mr, fsz)
Definition: mg_drawtext.c:110
#define U_CTRL_RS
Definition: mg_drawtext.c:81
U16BIT mlt
Definition: mg_ctxt.h:73
#define DBG_PRINTF(...)
Definition: glue_debug.h:127
S8BIT advance
Definition: mg_font.h:69
#define U_CTRL_H
Definition: mg_drawtext.c:63
const char * data
Definition: mh5gate.c:56
S32BIT hpxl_line_end
Definition: mg_drawtext.c:169
S32BIT hpxl_pen_posn
Definition: mg_drawtext.c:169
CacheSbit * sbit_cache
Definition: mg_font.h:84
#define U_CTRL_GS
Definition: mg_drawtext.c:80
struct s_properties S_PROPERTIES
pHyperAttribs p_ha
Definition: mg_drawtext.h:104
S8BIT char_adv
Definition: mg_drawtext.c:194
#define TRACE_UNIC(t, d, l)
Definition: glue_debug.h:122
U16BIT uni_chr
Definition: mg_drawtext.c:149
#define JUSTIFY_H_JUSTIFIED
Definition: mg_drawtext.h:40
#define U_CTRL_E
Definition: mg_drawtext.c:60
LineLimit break_line
Definition: mg_drawtext.c:188
Debug tracing.
U8BIT width
Definition: mg_drawtext.c:155
Font file handling with the Freetype.
#define U_CTRL_B
Definition: mg_drawtext.c:57
#define U_CTRL_Q
Definition: mg_drawtext.c:69
U32BIT OSDColor
Definition: osdtypes.h:41
#define COLOUR_FORMAT_ARGB4444
Definition: mheg5_control.h:80
S32BIT m_to_pix_mlt
Definition: mg_drawtext.c:169
U8BIT save_colour
Definition: mg_drawtext.h:91
OSDColor link_colour
Definition: mg_drawtext.h:83
void * MG_DrawText(const TextString unistr, pDrawTextAttrib attrib, const VRect txt_box)
Create Surface and draw text string on it and terminate freetype library.
Definition: mg_drawtext.c:2275
#define U_CTRL_U
Definition: mg_drawtext.c:73
#define U_CTRL_Z
Definition: mg_drawtext.c:78
S16BIT font_index
Definition: mg_drawtext.c:193
#define WRAP_WORDS
Definition: mg_drawtext.h:42
S8BIT figure_adv
Definition: mg_font.h:89
#define BUILT_IN_FONT
Definition: mg_font.h:36
S32BIT l_width
Definition: mg_drawtext.c:138
S_RATIO osd_y
Definition: mg_ctxt.h:86
S16BIT top
Definition: osdtypes.h:46
OSDColor fore_colour
Definition: mg_drawtext.h:105
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;.
#define FONT_STYLE_NO_SCALE
Definition: mg_drawtext.h:34
#define S_SPIXEL_POSITION(pp)
Definition: mg_drawtext.c:118
FT_Face face
Definition: mg_font.h:102
#define U_CTRL_F
Definition: mg_drawtext.c:61
S32BIT total_letter_space
Definition: mg_drawtext.c:169
int16_t S16BIT
Definition: techtype.h:85
#define UNICODE_SPACE
Definition: mg_drawtext.c:85
#define P_POINTS_POSITION(pp)
Definition: mg_drawtext.c:128
S32BIT pixel_par_x
Definition: mg_drawtext.c:169
E_HDMode mg_hd_mode
Definition: mg_font.c:76
U16BIT face_type
Definition: mg_font.h:110
U16BIT gf_ndx
Definition: mg_drawtext.c:150
U16BIT line_num
Definition: mg_drawtext.c:139
#define SRF_TYPE_TXT
Definition: mg_osd.h:32
#define UNICODE_TEXT_COLOUR_START
Definition: mg_drawtext.c:95
OSDColor colour
Definition: mg_drawtext.c:151
U32BIT buff_pitch
Definition: mg_osd.h:43
#define S_METRIC_POSITION(pp)
Definition: mg_drawtext.c:114
uint8_t U8BIT
Definition: techtype.h:82
U16BIT * data
Definition: mg_drawtext.h:77
S8BIT space_adv
Definition: mg_font.h:88
#define U_CTRL_K
Definition: mg_drawtext.c:64
#define U_CTRL_R
Definition: mg_drawtext.c:70
S32BIT hpxl_letter_offset
Definition: mg_drawtext.c:169
#define U_CTRL_N
Definition: mg_drawtext.c:66
EBreakState
Definition: mg_drawtext.c:158
S32BIT metric_break_length
Definition: mg_drawtext.c:169
U32BIT current_fnt_id
Definition: mg_font.h:111
void * hw_handle
Definition: mg_osd.h:42
#define COLOUR_STACK_SIZE
Definition: mg_drawtext.c:46
#define JUSTIFY_H_CENTRE
Definition: mg_drawtext.h:39
S_FontProp fp
Definition: mg_drawtext.h:116
Memory functions.
#define UNICODE_HYPER_ANCHOR_START
Definition: mg_drawtext.c:93
S_FontSize * p_font_size
Definition: mg_drawtext.c:184
U16BIT end_ndx
Definition: mg_drawtext.c:141
FT_UInt horiz_adv[CHAR_CACHE_SIZE]
Definition: mg_font.h:107
VBox bound_box
Definition: mg_font.h:82
#define JUSTIFY_V_END
Definition: mg_drawtext.h:51
S32BIT metric_line_length
Definition: mg_drawtext.c:169
S16BIT entry_point
Definition: mg_drawtext.h:108
#define FTYPE_PFR
Definition: mg_font.h:39
U16BIT left
Definition: mg_font.h:60
#define JUSTIFY_H_START
Definition: mg_drawtext.h:37
#define P_MTRC_2_SPXL(pp, mtr)
Definition: mg_drawtext.c:124
U32BIT fnt_id
Definition: mg_font.h:87
#define U_CTRL_FS
Definition: mg_drawtext.c:79
S32BIT pnts_font_size
Definition: mg_drawtext.c:169
S_MGContext mg_ctxt
Definition: mg_osd.c:144
int8_t S8BIT
Definition: techtype.h:83
#define FIRST_CACHE_CHAR
Definition: mg_font.h:34
U16BIT height
Definition: mg_osd.h:40
Interface to OSD.
#define JFY_HZ_MASK
Definition: mg_drawtext.h:46
S32BIT mtrc_position
Definition: mg_drawtext.c:147
S16BIT right
Definition: osdtypes.h:47
#define U_CTRL_W
Definition: mg_drawtext.c:75
U16BIT spxl_box_width
Definition: mg_drawtext.c:191
#define FONT_STYLE_SQUARE
Definition: mg_drawtext.h:33
#define U_CTRL_L
Definition: mg_drawtext.c:65
U8BIT pnts_xleftoffset
Definition: mg_font.h:94
S16BIT top
Definition: mg_drawtext.h:68
#define UNICODE_LF
Definition: mg_drawtext.c:87
#define ELSE
Definition: mg_ctxt.h:66
#define JUSTIFY_H_END
Definition: mg_drawtext.h:38
#define U_CTRL_O
Definition: mg_drawtext.c:67
U8BIT anchor_wrap
Definition: mg_drawtext.h:90
#define OSD_DbgAddSurf(s)
Definition: mg_osd.h:90
int len
Definition: mh5gate.c:57
#define U_CTRL_C
Definition: mg_drawtext.c:58
U8BIT font_style
Definition: mg_drawtext.c:196
#define U_CTRL_T
Definition: mg_drawtext.c:72
#define MAX_NUM_CHARS
Definition: mg_drawtext.c:107
int32_t S32BIT
Definition: techtype.h:87
S16BIT bottom
Definition: osdtypes.h:48
#define UNICODE_HYPER_ANCHOR_END
Definition: mg_drawtext.c:94
#define JUSTIFY_V_JUSTIFIED
Definition: mg_drawtext.h:53
#define MAX_NUM_LINES
Definition: mg_drawtext.c:106
#define UNICODE_TAB
Definition: mg_drawtext.c:86
OSDColor active_colour
Definition: mg_drawtext.h:84
S32BIT real_position
Definition: mg_drawtext.c:146
#define UNICODE_CR
Definition: mg_drawtext.c:88
uint16_t U16BIT
Definition: techtype.h:84
U16BIT width
Definition: mg_osd.h:39
#define P_METRIC_POSITION(pp)
Definition: mg_drawtext.c:126
#define U_CTRL_Y
Definition: mg_drawtext.c:77
S8BIT char_left
Definition: mg_drawtext.c:194
U16BIT len
Definition: mg_drawtext.h:76
FT_UInt glyph_last
Definition: mg_drawtext.c:185
#define U_CTRL_V
Definition: mg_drawtext.c:74
U16BIT height
Definition: mg_drawtext.h:70
#define JUSTIFY_V_START
Definition: mg_drawtext.h:50
S16BIT mtrc_advance
Definition: mg_drawtext.c:148
OSDColor visit_colour
Definition: mg_drawtext.h:85
S16BIT focus_position
Definition: mg_drawtext.h:86
U8BIT srf_type
Definition: mg_osd.h:45
struct _LineLimit LineLimit
S16BIT left
Definition: osdtypes.h:45
#define COLOUR_FORMAT_PALETTE
Definition: mheg5_control.h:79
#define UNICODE_FIGURE_SPACE
Definition: mg_drawtext.c:91
define asserts
#define FALSE
Definition: techtype.h:68
#define P_SPIXEL_POSITION(pp)
Definition: mg_drawtext.c:130
S32BIT metric_resn
Definition: mg_drawtext.c:169
#define U_CTRL_US
Definition: mg_drawtext.c:82
#define UNICODE_HARD_SPACE
Definition: mg_drawtext.c:90
U16BIT hpxl_box_width
Definition: mg_drawtext.c:191
#define U_CTRL_A
Definition: mg_drawtext.c:56
FT_UInt glyph_ndx[CHAR_CACHE_SIZE]
Definition: mg_font.h:108
FT_UInt fig_horiz_adv
Definition: mg_font.h:106
U16BIT div
Definition: mg_ctxt.h:74
struct _CharData CharData
S16BIT number_of_links
Definition: mg_drawtext.h:87
void * STB_OSDMhegLockBuffer(void *surface, U32BIT *pPitch)
Converts hardware surface handle returned by STB_OSDMhegCreateSurface() to buffer address that the en...
#define CHAR_CACHE_SIZE
Definition: mg_font.h:35
S_FontDetails * MG_FindFont(H_FontSize f_sz)
Get font from size.
Definition: mg_font.c:542
S32BIT hpxl_last_tab
Definition: mg_drawtext.c:169
U16BIT width
Definition: mg_drawtext.h:69
MHEG text render that uses the Freetype font library.
U8BIT BOOLEAN
Definition: techtype.h:99
#define U_CTRL_X
Definition: mg_drawtext.c:76
S32BIT break_letter_space
Definition: mg_drawtext.c:169
#define TRUE
Definition: techtype.h:69
void MG_CheckCache(S_FontSize *f_szdata)
Definition: mg_font.c:841
#define UNICODE_ESC
Definition: mg_drawtext.c:89
#define U_CTRL_D
Definition: mg_drawtext.c:59
S32BIT pnts_tab_start
Definition: mg_drawtext.c:169
Interface to the MHEG text render that uses Freetype font library.
#define U_CTRL_S
Definition: mg_drawtext.c:71
#define UNICODE_HYPER_ATTRIB_START
Definition: mg_drawtext.c:97
S32BIT m_to_pix_div
Definition: mg_drawtext.c:169
U8BIT markup_state
Definition: mg_drawtext.h:89
#define HK_FNT_MAGIC
Definition: mg_drawtext.h:63
#define UNICODE_TEXT_COLOUR_END
Definition: mg_drawtext.c:96
U8BIT bb_sd_width
Definition: mg_font.h:91
FT_UInt metric_resolution
Definition: mg_font.h:112
LineLimit * p_current_line
Definition: mg_drawtext.c:187
#define OSD_MemFree
Definition: glue_memory.h:97
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 ...
S_RATIO osd_x
Definition: mg_ctxt.h:85
S8BIT left
Definition: mg_font.h:71
uint32_t U32BIT
Definition: techtype.h:86
#define U_CTRL_G
Definition: mg_drawtext.c:62
FT_UInt glyph_index
Definition: mg_drawtext.c:185
void ProcessNewLine(S_PROPERTIES *pp, CharData *chars, S_FontSize *f_sz_data, U16BIT line_num, U8BIT justify)
Process for adding a new line.
Definition: mg_drawtext.c:1163
void STB_OSDMhegUnlockBuffer(void *surface)
This function informs HW that MHEG5 is finished writing to the buffer.
#define UNICODE_HYPER_ATTRIB_END
Definition: mg_drawtext.c:98
H_FontSize hdl
Definition: mg_drawtext.h:115
#define TRACE(t, x)
Definition: glue_debug.h:118
#define GLYPH_NDX(x)
Definition: mg_drawtext.c:103
union _DrawTextAttrib::@14 font