]> git.sesse.net Git - vlc/blob - modules/codec/ogt/render.c
render.c: RGB2 now gets the right color from the RGB color map.
[vlc] / modules / codec / ogt / render.c
1 /*****************************************************************************
2  * render.c : Philips OGT and CVD (VCD Subtitle) blending routines
3  *****************************************************************************
4  * Copyright (C) 2003, 2004 VideoLAN
5  * $Id: render.c,v 1.27 2004/01/31 05:53:35 rocky Exp $
6  *
7  * Author: Rocky Bernstein <rocky@panix.com>
8  *   based on code from: 
9  *          Sam Hocevar <sam@zoy.org>
10  *          Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
11  *          Roine Gustafsson <roine@popstar.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*#define TESTING_TRANSPARENCY 1*/
29
30 /*****************************************************************************
31  * Preamble
32  *****************************************************************************/
33 #include <vlc/vlc.h>
34 #include <vlc/vout.h>
35 #include <vlc/decoder.h>
36
37 #include "pixmap.h"
38 #include "subtitle.h"
39 #include "render.h"
40
41 /* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and
42    0 completely opaque. Note that although SVCD allow 8-bits, pixels 
43    previously should be scaled down to 4 bits to use these routines.
44 */
45 #define ALPHA_BITS (4)
46 #define MAX_ALPHA  ((1<<ALPHA_BITS) - 1) 
47 #define ALPHA_SCALEDOWN (8-ALPHA_BITS)
48
49 /* We use a fixed-point arithmetic to scaling ratios so that we
50    can use integer arithmetic and still get fairly precise
51    results. ASCALE is a left shift amount. 
52 */
53 #define ASCALE 6  /* 2^6 = 32 */
54
55 /* Horrible hack to get dbg_print to do the right thing */
56 #define p_dec p_vout
57
58 /*****************************************************************************
59  * Local prototypes
60  *****************************************************************************/
61 static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *,
62                         vlc_bool_t );
63 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
64                         const subpicture_t *p_spu, vlc_bool_t b_crop );
65 static void BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
66                        const subpicture_t *p_spu, vlc_bool_t b_crop,
67                        vlc_bool_t b_15bpp );
68 static void BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
69                         const subpicture_t *p_spu, vlc_bool_t b_crop );
70 static void BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
71                         const subpicture_t *p_spu, vlc_bool_t b_crop );
72 static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
73                         const subpicture_t *p_spu, vlc_bool_t b_crop );
74
75 /*****************************************************************************
76  * BlendSPU: blend a subtitle into a picture
77  *****************************************************************************
78  
79   This blends subtitles (a subpicture) into the underlying
80   picture. Subtitle data has been preprocessed as YUV + transparancy
81   or 4 bytes per pixel with interleaving of rows in the subtitle
82   removed. 
83
84  *****************************************************************************/
85 void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic,
86                    const subpicture_t *p_spu )
87 {
88     struct subpicture_sys_t *p_sys = p_spu->p_sys;
89   
90     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
91                "chroma %x", p_vout->output.i_chroma );
92
93     switch( p_vout->output.i_chroma )
94     {
95         /* I420 target, no scaling */
96         case VLC_FOURCC('I','4','2','0'):
97         case VLC_FOURCC('I','Y','U','V'):
98         case VLC_FOURCC('Y','V','1','2'):
99             BlendI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
100             break;
101
102         /* RGB 555 - scaled */
103         case VLC_FOURCC('R','V','1','5'):
104             BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop, 
105                        VLC_TRUE );
106             break;
107           
108         case VLC_FOURCC('R','V','1','6'):
109             BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
110                        /* Not sure under what conditions RV16 is really
111                           RV16 and not RV15.
112                         */
113 #if 0
114                        VLC_FALSE );
115 #else
116                        VLC_TRUE );
117 #endif
118             break;
119
120         /* RV24 target, scaling */
121         case VLC_FOURCC('R','V','2','4'):
122             BlendRV24( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
123             break;
124
125         /* RV32 target, scaling */
126         case VLC_FOURCC('R','V','3','2'):
127             BlendRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
128             break;
129
130         /* NVidia overlay, no scaling */
131         case VLC_FOURCC('Y','U','Y','2'):
132             BlendYUY2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
133             break;
134
135         /* Palettized 8 bits per pixel (256 colors). Each
136            pixel is an uint8_t index in the palette
137            Used in ASCII Art. 
138         */
139         case VLC_FOURCC('R','G','B','2'):
140             BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
141           
142             break;
143
144         default:
145             msg_Err( p_vout, "unknown chroma, can't render SPU" );
146             break;
147     }
148 }
149
150 /* Following functions are local */
151
152 /* 
153   YV12 format:  
154
155   All Y samples are found first in memory as an array of bytes
156   (possibly with a larger stride for memory alignment), followed
157   immediately by all Cr (=U) samples (with half the stride of the Y
158   lines, and half the number of lines), then followed immediately by
159   all Cb (=V) samples in a similar fashion.
160 */
161
162 static void BlendI420( vout_thread_t *p_vout, picture_t *p_pic,
163                         const subpicture_t *p_spu, vlc_bool_t b_crop )
164 {
165   /* Common variables */
166   uint8_t *p_pixel_base_Y, *p_pixel_base_V, *p_pixel_base_U;
167   ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
168
169   int i_x, i_y;
170   vlc_bool_t even_scanline = VLC_FALSE;
171
172   /* Crop-specific */
173   int i_x_start, i_y_start, i_x_end, i_y_end;
174   /* int i=0; */
175
176   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
177   
178   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
179              "spu width x height: (%dx%d), (x,y)=(%d,%d), yuv pitch (%d,%d,%d)", 
180              p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
181              p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
182
183   
184   p_pixel_base_Y = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x
185                  + p_pic->p[Y_PLANE].i_pitch * p_spu->i_y;
186   
187   p_pixel_base_U = p_pic->p[U_PLANE].p_pixels + p_spu->i_x/2
188                  + p_pic->p[U_PLANE].i_pitch * p_spu->i_y/2;
189   
190   p_pixel_base_V = p_pic->p[V_PLANE].p_pixels + p_spu->i_x/2
191                  + p_pic->p[V_PLANE].i_pitch * p_spu->i_y/2;
192   
193   i_x_start = p_sys->i_x_start;
194   i_y_start = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_start;
195   
196   i_x_end   = p_sys->i_x_end;
197   i_y_end   = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_end;
198   
199   p_source = (ogt_yuvt_t *)p_sys->p_data;
200   
201   /* Draw until we reach the bottom of the subtitle */
202   for( i_y = 0; 
203        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
204        i_y += p_pic->p[Y_PLANE].i_pitch )
205     {
206       uint8_t *p_pixel_base_Y_y = p_pixel_base_Y + i_y;
207       uint8_t *p_pixel_base_U_y = p_pixel_base_U + i_y/4;
208       uint8_t *p_pixel_base_V_y = p_pixel_base_V + i_y/4;
209
210       i_x = 0;
211
212       if ( b_crop ) {
213         if ( i_y > i_y_end ) break;
214         if (i_x_start) {
215           i_x = i_x_start;
216           p_source += i_x_start;
217         }
218       }
219
220       even_scanline = !even_scanline;
221
222       /* Draw until we reach the end of the line */
223       for( ; i_x < p_spu->i_width; i_x++, p_source++ )
224         {
225
226           if( b_crop ) {
227
228             /* FIXME: y cropping should be dealt with outside of this loop.*/
229             if ( i_y < i_y_start) continue;
230
231             if ( i_x > i_x_end )
232             {
233               p_source += p_spu->i_width - i_x;
234               break;
235             }
236           }
237
238 #ifdef TESTING_TRANSPARENCY
239           if (p_source->s.t == MAX_ALPHA) p_source->s.t >>= 1;
240 #endif
241
242           switch( p_source->s.t )
243             {
244             case 0: 
245               /* Completely transparent. Don't change pixel. */
246               break;
247               
248             case MAX_ALPHA:
249               {
250                 /* Completely opaque. Completely overwrite underlying
251                    pixel with subtitle pixel. */
252                 
253                 /* This is the location that's going to get changed.*/
254                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
255                 
256                 *p_pixel_Y = p_source->plane[Y_PLANE];
257
258                 if ( even_scanline && i_x % 2 == 0 ) {
259                   uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2;
260                   uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2;
261                   *p_pixel_U = p_source->plane[U_PLANE];
262                   *p_pixel_V = p_source->plane[V_PLANE];
263                 }
264                 
265                 break;
266               }
267               
268             default:
269               {
270                 /* Blend in underlying subtitle pixel. */
271                 
272                 /* This is the location that's going to get changed. */
273                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
274
275
276                 /* This is the weighted part of the subtitle. The
277                    color plane is 8 bits and transparancy is 4 bits so
278                    when multiplied we get up to 12 bits.
279                  */
280                 uint16_t i_sub_color_Y = 
281                   (uint16_t) ( p_source->plane[Y_PLANE] *
282                                (uint16_t) (p_source->s.t) );
283
284                 /* This is the weighted part of the underlying pixel.
285                    For the same reasons above, the result is up to 12
286                    bits.  However since the transparancies are
287                    inverses, the sum of i_sub_color and i_pixel_color
288                    will not exceed 12 bits.
289                 */
290                 uint16_t i_pixel_color_Y = 
291                   (uint16_t) ( *p_pixel_Y * 
292                                (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
293                 
294                 /* Scale the 12-bit result back down to 8 bits. A
295                    precise scaling after adding the two components,
296                    would divide by one less than a power of 2. However
297                    to simplify and speed things we use a power of
298                    2. This means the boundaries (either all
299                    transparent and all opaque) aren't handled properly.
300                    But we deal with them in special cases above. */
301
302                 *p_pixel_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> ALPHA_BITS;
303
304                 if ( even_scanline && i_x % 2 == 0 ) {
305                   uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2
306                     - p_pic->p[U_PLANE].i_pitch / 2;
307                   uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2
308                     - p_pic->p[V_PLANE].i_pitch / 2;
309                   uint16_t i_sub_color_U = 
310                     (uint16_t) ( p_source->plane[U_PLANE] *
311                                  (uint16_t) (p_source->s.t) );
312                   
313                   uint16_t i_sub_color_V = 
314                     (uint16_t) ( p_source->plane[V_PLANE] *
315                                  (uint16_t) (p_source->s.t) );
316                   uint16_t i_pixel_color_U = 
317                     (uint16_t) ( *p_pixel_U * 
318                                  (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
319                   uint16_t i_pixel_color_V = 
320                     (uint16_t) ( *p_pixel_V * 
321                                  (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
322                   *p_pixel_U = ( i_sub_color_U + i_pixel_color_U )>>ALPHA_BITS;
323                   *p_pixel_V = ( i_sub_color_V + i_pixel_color_V )>>ALPHA_BITS;
324                 }
325                 break;
326               }
327               
328             }
329         }
330     }
331 }
332
333 /*
334
335   YUY2 Format:
336
337   Data is found in memory as an array of bytes in which the first byte
338   contains the first sample of Y, the second byte contains the first
339   sample of Cb (=U), the third byte contains the second sample of Y,
340   the fourth byte contains the first sample of Cr (=V); and so
341   on. Each 32-bit word then contains information for two contiguous
342   horizontal pixels, two 8-bit Y values plus a single Cb and Cr which
343   spans the two pixels.
344 */
345
346 #define BYTES_PER_PIXEL 4
347
348 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
349                         const subpicture_t *p_spu, vlc_bool_t b_crop )
350 {
351   /* Common variables */
352   uint8_t *p_pixel_base;
353
354   /* This is the where the subtitle pixels come from */
355   ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;;
356
357   ogt_yuvt_t *p_source_end = (ogt_yuvt_t *)p_spu->p_sys->p_data + 
358     (p_spu->i_width * p_spu->i_height);
359
360   uint16_t i_x, i_y;
361
362   /* Make sure we start on a word (4-byte) boundary. */
363   uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2;
364
365   /* Crop-specific */
366   int i_x_start, i_y_start, i_x_end, i_y_end;
367
368   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
369   
370   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
371              "spu width x height: (%dx%d), (x,y)=(%d,%d), pitch: %d", 
372              p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
373              p_pic->p->i_pitch );
374
375   
376   p_pixel_base = p_pic->p->p_pixels + 
377     + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x;
378
379   i_x_start = p_sys->i_x_start;
380   i_y_start = p_sys->i_y_start * p_pic->p->i_pitch;
381   
382   i_x_end   = p_sys->i_x_end;
383   i_y_end   = p_sys->i_y_end   * p_pic->p->i_pitch;
384
385   /* Draw until we reach the bottom of the subtitle */
386   for( i_y = 0; 
387        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
388        i_y += p_pic->p[Y_PLANE].i_pitch )
389     {
390       uint8_t *p_pixel_base_y = p_pixel_base + i_y;
391
392       i_x = 0;
393
394       if ( b_crop ) {
395         if ( i_y > i_y_end ) break;
396         if (i_x_start) {
397           i_x = i_x_start;
398           p_source += (i_x_start*2);
399         }
400       }
401   
402
403       /* Draw until we reach the end of the line. Each output pixel
404          is a combination of two source pixels. 
405        */
406       for( i_x = 0;  i_x < p_spu->i_width / 2; i_x++, p_source +=2 )
407         {
408           uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/
409
410           if (p_source > p_source_end-1) {
411             msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d",
412                      i_x, i_y);
413             return;
414           }
415
416           if( b_crop ) {
417
418             /* FIXME: y cropping should be dealt with outside of this loop.*/
419             if ( i_y < i_y_start) continue;
420
421             if ( i_x > i_x_end )
422             {
423               p_source += p_spu->i_width - (i_x*2);
424               break;
425             }
426           }
427   
428           
429           /* Favor opaque subtitle pixels. */
430           if ( (p_source->s.t == 0) && (p_source+1)->s.t == MAX_ALPHA )
431             i_avg_tr = (p_source+1)->s.t;
432           else if ( (p_source->s.t == MAX_ALPHA) && (p_source+1)->s.t == 0 )
433             i_avg_tr = p_source->s.t;
434           else 
435             i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2;
436           
437 #ifdef TESTING_TRANSPARENCY 
438           if (i_avg_tr == MAX_ALPHA) i_avg_tr >>= 1;
439 #endif
440
441           switch( i_avg_tr )
442             {
443             case 0: 
444               /* Completely transparent. Don't change pixel. */
445               break;
446               
447             case MAX_ALPHA:
448               {
449                 /* Completely opaque. Completely overwrite underlying
450                    pixel with subtitle pixel. */
451                 
452                 /* This is the location that's going to get changed. */
453                 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
454                 uint8_t i_avg_u;
455                 uint8_t i_avg_v;
456
457                 /* Favor opaque subtitle pixel. */
458                 if (p_source->s.t == MAX_ALPHA ) {
459                   i_avg_u = p_source->plane[U_PLANE] ;
460                   i_avg_v = p_source->plane[V_PLANE] ;
461                 } else if ( (p_source+1)->s.t == MAX_ALPHA ) {
462                   i_avg_u = (p_source+1)->plane[U_PLANE] ;
463                   i_avg_v = (p_source+1)->plane[V_PLANE] ;
464                 } else {
465                   i_avg_u = ( p_source->plane[U_PLANE] 
466                               + (p_source+1)->plane[U_PLANE] ) / 2;
467                   i_avg_v = ( p_source->plane[V_PLANE] 
468                               + (p_source+1)->plane[V_PLANE] ) / 2;
469                 }
470
471                 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
472                 *p_pixel++ = p_source->plane[Y_PLANE] ;
473                 *p_pixel++ = i_avg_u;
474                 *p_pixel++ = (p_source+1)->plane[Y_PLANE] ;
475                 *p_pixel++ = i_avg_v;
476                 
477                 break;
478               }
479
480             default:
481               {
482                 /* Blend in underlying subtitle pixels. */
483                 
484                 /* This is the location that's going to get changed. */
485                 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
486                 uint8_t i_avg_u = ( p_source->plane[U_PLANE] 
487                                     + (p_source+1)->plane[U_PLANE] ) / 2;
488                 uint8_t i_avg_v = ( p_source->plane[V_PLANE] 
489                                     + (p_source+1)->plane[V_PLANE] ) / 2;
490
491                 /* This is the weighted part of the two subtitle
492                    pixels. The color plane is 8 bits and transparancy
493                    is 4 bits so when multiplied we get up to 12 bits.
494                  */
495                 uint16_t i_sub_color_Y1 = 
496                   (uint16_t) ( p_source->plane[Y_PLANE] *
497                                (uint16_t) (p_source->s.t) );
498
499                 uint16_t i_sub_color_Y2 = 
500                   (uint16_t) ( (p_source+1)->plane[Y_PLANE] *
501                                (uint16_t) ((p_source+1)->s.t) );
502
503                 /* This is the weighted part of the underlying pixels.
504                    For the same reasons above, the result is up to 12
505                    bits.  However since the transparancies are
506                    inverses, the sum of i_sub_color and i_pixel_color
507                    will not exceed 12 bits.
508                 */
509                 uint16_t i_sub_color_U = 
510                   (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr );
511                 
512                 uint16_t i_sub_color_V = 
513                   (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr );
514
515                 uint16_t i_pixel_color_Y1 = 
516                   (uint16_t) ( *(p_pixel) * 
517                                (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
518                 uint16_t i_pixel_color_Y2 = 
519                   (uint16_t) ( *(p_pixel+2) * 
520                                (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
521                 uint16_t i_pixel_color_U = 
522                   (uint16_t) ( *(p_pixel+1) * 
523                                (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
524                 uint16_t i_pixel_color_V = 
525                   (uint16_t) ( *(p_pixel+3) * 
526                                (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
527
528                 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
529
530                 /* Scale the 12-bit result back down to 8 bits. A
531                    precise scaling after adding the two components,
532                    would divide by one less than a power of 2. However
533                    to simplify and speed things we use a power of
534                    2. This means the boundaries (either all
535                    transparent and all opaque) aren't handled properly.
536                    But we deal with them in special cases above. */
537
538                 *p_pixel++ = ( i_sub_color_Y1 + i_pixel_color_Y1 )>>ALPHA_BITS;
539                 *p_pixel++ = ( i_sub_color_U + i_pixel_color_U )  >>ALPHA_BITS;
540                 *p_pixel++ = ( i_sub_color_Y2 + i_pixel_color_Y2 )>>ALPHA_BITS;
541                 *p_pixel++ = ( i_sub_color_V + i_pixel_color_V )  >>ALPHA_BITS;
542                 break;
543               }
544             }
545         }
546
547       /* For an odd width source, we'll just have to drop off a pixel. */
548       if (p_spu->i_width % 2) p_source++;
549     }
550 }
551
552 /**
553    Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel.
554
555    A RGB 5-5-5 pixel looks like this:
556    RGB 5-5-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
557                  p        ? B4  B3 B2 B1 B0 R4  R3
558                  q       R2 R1  R0 G4 G3 G2 G1  G0
559
560 **/
561
562 static inline void
563 yuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
564 {
565
566   uint8_t rgb[RGB_SIZE];
567
568   yuv2rgb(p_yuv, rgb);
569   
570   /* Scale RGB from 8 bits down to 5. */
571   rgb[RED_PIXEL]   >>= (8-5);
572   rgb[GREEN_PIXEL] >>= (8-5);
573   rgb[BLUE_PIXEL]  >>= (8-5);
574   
575   *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c ) | ( (rgb[RED_PIXEL]>>3) & 0x03 );
576   *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
577
578 #if 0
579   printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
580          "rgb1: %02x, rgb2 %02x\n",
581          p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
582          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
583          *p_rgb1, *p_rgb2);
584 #endif
585
586 }
587
588 /**
589    Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel.
590
591    A RGB 5-6-5 pixel looks like this:
592    RGB 5-6-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
593                  p       B4 B3  B2 B1 B0 R5 R4  R3
594                  q       R2 R1  R0 G4 G3 G2 G1  G0
595
596 **/
597
598 static inline void
599 yuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
600 {
601
602   uint8_t rgb[RGB_SIZE];
603
604   yuv2rgb(p_yuv, rgb);
605   
606   /* Scale RGB from 8 bits down to 5 or 6 bits. */
607   rgb[RED_PIXEL]   >>= (8-6);
608   rgb[GREEN_PIXEL] >>= (8-5);
609   rgb[BLUE_PIXEL]  >>= (8-5);
610   
611   *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 ) | ( (rgb[RED_PIXEL]>>3) & 0x07 );
612   *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
613
614 #if 0
615   printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
616          "rgb1: %02x, rgb2 %02x\n",
617          p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
618          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
619          *p_rgb1, *p_rgb2);
620 #endif
621
622 }
623
624 static inline void
625 rv16_pack_blend(uint8_t *p_pixel, ogt_yuvt_t *p_source,  uint8_t *p_rgb1,
626                 uint8_t *p_rgb2, vlc_bool_t b_15bpp, uint8_t i_alpha, 
627                 int a_scale_down )
628 {
629   uint8_t rgb_source[3];
630   uint8_t rgb[RGB_SIZE];
631   int i;
632 #ifdef FIXED_RV16_TRANSPARENCY
633   uint8_t i_dest_alpha = MAX_ALPHA - i_alpha;
634 #endif
635
636   yuv2rgb(p_source, rgb_source);
637
638   /* Scale RGB from 8 bits down to 6 or 5. */
639   rgb_source[GREEN_PIXEL] >>= (8-5);
640   rgb_source[BLUE_PIXEL]  >>= (8-5);
641
642   rgb[GREEN_PIXEL] = *(p_pixel+1)    & 0x1f;
643   if (b_15bpp) {
644     rgb_source[RED_PIXEL]   >>= (8-5);
645     rgb[BLUE_PIXEL]  = ((*p_pixel)>>2) & 0x1f;
646     rgb[RED_PIXEL]   = ((*p_pixel & 0x03) << 3) | ((*(p_pixel+1)&0xe0)>>5);
647   } else {
648     rgb_source[RED_PIXEL]   >>= (8-6);
649     rgb[BLUE_PIXEL]  = ((*p_pixel)>>3) & 0x1f;
650     rgb[RED_PIXEL]   = ((*p_pixel & 0x07) << 3) | ((*(p_pixel+1)&0xe0)>>5);
651   }
652   
653
654 #if 0
655   printf("r,g,b=(%d,%d,%d), source r,g,b=(%d,%d,%d), alpha %d, dest_alpha %d\n",
656          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
657          rgb_source[RED_PIXEL], rgb_source[GREEN_PIXEL], 
658          rgb_source[BLUE_PIXEL], i_alpha, i_dest_alpha);
659 #endif
660
661   for (i=0; i < RGB_SIZE; i++) {
662     /* Average the two pixels.  */
663
664 #ifdef FIXED_RV16_TRANSPARENCY
665     rgb[i] = ( (uint16_t) rgb_source[i]*i_alpha + rgb[i]*i_dest_alpha) >>
666       ALPHA_BITS;
667 #else 
668     /* For now the Best we can do is fade the color. Picking up 
669        video underneath doesn't work. */
670     /* rgb[i] = ( (uint16_t) rgb[i]*i_dest_alpha ) >> ALPHA_BITS; */
671     rgb[i] = ( (uint16_t) rgb_source[i]*i_alpha ) >> ALPHA_BITS;
672 #endif 
673   }
674   
675
676 #if 0
677   printf("avg r,g,b=(%d,%d,%d)\n",
678          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL] );
679 #endif
680
681 #if 0
682   if (b_15bpp) {
683     *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c )|( (rgb[RED_PIXEL]>>3)&0x03 );
684   } else {
685     *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 )|( (rgb[RED_PIXEL]>>3)&0x07 );
686   }
687   *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
688 #else 
689   *p_rgb1 = (*p_rgb1)+1;
690   *p_rgb2 = (*p_rgb2)+1;
691 #endif
692   
693 }
694
695 #undef BYTES_PER_PIXEL
696 #define BYTES_PER_PIXEL 2
697
698 static void 
699 BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
700            const subpicture_t *p_spu, vlc_bool_t b_crop,
701            vlc_bool_t b_15bpp )
702 {
703     /* Common variables */
704     uint8_t *p_pixel_base;
705     ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
706     ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
707     ogt_yuvt_t *p_source;
708
709     int i_x, i_y;
710     int i_y_src;
711
712     /* Chroma specific */
713     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
714                             multiplied by 2**ASCALE. */
715     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
716                             multiplied by 2**ASCALE. */
717
718     int i_width, i_height, i_ytmp, i_ynext;
719
720     /* Crop-specific */
721     int i_x_start, i_y_start, i_x_end, i_y_end;
722
723     struct subpicture_sys_t *p_sys = p_spu->p_sys;
724
725     i_xscale = ( p_vout->output.i_width << ASCALE ) / p_vout->render.i_width;
726     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
727
728     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
729                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
730                p_spu->i_width,  p_spu->i_height, 
731                p_vout->output.i_width, p_vout->output.i_height,
732                p_vout->render.i_width, p_vout->render.i_height,
733                i_xscale, i_yscale
734                );
735
736     i_width  = p_spu->i_width  * i_xscale;
737     i_height = p_spu->i_height * i_yscale;
738
739     /* Set where we will start blending subtitle from using
740        the picture coordinates subtitle offsets
741     */
742     p_pixel_base = p_pic->p->p_pixels 
743               + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
744               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
745
746     i_x_start = p_sys->i_x_start;
747     i_y_start = i_yscale * p_sys->i_y_start;
748     i_x_end   = p_sys->i_x_end;
749     i_y_end   = i_yscale * p_sys->i_y_end;
750
751     p_source = (ogt_yuvt_t *)p_sys->p_data;
752   
753     /* Draw until we reach the bottom of the subtitle */
754     i_y = 0;
755     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
756          i_y_src += p_spu->i_width )
757     {
758         uint8_t *p_pixel_base_y;
759         i_ytmp = i_y >> ASCALE;
760         i_y += i_yscale;
761         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
762         i_x = 0;
763
764         if ( b_crop ) {
765           if ( i_y > i_y_end ) break;
766           if (i_x_start) {
767             i_x = i_x_start;
768             p_source += i_x_start;
769           }
770         }
771
772         /* Check whether we need to draw one line or more than one */
773         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
774         {
775           /* Draw until we reach the end of the line */
776           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
777             {
778
779 #if 0              
780               uint8_t *p=(uint8_t *) p_source;
781               printf("+++ %02x %02x %02x %02x\n", 
782                      p[0], p[1], p[2], p[3]);
783 #endif
784     
785               if( b_crop ) {
786                 
787                 /* FIXME: y cropping should be dealt with outside of this 
788                    loop.*/
789                 if ( i_y < i_y_start) continue;
790                 
791                 if ( i_x > i_x_end )
792                   {
793                     p_source += p_spu->i_width - i_x;
794                     break;
795                   }
796               }
797
798               if (p_source >= p_src_end) {
799                 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
800                          i_x, i_y / i_yscale, i_height);
801                 return;
802               }
803               
804 #ifdef TESTING_TRANSPARENCY
805               if (p_source->s.t == MAX_ALPHA) p_source->s.t >>= 1;
806 #endif
807
808               switch( p_source->s.t )
809                 {
810                 case 0:
811                   /* Completely transparent. Don't change pixel. */
812                   break;
813                   
814                 case MAX_ALPHA:
815                   {
816                     /* Completely opaque. Completely overwrite underlying
817                        pixel with subtitle pixel. */
818                 
819                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
820                                          * BYTES_PER_PIXEL );
821                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
822                                          * BYTES_PER_PIXEL );
823                     uint32_t len     = i_xlast - i_xdest;
824
825                     uint8_t i_rgb1;
826                     uint8_t i_rgb2;
827
828                     /* This is the location that's going to get changed. */
829                     uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
830
831                     if (b_15bpp) 
832                       yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
833                     else 
834                       yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
835
836                     for ( len = i_xlast - i_xdest; len ; len--) {
837                       *p_dest++ = i_rgb1;
838                       *p_dest++ = i_rgb2;
839                     }
840                     break;
841                   }
842
843                 default:
844                   {
845                     /* Blend in underlying pixel subtitle pixel. */
846                     
847                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
848                                          * BYTES_PER_PIXEL );
849                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
850                                          * BYTES_PER_PIXEL );
851                     uint8_t i_rgb1;
852                     uint8_t i_rgb2;
853                     uint32_t len     = i_xlast - i_xdest;
854
855                     /* This is the location that's going to get changed. */
856                     uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
857
858                     for ( len = i_xlast - i_xdest; len ; len--) {
859                       rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2, 
860                                       b_15bpp, p_source->s.t, ALPHA_SCALEDOWN);
861                       *p_dest++ = i_rgb1;
862                       *p_dest++ = i_rgb2;
863                     }
864                     break;
865                   }
866                 }
867             }
868         }
869         else
870         {
871             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
872
873
874             /* Draw until we reach the end of the line */
875             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
876             {
877
878               if( b_crop ) {
879                 
880                 /* FIXME: y cropping should be dealt with outside of this 
881                    loop.*/
882                 if ( i_y < i_y_start) continue;
883                 
884                 if ( i_x > i_x_end )
885                   {
886                     p_source += p_spu->i_width - i_x;
887                     break;
888                   }
889               }
890               
891               if (p_source >= p_src_end) {
892                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
893                          i_x, i_y / i_yscale, i_height);
894                 return;
895               }
896               
897               switch( p_source->s.t )
898                 {
899                 case 0:
900                     /* Completely transparent. Don't change pixel. */
901                     break;
902
903                 case MAX_ALPHA: 
904                   {
905                     /* Completely opaque. Completely overwrite underlying
906                        pixel with subtitle pixel. */
907
908                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
909                                          * BYTES_PER_PIXEL );
910                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
911                                          * BYTES_PER_PIXEL );
912                     uint32_t len     = i_xlast - i_xdest;
913
914                     uint8_t *p_pixel_base_x = p_pixel_base + i_xdest;
915
916                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
917                     {
918                       /* This is the location that's going to get changed. */
919                       uint8_t *p_dest = p_pixel_base_x + i_ytmp;
920                       uint8_t i_rgb1, i_rgb2;
921                       if (b_15bpp) 
922                         yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
923                       else 
924                         yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
925
926                       for ( len = i_xlast - i_xdest; len ; len--) {
927                         *p_dest++ = i_rgb1;
928                         *p_dest++ = i_rgb2;
929                       }
930                     }
931                     break;
932                   }
933                 default: 
934                   {
935                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
936                                          * BYTES_PER_PIXEL );
937                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
938                                          * BYTES_PER_PIXEL );
939                     uint32_t len     = i_xlast - i_xdest;
940                     uint8_t i_rgb1, i_rgb2;
941                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
942                     {
943                       /* Blend in underlying pixel subtitle pixel. */
944                       uint8_t *p_dest = p_pixel_base + i_ytmp;
945                       for ( len = i_xlast - i_xdest; len ; len--) {
946                         rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2,
947                                       b_15bpp, p_source->s.t, ALPHA_SCALEDOWN);
948                         *p_dest++ = i_rgb1;
949                         *p_dest++ = i_rgb2;
950                       }
951                     }
952                     break;
953                   }
954                 }
955             }
956         }
957     }
958 }
959
960 #undef  BYTES_PER_PIXEL
961 #define BYTES_PER_PIXEL 4
962
963 static inline void
964 rv24_pack_blend(uint8_t *p_pixel, uint8_t *rgb_source,  uint8_t i_alpha,  
965                 int a_scale_down )
966 {
967   int i;
968   uint8_t i_dest_alpha = MAX_ALPHA - i_alpha;
969
970 #if 0
971   printf("r,g,b=(%d,%d,%d), source r,g,b=(%d,%d,%d), alpha %d, dest_alpha %d\n",
972          p_pixel[RED_PIXEL], p_pixel[GREEN_PIXEL], p_pixel[BLUE_PIXEL],
973          rgb_source[RED_PIXEL], rgb_source[GREEN_PIXEL], 
974          rgb_source[BLUE_PIXEL], i_alpha, i_dest_alpha);
975 #endif
976
977 #ifdef WORDS_BIGENDIAN
978   *p_pixel++;
979 #endif
980
981   for (i=0; i < RGB_SIZE; i++) {
982     /* Average the two pixels.  */
983
984     p_pixel[i] = ( (uint16_t) rgb_source[i]*i_alpha + p_pixel[i]*i_dest_alpha) 
985               >> ALPHA_BITS;
986   }
987   
988 #if 0
989   printf("avg r,g,b=(%d,%d,%d)\n",
990          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL] );
991 #endif
992
993 }
994
995 /* 
996   RV24 format??? Is this just for X11? Or just not for Win32? Is this
997   the same as RV32?
998
999   a pixel is represented by 3 bytes containing a red,
1000   blue and green sample with blue stored at the lowest address, green
1001   next then red. One padding byte is added between pixels. Although
1002   this may not be part of a spec, images should be stored with each
1003   line padded to a u_int32 boundary. 
1004 */
1005 static void 
1006 BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
1007             const subpicture_t *p_spu, vlc_bool_t b_crop )
1008 {
1009   /* Common variables */
1010   uint8_t *p_pixel_base;
1011   ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
1012   ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1013   ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
1014   
1015   int i_x, i_y;
1016   int i_y_src;
1017   
1018   /* Make sure we start on a word (4-byte) boundary. */
1019   uint32_t i_spu_x;
1020   
1021   /* Chroma specific */
1022   uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1023                           multiplied by 2**ASCALE. */
1024   uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1025                           multiplied by 2**ASCALE. */
1026   
1027   int i_width, i_height, i_ytmp, i_ynext;
1028   
1029   /* Crop-specific */
1030   int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1031   
1032   struct subpicture_sys_t *p_sys = p_spu->p_sys;
1033   unsigned int i_aspect_x, i_aspect_y;
1034   
1035   vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
1036                     &i_aspect_x );
1037   
1038   i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1039     / (i_aspect_y * p_vout->render.i_width);
1040   i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1041   
1042   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1043              "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1044              p_spu->i_width,  p_spu->i_height, 
1045              p_vout->output.i_width, p_vout->output.i_height,
1046              p_vout->render.i_width, p_vout->render.i_height,
1047              i_xscale, i_yscale
1048              );
1049   
1050   i_width  = p_spu->i_width  * i_xscale;
1051   i_height = p_spu->i_height * i_yscale;
1052   
1053   /* Set where we will start blending subtitle from using
1054      the picture coordinates subtitle offsets.
1055   */
1056   i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
1057   
1058   p_pixel_base = p_pic->p->p_pixels + i_spu_x
1059     + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1060   
1061   i_x_start = p_sys->i_x_start;
1062   i_y_start = i_yscale * p_sys->i_y_start;
1063   i_x_end   = p_sys->i_x_end;
1064   i_y_end   = i_yscale * p_sys->i_y_end;
1065   
1066   p_source = (ogt_yuvt_t *)p_sys->p_data;
1067   
1068   /* Draw until we reach the bottom of the subtitle */
1069   i_y = 0;
1070   for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1071        i_y_src += p_spu->i_width )
1072     {
1073       uint8_t *p_pixel_base_y;
1074       i_ytmp = i_y >> ASCALE;
1075       i_y += i_yscale;
1076       p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1077       i_x = 0;
1078       
1079       if ( b_crop ) {
1080         if ( i_y > i_y_end ) break;
1081         if (i_x_start) {
1082           i_x = i_x_start;
1083           p_source += i_x_start;
1084         }
1085       }
1086       
1087       /* Check whether we need to draw one line or more than one */
1088       if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1089         {
1090           /* Draw until we reach the end of the line */
1091           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
1092             {
1093               
1094               if( b_crop ) {
1095                 
1096                 /* FIXME: y cropping should be dealt with outside of this 
1097                    loop.*/
1098                 if ( i_y < i_y_start) continue;
1099                 
1100                 if ( i_x > i_x_end )
1101                   {
1102                     p_source += p_spu->i_width - i_x;
1103                     break;
1104                   }
1105               }
1106               
1107               if (p_source >= p_src_end) {
1108                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1109                          i_x, i_y / i_yscale, i_height);
1110                 return;
1111               }
1112               
1113 #ifdef TESTING_TRANSPARENCY
1114               if (p_source->s.t == MAX_ALPHA) p_source->s.t >>= 2;
1115 #endif
1116
1117               switch( p_source->s.t )
1118                 {
1119                 case 0:
1120                   /* Completely transparent. Don't change pixel. */
1121                   break;
1122                   
1123                 case MAX_ALPHA:
1124                   {
1125                     /* Completely opaque. Completely overwrite underlying
1126                        pixel with subtitle pixel. */
1127                     
1128                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1129                                          * BYTES_PER_PIXEL );
1130                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1131                                          * BYTES_PER_PIXEL );
1132                     uint32_t len     = i_xlast - i_xdest;
1133                     
1134                     uint8_t rgb[RGB_SIZE];
1135                     
1136                     /* This is the location that's going to get changed. */
1137                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1138                     
1139                     yuv2rgb(p_source, rgb);
1140                     
1141                     for ( len = i_xlast - i_xdest; len ; len--) {
1142                       put_rgb24_pixel(rgb, p_dest);
1143                       p_dest += BYTES_PER_PIXEL;
1144                     }
1145                     
1146                   default:
1147                     {
1148                       /* Blend in underlying pixel subtitle pixel. */
1149                       
1150                       uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1151                                            * BYTES_PER_PIXEL );
1152                       uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1153                                            * BYTES_PER_PIXEL );
1154                       uint32_t len     = i_xlast - i_xdest * BYTES_PER_PIXEL;
1155                       
1156                       /* To be able to scale correctly for full opaqueness, we
1157                          add 1 to the alpha.  This means alpha value 0 won't
1158                          be completely transparent and is not correct, but
1159                          that's handled in a special case above anyway. */
1160                       
1161                       /* This is the location that's going to get changed. */
1162                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1163                       uint8_t rgb[RGB_SIZE];
1164                       
1165                       yuv2rgb(p_source, rgb);
1166
1167                       for ( len = i_xlast - i_xdest; len ; len--) {
1168                         rv24_pack_blend(p_dest, rgb, p_source->s.t,
1169                                         ALPHA_SCALEDOWN);
1170                         p_dest += BYTES_PER_PIXEL;
1171                       }
1172                       break;
1173                     }
1174                   }
1175                 }
1176             }
1177         } 
1178         else
1179         {
1180             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1181
1182
1183             /* Draw until we reach the end of the line */
1184             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1185             {
1186
1187               if( b_crop ) {
1188                 
1189                 /* FIXME: y cropping should be dealt with outside of this 
1190                    loop.*/
1191                 if ( i_y < i_y_start) continue;
1192                 
1193                 if ( i_x > i_x_end )
1194                   {
1195                     p_source += p_spu->i_width - i_x;
1196                     break;
1197                   }
1198               }
1199               
1200               if (p_source >= p_src_end) {
1201                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1202                          i_x, i_y / i_yscale, i_height);
1203                 return;
1204               }
1205               
1206               switch( p_source->s.t )
1207                 {
1208                 case 0:
1209                     /* Completely transparent. Don't change pixel. */
1210                     break;
1211
1212                 case MAX_ALPHA: 
1213                   {
1214                     /* Completely opaque. Completely overwrite underlying
1215                        pixel with subtitle pixel. */
1216
1217                     /* This is the location that's going to get changed. */
1218                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1219                                          * BYTES_PER_PIXEL );
1220                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1221                                          * BYTES_PER_PIXEL );
1222                     uint32_t len     = i_xlast - i_xdest;
1223
1224                     uint8_t rgb[RGB_SIZE];
1225
1226                     yuv2rgb(p_source, rgb); 
1227
1228                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1229                     {
1230                       /* Completely opaque. Completely overwrite underlying
1231                          pixel with subtitle pixel. */
1232                       
1233                       /* This is the location that's going to get changed. */
1234                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1235                       
1236                       for ( len = i_xlast - i_xdest; len ; len--) {
1237                         put_rgb24_pixel(rgb, p_dest);
1238                         p_dest += BYTES_PER_PIXEL;
1239                       }
1240                     }
1241                     break;
1242                   }
1243                 default: 
1244                   {
1245                     
1246
1247                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1248                                          * BYTES_PER_PIXEL );
1249                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1250                                          * BYTES_PER_PIXEL );
1251                     uint32_t len     = i_xlast - i_xdest;
1252                     uint8_t  rgb[RGB_SIZE];
1253
1254                     yuv2rgb(p_source, rgb);
1255
1256                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1257                     {
1258                       /* Blend in underlying pixel subtitle pixel. */
1259                       
1260                       /* This is the location that's going to get changed. */
1261                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1262
1263                       /* To be able to scale correctly for full opaqueness, we
1264                          add 1 to the alpha.  This means alpha value 0 won't
1265                          be completely transparent and is not correct, but
1266                          that's handled in a special case above anyway. */
1267
1268                       for ( len = i_xlast - i_xdest; len ; len--) {
1269                         rv24_pack_blend(p_dest, rgb, p_source->s.t,
1270                                         ALPHA_SCALEDOWN);
1271                         p_dest += BYTES_PER_PIXEL;
1272                       }
1273                     }
1274                     break;
1275                   }
1276                 }
1277             }
1278         }
1279     }
1280 }
1281
1282 #undef  BYTES_PER_PIXEL
1283 #define BYTES_PER_PIXEL 4
1284
1285 /* 
1286   RV32 format??? Is this just for X11? Or just not for Win32? Is this
1287   the same as RV24?
1288
1289   RV32 format: a pixel is represented by 4 bytes containing a red,
1290   blue and green sample with blue stored at the lowest address, green
1291   next then red. One padding byte is added between pixels. Although
1292   this may not be part of a spec, images should be stored with each
1293   line padded to a u_int32 boundary. 
1294 */
1295 static void 
1296 BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
1297             const subpicture_t *p_spu, vlc_bool_t b_crop )
1298 {
1299     /* Common variables */
1300     uint8_t *p_pixel_base;
1301     ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
1302     ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1303     ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
1304
1305     int i_x, i_y;
1306     int i_y_src;
1307
1308     /* Make sure we start on a word (4-byte) boundary. */
1309     uint32_t i_spu_x;
1310
1311     /* Chroma specific */
1312     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1313                             multiplied by 2**ASCALE. */
1314     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1315                             multiplied by 2**ASCALE. */
1316
1317     int i_width, i_height, i_ytmp, i_ynext;
1318
1319     /* Crop-specific */
1320     int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1321
1322     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1323     unsigned int i_aspect_x, i_aspect_y;
1324
1325     vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
1326                       &i_aspect_x );
1327
1328     i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1329       / (i_aspect_y * p_vout->render.i_width);
1330     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1331
1332     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1333                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1334                p_spu->i_width,  p_spu->i_height, 
1335                p_vout->output.i_width, p_vout->output.i_height,
1336                p_vout->render.i_width, p_vout->render.i_height,
1337                i_xscale, i_yscale
1338                );
1339
1340     i_width  = p_spu->i_width  * i_xscale;
1341     i_height = p_spu->i_height * i_yscale;
1342
1343     /* Set where we will start blending subtitle from using
1344        the picture coordinates subtitle offsets.
1345     */
1346     i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL; 
1347
1348     p_pixel_base = p_pic->p->p_pixels + i_spu_x
1349               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1350
1351     i_x_start = p_sys->i_x_start;
1352     i_y_start = i_yscale * p_sys->i_y_start;
1353     i_x_end   = p_sys->i_x_end;
1354     i_y_end   = i_yscale * p_sys->i_y_end;
1355
1356     p_source = (ogt_yuvt_t *)p_sys->p_data;
1357   
1358     /* Draw until we reach the bottom of the subtitle */
1359     i_y = 0;
1360     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1361          i_y_src += p_spu->i_width )
1362     {
1363         uint8_t *p_pixel_base_y;
1364         i_ytmp = i_y >> ASCALE;
1365         i_y += i_yscale;
1366         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1367         i_x = 0;
1368
1369         if ( b_crop ) {
1370           if ( i_y > i_y_end ) break;
1371           if (i_x_start) {
1372             i_x = i_x_start;
1373             p_source += i_x_start;
1374           }
1375         }
1376
1377         /* Check whether we need to draw one line or more than one */
1378         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1379         {
1380           /* Draw until we reach the end of the line */
1381           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
1382             {
1383
1384               if( b_crop ) {
1385                 
1386                 /* FIXME: y cropping should be dealt with outside of this 
1387                    loop.*/
1388                 if ( i_y < i_y_start) continue;
1389                 
1390                 if ( i_x > i_x_end )
1391                   {
1392                     p_source += p_spu->i_width - i_x;
1393                     break;
1394                   }
1395               }
1396
1397               if (p_source >= p_src_end) {
1398                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1399                          i_x, i_y / i_yscale, i_height);
1400                 return;
1401               }
1402               
1403               switch( p_source->s.t )
1404                 {
1405                 case 0:
1406                   /* Completely transparent. Don't change pixel. */
1407                   break;
1408                   
1409                 default:
1410                 case MAX_ALPHA:
1411                   {
1412                     /* Completely opaque. Completely overwrite underlying
1413                        pixel with subtitle pixel. */
1414
1415                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1416                                          * BYTES_PER_PIXEL );
1417                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1418                                          * BYTES_PER_PIXEL );
1419                     uint32_t len     = i_xlast - i_xdest;
1420
1421                     uint8_t rgb[RGB_SIZE];
1422
1423                     /* This is the location that's going to get changed. */
1424                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1425
1426                     yuv2rgb(p_source, rgb);
1427
1428                     for ( len = i_xlast - i_xdest; len ; len--) {
1429                       *p_dest++ = rgb[BLUE_PIXEL];
1430                       *p_dest++ = rgb[GREEN_PIXEL];
1431                       *p_dest++ = rgb[RED_PIXEL];
1432                       *p_dest++;
1433                     }
1434
1435 #ifdef TRANSPARENCY_FINISHED
1436                   default:
1437                     {
1438                       /* Blend in underlying pixel subtitle pixel. */
1439                       
1440                       uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1441                                            * BYTES_PER_PIXEL );
1442                       uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1443                                            * BYTES_PER_PIXEL );
1444                       uint32_t len     = i_xlast - i_xdest;
1445
1446                       /* To be able to scale correctly for full opaqueness, we
1447                          add 1 to the alpha.  This means alpha value 0 won't
1448                          be completely transparent and is not correct, but
1449                          that's handled in a special case above anyway. */
1450                       
1451                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1452                       uint8_t rgb[RGB_SIZE];
1453
1454                       /* This is the location that's going to get changed. */
1455                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1456                       
1457                       yuv2rgb(p_source, rgb);
1458                       rv32_pack_blend(p_dest, rgb, dest_alpha, 
1459                                       ALPHA_SCALEDOWN);
1460
1461                       for ( len = i_xlast - i_xdest; len ; len--) {
1462                         *p_dest++ = rgb[BLUE_PIXEL];
1463                         *p_dest++ = rgb[GREEN_PIXEL];
1464                         *p_dest++ = rgb[RED_PIXEL];
1465                         *p_dest++;
1466                       }
1467                       break;
1468                     }
1469 #endif /*TRANSPARENCY_FINISHED*/
1470                   }
1471                 }
1472             }
1473         } 
1474         else
1475         {
1476             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1477
1478
1479             /* Draw until we reach the end of the line */
1480             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1481             {
1482
1483               if( b_crop ) {
1484                 
1485                 /* FIXME: y cropping should be dealt with outside of this 
1486                    loop.*/
1487                 if ( i_y < i_y_start) continue;
1488                 
1489                 if ( i_x > i_x_end )
1490                   {
1491                     p_source += p_spu->i_width - i_x;
1492                     break;
1493                   }
1494               }
1495               
1496               if (p_source >= p_src_end) {
1497                 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1498                          i_x, i_y / i_yscale, i_height);
1499                 return;
1500               }
1501               
1502               switch( p_source->s.t )
1503                 {
1504                 case 0:
1505                     /* Completely transparent. Don't change pixel. */
1506                     break;
1507
1508                 default:
1509                 case MAX_ALPHA: 
1510                   {
1511                     /* Completely opaque. Completely overwrite underlying
1512                        pixel with subtitle pixel. */
1513
1514                     /* This is the location that's going to get changed. */
1515                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1516                                          * BYTES_PER_PIXEL );
1517                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1518                                          * BYTES_PER_PIXEL );
1519                     uint32_t len     = i_xlast - i_xdest;
1520
1521                     uint8_t rgb[RGB_SIZE];
1522
1523                     yuv2rgb(p_source, rgb); 
1524
1525                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1526                     {
1527                       /* Completely opaque. Completely overwrite underlying
1528                          pixel with subtitle pixel. */
1529                       
1530                       /* This is the location that's going to get changed. */
1531                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1532                       
1533                       for ( len = i_xlast - i_xdest; len ; len--) {
1534                         put_rgb24_pixel(rgb, p_dest);
1535                       }
1536                     }
1537                     break;
1538                   }
1539 #ifdef TRANSPARENCY_FINISHED
1540                 default: 
1541                   {
1542                     
1543
1544                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1545                                          * BYTES_PER_PIXEL );
1546                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1547                                          * BYTES_PER_PIXEL );
1548                     uint32_t len     = i_xlast - i_xdest;
1549                     uint8_t rgb[RGB_SIZE];
1550
1551                     yuv2rgb(p_source, rgb);
1552
1553                     for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1554                     {
1555                       /* Blend in underlying pixel subtitle pixel. */
1556                       
1557                       /* This is the location that's going to get changed. */
1558                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1559
1560                       /* To be able to scale correctly for full opaqueness, we
1561                          add 1 to the alpha.  This means alpha value 0 won't
1562                          be completely transparent and is not correct, but
1563                          that's handled in a special case above anyway. */
1564
1565                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1566                       rv32_pack_blend(p_dest, rgb, dest_alpha,
1567                                       ALPHA_SCALEDOWN);
1568                     }
1569                     break;
1570 #endif /*TRANSPARENCY_FINISHED*/
1571                 }
1572             }
1573         }
1574     }
1575 }
1576
1577 /*
1578   Return the colormap index for the average of p_pixel and a subtitle
1579   pixel in RGB form.
1580  */
1581 static inline cmap_t
1582 avg_rgb2(const vout_thread_t *p_vout, uint8_t i_pixel, cmap_t i_cmap_sub,
1583          const uint8_t rgb_sub[] )
1584 {
1585   uint8_t rgb_vout[RGB_SIZE];
1586   static cmap_t avg_cache[CMAP_RGB2_SIZE][NUM_SUBTITLE_COLORS];
1587   static vlc_bool_t b_first_time = VLC_TRUE;
1588   int i;
1589
1590   /* FIXME: really we need to save subtitle number since in theory
1591      the palette can change each on each distinct subtitle. In practice
1592      this doesn't happen that much.
1593    */
1594   if (b_first_time) 
1595     {
1596       int i, j;
1597       for (i=0; i<CMAP_RGB2_SIZE; i++) 
1598         for (j=0; j<NUM_SUBTITLE_COLORS; j++) 
1599           avg_cache[i][j] = INVALID_CMAP_ENTRY;
1600     }
1601
1602   if ( avg_cache[i_pixel][i_cmap_sub] != INVALID_CMAP_ENTRY ) 
1603     return avg_cache[i_pixel][i_cmap_sub];
1604
1605   if ( !query_color(p_vout, i_pixel, rgb_vout) ) return INVALID_CMAP_ENTRY;
1606
1607   for (i = 0; i < RGB_SIZE; i++) 
1608     {
1609       rgb_vout[i] = (rgb_vout[i] + rgb_sub[i]) / 2;
1610     }
1611
1612 #if 0
1613  {
1614   uint8_t rgb_approx[RGB_SIZE];
1615
1616   avg_cache[i_pixel][i_cmap_sub] = 
1617     find_cmap_rgb8_nearest(p_vout, rgb_vout, rgb_approx);
1618   printf(
1619          "cmap old %0x new 0%x sub=(%0x, %0x, %0x) "
1620          "avg=(%0x, %0x, %0x) vout=(%0x, %0x, %0x)\n", 
1621          i_pixel, i_cmap,
1622          rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], rgb_sub[BLUE_PIXEL],
1623          rgb_approx[RED_PIXEL], rgb_approx[GREEN_PIXEL], rgb_approx[BLUE_PIXEL],
1624          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL]);
1625  }  
1626 #else 
1627   avg_cache[i_pixel][i_cmap_sub] = 
1628     find_cmap_rgb8_nearest(p_vout, rgb_vout, NULL);
1629 #endif
1630   return avg_cache[i_pixel][i_cmap_sub];
1631 }
1632
1633 #undef  BYTES_PER_PIXEL
1634 #define BYTES_PER_PIXEL 1
1635
1636 static void 
1637 BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
1638             const subpicture_t *p_spu, vlc_bool_t b_crop )
1639 {
1640     /* Common variables */
1641     uint8_t *p_pixel_base;
1642     uint8_t *p_src_start = (uint8_t *)p_spu->p_sys->p_data;
1643     uint8_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1644     uint8_t *p_source; /* This is the where the subtitle pixels come from */
1645
1646     int i_x, i_y;
1647     int i_y_src;
1648
1649     /* Chroma specific */
1650     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1651                             multiplied by 2**ASCALE. */
1652     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1653                             multiplied by 2**ASCALE. */
1654
1655     int i_width, i_height, i_ytmp;
1656
1657     /* Crop-specific */
1658     int i_x_start, i_y_start, i_x_end, i_y_end;
1659
1660     /* 4-entry array of colormap indices */
1661     uint8_t cmap[NUM_SUBTITLE_COLORS];
1662     int i;
1663
1664     /* Actual RGB values for above; this is used in blending.*/
1665     uint8_t cmap_rgb[NUM_SUBTITLE_COLORS][RGB_SIZE];
1666
1667     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1668     unsigned int i_aspect_x, i_aspect_y;
1669
1670     vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
1671                       &i_aspect_x );
1672     
1673     i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1674       / (i_aspect_y * p_vout->render.i_width);
1675     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1676
1677     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1678                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1679                p_spu->i_width,  p_spu->i_height, 
1680                p_vout->output.i_width, p_vout->output.i_height,
1681                p_vout->render.i_width, p_vout->render.i_height,
1682                i_xscale, i_yscale
1683                );
1684
1685     i_width  = p_spu->i_width  * i_xscale;
1686     i_height = p_spu->i_height * i_yscale;
1687
1688
1689     /** FIXME: do once per subtitle in subtitle processing, not here
1690         each time we render.  */
1691     /* Find a corresponding colormap entries for our palette entries. */
1692     for( i = 0; i < NUM_SUBTITLE_COLORS; i++ )
1693     {
1694
1695       if ( p_sys->p_palette[i].s.t != 0 ) {
1696         uint8_t rgb[RGB_SIZE]; 
1697         uint8_t approx_rgb[RGB_SIZE]; 
1698         yuv2rgb(&(p_sys->p_palette[i]), rgb);
1699         cmap[i] = 
1700           find_cmap_rgb8_nearest(p_vout, rgb, approx_rgb);
1701         dbg_print( (DECODE_DBG_RENDER), 
1702                    "palette %d RGB=(%0x, %0x, %0x)\n", i,
1703                    rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL]);
1704       }
1705     }
1706
1707     /* Set where we will start blending subtitle from using
1708        the picture coordinates subtitle offsets
1709     */
1710     p_pixel_base = p_pic->p->p_pixels 
1711               + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
1712               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1713
1714     i_x_start = p_sys->i_x_start;
1715     i_y_start = i_yscale * p_sys->i_y_start;
1716     i_x_end   = p_sys->i_x_end;
1717     i_y_end   = i_yscale * p_sys->i_y_end;
1718
1719     p_source = (uint8_t *)p_sys->p_data;
1720   
1721     /* Draw until we reach the bottom of the subtitle */
1722     i_y = 0;
1723     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1724          i_y_src += p_spu->i_width )
1725       {
1726         uint8_t *p_pixel_base_y;
1727         i_ytmp = i_y >> ASCALE;
1728         i_y += i_yscale;
1729         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1730         i_x = 0;
1731
1732         if ( b_crop ) {
1733           if ( i_y > i_y_end ) break;
1734           if (i_x_start) {
1735             i_x = i_x_start;
1736             p_source += i_x_start;
1737           }
1738         }
1739         
1740         /* Check whether we need to draw one line or more than one */
1741         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1742         {
1743
1744           /* Draw until we reach the end of the line */
1745           for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1746             {
1747               ogt_yuvt_t p_yuvt;
1748
1749               if( b_crop ) {
1750                 
1751                 /* FIXME: y cropping should be dealt with outside of this 
1752                    loop.*/
1753                 if ( i_y < i_y_start) continue;
1754                 
1755                 if ( i_x > i_x_end )
1756                   {
1757                     p_source += p_spu->i_width - i_x;
1758                     break;
1759                   }
1760               }
1761               
1762               if (p_source >= p_src_end) {
1763                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1764                          i_x, i_y / i_yscale, i_height);
1765                 return;
1766               }
1767               
1768               p_yuvt = p_sys->p_palette[*p_source & 0x3];
1769
1770 #ifdef TESTING_TRANSPARENCY
1771               if (p_yuvt.s.t == MAX_ALPHA) p_yuvt.s.t >>= 1;
1772 #endif
1773
1774               switch ( p_yuvt.s.t ) 
1775                 {
1776                 case 0:
1777                   /* Completely transparent. Don't change pixel. */
1778 #if 0
1779                   printf(" "); /*++++*/
1780 #endif
1781                   break;
1782                 case MAX_ALPHA: 
1783                   {
1784                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1785                                          * BYTES_PER_PIXEL );
1786                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1787                                          * BYTES_PER_PIXEL );
1788                     /* This is the pixel that's going to change;*/
1789                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1790                     memset( p_dest, cmap[*p_source & 0x3], i_xlast - i_xdest );
1791 #if 0
1792                     printf("%1d", *p_source); /*++++*/
1793 #endif
1794                     break;
1795                   }
1796                 default:
1797                   {
1798                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1799                                          * BYTES_PER_PIXEL );
1800                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1801                                          * BYTES_PER_PIXEL );
1802                     /* This is the pixel that's going to change;*/
1803                     uint8_t *p_pixel = p_pixel_base_y + i_xdest;
1804                     uint32_t len     = i_xlast - i_xdest;
1805
1806                     for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
1807                       {
1808                         cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, 
1809                                                   cmap[*p_source],
1810                                                   cmap_rgb[*p_source]);
1811                         if (i_cmap != INVALID_CMAP_ENTRY) 
1812                           *p_pixel= (uint8_t) i_cmap;
1813                         p_pixel++;
1814                       }
1815 #if 0
1816                     printf("%1d", *p_source); /*++++*/
1817 #endif
1818                   }
1819                 }
1820             }
1821 #if 0
1822           printf("\n"); /*++++*/
1823 #endif
1824         } else {
1825           /* Have to scale over many lines. */
1826           int i_yreal = p_pic->p->i_pitch * i_ytmp;
1827           int i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1828
1829            /* Draw until we reach the end of the line */
1830            for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1831              {
1832               ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];
1833
1834               if( b_crop ) {
1835                 
1836                 /* FIXME: y cropping should be dealt with outside of this 
1837                    loop.*/
1838                 if ( i_y < i_y_start) continue;
1839                 
1840                 if ( i_x > i_x_end )
1841                   {
1842                     p_source += p_spu->i_width - i_x;
1843                     break;
1844                   }
1845               }
1846               
1847               if (p_source >= p_src_end) {
1848                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1849                          i_x, i_y / i_yscale, i_height);
1850                 return;
1851               }
1852               
1853 #ifdef TESTING_TRANSPARENCY
1854               if (p_yuvt.s.t == MAX_ALPHA) p_yuvt.s.t >>= 1;
1855 #endif
1856               switch ( p_yuvt.s.t ) 
1857                 {
1858                 case 0:
1859                   /* Completely transparent. Don't change pixel. */
1860 #if 0
1861                   printf(" "); /*++++*/
1862 #endif
1863                   break;
1864                 case MAX_ALPHA: 
1865                   {
1866                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1867                                          * BYTES_PER_PIXEL );
1868                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1869                                          * BYTES_PER_PIXEL );
1870                     uint32_t len     = i_xlast - i_xdest;
1871 #if 0
1872                     printf("%1d", *p_source); /*++++*/
1873 #endif
1874                     for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
1875                          i_ytmp += p_pic->p->i_pitch ) {
1876                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1877                       memset( p_dest, cmap[*p_source & 0x3], len );
1878                     }
1879                     break;
1880                   }
1881                 default:
1882                   {
1883                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1884                                          * BYTES_PER_PIXEL );
1885                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1886                                          * BYTES_PER_PIXEL );
1887                     int32_t len;
1888 #if 0
1889                     printf("%1d", *p_source); /*++++*/
1890 #endif
1891
1892                     for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
1893                          i_ytmp += p_pic->p->i_pitch ) {
1894                       /* This is the pixel that's going to change;*/
1895                       uint8_t *p_pixel = p_pixel_base + i_ytmp + i_xdest;
1896                       for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
1897                         {
1898                           cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, 
1899                                                     cmap[*p_source],
1900                                                     cmap_rgb[*p_source]);
1901                           if (i_cmap != INVALID_CMAP_ENTRY) 
1902                             *p_pixel= (uint8_t) i_cmap;
1903                           p_pixel++;
1904                         }
1905                     }
1906                   }
1907                 }
1908              }
1909         }
1910       }
1911 }
1912
1913 \f
1914 /* 
1915  * Local variables:
1916  *  c-file-style: "gnu"
1917  *  tab-width: 8
1918  *  indent-tabs-mode: nil
1919  * End:
1920  */