source: svn/trunk/newcon3bcm2_21bu/dta/src/app/bgfx.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 70.0 KB
Line 
1/***************************************************************
2**
3** Broadcom Corp. Confidential
4** Copyright 2002 Broadcom Corp. All Rights Reserved.
5**
6** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
7** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
8** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
9** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
10**
11** Description: bgfx core implementation
12**
13** Created: 8/22/2002 by Jeffrey P. Fisher
14**
15**
16**
17****************************************************************/
18
19/** include files **/
20#include "bgfx.h"
21
22#define ZORDER_TUNNEL   3
23#define ZORDER_FX       2
24#define ZORDER_TOP      1
25#define ZORDER_BOTTOM   0
26
27
28#define SURF_WIDTH 720
29
30#define BGFX_MIN(x,y)   ((x < y) ? x : y)
31#define bgfx_clut8_to_rgb(clut,c) (uint32_t)(clut[c])   
32
33#define MAX_TEXT_BOX_CHARS  512
34#define MAX_LINES           16
35static unsigned long s_null_char    = 0x00000000;
36static unsigned long s_space_char   = 0x00000020;
37static unsigned long s_hyphen_char  = 0x0000002D;
38static unsigned long s_newline_char = 0x0000000A;
39
40/* structure to maintain per-line info */
41typedef struct lineinfo_t
42{
43    uint16_t w,h;               /* width and height of line */
44    uint16_t e;                 /* where line ends in text string */
45    uint16_t c;                 /*  number of printable chars on line */
46} lineinfo_t;
47
48/* blit row a1 to clut 8 destination */
49static inline void bgfx_render_a1_to_clut4( uint8_t *src, uint8_t *dst, 
50                                                                                        int width, uint8_t c, int odd_pixel )
51{
52        int i;
53
54        BGFX_TRACE(("%p,%p,%d,0x%02x\n",src,dst,width,c));
55        for (i = 0; i < width; i++)
56        {
57                if (src[i>>3] & (1<<(7-(i%8))))
58                {
59                        if (odd_pixel & 1)
60                        {
61                                *dst &= 0xF0;
62                                *dst |= (c & 0xF);
63                        }
64                        else
65                        {
66                                *dst &= 0xF;
67                                *dst |= (c & 0xF) << 4;
68                        }
69                        BGFX_TRACE(("%d,",i));
70                }
71                if (odd_pixel)
72                {
73                        odd_pixel = 0;
74                        dst++;
75                }
76                else
77                        odd_pixel = 1;
78
79        }
80        BGFX_TRACE(("\n"));
81}
82
83/* blit row a8 to clut 8 destination */
84static inline void bgfx_render_a8_to_clut4( uint8_t *src, uint8_t *dst, int width, uint8_t c )
85{
86        int i;
87        for (i = 0; i < width; i++)
88        {
89                if (*src > 0x80)
90                {
91                        if (i & 1)
92                        {
93                                *dst &= 0xF0;
94                                *dst |= (c & 0xF);
95                        }
96                        else
97                        {
98                                *dst &= 0xF;
99                                *dst |= (c & 0xF) << 4;
100                        }
101                }
102                BGFX_TRACE(("0x%02x(0x%02x)",*src,*dst));
103                if (i & 1)
104                        dst++;
105                src++;
106        }
107        BGFX_TRACE(("\n"));
108}
109
110
111/* blit row a1 to clut 8 destination */
112static inline void bgfx_render_a1_to_clut8( uint8_t *src, uint8_t *dst, int width, uint8_t c )
113{
114        int i;
115
116        BGFX_TRACE(("%p,%p,%d,0x%02x\n",src,dst,width,c));
117        for (i = 0; i < width; i++)
118        {
119                if (src[i>>3] & (1<<(7-(i%8))))
120                {
121                        *dst = c;
122                        BGFX_TRACE(("%d,",i));
123                }
124                dst++;
125        }
126        BGFX_TRACE(("\n"));
127}
128/* blit row a8 to clut 8 destination */
129static inline void bgfx_render_a8_to_clut8( uint8_t *src, uint8_t *dst, int width, uint8_t c )
130{
131        int i;
132        for (i = 0; i < width; i++)
133        {
134                if (*src > 0x80)
135                {
136                        *dst = c;
137                }
138                BGFX_TRACE(("0x%02x(0x%02x)",*src,*dst));
139                dst++;
140                src++;
141        }
142        BGFX_TRACE(("\n"));
143}
144
145/* blit row a1 to 8888 ARGB destination */
146static inline void bgfx_render_a1_to_rgb( uint8_t *src, uint8_t *dst, int width, uint32_t c )
147{
148        int i;
149
150        BGFX_TRACE(("%p,%p,%d,0x%08x\n",src,dst,width,c));
151        for (i = 0; i < width; i++)
152        {
153                if (src[i>>3] & (1<<(7-(i%8))))
154                {
155                        *((uint32_t*)dst) = c;
156                        BGFX_TRACE(("%d,",i));
157                }
158                dst += 4;
159        }
160        BGFX_TRACE(("\n"));
161}
162/* blit row a8 to 8888 ARGB destination */
163/*
164        #define BGFX_BLEND(a,rs,rd)     (((rs * a)/0xFF) + (rd - ((a * rd)/0xFF)) & 0xFF)
165*/
166#define BGFX_BLEND(a,rs,rd)     ((a * (rs-rd) >> 8) + rd)
167static inline void bgfx_render_a8_to_rgb( uint8_t *src, uint8_t *dst, int width, uint32_t c)
168{
169        register int i;
170        register uint32_t a,r,g,b;
171        register uint32_t a_src;
172        register uint32_t r_src =  (c >> 16) & 0xFF;
173        register uint32_t g_src =  (c >> 8) & 0xFF;
174        register uint32_t b_src =  (c >> 0) & 0xFF;
175        for (i = 0; i < width; i++)
176        {
177                a_src = *src;
178                a = dst[3]; r =  dst[2]; g =  dst[1]; b =  dst[0];
179
180                *((uint32_t*)dst) = ((a_src==0)?(a<<24):(c&0xFF000000)) |
181                                                        (BGFX_BLEND(a_src,r_src,r) << 16) |
182                                                        (BGFX_BLEND(a_src,g_src,g) << 8) |
183                                                        BGFX_BLEND(a_src,b_src,b);
184                BGFX_TRACE(("0x%02x(0x%08x)",*src,*((uint32_t*)dst)));
185                dst += 4;
186                src++;
187        }
188        BGFX_TRACE(("\n"));
189}
190
191/****************************************************************}
192* INPUTS:       io and protection function structures
193* OUTPUTS:      none
194* RETURNS:      non-zero on failure
195* FUNCTION: initialize sgl, primarily for handling freetype
196*
197****************************************************************/
198int bgfx_init(bgfx_io_t *io_p,bgfx_prot_t *prot_p,bgfx_hw_t *hw_p)
199{
200        bgfx_config(io_p,prot_p,hw_p);
201        return bgfx_font_init();
202}
203/****************************************************************}
204* INPUTS:       none
205* OUTPUTS:      none
206* RETURNS:      non-zero on failure
207* FUNCTION: release sgl global resources, primarily for handling freetype
208*
209****************************************************************/
210void bgfx_done(void)
211{
212        bgfx_font_done();
213}
214
215/****************************************************************}
216* bgfx_create
217*
218* INPUTS:       node_name - name of the node to create surface in
219*           p - surface structure to initialize
220* OUTPUTS:      none
221* RETURNS:      non-zero on failure
222* FUNCTION: initialize and create the surface.
223*
224****************************************************************/
225int bgfx_create(bgfx_surf_p p,uint16_t width,uint16_t height,
226                           uint8_t      *ptr, uint16_t pitch,
227                           bgfx_palette_t *palette,
228                           uint32_t flags)
229{
230        void *tmp_surf = NULL;
231        BGFX_DEBUG(("bgfx_create flags = 0x%08x\n",flags));
232
233        if ((flags & BGFX_SURF_GRC) && bgfx_hw_get_fcn() && p->surface.surf) 
234        {
235                tmp_surf = p->surface.surf;
236        }
237        BGFX_MEMSET(p,0,sizeof(bgfx_surf_t));
238
239        if (!ptr && (flags & BGFX_SURF_PRIMARY))
240        {
241                BGFX_DEBUG(("bgfx_create BGFX_SURF_FULLSCREEN requires valid memory ptr.\n"));
242        }
243
244        p->bpp = BGFX_SURF_GET_BPP(flags);
245
246        BGFX_DEBUG(("bgfx_create bpp = %d.\n",p->bpp));
247
248        if ((p->bpp == 0) || ((flags & BGFX_SURF_RGB) && (p->bpp != 32)))
249        {
250                BGFX_DEBUG(("bgfx_create invalid bpp = %d.\n",p->bpp));
251                return -1;
252        }
253
254        if ((flags & BGFX_SURF_GRC) && !bgfx_hw_get_fcn()) 
255        {
256                flags &= ~BGFX_SURF_GRC;
257        }
258
259        p->flags = flags;
260        if (ptr)
261        {
262                p->surface.pitch = pitch;
263                p->surface.buf = ptr;
264                p->surface.width = width;
265                p->surface.height = height;
266               
267                if (p->flags & BGFX_SURF_GRC)
268                {
269                        p->surface.surf = tmp_surf;
270                }
271                else
272                {
273                p->surface.surf = NULL;
274                }
275        }
276        else
277        {
278
279                p->surface.pitch = width * p->bpp / 8;
280                if (p->surface.pitch & 0x1)
281                        p->surface.pitch += 1;
282
283                p->surface.width = width;
284                p->surface.height = height;
285               
286                p->surface.surf = NULL;
287                if (p->flags & BGFX_SURF_GRC) 
288                {
289                        int format = (flags & BGFX_SURF_RGB) ? 5 /*bgraphics_pixel_format_a8_r8_g8_b8*/ : 10/*bgraphics_pixel_format_y08_cb8_y18_cr8*/;
290                        uint32_t pitch;
291                        if (bgfx_hw_surf_create(width, height,format,&(p->surface.buf),&pitch, (void*)&(p->surface.surf)) != BERR_SUCCESS) 
292                        {
293                                return -1;
294                        }
295                        p->flags |= BGFX_SURF_ALLOC;
296                }
297                else 
298                {
299                        p->surface.buf = BGFX_MALLOC(p->surface.pitch * p->surface.height);
300                        p->flags |= BGFX_SURF_ALLOC;
301                }
302        }
303
304        if (palette)
305        {
306                BGFX_MEMCPY(&p->palette,palette,sizeof(bgfx_palette_t));
307        }
308        return 0;
309}
310
311/****************************************************************
312* bgfx_destroy
313*
314* INPUTS:       p - surface structure
315* OUTPUTS:      none
316* RETURNS:      none
317* FUNCTION:     free up surface resources
318*
319****************************************************************/
320void bgfx_destroy(bgfx_surf_p p)
321{
322        if ((p->flags & BGFX_SURF_GRC) && p->surface.surf && (p->flags & BGFX_SURF_ALLOC) ) 
323        {
324                bgfx_hw_surf_destroy(p->surface.surf);
325        }
326
327        if (p->flags & BGFX_SURF_ALLOC)
328        {
329                BGFX_FREE(p->surface.buf);
330                return;
331        }
332}
333/****************************************************************
334* bgfx_fill_rect
335*
336* INPUTS:       p - surface structure
337* OUTPUTS:      w,h,flags - surface width,height and flags
338* RETURNS:      none
339* FUNCTION:     Return surface information (width,height, and flags)
340*
341****************************************************************/
342void bgfx_get_info(bgfx_surf_p p,uint16_t *w,uint16_t *h,uint16_t *pitch, uint32_t *flags)
343{
344        *w = p->surface.width;
345        *h = p->surface.height;
346        *pitch = p->surface.pitch;
347        *flags = p->flags;
348}
349/****************************************************************
350* bgfx_get_palette
351*
352* INPUTS:       p - surface structure
353* OUTPUTS:      palette_p - return current palette
354* RETURNS:      none
355* FUNCTION:     get the current palett
356*
357****************************************************************/
358void bgfx_get_palette(bgfx_surf_p p,bgfx_palette_t *palette_p)
359{
360        BGFX_MEMCPY(palette_p,&p->palette,sizeof(bgfx_palette_t));
361}
362/****************************************************************
363* bgfx_set_palette
364*
365* INPUTS:       p - surface structure
366*                       palette_p - the palette
367* OUTPUTS:      none
368* RETURNS:      none
369* FUNCTION:     set the global system palette
370*
371****************************************************************/
372void bgfx_set_palette(bgfx_surf_p p, bgfx_palette_t *palette_p)
373{
374        BGFX_MEMCPY(&p->palette,palette_p,sizeof(bgfx_palette_t));
375}
376
377/****************************************************************
378* bgfx_set_pixel
379*
380* INPUTS:       p - surface structure
381*                       x,y - coordinates
382*                       c - pixel value
383* OUTPUTS:      none
384* RETURNS:      none
385* FUNCTION:     set the pixel at x,y
386*
387****************************************************************/
388void bgfx_set_pixel(bgfx_surf_p p,uint16_t x,uint16_t y,bgfx_pixel c)
389{
390        uint8_t *dst;
391
392        if ((x >= p->surface.width) || (y >= p->surface.height))
393        {
394                BGFX_DEBUG(("bgfx_set_pixel param error (%p,%d,%d)\n",p,x,y));
395                return;
396        }
397
398        dst = (uint8_t*)p->surface.buf;
399        dst += y * p->surface.pitch + (x * p->bpp)/8;
400        if (p->flags & BGFX_SURF_RGB)
401        {
402                *((uint32_t*)dst) = c;
403                bgfx_cacheflush(dst,4);
404        }
405        else if (p->bpp == 8)
406        {
407                *dst = (uint8_t)c;
408                bgfx_cacheflush(dst,1);
409        }
410        else
411        {
412                if (x & 1)
413                {
414                        *dst &= 0xF0;
415                        *dst |= (uint8_t)(c & 0xF);
416                }
417                else
418                {
419                        *dst &= 0xF;
420                        *dst |= (uint8_t)((c & 0xF) << 4);
421                }
422                bgfx_cacheflush(dst,1);
423        }
424}
425/****************************************************************
426* bgfx_get_pixel
427*
428* INPUTS:       p - surface structure
429*                       x,y - coordinates
430*                       c - pixel value
431* OUTPUTS:      none
432* RETURNS:      none
433* FUNCTION:     get the pixel value at x,y.  The bgfx_color will be the
434*                       actual pixel value.
435*
436* NOTE:  Not supported for RGB surfaces.  To get a pixel for RGB access buf
437* directly.
438*
439****************************************************************/
440bgfx_pixel bgfx_get_pixel(bgfx_surf_p p,uint16_t x,uint16_t y)
441{
442        uint8_t *dst;
443        if ((x >= p->surface.width) || (y >= p->surface.height))
444        {
445                BGFX_DEBUG(("bgfx_get_pixel param error (%p,%d,%d)\n",p,x,y));
446                return 0;
447        }
448        dst = (uint8_t*)p->surface.buf;
449        dst += y * p->surface.pitch + (x * p->bpp)/8;
450        if (p->flags & BGFX_SURF_RGB)
451        {
452                return *((uint32_t*)dst);
453        }
454        else if (p->bpp == 8)
455        {
456                return *dst;
457        }
458       
459        /* p->bpp == 4 */
460        if (x & 1)
461        {
462                return (*dst  & 0xF0);
463        }
464
465        return (*dst >> 4);
466}
467/****************************************************************
468* bgfx_h_draw_line
469*
470* INPUTS:       p - surface structure
471*                       x1,x2,y - coordinates
472*                       c - pixel value
473* OUTPUTS:      none
474* RETURNS:      none
475* FUNCTION:     Draw a horizontal line make of pixels defined by the value c.
476*
477*  JPF - these need to be optimized
478*
479****************************************************************/
480void bgfx_h_draw_line(bgfx_surf_p p,uint16_t x1,uint16_t x2,uint16_t y,
481                                         bgfx_pixel c)
482{
483        int w = x2 - x1;
484
485        if (w < 0)
486        {
487                w = -w;
488                bgfx_fill_rect(p,x2,y,(uint16_t)w,1, c);
489        }
490        else
491        {
492                bgfx_fill_rect(p,x1,y,(uint16_t)w,1, c);
493        }
494}
495/****************************************************************
496* bgfx_v_draw_line
497*
498* INPUTS:       p - surface structure
499*                       x,y1,y2 - coordinates
500*                       c - pixel value
501* OUTPUTS:      none
502* RETURNS:      none
503* FUNCTION:     Draw a vertical line make of pixels defined by the value c.
504*
505*   JPF - these need to be optimized
506*
507****************************************************************/
508void bgfx_v_draw_line(bgfx_surf_p p,uint16_t x,uint16_t y1,uint16_t y2,
509                                         bgfx_pixel c)
510{
511        uint8_t *dst;
512        uint16_t h = y2 - y1;
513        if ((y2 <= y1) || (x >= p->surface.width))
514        {
515                BGFX_DEBUG(("bgfx_v_draw_line param error (%p,%d,%d,%d,0x%08x)\n",p,x,y1,y2,c));
516                return;
517        }
518
519        if (h > p->surface.height - y1)
520                h = p->surface.height - y1;
521        dst = (uint8_t*)p->surface.buf;
522        dst += y1 * p->surface.pitch + x * p->bpp/8;
523
524        if (p->flags & BGFX_SURF_RGB)
525        {
526                while (h--)
527                {
528                        *((uint32_t*)dst) = c;
529                        dst += p->surface.pitch;
530                }
531        }
532        else if (p->bpp == 8)
533        {
534                while (h--)
535                {
536                        *dst = (uint8_t)c;
537                        dst += p->surface.pitch;
538                }
539        }
540        else
541        {
542                while (h--)
543                {
544                        if (x & 1)
545                        {
546                                *dst &= 0xF0;
547                                *dst |= (uint8_t)(c & 0xF);
548                        }
549                        else
550                        {
551                                *dst &= 0xF;
552                                *dst |= (uint8_t)((c & 0xF) << 4);
553                        }
554                        dst += p->surface.pitch;
555                }
556        }
557        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
558}
559/****************************************************************
560* bgfx_fill_rect
561*
562* INPUTS:       p - surface structure
563*                       x1,x2,y1,y2 - coordinates
564*                       c - pixel value
565* OUTPUTS:      none
566* RETURNS:      none
567* FUNCTION:     Fill the rectangle with pixels defined by the value c.
568*
569*   JPF - these need to be optimized
570*
571****************************************************************/
572/* TODO create optimized version of memset */
573#if 0
574static inline void *bgfx_memset(void *dest,int c,size_t count)
575{
576        uint8_t *d = dest;
577        for(;count>0;count--) {
578                *d++ = c;
579        }
580        return dest;
581}
582#else
583#define bgfx_memset BGFX_MEMSET
584#endif
585
586void bgfx_fill_rect(bgfx_surf_p p,uint16_t x,uint16_t y,uint16_t w,uint16_t h,
587                                   bgfx_pixel c)
588{
589        uint8_t *tdst;
590        uint16_t i;
591        uint8_t *dst;
592        uint16_t j;     
593       
594        if ((x > p->surface.width) || (y > p->surface.height))
595        {
596                BGFX_DEBUG(("bgfx_fill_rect param error (%p,%d,%d,%d,%d,0x%08x)\n",p,x,y,w,h,c));
597                return;
598        }
599        if (y + h > p->surface.height)
600                h = p->surface.height - y;
601
602        if (w + x > p->surface.width)
603                w = p->surface.width - x;
604       
605        if (p->flags & BGFX_SURF_GRC) 
606        {
607                if (!w || !h) 
608                        return;
609
610                bgfx_rect rect;
611                rect.x = x;
612                rect.y = y;
613                rect.width = w;
614                rect.height = h;
615                bgfx_hw_fill((void *)p->surface.surf, &rect, c);
616                return ;
617        }
618
619
620        dst = (uint8_t*)p->surface.buf;
621        dst += y * p->surface.pitch + x * p->bpp/8;
622
623        if (p->flags & BGFX_SURF_RGB)
624        {
625                for (j = 0; j < h; ++j)
626                {
627                        tdst = dst;
628                        for (i = 0; i < w; ++i)
629                        {
630                                *((uint32_t*)tdst) = c;
631                                tdst += p->bpp/8;
632                        }
633                        dst += p->surface.pitch;
634                }
635        }
636        else if (p->bpp == 8)
637        {
638                for (j = 0; j < h; ++j)
639                {
640                        bgfx_memset(dst,(uint8_t)c,w);
641                        dst += p->surface.pitch;
642                }
643        }
644        else
645        {
646                unsigned char two_pixel = (uint8_t)((c << 4) | c);
647                for (j = 0; j < h; ++j)
648                {
649                        unsigned int num_bytes = (w * p->bpp)/8;
650                        if (x & 1)
651                        {
652                                *dst &= 0xF0;
653                                *dst |= (uint8_t)(c & 0xF);
654                                if (w & 1)
655                                {
656                                        bgfx_memset(&dst[1],two_pixel,num_bytes);
657                                }
658                                else
659                                {
660                                        bgfx_memset(&dst[1],two_pixel,num_bytes - 1);
661                                        dst[num_bytes] &= 0x0F;
662                                        dst[num_bytes] |= (uint8_t)((c & 0xF) << 4);
663                                }
664                        }
665                        else
666                        {
667                                if (w & 1)
668                                {
669                                        bgfx_memset(dst,two_pixel,num_bytes);
670                                        dst[num_bytes] &= 0x0F;
671                                        dst[num_bytes] |= (uint8_t)((c & 0xF) << 4);
672                                }
673                                else
674                                        bgfx_memset(dst,two_pixel,num_bytes);
675                        }
676                        dst += p->surface.pitch;
677                }
678        }
679        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
680}
681/****************************************************************
682* bgfx_render_glyph
683*
684* INPUTS:       p - surface structure
685*                       x,y - coordinates
686*                       a_char - character to render
687*                       font_p - font definition
688*                       c - color
689* OUTPUTS:      none
690* RETURNS:      character advance
691* FUNCTION:     Fill the rectangle with pixels defined by the value c.
692*
693****************************************************************/
694#define IT_OFFSET       3
695static inline int bgfx_render_glyph(bgfx_surf_p p,uint16_t x,uint16_t y,
696                                         const unsigned long a_char, bgfx_font_t *font_p,bgfx_pixel c,
697                                          bgfx_glyph_t * p_bgfx_glyph,bgfx_text_style style)
698{
699        int max_width,ybase;
700        uint16_t row;
701        uint8_t *src,*dst;
702        bgfx_glyph_t * bgfx_glyph = p_bgfx_glyph;
703        unsigned char   glyph_width;            /* width of the rendered character bitmap in pixels */
704        unsigned char   glyph_height;           /* height of the rendered character bitmap in pixels */
705
706        ybase = y;
707        if (x > p->surface.width)
708        {
709                BGFX_TRACE(("bgfx_render_glyph x > width (%d,%d)\n",x,p->surface.width));
710                return 0;
711        }
712
713        /* if using glyph cache use the get glyph rather than render directly to surface buffer */
714        if (!bgfx_glyph && (font_p->cache_size > 0))
715        {
716                bgfx_glyph = bgfx_get_glyph(font_p,a_char);
717        }
718
719        if (!bgfx_glyph)
720        {
721                BGFX_DEBUG(("bgfx_render_glyph could not load glyph 0x%08lx\n",a_char));
722                return 0;
723        }
724        BGFX_TRACE(("bgfx_render_glyph glyph (%p,%d,%d)\n",bgfx_glyph->buf,bgfx_glyph->height,bgfx_glyph->width));
725
726        glyph_width = bgfx_glyph->width;
727        glyph_height = bgfx_glyph->height;
728
729        if (bgfx_glyph->left + x > 0)
730                x += bgfx_glyph->left;
731        if (y-bgfx_glyph->top > 0)
732                y -= bgfx_glyph->top;
733        else
734                y = 0;
735
736        if (glyph_height + y > p->surface.height)
737                glyph_height = p->surface.height - y;
738        if (glyph_width + x > p->surface.width)
739                glyph_width = p->surface.width - x;
740
741        src = (uint8_t*)bgfx_glyph->buf;
742        dst = (uint8_t*)p->surface.buf;
743
744        BGFX_TRACE(("bgfx_render_glyph suface (%p(y = %d,x = %d,pitch = %d,bpp = %d)\n",dst,y,x,p->surface.pitch, p->bpp));
745       
746        dst += y * p->surface.pitch + x * p->bpp/8;
747        if (style & eBGFX_ITALIC)
748                max_width = BGFX_MIN(glyph_width + IT_OFFSET, p->surface.width - x);
749        else
750                max_width = BGFX_MIN(glyph_width, p->surface.width - x);
751       
752        if (max_width <= 0)
753        {
754                if (glyph_width != 0)
755                {
756                        BGFX_TRACE(("bgfx_render_glyph glyph_width = %d\n", glyph_width));
757                }
758                return bgfx_glyph->advance;
759        }
760
761        /* Render mono glyph */
762        if (font_p->format & BGFX_MONO)
763        {
764                BGFX_TRACE(("bgfx_render_glyph Alpha 1 font\n"));
765
766                if (p->flags & BGFX_SURF_RGB)
767                {
768                        uint16_t adjx = 0;
769                        for (row = 0; row < glyph_height; row++)
770                        {
771                                if (style & eBGFX_ITALIC) {
772                                        adjx = IT_OFFSET - ((row*IT_OFFSET)/glyph_height);     
773                                }
774                               
775                                bgfx_render_a1_to_rgb( src, dst+adjx*p->bpp/8, max_width,c );
776
777                                src += bgfx_glyph->pitch;
778                                dst += p->surface.pitch;
779                        }
780                }
781                else if (p->bpp == 8)
782                {
783                        for (row = 0; row < glyph_height; row++)
784                        {
785                                bgfx_render_a1_to_clut8( src, dst, max_width,c );
786
787                                src += bgfx_glyph->pitch;
788                                dst += p->surface.pitch;
789                        }
790                }
791                else
792                {
793                        uint16_t adjx = x;
794                        for (row = 0; row < glyph_height; row++)
795                        {
796                                if (style & eBGFX_ITALIC)
797                                {
798                                        adjx = x + IT_OFFSET - ((row * IT_OFFSET)/glyph_height);
799                                        dst = (uint8_t*)p->surface.buf;
800                                        dst += (y + row) * p->surface.pitch + adjx * p->bpp/8;
801                                }
802                                bgfx_render_a1_to_clut4( src, dst, max_width,c, adjx & 0x1 );
803
804                                src += bgfx_glyph->pitch;
805                                dst += p->surface.pitch;
806                        }
807                }
808        }
809        else /* Render 8 bit grayscale glyph */
810        {
811                BGFX_TRACE(("bgfx_render_glyph Alpha 8 font\n"));
812                if (p->flags & BGFX_SURF_RGB)
813                {
814                        uint16_t adjx = 0;
815                        for (row = 0; row < glyph_height; row++)
816                        {
817                                if (style & eBGFX_ITALIC) {
818                                        adjx = IT_OFFSET - ((row*IT_OFFSET)/glyph_height);
819                                }
820                                /* TODO:: it's for nanotv up/down/left/right cursor, which is from mono type font */
821                                if (a_char >= 0x193 && a_char <= 0x196)
822                                        bgfx_render_a1_to_rgb(src, dst+adjx*p->bpp/8, glyph_width,c);
823                                else
824                                        bgfx_render_a8_to_rgb( src, dst+adjx*p->bpp/8, glyph_width,c);
825
826                                src += bgfx_glyph->pitch;
827                                dst += p->surface.pitch;
828                        }
829                }
830                else if (p->bpp == 8)
831                {
832                        for (row = 0; row < glyph_height; row++)
833                        {
834                                bgfx_render_a8_to_clut8( src, dst, glyph_width,c );
835
836                                src += bgfx_glyph->pitch;
837                                dst += p->surface.pitch;
838                        }
839                }
840                else
841                {
842                        for (row = 0; row < glyph_height; row++)
843                        {
844                                bgfx_render_a8_to_clut4( src, dst, glyph_width,c );
845
846                                src += bgfx_glyph->pitch;
847                                dst += p->surface.pitch;
848                        }
849                }
850        }
851        if (style & eBGFX_UNDERLINE)
852        {
853                bgfx_h_draw_line(p,x,x + bgfx_glyph->advance,ybase,c);
854                bgfx_h_draw_line(p,x,x + bgfx_glyph->advance,ybase+1,c);
855        }
856        return bgfx_glyph->advance;
857}
858
859/****************************************************************
860* bgfx_draw_text
861*
862* INPUTS:       p - surface structure
863*                       x,y - coordinates
864*                       str_p - array of 32-bit unicode characters
865                        str_len - number of 32-bit characters in array
866*                       font_p - font definition
867*                       c - color
868* OUTPUTS:      none
869* RETURNS:      none
870* FUNCTION:     Fill the rectangle with pixels defined by the value c.
871*
872****************************************************************/
873void bgfx_draw_text(bgfx_surf_p p,uint16_t x,uint16_t y,
874                                   const unsigned long *str_p, int str_len, 
875                                   bgfx_font_t *font_p,bgfx_pixel c, bgfx_text_style style)
876{
877        int offset;
878
879        BGFX_TRACE(("bgfx_draw_text %d characters.\n",str_len));
880       
881        for (offset = 0; offset < str_len; offset++)
882        {
883                x += bgfx_render_glyph(p,x,y, str_p[offset], font_p,c,NULL,style);
884        }
885        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
886}
887/****************************************************************
888* bgfx_draw_text_box
889*
890* INPUTS:       p - surface structure
891*                       x,y - coordinates
892*                       width,height - width and hegith of the text box to draw
893*                       str_p - array of 32-bit unicode characters
894                        str_len - number of 32-bit characters in array
895*                       font_p - font definition
896*                       c - color
897                        line_spacing - line space
898* OUTPUTS:      none
899* RETURNS:      none
900* FUNCTION:     Fill the rectangle with pixels defined by the value c.
901*
902****************************************************************/
903//#define MAX_TEXT_BOX_CHARS    512
904//#define MAX_LINES                     16
905//static unsigned long s_test_char = 0x00000057UL;
906/* TODO:  Might want to improve macro to check for chars other than spaces */
907#define BGFX_IS_BREAK(x)        ((x == 0x00000020) ? 1 : 0)
908
909void bgfx_draw_text_box(bgfx_surf_p p,uint16_t x,uint16_t y,
910                                                uint16_t width, uint16_t height,
911                                                const unsigned long *str_p, int str_len, 
912                                                bgfx_font_t *font_p,bgfx_pixel c, 
913                                                uint16_t line_spacing)
914{
915        int offset,bw_off,line_idx;
916        static bgfx_glyph_t * p_bgfx_glyph[MAX_TEXT_BOX_CHARS]; /* Not thread safe */
917        static uint8_t brk_loc[MAX_TEXT_BOX_CHARS];
918        uint16_t max_h[MAX_LINES],ch_w,test_max_h,bot;
919
920        BGFX_TRACE(("bgfx_draw_text_box(%d,%d,%d,%d,%d) %d characters.\n",x,y,width,height,line_spacing,str_len));
921        if (str_len > MAX_TEXT_BOX_CHARS) 
922        {
923                BGFX_DEBUG(("bgfx_draw_text %d > %d maximum characters.\n",str_len,MAX_TEXT_BOX_CHARS));
924                str_len = MAX_TEXT_BOX_CHARS;
925        }
926        y += font_p->ascender;
927
928        bot = y + height;
929       
930        test_max_h = font_p->height;
931
932        for (line_idx = 0; line_idx < MAX_LINES; ++line_idx)
933                max_h[line_idx] = test_max_h;
934       
935        ch_w = 0;
936        line_idx = 0;
937        for (offset = 0; offset < str_len; offset++)
938        {
939                brk_loc[offset] = 0;
940                p_bgfx_glyph[offset] = bgfx_get_glyph(font_p,str_p[offset]);
941                if (p_bgfx_glyph[offset] == NULL)
942                {
943                        BGFX_DEBUG(("%s:%d str[%d] = 0x%08lx\n",__FUNCTION__,__LINE__,offset,str_p[offset]));
944                        /* if not a printable charactor, then use space instead */
945                        p_bgfx_glyph[offset] = bgfx_get_glyph(font_p,0x00000020);
946                        continue;
947                }
948                ch_w += p_bgfx_glyph[offset]->advance;
949
950                if (p_bgfx_glyph[offset]->height > max_h[line_idx]) 
951                        max_h[line_idx] = p_bgfx_glyph[offset]->height;
952
953                if (ch_w >= width) 
954                {
955                        line_idx++;
956                        for (bw_off = offset - 1; bw_off >= 0; --bw_off)
957                        {
958                                if (brk_loc[bw_off]) {
959                                        bw_off = -1;
960                                        break;
961                                }
962                                if (BGFX_IS_BREAK(str_p[bw_off])) 
963                                {
964                                        brk_loc[bw_off] = 1;
965                                        break;
966                                }
967                        }
968
969                        /* last resort, break on preceding character */
970                        if (bw_off < 0) 
971                        {
972                                brk_loc[offset - 1] = 1;
973                                ch_w = p_bgfx_glyph[offset]->advance;
974                        }
975                        else
976                        {
977                                offset = bw_off;
978                                ch_w = 0;
979                        }
980                }
981        }
982
983        /* offset y so text is inside box */
984        line_idx = 0;
985        ch_w = 0;
986
987        for (offset = 0; (offset < str_len) && (line_idx < MAX_LINES); offset++)
988        {
989                if (brk_loc[offset]) 
990                {
991                        line_idx++;
992                        ch_w = 0;
993#ifdef BGFX_VARIABL_LINE_HEIGHT
994                        y += line_spacing + max_h[line_idx];
995                        if ((y - max_h[line_idx]) > bot) 
996                                break;
997#else
998                        y += line_spacing + test_max_h;
999                        if ((y - test_max_h) > bot) 
1000                                break;
1001#endif
1002                        continue;
1003                }
1004                ch_w += bgfx_render_glyph(p,x + ch_w,y, str_p[offset], font_p,c,p_bgfx_glyph[offset],eBGFX_NORMAL);
1005        }
1006        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
1007}
1008
1009static inline void bgfx_csc_YCbCr_to_RGB(uint32_t *ycbcr)
1010{
1011        uint8_t y,cb,cr,r,g,b;
1012
1013        y = *ycbcr>>16;
1014        cb = *ycbcr>>8;
1015        cr = *ycbcr;
1016
1017        r = 1.164*(y-16)+1.596*(cr-128);
1018        g = 1.164*(y-16)-0.813*(cr-128)-0.391*(cb-128);
1019        b = 1.164*(y-16)+2.018*(cb-128);
1020
1021        *ycbcr = (*ycbcr&0xFF000000)|(r<<16)|(g<<8)|b;
1022}
1023/****************************************************************
1024* INPUTS:       s_pixel,d_pixel - source and destination pixles
1025* OUTPUTS:      none
1026* RETURNS:      blended pixel
1027* FUNCTION:     blend argb pixels
1028*
1029****************************************************************/
1030
1031static inline uint32_t bgfx_blend_argb_pixels(uint32_t s_pixel,uint32_t d_pixel)
1032{
1033        uint32_t sr,sg,sb,sa,dr,dg,db,da,oa;
1034        sa = (s_pixel >> 24) & 0xFF;
1035        da = (d_pixel >> 24) & 0xFF;
1036        if ((sa == 0xFF) || (da == 0x00))
1037        {
1038                return s_pixel;
1039        }
1040        if ((da == 0xFF) && (sa == 0x00))
1041        {
1042                return d_pixel;
1043        }
1044       
1045        sr = (s_pixel >> 16) & 0xFF;
1046        sg = (s_pixel >> 8) & 0xFF;
1047        sb = (s_pixel >> 0) & 0xFF;
1048        dr = (d_pixel >> 16) & 0xFF;
1049        dg = (d_pixel >> 8) & 0xFF;
1050        db = (d_pixel >> 0) & 0xFF;
1051
1052        dr = (((sr * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * dr)/0xFF) & 0xFF);
1053        dg = (((sg * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * dg)/0xFF) & 0xFF);
1054        db = (((sb * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * db)/0xFF) & 0xFF);
1055
1056        oa = da;
1057
1058        return (oa << 24) | (dr << 16) | (dg << 8) | db;
1059}
1060
1061/****************************************************************
1062* bgfx_render_file
1063*
1064* INPUTS:       p - surface structure
1065*                       x,y - coordinates
1066*                       file_p - file to get image from
1067*                       set_palette - use the palette in the file to set the
1068*                                               global palette.
1069* OUTPUTS:      none
1070* RETURNS:      non-zero on error
1071* FUNCTION:     Render the image in the file to the x,y location
1072*
1073****************************************************************/
1074
1075int bgfx_render_file(bgfx_surf_p p,uint16_t x,uint16_t y,
1076                                        void *file_p,int set_palette)
1077{
1078        bcm_raw_8_t header;
1079        int result = -1;
1080        uint16_t row,rows,rowbytes,width;
1081        uint8_t *dst_ptr;
1082        int palette_bytes;
1083        uint16_t i;
1084        static uint32_t tbuf_32[SURF_WIDTH];
1085        static uint8_t *tbuf = (uint8_t*)tbuf_32;
1086
1087        if (bgfx_read(&header,1,sizeof(header),file_p) == sizeof(header))
1088        {
1089                if (header.type != RAW_TYPE || header.version != RAW_VERSION)
1090                {
1091                        BGFX_DEBUG(("bgfx_render_file failed version,type invalid(0x%08x,0x%08x)\n",header.type,header.version));
1092                        return -1;
1093                }
1094                BGFX_TRACE(("header.version = 0x%08x\n",header.version));
1095                BGFX_TRACE(("header.type = 0x%08x\n",header.type));
1096                BGFX_TRACE(("header.clut_size = %d\n",header.clut_size));
1097                BGFX_TRACE(("header.color_key = 0x%02x\n",header.color_key));
1098                BGFX_TRACE(("header.pitch = %d\n",header.pitch));
1099                BGFX_TRACE(("header.width = 0x%08x\n",header.width));
1100                BGFX_TRACE(("header.height = 0x%08x\n",header.height));
1101
1102                width = BGFX_MIN(header.width, (p->surface.width - x));
1103                if (header.clut_size == 0)
1104                {
1105                        if (!(p->flags & BGFX_SURF_RGB))
1106                        {
1107                                BGFX_DEBUG(("bgfx_render_file failed, rendering ARGB to ARGB only\n"));
1108                                return -1;
1109                        }
1110                        rows = BGFX_MIN(header.height, p->surface.height - y);
1111                        rowbytes = header.pitch;
1112
1113                        dst_ptr = (uint8_t*)p->surface.buf;
1114                        dst_ptr += y * p->surface.pitch + x * p->bpp/8;
1115                        for (row = 0; row < rows; row++)
1116                        {
1117                                bgfx_read(tbuf ,1,rowbytes,file_p);
1118                                for (i = 0; i < width; ++i)
1119                                {
1120                                        ((uint32_t*)dst_ptr)[i] = bgfx_blend_argb_pixels(tbuf_32[i],((uint32_t*)dst_ptr)[i]);
1121                                }
1122
1123                                dst_ptr += p->surface.pitch;
1124                        }
1125
1126                        BGFX_TRACE(("Render - done\n"));
1127                        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
1128                        result = 0;
1129                        return result;
1130                }
1131
1132                palette_bytes = (sizeof(unsigned long) * header.clut_size);
1133                if (bgfx_read(&p->palette,1,palette_bytes,file_p) == palette_bytes)
1134                {
1135                        if (set_palette && (header.clut_size == PALETTE_SIZE))
1136                                bgfx_set_palette(p,&p->palette);
1137                        if (p->flags & BGFX_SURF_RGB) {
1138                                for (i=0; i<header.clut_size; i++) {
1139                                        bgfx_csc_YCbCr_to_RGB(&p->palette.clut[i]);
1140                                }
1141                        }
1142                }
1143
1144                if ((header.width == p->surface.width) && (header.height == p->surface.height) &&
1145                        (p->surface.pitch == header.pitch) && (x == 0) && (y == 0)
1146                                 && !(p->flags & BGFX_SURF_RGB))
1147                {
1148                        BGFX_TRACE(("Fast Render\n"));
1149                        bgfx_read(p->surface.buf,1,header.pitch*header.height,file_p);
1150                }
1151                else if ((p->palette.clut[header.color_key] & 0xFF000000) != 0)
1152                {
1153                        BGFX_TRACE(("Render - no color key\n"));
1154                //      rowbytes = BGFX_MIN(header.width,p->surface.width - x) * p->bpp/8;
1155                        rowbytes = header.pitch;
1156                        rows = BGFX_MIN(header.height, p->surface.height - y);
1157
1158                        dst_ptr = (uint8_t*)p->surface.buf;
1159                        dst_ptr += y * p->surface.pitch + x * p->bpp/8;
1160
1161                        if (p->flags & BGFX_SURF_RGB)
1162                        {
1163                                for (row = 0; row < rows; row++)
1164                                {
1165                                        bgfx_read(tbuf ,1,rowbytes,file_p);
1166                                        for (i = 0; i < width; ++i)
1167                                        {
1168                                                uint32_t src_c,cnt=0;
1169                                                src_c = bgfx_clut8_to_rgb(p->palette.clut,(tbuf[i]>>4)&0x0f);
1170half:
1171                                                cnt++;
1172                                               
1173                                                ((uint32_t*)dst_ptr)[i] = bgfx_blend_argb_pixels(src_c,((uint32_t*)dst_ptr)[i]);
1174                                               
1175                                                if (cnt == 2) 
1176                                                        continue;
1177                                                src_c = bgfx_clut8_to_rgb(p->palette.clut,(tbuf[i])&0x0f);
1178                                                goto half;     
1179                                        }
1180
1181                                        if (header.pitch > rowbytes)
1182                                        {
1183                                                bgfx_read(tbuf ,1,header.pitch - rowbytes,file_p);
1184                                        }
1185                                        dst_ptr += p->surface.pitch;
1186                                }
1187                        }
1188                        else
1189                        {
1190                                for (row = 0; row < rows; row++)
1191                                {
1192                                        bgfx_read(dst_ptr ,1,rowbytes,file_p);
1193                                        if (header.pitch > rowbytes)
1194                                        {
1195                                                bgfx_read(tbuf ,1,header.pitch - rowbytes,file_p);
1196                                        }
1197                                        dst_ptr += p->surface.pitch;
1198                                }
1199                        }
1200                }
1201                else
1202                {
1203                        BGFX_TRACE(("Render - color key\n"));
1204                        rowbytes = BGFX_MIN(header.width,(p->surface.width - x)) * p->bpp/8;
1205                        rows = BGFX_MIN(header.height, (p->surface.height - y));
1206                        dst_ptr = (uint8_t*)p->surface.buf;
1207                        dst_ptr += y * p->surface.pitch + x * p->bpp/8;
1208
1209                        if (p->flags & BGFX_SURF_RGB)
1210                        {
1211                                for (row = 0; row < rows; row++)
1212                                {
1213                                        bgfx_read(tbuf ,1,rowbytes,file_p);
1214                                        for (i = 0; i < width; ++i)
1215                                        {
1216                                                if (tbuf[i] != header.color_key)
1217                                                {
1218                                                        uint32_t src_c;
1219                                                        src_c = bgfx_clut8_to_rgb(p->palette.clut,tbuf[i]);
1220                                                        ((uint32_t*)dst_ptr)[i] = bgfx_blend_argb_pixels(src_c,((uint32_t*)dst_ptr)[i]);
1221                                                        }
1222                                        }
1223                                        if (header.pitch > rowbytes)
1224                                        {
1225                                                bgfx_read(tbuf ,1,header.pitch - rowbytes,file_p);
1226                                        }
1227                                        dst_ptr += p->surface.pitch;
1228                                }
1229                        }
1230                        else
1231                        {
1232                                for (row = 0; row < rows; row++)
1233                                {
1234                                        bgfx_read(dst_ptr ,1,rowbytes,file_p);
1235                                        if (header.pitch > rowbytes)
1236                                        {
1237                                                bgfx_read(tbuf ,1,header.pitch - rowbytes,file_p);
1238                                        }
1239                                        dst_ptr += p->surface.pitch;
1240                                }
1241                        }
1242                }
1243        }
1244        BGFX_TRACE(("Render - done\n"));
1245        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
1246        result = 0;
1247        return result;
1248}
1249
1250/****************************************************************
1251* bgfx_blit
1252*
1253* INPUTS:       p_src,p_dst - surface structure
1254*                       x,y - destination coordinates
1255* OUTPUTS:      none
1256* RETURNS:      non-zero on error
1257* FUNCTION:     Blit between the two surfaces, only the destination can be RGB
1258*
1259****************************************************************/
1260static int32_t g_ai32_Matrix_RGBtoYCbCr_BT_709[20] =
1261{
1262    (int32_t) ( 0.183f * (1 << 8)),   /*  R factor for Y */
1263    (int32_t) ( 0.614f * (1 << 8)),   /*  G factor for Y */
1264    (int32_t) ( 0.062f * (1 << 8)),   /*  B factor for Y */
1265    (int32_t) 0,                      /*  A factor for Y */
1266    (int32_t) (16 * (1 << 8)),        /* Increment for Y */
1267    (int32_t) (-0.101f * (1 << 8)),   /*  R factor for Cb */
1268    (int32_t) (-0.339f * (1 << 8)),   /*  G factor for Cb */
1269    (int32_t) ( 0.439f * (1 << 8)),   /*  B factor for Cb */
1270    (int32_t) 0,                      /*  A factor for Cb */
1271    (int32_t) (128 * (1 << 8)),       /* Increment for Cb */
1272    (int32_t) ( 0.439f * (1 << 8)),   /*  R factor for Cr */
1273    (int32_t) (-0.339f * (1 << 8)),   /*  G factor for Cr */
1274    (int32_t) (-0.040f * (1 << 8)),   /*  B factor for Cr */
1275    (int32_t) 0,                      /*  A factor for Cr */
1276    (int32_t) (128 * (1 << 8)),       /* Increment for Cr */
1277    (int32_t) 0,                      /*  R factor for A */
1278    (int32_t) 0,                      /*  G factor for A */
1279    (int32_t) 0,                      /*  B factor for A */
1280    (int32_t) (1 << 8),               /*  A factor for A */
1281    (int32_t) 0,                      /* Increment for A */
1282};
1283
1284
1285#define bgfx_csc_RGB_2_YCbCr_macro(y,cb,cr,R,G,B) \
1286        { \
1287        y =((m0*R + m1*G + m2*B + m4) >> shift); \
1288        cb = ((m5*R + m6*G + m7*B + m9) >> shift); \
1289        cr = ((m10*R + m11*G + m12*B + m14) >> shift); \
1290}
1291
1292int bgfx_blit(bgfx_surf_p p_src, bgfx_surf_p p_dst, uint16_t x,uint16_t y)
1293{
1294        uint8_t *dst,*src;
1295        uint16_t j,w,h,rowbytes;
1296        uint16_t i;
1297        uint8_t *tdst;
1298
1299        if ((p_src->flags & BGFX_SURF_GRC) && (p_dst->flags & BGFX_SURF_GRC)) 
1300        {
1301                void *src,*dst,*out;
1302                bgfx_rect src_r,dst_r,out_r;
1303                src = p_src->surface.surf;
1304                out = p_dst->surface.surf;
1305                dst = NULL;
1306               
1307                src_r.x = dst_r.x = out_r.x = 0;
1308                src_r.y = dst_r.y = out_r.y = 0;
1309                src_r.width = p_src->surface.width;
1310                src_r.height = p_src->surface.height;
1311                dst_r.width = p_dst->surface.width;
1312                dst_r.height = p_dst->surface.height;
1313                out_r.width = p_dst->surface.width;
1314                out_r.height = p_dst->surface.height;
1315
1316                bgfx_hw_blit(src,&src_r, dst, &dst_r,out, &out_r);
1317                return 0;
1318        }
1319
1320        BGFX_TRACE(("bgfx_blit x,y (%d,%d)\n",x,y));           
1321
1322        if ((x > p_dst->surface.width) || (y > p_dst->surface.height))
1323        {
1324                BGFX_DEBUG(("bgfx_blit x,y (%d,%d) outside destination (%d,%d)\n",x,y,
1325                                   p_dst->surface.width,p_dst->surface.height));
1326                return -1;
1327        }
1328
1329        w = p_src->surface.width;
1330        if (w > p_dst->surface.width - x)
1331                w = p_dst->surface.width - x;
1332        h = p_src->surface.height;
1333        if (h > p_dst->surface.height - y)
1334                h = p_dst->surface.height - y;
1335
1336        src = (uint8_t*)p_src->surface.buf;
1337        dst = (uint8_t*)p_dst->surface.buf;
1338        dst += y * p_dst->surface.pitch + x * p_dst->bpp/8;
1339
1340        if (p_dst->flags & BGFX_SURF_RGB)
1341        {
1342                if (p_src->flags & BGFX_SURF_RGB) {
1343                        uint16_t rows;
1344                        rows = p_src->surface.height - y;
1345                        rowbytes = p_src->surface.pitch;
1346
1347                        dst = (uint8_t*)p_dst->surface.buf;
1348                        dst += y * p_dst->surface.pitch + x * p_dst->bpp/8;
1349                        src = (uint8_t*)p_src->surface.buf;
1350                        src += y * p_src->surface.pitch + x * p_src->bpp/8;
1351                        for (j = 0; j < rows; j++)
1352                        {
1353                                for (i = 0; i < rowbytes/(p_src->bpp/8); ++i)
1354                                {
1355                                        ((uint32_t*)dst)[i] = bgfx_blend_argb_pixels(((uint32_t*)src)[i],((uint32_t*)dst)[i]);
1356                                }
1357
1358                                dst += p_dst->surface.pitch;
1359                                src += p_src->surface.pitch;
1360                        }
1361                }
1362                else 
1363                {
1364                        int32_t rgb, y1, cb, cr, a, r, g, b, shift;             
1365
1366                        int32_t m0 = g_ai32_Matrix_RGBtoYCbCr_BT_709[0];
1367                        int32_t m1 = g_ai32_Matrix_RGBtoYCbCr_BT_709[1];
1368                        int32_t m2 = g_ai32_Matrix_RGBtoYCbCr_BT_709[2];
1369                        int32_t m4 = g_ai32_Matrix_RGBtoYCbCr_BT_709[4];
1370                        int32_t m5 = g_ai32_Matrix_RGBtoYCbCr_BT_709[5];
1371                        int32_t m6 = g_ai32_Matrix_RGBtoYCbCr_BT_709[6];
1372                        int32_t m7 = g_ai32_Matrix_RGBtoYCbCr_BT_709[7];
1373                        int32_t m9 = g_ai32_Matrix_RGBtoYCbCr_BT_709[9];
1374                        int32_t m10 = g_ai32_Matrix_RGBtoYCbCr_BT_709[10];
1375                        int32_t m11 = g_ai32_Matrix_RGBtoYCbCr_BT_709[11];
1376                        int32_t m12 = g_ai32_Matrix_RGBtoYCbCr_BT_709[12];
1377                        int32_t m14 = g_ai32_Matrix_RGBtoYCbCr_BT_709[14];
1378                        shift = 8;
1379
1380                        for (j = 0; j < h; ++j)
1381                        {
1382                                /* convert rgb to ycbcr */
1383                                tdst = dst;
1384                                for (i=0; i<(w << 2); i+=4, tdst+=4)
1385                                {
1386                                        rgb = *(uint32_t *)&src[i];
1387
1388                                        a = ((rgb>>24)&0xff);
1389                                        r = ((rgb>>16)&0xff);
1390                                        g = ((rgb>>8)&0xff);
1391                                        b = rgb&0xff;
1392                                        bgfx_csc_RGB_2_YCbCr_macro(y1,cb,cr,r,g,b);
1393                                        *((uint32_t *)tdst)= ((a<<24)|(y1<<16)|(cb<<8)|cr);     
1394                                }
1395                                dst += p_dst->surface.pitch;
1396                                src += p_src->surface.pitch;
1397                        }
1398                }
1399        }
1400        else
1401        {
1402                rowbytes = BGFX_MIN(p_src->surface.width,p_dst->surface.width - x) * p_dst->bpp/8;
1403                for (j = 0; j < h; ++j)
1404                {
1405                        BGFX_MEMCPY(dst,src,rowbytes);
1406                        dst += p_dst->surface.pitch;
1407                        src += p_src->surface.pitch;
1408                }
1409        }
1410        bgfx_cacheflush(p_dst->surface.buf,p_dst->surface.pitch * p_dst->surface.height);
1411        return 0;
1412}
1413/****************************************************************
1414* INPUTS:       p_src,p_dst - source and destination buffer pointers
1415*                       sx
1416*                       dx
1417*                       w - width
1418* OUTPUTS:      none
1419* RETURNS:      non-zero on error
1420* FUNCTION:     Blit a region of one surface to another (for 4 bpp )
1421*
1422****************************************************************/
1423
1424static inline void bgfx_row_copy(unsigned char *src, unsigned char *dst,
1425                                  uint16_t sx,uint16_t dx,uint16_t w, int bpp)
1426{
1427        if (bpp == 8)
1428        {
1429                BGFX_MEMCPY(dst,src,w); 
1430        }
1431        else
1432        {
1433                unsigned int num_bytes = (w * 4)/8;
1434                int pix;
1435       
1436                if (sx & 1)
1437                {
1438                        if (dx & 1)
1439                        {
1440                                *dst &= 0xF0;
1441                                *dst |= (*src & 0xF);
1442                                if (w & 1)
1443                                {
1444                                        BGFX_MEMCPY(&dst[1],&src[1],num_bytes);
1445                                }
1446                                else
1447                                {
1448                                        BGFX_MEMCPY(&dst[1],&src[1],num_bytes - 1);
1449                                        dst[num_bytes] &= 0x0F;
1450                                        dst[num_bytes] |= (src[num_bytes] & 0xF0);
1451                                }
1452                        }
1453                        else
1454                        {
1455                                for (pix = 0; pix < w; ++pix)
1456                                {
1457                                        if (pix & 1)
1458                                        {
1459                                                *dst &= 0xF0;
1460                                                *dst |= (*src & 0xF0) >> 4;
1461                                                dst++;
1462                                        }
1463                                        else
1464                                        {
1465                                                *dst &= 0x0F;
1466                                                *dst |= (*src & 0xF) << 4;
1467                                                src++;
1468                                        }
1469                                }
1470                        }
1471                }
1472                else
1473                {
1474                        if (dx & 1)
1475                        {
1476                                for (pix = 0; pix < w; ++pix)
1477                                {
1478                                        if (pix & 1)
1479                                        {
1480                                                *dst &= 0x0F;
1481                                                *dst |= (*src & 0xF) << 4;
1482                                                src++;
1483                                        }
1484                                        else
1485                                        {
1486                                                *dst &= 0xF0;
1487                                                *dst |= (*src & 0xF0) >> 4;
1488                                                dst++;
1489                                        }
1490                                }
1491                        }
1492                        else
1493                        {
1494                                if (w & 1)
1495                                {
1496                                        BGFX_MEMCPY(dst,src,num_bytes);
1497                                        dst[num_bytes] &= 0x0F;
1498                                        dst[num_bytes] |= (src[num_bytes] & 0xF0);
1499                                }
1500                                else
1501                                {
1502                                        BGFX_MEMCPY(dst,src,num_bytes);
1503                                }
1504                        }
1505                }
1506        }
1507}
1508/****************************************************************
1509* INPUTS:       p_src,p_dst - source and destination surface structures
1510*                       sx,sy - source coordinates
1511*                       dx,dy - destination coordinates
1512*                       sw,sh - width and height of region
1513* OUTPUTS:      none
1514* RETURNS:      non-zero on error
1515* FUNCTION:     Blit a region of one surface to another
1516*
1517****************************************************************/
1518
1519int bgfx_stretch_blit(bgfx_surf_p p_src, bgfx_surf_p p_dst,
1520        uint16_t sx,uint16_t sy,uint16_t dx,uint16_t dy,
1521        uint16_t sw,uint16_t sh,uint16_t dw,uint16_t dh)
1522{
1523        int rc = 0;
1524        if ((p_src->flags & BGFX_SURF_GRC) && (p_dst->flags & BGFX_SURF_GRC)) 
1525        {
1526                void *src,*dst,*out;
1527                bgfx_rect src_r,dst_r,out_r;
1528
1529                src = p_src->surface.surf;
1530                out = p_dst->surface.surf;
1531                dst = out;
1532                src_r.x = sx;
1533                src_r.y = sy;
1534                src_r.width = sw;
1535                src_r.height = sh;
1536                out_r.x = dst_r.x = dx;
1537                out_r.y = dst_r.y = dy;
1538                out_r.width = dst_r.width = dw;
1539                out_r.height = dst_r.height = dh;
1540
1541                rc = bgfx_hw_blit(src,&src_r, dst, &dst_r,out, &out_r);
1542        }
1543        else if ((p_src->flags & BGFX_SURF_RGB) && (p_dst->flags & BGFX_SURF_RGB))
1544        {
1545                /* Nearest neighbor stretch blit */
1546                int i,j,dst_off,src_off;
1547                uint32_t fx_delta_x = (sw * 256)/dw; 
1548                uint32_t fx_delta_y = (sh * 256)/dh;
1549                uint32_t *dst_ptr,*src_ptr;
1550                uint32_t m,n;
1551               
1552                src_ptr = (uint32_t*)p_src->surface.buf;
1553                dst_ptr = (uint32_t*)p_dst->surface.buf;
1554
1555                for (i = 0; i < dh; i++)
1556                {
1557                        for (j=0; j < dw; j++)
1558                        {
1559                                dst_off = ((p_dst->surface.pitch)/4 * (i + dy)) + dx + j;
1560                               
1561                                m = (((i << 8) * fx_delta_y)/256) >> 8;
1562                                n = (((j << 8) * fx_delta_x)/256) >> 8;
1563                                src_off = sx + ((sy + m) * (p_src->surface.pitch/4)) + n;
1564                               
1565                                //dst_ptr[dst_off] = src_ptr[src_off];
1566                                dst_ptr[dst_off] = bgfx_blend_argb_pixels(src_ptr[src_off],dst_ptr[dst_off]);
1567                        }
1568                }
1569        }
1570        return rc;
1571}
1572
1573/****************************************************************
1574* INPUTS:       p_src,p_dst - source and destination surface structures
1575*                       sx,sy - source coordinates
1576*                       dx,dy - destination coordinates
1577*                       sw,sh - width and height of region
1578* OUTPUTS:      none
1579* RETURNS:      non-zero on error
1580* FUNCTION:     Blit a region of one surface to another
1581*
1582****************************************************************/
1583int bgfx_blit_rect(bgfx_surf_p p_src, bgfx_surf_p p_dst, 
1584                                  uint16_t sx,uint16_t sy, uint16_t dx,uint16_t dy, 
1585                                  uint16_t sw,uint16_t sh)
1586{
1587        uint8_t *dst,*src;
1588        uint16_t i,j,w,h;
1589        uint8_t *tdst;
1590
1591        if ((dx >= p_dst->surface.width) || (dy >= p_dst->surface.height))
1592        {
1593                BGFX_DEBUG(("bgfx_blit_rect dst_x,dst_y (%d,%d) outside destination (%d,%d)\n",dx,dy,
1594                                   p_dst->surface.width,p_dst->surface.height));
1595                return -1;
1596        }
1597
1598        if ((sx >= p_src->surface.width) || (sy >= p_src->surface.height))
1599        {
1600                BGFX_DEBUG(("bgfx_blit_rect src_x,src_y (%d,%d) outside source (%d,%d)\n",sx,sy,
1601                                   p_src->surface.width,p_src->surface.height));
1602                return -1;
1603        }
1604
1605        if ((p_src->flags & BGFX_SURF_GRC) && (p_dst->flags & BGFX_SURF_GRC)) {
1606                void *src,*dst,*out;
1607                bgfx_rect src_r,dst_r,out_r;
1608                int rc;
1609
1610                src = p_src->surface.surf;
1611                out = p_dst->surface.surf;
1612                dst = out;
1613                src_r.x = sx;
1614                src_r.y = sy;
1615                src_r.width = sw;
1616                src_r.height = sh;
1617                out_r.x = dst_r.x = dx;
1618                out_r.y = dst_r.y = dy;
1619                out_r.width = dst_r.width = sw;
1620                out_r.height = dst_r.height = sh;
1621
1622                rc = bgfx_hw_blit(src,&src_r, dst, &dst_r,out, &out_r);
1623                return rc;
1624        }
1625       
1626        src = (uint8_t*)p_src->surface.buf;
1627        src += (sy * p_src->surface.pitch) + ((sx * p_src->bpp)/8);
1628        dst = (uint8_t*)p_dst->surface.buf;
1629        dst += (dy * p_dst->surface.pitch) + ((dx * p_dst->bpp)/8);
1630
1631    w = sw;
1632       
1633        if (sw >= (p_src->surface.width - sx))
1634                w= p_src->surface.width - sx;
1635       
1636        if (w >= p_dst->surface.width - dx)
1637                w = p_dst->surface.width - dx;
1638
1639        h = sh;
1640
1641        if (sh >= (p_src->surface.height - sy))
1642                h= p_src->surface.height - sy;
1643
1644        if (h >= p_dst->surface.height - dy)
1645                h = p_dst->surface.height - dy;
1646       
1647
1648        if (p_dst->flags & BGFX_SURF_RGB)
1649        {
1650                for (j = 0; j < h; ++j)
1651                {
1652                        if (p_src->flags & BGFX_SURF_RGB)
1653                                BGFX_MEMCPY(dst, src, w*p_src->bpp/8);
1654                        else
1655                        {
1656                                tdst = dst;
1657                                for (i = 0; i < w; ++i)
1658                                {
1659                                        if (src[i] != 0xFF)
1660                                                *((uint32_t*)tdst) = bgfx_clut8_to_rgb(p_src->palette.clut,src[i]);
1661                                        tdst += p_dst->bpp/8;
1662                                }
1663                        }
1664                        dst += p_dst->surface.pitch;
1665                        src += p_src->surface.pitch;
1666                }
1667        }
1668        else
1669        {
1670                for (j = 0; j < h; ++j)
1671                {
1672                        if (p_dst->bpp == 8)
1673                        {
1674                                for (i = 0; i < w; ++i)
1675                                {
1676                                        if (p_src->palette.clut[src[i]] & 0xFF000000)
1677                                        {
1678                                                dst[i] = src[i];
1679                                        }
1680                                }
1681                        }
1682                        else
1683                        {
1684                                bgfx_row_copy(src,dst,sx,dx,w,p_dst->bpp);
1685                        }
1686                        dst += p_dst->surface.pitch;
1687                        src += p_src->surface.pitch;
1688                }
1689        }
1690        bgfx_cacheflush(p_dst->surface.buf,p_dst->surface.pitch * p_dst->surface.height);
1691        return 0;
1692}
1693
1694#ifdef  HAS_SUBTITLE
1695void bgfx_fill_box_subtitle(
1696    bgfx_surf_p p,              /* surface buffer to draw */
1697    uint16_t x,uint16_t y,      /* x and y */
1698    uint16_t w,uint16_t h,      /* w and h */
1699    uint8_t *pbuf,              /* pointer to a buffer with bitmap for subtitle to draw */
1700    uint16_t buf_len,           /* buf length, should match the w * h * format bytes */
1701    bgfx_pixel  bg,             /* background color, for palettle, it is color index */
1702    bgfx_pixel  fg,             /* forground color, for palettle, it is color index */
1703    bool update_bg              /* update backgound with given color */
1704)
1705{
1706        register uint8_t *dst;
1707        register uint16_t i, j;
1708        register int16_t shift;
1709#ifdef CONFIG_BGFX_SURF_RGB
1710        uint8_t *tdst;
1711#endif
1712        if (y + h > p->surface.height)
1713                h = p->surface.height - y;
1714
1715        /* TODO we shouldn't make modification to in horizontal size otherwise it may not match bitmap passed */
1716        if (w + x > p->surface.width)
1717                w = p->surface.width - x;
1718
1719        dst = (uint8_t*)p->surface.buf + (y * p->surface.pitch + ((x * p->bpp) >> 3));
1720
1721        shift = 7;
1722#ifdef CONFIG_BGFX_SURF_RGB
1723        int flags = p->flags;
1724        if (p->bpp <= 8) {
1725            /* clear bit so that we can reuse code */
1726            flags &= ~BGFX_SURF_RGB;
1727        }
1728
1729        if (flags & BGFX_SURF_RGB)
1730        {
1731                uint32_t cfg, cbg;
1732
1733                cfg = fg;
1734                cbg = bg;
1735
1736                cfg = BPXL_MAKE_PIXEL(bgfx_colorformat_mapping(p->format),
1737                    (cfg>>24) & 0xff, (cfg>>16)&0xff, (cfg>>8)&0xff, cfg&0xff);
1738                cbg = BPXL_MAKE_PIXEL(bgfx_colorformat_mapping(p->format),
1739                    (cbg>>24) & 0xff, (cbg>>16)&0xff, (cbg>>8)&0xff, cbg&0xff);
1740                /* if all zero in forground color, modified it to avoid same color as clear */
1741                if (0x8000 == cfg)
1742                    cfg = 0x8421;
1743
1744                if (32 == p->bpp) {
1745                    for (j = 0; j < h; j++) {
1746                        tdst = dst;
1747                        for (i = 0; (i < w) && ((int)buf_len > 0); i++, tdst += 4) {
1748                            if (*pbuf & (1 << shift))
1749                                *((uint32_t*)tdst) = cfg;
1750                            else {
1751                                if (update_bg)
1752                                    *((uint32_t*)tdst) = cbg;
1753                            }
1754
1755                            if (shift <= 0) {
1756                                shift = 7;
1757                                pbuf++; buf_len--;
1758                            }
1759                            else
1760                                shift--;
1761                        }
1762                        dst += p->surface.pitch;
1763                    }
1764                }
1765                else {
1766                    /* 16 bits */
1767                    for (j = 0; j < h; j++) {
1768                        tdst = dst;
1769                        for (i = 0; (i < w) && ((int)buf_len > 0); i++, tdst += 2) {
1770                            if (*pbuf & (1 << shift))
1771                                *((uint16_t*)tdst) = (uint16_t)cfg;
1772                            else {
1773                                if (update_bg)
1774                                    *((uint16_t*)tdst) = (uint16_t)cbg;
1775                            }
1776
1777                            if (shift <= 0) {
1778                                shift = 7;
1779                                pbuf++; buf_len--;
1780                            }
1781                            else
1782                                shift--;
1783                        }
1784                        dst += p->surface.pitch;
1785                    }
1786                }
1787        }
1788        else
1789#endif
1790        {
1791                uint8_t c;
1792
1793                /* for performance */
1794                if (p->format == bgraphics_pixel_format_palette4) {
1795                    /* special case for P4 */
1796                    dst = (uint8_t*)p->surface.buf + y * p->surface.pitch;
1797                    fg &= 0x0f;
1798                    bg &= 0x0f;
1799                }
1800                else if (p->format != bgraphics_pixel_format_palette4)
1801                    return;
1802
1803                for (j = 0; j < h; j++)
1804                {
1805                        if(p->format == bgraphics_pixel_format_palette4)
1806                        {
1807                            for (i = x; (i < (w + x)) && ((int)buf_len > 0); i++) {
1808                                if (*pbuf & (1 << shift))
1809                                    c = (uint8_t)fg;
1810                                else {
1811                                    if (update_bg)
1812                                        c = (uint8_t)bg;
1813                                    else {
1814                                        goto SKIP_IT;
1815                                    }
1816                                }
1817
1818                                if (i & 1)
1819                                {
1820                                    *(dst + (i >> 1)) &= 0xF0;
1821                                    *(dst + (i >> 1)) |= c;
1822                                }
1823                                else
1824                                {
1825                                    *(dst + (i >> 1)) &= 0x0F;
1826                                    *(dst + (i >> 1)) |= (c << 4);
1827                                }
1828
1829SKIP_IT:
1830                                if (shift <= 0) {
1831                                    shift = 7;
1832                                    pbuf++;
1833                                    buf_len--;
1834                                }
1835                                else
1836                                    shift--;
1837                            }
1838                        }
1839                        else
1840                        {
1841                            for (i = 0; (i < w) && ((int)buf_len > 0); i++) {
1842                                if (*pbuf & (1 << shift))
1843                                    *(dst + i) = (uint8_t)fg;
1844                                else {
1845                                    if (update_bg)
1846                                        *(dst + i) = (uint8_t)bg;
1847                                }
1848
1849                                if (shift <= 0) {
1850                                    shift = 7;
1851                                    pbuf++; buf_len--;
1852                                }
1853                                else
1854                                    shift--;
1855                        }
1856                    }
1857                    dst += p->surface.pitch;
1858                }
1859        }
1860
1861        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
1862}
1863
1864#endif
1865
1866/****************************************************************
1867* bgfx_draw_text_ex - extended version of draw_text; draws text
1868*           within a bounded area, and returns the actual text
1869*           dimensions
1870*
1871* INPUTS:   p - surface structure
1872*           x,y - coordinates
1873*           width,height - width and height of the text box to draw
1874*           str_p - array of 32-bit unicode characters
1875*           str_len - number of 32-bit characters in array
1876*           font_p - font definition
1877*           fg - foreground color
1878*           line_spacing - line space
1879*           justify - 0=left, 1=center, 2=right; default is left
1880*           render - true to render text, false to just size it
1881* OUTPUTS:  width,height - actual max width and height of text
1882* RETURNS:  true if text fits, false if text does not fit
1883*
1884****************************************************************/
1885#define max_uint16 0xFFFF
1886bool bgfx_draw_text_ex(
1887                      bgfx_surf_p p,              /* pointer to initialized surface structure */
1888                      uint16_t x,                 /* horizontal location in pixels (top/left 0,0) */
1889                      uint16_t y,                 /* vertical location in pixels */
1890                      uint16_t *width,            /* horizontal size in pixels (top/left 0,0) */
1891                      uint16_t *height,           /* vertical size in pixels */
1892                      const unsigned int *str_p,  /* array of 32-bit unicode characters */
1893                      uint16_t str_len,           /* length of character array */
1894                      bgfx_font_t *font_p,        /* initialized font structure (see sgl_font.h) */
1895                      bgfx_pixel fg,              /* foreground color */
1896                      int line_spacing,           /* leading (extra space between lines) */
1897                      uint16_t justify,           /* justification type: 0=left, 1=center, 2=right */
1898                      bool render                 /* true to render the text, false to just size it */
1899                      )
1900{
1901    uint16_t offset, bi, bw, bstop, line_idx, last_line, ch_w, ch_nw, bot, h, rh, max_w, cc, adv;
1902    static bgfx_glyph_t * p_bgfx_glyph[MAX_TEXT_BOX_CHARS];
1903    static lineinfo_t ln[MAX_LINES];
1904    bool rc = true;
1905
1906    /* limit size of text */
1907    if (str_len > MAX_TEXT_BOX_CHARS-1)
1908    {
1909        str_len = MAX_TEXT_BOX_CHARS-1;
1910    }
1911
1912    bot = y + *height;                              /* calculate bottom boundary of text box  */
1913    max_w = ch_w = line_idx = cc = 0;               /* init max width, line width, line index, char count (per line) */
1914    ln[0].e = max_uint16;                           /* bounds of first line not yet known */
1915    bi = 0;
1916    /* -------------------------------------------------- */
1917    /* first pass: determine where lines begin and end */
1918    /* -------------------------------------------------- */
1919    for (offset = 0; offset < str_len; offset++)
1920    {  /* for each 32-bit character in the "string" */
1921
1922        /* set up some shorthand */
1923        unsigned long uc = str_p[offset];           /* get 32-bit char */
1924        char c = (char)(uc & 0xFF);                 /* assume char is actually ascii */
1925        if (uc & 0xFFFFFF00) c = 0;                 /* if not, clear ascii char */
1926        if ((c < 0x20) || (c > 0x7E)) c = 0;        /* only printable ascii, actually */
1927
1928        /* get glyph info for next character */
1929        p_bgfx_glyph[offset] = bgfx_get_glyph(font_p,uc); /* get glyph data for next character */
1930        if (p_bgfx_glyph[offset] == NULL)
1931        {         /* if unprintable */
1932            p_bgfx_glyph[offset] = bgfx_get_glyph(font_p,s_space_char); /* substitute a space character */
1933        }
1934        adv = p_bgfx_glyph[offset]->advance;        /* get width of glyph */
1935        if (c == 0)
1936        {                                /* if not printable ascii */
1937            BGFX_DEBUG(("str[%d]=0x%08lX glyph: left=%d,top=%d,adv=%d,width=%d,height=%d,pitch=%d\n",
1938                       offset,uc,
1939                       p_bgfx_glyph[offset]->left,p_bgfx_glyph[offset]->top,adv,
1940                       p_bgfx_glyph[offset]->width,p_bgfx_glyph[offset]->height,p_bgfx_glyph[offset]->pitch));
1941        }
1942        else
1943        {
1944            BGFX_DEBUG(("str[%d]='%c' glyph: left=%d,top=%d,adv=%d,width=%d,height=%d,pitch=%d\n",
1945                       offset,c,
1946                       p_bgfx_glyph[offset]->left,p_bgfx_glyph[offset]->top,adv,
1947                       p_bgfx_glyph[offset]->width,p_bgfx_glyph[offset]->height,p_bgfx_glyph[offset]->pitch));
1948        }
1949
1950        /* check for line boundaries */
1951        ch_nw = ch_w + adv;                         /* calculate potential new width */
1952        if (uc == s_null_char)
1953        {                    /* if this is a null */
1954            BGFX_DEBUG(("Ignoring null char at offset %d\n",offset)); /* just ignore it */
1955        }
1956        else if (uc == s_newline_char)
1957        {          /* if this is a forced newline */
1958            ln[line_idx].e = offset;                /* note line is terminated */
1959            ln[line_idx].w = ch_w;                  /* note length of this line */
1960            ln[line_idx].c = cc;                    /* save count of chars on this line (not including newline char) */
1961            ch_w = cc = 0;                          /* set starting width and char count for next line */
1962        }
1963        else if (ch_nw <= *width)
1964        {               /* if char fits on this line */
1965            ch_w = ch_nw;                           /* add advance */
1966            BGFX_DEBUG(("char %d fits; ch_w is now %d\n",cc,ch_w));
1967            cc++;                                   /* count this char */
1968        }
1969        else
1970        {                                    /* char does NOT fit on current line */
1971            bstop = (line_idx == 0) ? 1 : ln[line_idx-1].e + 1; /* where to stop - start of line or whole string */
1972
1973            /* see if there's a word space that can serve as the breakpoint */
1974            bw = 0;                                 /* to accumulate widths of backed-off chars */
1975            bi = offset;                            /* start scanning back from current character */
1976            while (bi > bstop)
1977            {                    /* while there are still chars to check */
1978                if (str_p[bi] == s_space_char)
1979                {    /* if we can break on this character */
1980                    break;                          /* break out of the loop */
1981                }
1982
1983                bw += p_bgfx_glyph[bi]->advance;    /* add width of this char (for next line) */
1984                BGFX_DEBUG(("Backing up over char 0x%08X at offset %d, bw is now %d\n",str_p[bi],bi,bw));
1985                bi--;                               /* back up to prior char */
1986            }
1987            if (bi > bstop)
1988            {                       /* if space found */
1989                /* set initial metrics for next line */
1990                ch_w = bw;                          /* set starting width for next line (drop space) */
1991                cc = offset - bi;                   /* set starting char count for next line */
1992                /* trim all trailing spaces at end of line so that justification works right */
1993                while ((bi > bstop) && (str_p[bi] == s_space_char))
1994                { /* for all trailing spaces on this line */
1995                    bw += p_bgfx_glyph[bi]->advance; /* add its width to the stuff being removed from this line */
1996                    BGFX_DEBUG(("Backing up over space char at offset %d, bw is now %d\n",str_p[bi],bi,bw));
1997                    bi--;                           /* back up over it */
1998                }
1999                ln[line_idx].e = bi+1;              /* set first space as end of current line */
2000                ln[line_idx].w = ch_nw - bw;        /* adjust line width to just the chars now on this line */
2001                ln[line_idx].c = cc - (offset - bi+1); /* set char count for this line */
2002            }
2003
2004            /* if no breaking word space found, try for a hyphen */
2005            if (ln[line_idx].e == max_uint16)
2006            {      /* no breaking space found */
2007                bw = 0;                             /* to accumulate widths of backed-off chars */
2008                bi = offset-1;                      /* start scanning back from previous character */
2009                while (bi > bstop)
2010                {                /* while there are still chars to check */
2011                    if (str_p[bi] == s_hyphen_char)
2012                    { /* if we can break on this character */
2013                        ln[line_idx].e = bi;        /* set as end of current line */
2014                        ln[line_idx].w = ch_w - bw; /* adjust line width (includes hyphen) */
2015                        ln[line_idx].c = cc - (offset - bi); /* set char count for this line */
2016                        ch_w = bw + adv;            /* set starting width for next line */
2017                        cc = offset - bi;           /* set starting char count for next line */
2018                        bi = 0;                     /* to stop loop now */
2019                        break;
2020                    }
2021                    bw += p_bgfx_glyph[bi]->advance; /* add width of this char */
2022                    bi--;                           /* back up to prior char */
2023                }
2024            }
2025
2026            /* if neither a space nor hyphen found to break on, force break at current character (move to next line) */
2027            if (ln[line_idx].e == max_uint16)
2028            {      /* if still no breaking character found */
2029                ln[line_idx].e = offset-1;          /* mark previous char as last on this line */
2030                ln[line_idx].w = ch_w;              /* set length of this line */
2031                ln[line_idx].c = cc;                /* set char count, not including current char */
2032                ch_w = adv;                         /* set starting width for next line */
2033                cc = 1;                             /* this char is already on next line */
2034            }
2035        }
2036
2037        /* if line finished off, move to next line */
2038        if (ln[line_idx].e != max_uint16)
2039        {          /* if current line has been finished off */
2040            if (ln[line_idx].w > max_w)
2041            {            /* if longest line so far */
2042                max_w = ln[line_idx].w;             /* update max width */
2043            }
2044            line_idx++;                             /* advance line index */
2045            ln[line_idx].e = max_uint16;            /* end of line not yet known */
2046        }
2047
2048                if (line_idx >= (MAX_LINES - 1))
2049                {
2050                        break;
2051                }
2052    }
2053
2054    /* if there's data on the last line, finish it off */
2055    if (ch_w > 0)
2056    {                                  /* if there's data there */
2057        ln[line_idx].e = str_len-1;                 /* terminate the last line at the last char */
2058        ln[line_idx].w = ch_w;                      /* note length */
2059        ln[line_idx].c = cc;                        /* set char count */
2060        if (ln[line_idx].w > max_w)
2061        {                /* if last line is longest */
2062            max_w = ln[line_idx].w;                 /* update max width */
2063        }
2064        line_idx++;                                 /* count it */
2065    }
2066    last_line = line_idx;
2067
2068    /* -------------------------------------------------- */
2069    /* second pass: determine line heights and total height */
2070    /* -------------------------------------------------- */
2071    line_idx = h = rh = 0;                          /* init line index, line height, running height */
2072    for (offset = 0; offset < str_len; offset++)
2073    {  /* for each char */
2074        if (p_bgfx_glyph[offset]->height > h)
2075        {      /* if this glyph's height is largest on this line so far */
2076#ifdef BGFX_VARIABL_LINE_HEIGHT           
2077                        h = p_bgfx_glyph[offset]->height;       /* note the largest glyph on this line */
2078#else
2079                        h = font_p->height;       /* note the largest glyph on this line */
2080#endif
2081        }
2082        if (offset == ln[line_idx].e)
2083        {             /* if this is the end of the line */
2084            ln[line_idx].h = h;                     /* store line height */
2085            if (rh != 0) 
2086                                rh += line_spacing;         /* add leading (space between lines) */
2087            rh += h;                                /* add line height */
2088            if (rh > bot)
2089            {                         /* if exceeded vertical size of text box */
2090                last_line = line_idx;               /* update last line number */
2091                rc = false;                         /* note so we can return indication */
2092                break;                              /* bail out of pass 2 loop now */
2093            }
2094            line_idx++;                             /* advance to next line */
2095            h = 0;                                  /* reset line height */
2096        }
2097    }
2098
2099    /* -------------------------------------------------- */
2100    /* last pass: render the text */
2101    /* -------------------------------------------------- */
2102    if (render)
2103    {                                    /* if text is to actually be drawn */
2104        ch_w = line_idx = 0;                        /* init line width, line index */
2105                h = font_p->ascender;
2106        for (offset = 0; offset < str_len; offset++)
2107        { /* for each char */
2108
2109            unsigned long uc = str_p[offset];       /* get 32-bit char */
2110            char c = (char)(uc & 0xFF);             /* assume char is actually ascii */
2111            if (uc & 0xFFFFFF00) c = 0;             /* if not, clear ascii char */
2112            if ((c < 0x20) || (c > 0x7E)) c = 0;    /* only printable ascii, actually */
2113
2114            /* at beginning of line, determine starting horizontal offset */
2115            if (ch_w == 0)
2116            {                         /* if start of line */
2117                switch (justify)
2118                {                  /* depending on justification mode */
2119                case 1:                         /* to center text */
2120                    bi = (*width - ln[line_idx].w)/2; /* divide extra space in half */
2121                    break;
2122                case 2:                         /* to right-justify text */
2123                    bi = *width - ln[line_idx].w; /* place all extra space at left */
2124                    break;
2125                default:
2126                    bi = 0;                     /* all extra space is at right */
2127                    break;
2128                } /* switch */
2129            }
2130
2131
2132            /* at end of line, render last char if needed and set up for next line */
2133            if (offset == ln[line_idx].e)
2134            {         /* if this is the end of the line */
2135                /* if other than null or newline, last char must be rendered */
2136                if ((str_p[offset] != s_null_char) && (str_p[offset] != s_newline_char))
2137                {
2138                    if (c == 0)
2139                    {
2140                        BGFX_DEBUG(("Rendering char %d (0x%08lX) at (%d,%d) - last glyph on line\n",offset,uc,x+ch_w+bi,y+h));
2141                    }
2142                    else
2143                    {
2144                        BGFX_DEBUG(("Rendering char %d (%c) at (%d,%d) - last glyph on line\n",offset,c,x+ch_w+bi,y+h));
2145                    }
2146                    bgfx_render_glyph(p,x+ch_w+bi,y+h,str_p[offset],font_p,fg,p_bgfx_glyph[offset],eBGFX_NORMAL);
2147                }
2148                else
2149                {
2150                    BGFX_DEBUG(("Last glyph on line is null, space, or newline\n",offset,uc,x+ch_w+bi,y+h));
2151                }
2152                h += line_spacing + ln[line_idx].h; /* add leading plus height of current line */
2153                line_idx++;                         /* advance to next line */
2154                ch_w = 0;                           /* reset horizontal position */
2155                if (line_idx == last_line) break;    /* don't exceed bottom boundary of text box */
2156            }
2157            else if (uc != s_null_char)
2158            {         /* render non-null glyph and add width to running line width */
2159                if (c == 0)
2160                {
2161                    BGFX_DEBUG(("Rendering char %d (0x%08lX) at (%d,%d)\n",offset,uc,x+ch_w+bi,y+h));
2162                }
2163                else
2164                {
2165                    BGFX_DEBUG(("Rendering char %d (%c) at (%d,%d)\n",offset,c,x+ch_w+bi,y+h));
2166                }
2167                ch_w += bgfx_render_glyph(p,x+ch_w+bi,y+h,str_p[offset],font_p,fg,p_bgfx_glyph[offset],eBGFX_NORMAL);
2168            }
2169        }
2170        bgfx_cacheflush(p->surface.buf,p->surface.pitch * p->surface.height);
2171    }
2172
2173    /* return required info */
2174    *width = max_w;
2175    *height = rh;
2176    return rc;
2177}
2178
2179/****************************************************************
2180* bgfx_draw_text_box_ex - extended version of draw_text_box;
2181*           draws specified text in bounded box, with specified
2182*           background and border colors
2183*
2184* INPUTS:   p - surface structure
2185*           x,y - coordinates
2186*           width,height - maximum width and height of text box
2187*           str_p - array of 32-bit unicode characters
2188*           str_len - number of 32-bit characters in array
2189*           f - font definition
2190*           fg - foreground color
2191*           bg - background color
2192*           bc - border color
2193*           line_spacing - line space
2194*           m - text margin, in pixels
2195*           b - border width, in pixels; 0 = no border
2196*           justify - 0=left, 1=center, 2=right; default is left
2197* OUTPUTS:  none
2198* RETURNS:  true if text fits in box, false if not
2199*
2200****************************************************************/
2201bool bgfx_draw_text_box_ex(
2202        bgfx_surf_p p,              /* pointer to initialized surface structure */
2203    uint16_t *x,                /* horizontal location in pixels (top/left 0,0)*/
2204    uint16_t *y,                /* vertical location in pixels */
2205    uint16_t *w,                /* horizontal size in pixels (top/left 0,0) */
2206    uint16_t *h,                /* vertical size in pixels */
2207    const unsigned int *str_p,  /* array of 32-bit unicode characters */
2208    uint16_t str_len,           /* length of character array */
2209    bgfx_font_t *f,             /* initialized font structure (see sgl_font.h) */
2210    bgfx_pixel fg,              /* foreground color */
2211    bgfx_pixel bg,              /* background color */
2212    bgfx_pixel bc,              /* border color */
2213    uint16_t line_spacing,              /* leading (extra space between lines) */
2214    uint16_t m,             /* margin between text and borders */
2215    uint16_t b,             /* width of border (on the outside of the box) */
2216    uint16_t h_justify,         /* Horizontal justification type: 0=left, 1=center, 2=right */
2217    uint16_t v_justify                      /* Vertical justification type:0=top, 1=center */
2218    )
2219{
2220    uint16_t margin,width,height,horadj,veradj,left,top;
2221    int i;
2222    bool res = true;
2223
2224    margin = m + m;                     /* total margin (top and bottom or left and right) */
2225    if ((*x < b) || (*y < b))
2226    {          /* if origin doesn't allow room for borders on left or top */
2227        return false;
2228    }
2229    if (((*x + *w) > (p->surface.width - b)) || ((*y + *h) > (p->surface.height - b)))
2230    { /* if origin + size doesn't allow room for borders on right or bottom */
2231        return false;
2232    }
2233    if ((*w <= margin) || (*h <= margin))
2234    {  /* if not enough room for any text between margins */
2235        return false;
2236    }
2237
2238    /* determine initial bounds of text area */
2239    left = *x + m; top = *y + m;        /* add text margin to box origin */
2240    width = *w - margin;                /* adjust dimensions so text area is inside margins */
2241    height = *h - margin;
2242
2243    /* size up the text vertically and horizontally */
2244    if (!bgfx_draw_text_ex(p,                        /* graphics surface */
2245                         left, top,              /* box left and top */
2246                         &width, &height,        /* box width and height */
2247                         str_p, str_len,         /* text string and character count */
2248                         f,                      /* font */
2249                         fg,                     /* foreground color */
2250                         line_spacing,           /* vertical line spacing */
2251                         h_justify,              /* horizontal justification */
2252                         false))                 /* don't render on this pass */
2253    {
2254        res = false;
2255    }
2256
2257    /* adjust box dimensions based on sized text */
2258    horadj = (*w - margin) - width;     /* horizontal adjustment */
2259    veradj = (*h - margin) - height;    /* vertical adjustment */
2260    *x += horadj/2; *w -= horadj;       /* to center box horizontally */
2261    *y += veradj/2; *h -= veradj;       /* to center box vertically */
2262
2263    /* draw screen background based on resulting size  */
2264    bgfx_fill_rect(p,*x,*y,*w,*h,bg);   /* fill in box with background color */
2265    for (i = 0; i < b; i++)
2266    {           /* now draw the borders */
2267        BGFX_DEBUG(("   top border (x1,x2,y)=(%d,%d,%d)\n",*x-b+i,*x+b+*w-i,*y-b+i));
2268        bgfx_h_draw_line(p,*x-b+i,*x+b+*w-i,*y-b+i,bc); /* top border */
2269        BGFX_DEBUG(("bottom border (x1,x2,y)=(%d,%d,%d)\n",*x-b+i,*x+b+*w-i,*y+b+*h-1-i));
2270        bgfx_h_draw_line(p,*x-b+i,*x+b+*w-i,*y+b+*h-1-i,bc); /* bottom border */
2271        BGFX_DEBUG(("  left border (x,y1,y2)=(%d,%d,%d)\n",*x-b+i,*y-b+i,*y+b+*h-1-i));
2272        bgfx_v_draw_line(p,*x-b+i,*y-b+i,*y+b+*h-1-i,bc); /* left border */
2273        BGFX_DEBUG((" right border (x,y1,y2)=(%d,%d,%d)\n",*x+b+*w-i-1,*y-b+i,*y+b+*h-1-i));
2274        bgfx_v_draw_line(p,*x+b+*w-i-1,*y-b+i,*y+b+*h-1-i,bc); /* right border */
2275    }
2276
2277        if ( v_justify != 0 )
2278    {
2279        left = *x + m;                      /* to center horizontally */
2280        top = *y + m;                        /* to center vertically */
2281    }
2282
2283    /* render the text, centered in the box */
2284    bgfx_draw_text_ex( p,                       /* graphics surface */
2285                        left, top,              /* box left and top */
2286                        &width, &height,        /* box width and height */
2287                        str_p, str_len,         /* text string and character count */
2288                        f,                      /* font */
2289                        fg,                     /* foreground color */
2290                        line_spacing,           /* vertical line spacing */
2291                        h_justify,              /* horizontal justification */
2292                        true);                  /* render text on second pass */
2293
2294    return res;
2295}
2296
Note: See TracBrowser for help on using the repository browser.