summaryrefslogtreecommitdiff
path: root/noncore/multimedia/opieplayer2/alphablend.c
Unidiff
Diffstat (limited to 'noncore/multimedia/opieplayer2/alphablend.c') (more/less context) (show whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/alphablend.c753
1 files changed, 753 insertions, 0 deletions
diff --git a/noncore/multimedia/opieplayer2/alphablend.c b/noncore/multimedia/opieplayer2/alphablend.c
new file mode 100644
index 0000000..57f6013
--- a/dev/null
+++ b/noncore/multimedia/opieplayer2/alphablend.c
@@ -0,0 +1,753 @@
1//TOAST_SPU will define ALL spu entries - no matter the tranparency
2//#define TOAST_SPU
3/* #define PRIV_CLUT */
4/* Currently only blend_yuv(..) works */
5/*
6 *
7 * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001
8 *
9 * Copyright (C) 2000 Thomas Mirlacher
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * The author may be reached as <dent@linuxvideo.org>
26 *
27 *------------------------------------------------------------
28 *
29 */
30
31/*
32#define LOG_BLEND_YUV
33*/
34
35#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <inttypes.h>
39
40#include <xine/video_out.h>
41#include "alphablend.h"
42
43
44#define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask)
45
46#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf)
47
48static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) {
49 uint16_t *limit = mem + len;
50 while (mem < limit) {
51 *mem =
52 BLEND_COLOR(*mem, clr, 0xf800, o) |
53 BLEND_COLOR(*mem, clr, 0x07e0, o) |
54 BLEND_COLOR(*mem, clr, 0x001f, o);
55 mem++;
56 }
57}
58
59static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
60 uint8_t o, int len) {
61 uint8_t *limit = mem + len*3;
62 while (mem < limit) {
63 *mem = BLEND_BYTE(*mem, r, o);
64 mem++;
65 *mem = BLEND_BYTE(*mem, g, o);
66 mem++;
67 *mem = BLEND_BYTE(*mem, b, o);
68 mem++;
69 }
70}
71
72static void mem_blend24_32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
73 uint8_t o, int len) {
74 uint8_t *limit = mem + len*4;
75 while (mem < limit) {
76 *mem = BLEND_BYTE(*mem, r, o);
77 mem++;
78 *mem = BLEND_BYTE(*mem, g, o);
79 mem++;
80 *mem = BLEND_BYTE(*mem, b, o);
81 mem += 2;
82 }
83}
84
85static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
86 uint8_t *limit = mem + len*4;
87 while (mem < limit) {
88 *mem = BLEND_BYTE(*mem, src[0], o);
89 mem++;
90 *mem = BLEND_BYTE(*mem, src[1], o);
91 mem++;
92 *mem = BLEND_BYTE(*mem, src[2], o);
93 mem++;
94 *mem = BLEND_BYTE(*mem, src[3], o);
95 mem++;
96 }
97}
98
99
100/*
101 * Some macros for fixed point arithmetic.
102 *
103 * The blend_rgb* routines perform rle image scaling using
104 * scale factors that are expressed as integers scaled with
105 * a factor of 2**16.
106 *
107 * INT_TO_SCALED()/SCALED_TO_INT() converts from integer
108 * to scaled fixed point and back.
109 */
110 #define SCALE_SHIFT 16
111 #define SCALE_FACTOR (1<<SCALE_SHIFT)
112 #defineINT_TO_SCALED(i) ((i) << SCALE_SHIFT)
113 #defineSCALED_TO_INT(sc) ((sc) >> SCALE_SHIFT)
114
115
116static rle_elem_t *
117rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w)
118{
119 int x;
120
121 for (x = 0; x < w && rle < rle_limit; ) {
122 x += rle->len;
123 rle++;
124 }
125 return rle;
126}
127
128
129void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
130 int img_width, int img_height,
131 int dst_width, int dst_height)
132{
133 uint8_t *trans;
134 clut_t* clut = (clut_t*) img_overl->clip_color;
135
136 int src_width = img_overl->width;
137 int src_height = img_overl->height;
138 rle_elem_t *rle = img_overl->rle;
139 rle_elem_t *rle_limit = rle + img_overl->num_rle;
140 int x, y, x1_scaled, x2_scaled;
141 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */
142 int clip_right;
143 uint16_t *img_pix;
144
145 dy_step = INT_TO_SCALED(dst_height) / img_height;
146 x_scale = INT_TO_SCALED(img_width) / dst_width;
147
148 img_pix = (uint16_t *) img
149 + (img_overl->y * img_height / dst_height) * img_width
150 + (img_overl->x * img_width / dst_width);
151
152 trans = img_overl->clip_trans;
153
154 /* avoid wraping overlay if drawing to small image */
155 if( (img_overl->x + img_overl->clip_right) < dst_width )
156 clip_right = img_overl->clip_right;
157 else
158 clip_right = dst_width - 1 - img_overl->x;
159
160 /* avoid buffer overflow */
161 if( (src_height + img_overl->y) >= dst_height )
162 src_height = dst_height - 1 - img_overl->y;
163
164 for (y = dy = 0; y < src_height && rle < rle_limit;) {
165 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
166 rle_elem_t *rle_start = rle;
167
168 for (x = x1_scaled = 0; x < src_width;) {
169 uint8_t clr;
170 uint16_t o;
171 int rlelen;
172
173 clr = rle->color;
174 o = trans[clr];
175 rlelen = rle->len;
176
177 if (o && mask) {
178 /* threat cases where clipping border is inside rle->len pixels */
179 if ( img_overl->clip_left > x ) {
180 if( img_overl->clip_left < x + rlelen ) {
181 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
182 rlelen -= img_overl->clip_left - x;
183 x += img_overl->clip_left - x;
184 } else {
185 o = 0;
186 }
187 } else if( clip_right < x + rlelen ) {
188 if( clip_right > x ) {
189 x2_scaled = SCALED_TO_INT( clip_right * x_scale);
190 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o,
191 x2_scaled-x1_scaled);
192 o = 0;
193 } else {
194 o = 0;
195 }
196 }
197 }
198
199 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
200 if (o && mask) {
201 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
202 }
203
204 x1_scaled = x2_scaled;
205 x += rlelen;
206 rle++;
207 if (rle >= rle_limit) break;
208 }
209
210 img_pix += img_width;
211 dy += dy_step;
212 if (dy >= INT_TO_SCALED(1)) {
213 dy -= INT_TO_SCALED(1);
214 ++y;
215 while (dy >= INT_TO_SCALED(1)) {
216 rle = rle_img_advance_line(rle, rle_limit, src_width);
217 dy -= INT_TO_SCALED(1);
218 ++y;
219 }
220 } else {
221 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
222 }
223 }
224}
225
226void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
227 int img_width, int img_height,
228 int dst_width, int dst_height)
229{
230 clut_t* clut = (clut_t*) img_overl->clip_color;
231 uint8_t *trans;
232 int src_width = img_overl->width;
233 int src_height = img_overl->height;
234 rle_elem_t *rle = img_overl->rle;
235 rle_elem_t *rle_limit = rle + img_overl->num_rle;
236 int x, y, x1_scaled, x2_scaled;
237 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */
238 int clip_right;
239 uint8_t *img_pix;
240
241 dy_step = INT_TO_SCALED(dst_height) / img_height;
242 x_scale = INT_TO_SCALED(img_width) / dst_width;
243
244 img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width
245 + (img_overl->x * img_width / dst_width));
246
247 trans = img_overl->clip_trans;
248
249 /* avoid wraping overlay if drawing to small image */
250 if( (img_overl->x + img_overl->clip_right) < dst_width )
251 clip_right = img_overl->clip_right;
252 else
253 clip_right = dst_width - 1 - img_overl->x;
254
255 /* avoid buffer overflow */
256 if( (src_height + img_overl->y) >= dst_height )
257 src_height = dst_height - 1 - img_overl->y;
258
259 for (dy = y = 0; y < src_height && rle < rle_limit; ) {
260 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
261 rle_elem_t *rle_start = rle;
262
263 for (x = x1_scaled = 0; x < src_width;) {
264 uint8_t clr;
265 uint16_t o;
266 int rlelen;
267
268 clr = rle->color;
269 o = trans[clr];
270 rlelen = rle->len;
271
272 if (o && mask) {
273 /* threat cases where clipping border is inside rle->len pixels */
274 if ( img_overl->clip_left > x ) {
275 if( img_overl->clip_left < x + rlelen ) {
276 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
277 rlelen -= img_overl->clip_left - x;
278 x += img_overl->clip_left - x;
279 } else {
280 o = 0;
281 }
282 } else if( clip_right < x + rlelen ) {
283 if( clip_right > x ) {
284 x2_scaled = SCALED_TO_INT( clip_right * x_scale);
285 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb,
286 clut[clr].cr, clut[clr].y,
287 o, x2_scaled-x1_scaled);
288 o = 0;
289 } else {
290 o = 0;
291 }
292 }
293 }
294
295 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
296 if (o && mask) {
297 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb,
298 clut[clr].cr, clut[clr].y,
299 o, x2_scaled-x1_scaled);
300 }
301
302 x1_scaled = x2_scaled;
303 x += rlelen;
304 rle++;
305 if (rle >= rle_limit) break;
306 }
307
308 img_pix += img_width * 3;
309 dy += dy_step;
310 if (dy >= INT_TO_SCALED(1)) {
311 dy -= INT_TO_SCALED(1);
312 ++y;
313 while (dy >= INT_TO_SCALED(1)) {
314 rle = rle_img_advance_line(rle, rle_limit, src_width);
315 dy -= INT_TO_SCALED(1);
316 ++y;
317 }
318 } else {
319 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
320 }
321 }
322}
323
324void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
325 int img_width, int img_height,
326 int dst_width, int dst_height)
327{
328 clut_t* clut = (clut_t*) img_overl->clip_color;
329 uint8_t *trans;
330 int src_width = img_overl->width;
331 int src_height = img_overl->height;
332 rle_elem_t *rle = img_overl->rle;
333 rle_elem_t *rle_limit = rle + img_overl->num_rle;
334 int x, y, x1_scaled, x2_scaled;
335 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */
336 int clip_right;
337 uint8_t *img_pix;
338
339 dy_step = INT_TO_SCALED(dst_height) / img_height;
340 x_scale = INT_TO_SCALED(img_width) / dst_width;
341
342 img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width
343 + (img_overl->x * img_width / dst_width));
344
345 trans = img_overl->clip_trans;
346
347 /* avoid wraping overlay if drawing to small image */
348 if( (img_overl->x + img_overl->clip_right) < dst_width )
349 clip_right = img_overl->clip_right;
350 else
351 clip_right = dst_width - 1 - img_overl->x;
352
353 /* avoid buffer overflow */
354 if( (src_height + img_overl->y) >= dst_height )
355 src_height = dst_height - 1 - img_overl->y;
356
357 for (y = dy = 0; y < src_height && rle < rle_limit; ) {
358 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
359 rle_elem_t *rle_start = rle;
360
361 for (x = x1_scaled = 0; x < src_width;) {
362 uint8_t clr;
363 uint16_t o;
364 int rlelen;
365
366 clr = rle->color;
367 o = trans[clr];
368 rlelen = rle->len;
369
370 if (o && mask) {
371 /* threat cases where clipping border is inside rle->len pixels */
372 if ( img_overl->clip_left > x ) {
373 if( img_overl->clip_left < x + rlelen ) {
374 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
375 rlelen -= img_overl->clip_left - x;
376 x += img_overl->clip_left - x;
377 } else {
378 o = 0;
379 }
380 } else if( clip_right < x + rlelen ) {
381 if( clip_right > x ) {
382 x2_scaled = SCALED_TO_INT( clip_right * x_scale);
383 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb,
384 clut[clr].cr, clut[clr].y,
385 o, x2_scaled-x1_scaled);
386 o = 0;
387 } else {
388 o = 0;
389 }
390 }
391 }
392
393 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
394 if (o && mask) {
395 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb,
396 clut[clr].cr, clut[clr].y,
397 o, x2_scaled-x1_scaled);
398 }
399
400 x1_scaled = x2_scaled;
401 x += rlelen;
402 rle++;
403 if (rle >= rle_limit) break;
404 }
405
406 img_pix += img_width * 4;
407 dy += dy_step;
408 if (dy >= INT_TO_SCALED(1)) {
409 dy -= INT_TO_SCALED(1);
410 ++y;
411 while (dy >= INT_TO_SCALED(1)) {
412 rle = rle_img_advance_line(rle, rle_limit, src_width);
413 dy -= INT_TO_SCALED(1);
414 ++y;
415 }
416 } else {
417 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
418 }
419 }
420}
421
422static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz)
423{
424 uint8_t *limit = mem + sz;
425 while (mem < limit) {
426 *mem = BLEND_BYTE(*mem, val, o);
427 mem++;
428 }
429}
430
431void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
432 int dst_width, int dst_height)
433{
434 clut_t *my_clut;
435 uint8_t *my_trans;
436
437 int src_width = img_overl->width;
438 int src_height = img_overl->height;
439 rle_elem_t *rle = img_overl->rle;
440 rle_elem_t *rle_limit = rle + img_overl->num_rle;
441 int x_off = img_overl->x;
442 int y_off = img_overl->y;
443 int ymask,xmask;
444 int rle_this_bite;
445 int rle_remainder;
446 int rlelen;
447 int x, y;
448 int clip_right;
449 uint8_t clr=0;
450
451 uint8_t *dst_y = dst_base[0] + dst_width * y_off + x_off;
452 uint8_t *dst_cr = dst_base[2] +
453 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1;
454 uint8_t *dst_cb = dst_base[1] +
455 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1;
456#ifdef LOG_BLEND_YUV
457 printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height);
458#endif
459 my_clut = (clut_t*) img_overl->clip_color;
460 my_trans = img_overl->clip_trans;
461
462 /* avoid wraping overlay if drawing to small image */
463 if( (x_off + img_overl->clip_right) < dst_width )
464 clip_right = img_overl->clip_right;
465 else
466 clip_right = dst_width - 1 - x_off;
467
468 /* avoid buffer overflow */
469 if( (src_height + y_off) >= dst_height )
470 src_height = dst_height - 1 - y_off;
471
472 rlelen=rle_remainder=0;
473 for (y = 0; y < src_height; y++) {
474 ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y));
475 xmask = 0;
476#ifdef LOG_BLEND_YUV
477 printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height);
478#endif
479
480 for (x = 0; x < src_width;) {
481 uint16_t o;
482#ifdef LOG_BLEND_YUV
483 printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
484#endif
485
486 if ((rlelen < 0) || (rle_remainder < 0)) {
487 printf("alphablend: major bug in blend_yuv < 0\n");
488 }
489 if (rlelen == 0) {
490 rle_remainder = rlelen = rle->len;
491 clr = rle->color;
492 rle++;
493 }
494 if (rle_remainder == 0) {
495 rle_remainder = rlelen;
496 }
497 if ((rle_remainder + x) > src_width) {
498 /* Do something for long rlelengths */
499 rle_remainder = src_width - x;
500 ;
501 }
502#ifdef LOG_BLEND_YUV
503 printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
504#endif
505
506 if (ymask == 0) {
507 if (x <= img_overl->clip_left) {
508 /* Starts outside clip area */
509 if ((x + rle_remainder - 1) > img_overl->clip_left ) {
510#ifdef LOG_BLEND_YUV
511 printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
512#endif
513 /* Cutting needed, starts outside, ends inside */
514 rle_this_bite = (img_overl->clip_left - x + 1);
515 rle_remainder -= rle_this_bite;
516 rlelen -= rle_this_bite;
517 my_clut = (clut_t*) img_overl->color;
518 my_trans = img_overl->trans;
519 xmask = 0;
520 } else {
521#ifdef LOG_BLEND_YUV
522 printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
523#endif
524 /* no cutting needed, starts outside, ends outside */
525 rle_this_bite = rle_remainder;
526 rle_remainder = 0;
527 rlelen -= rle_this_bite;
528 my_clut = (clut_t*) img_overl->color;
529 my_trans = img_overl->trans;
530 xmask = 0;
531 }
532 } else if (x < clip_right) {
533 /* Starts inside clip area */
534 if ((x + rle_remainder) > clip_right ) {
535#ifdef LOG_BLEND_YUV
536 printf("Inside clip right %d, ending outside\n", clip_right);
537#endif
538 /* Cutting needed, starts inside, ends outside */
539 rle_this_bite = (clip_right - x);
540 rle_remainder -= rle_this_bite;
541 rlelen -= rle_this_bite;
542 my_clut = (clut_t*) img_overl->clip_color;
543 my_trans = img_overl->clip_trans;
544 xmask++;
545 } else {
546#ifdef LOG_BLEND_YUV
547 printf("Inside clip right %d, ending inside\n", clip_right);
548#endif
549 /* no cutting needed, starts inside, ends inside */
550 rle_this_bite = rle_remainder;
551 rle_remainder = 0;
552 rlelen -= rle_this_bite;
553 my_clut = (clut_t*) img_overl->clip_color;
554 my_trans = img_overl->clip_trans;
555 xmask++;
556 }
557 } else if (x >= clip_right) {
558 /* Starts outside clip area, ends outsite clip area */
559 if ((x + rle_remainder ) > src_width ) {
560#ifdef LOG_BLEND_YUV
561 printf("Outside clip right %d, ending eol\n", clip_right);
562#endif
563 /* Cutting needed, starts outside, ends at right edge */
564 /* It should never reach here due to the earlier test of src_width */
565 rle_this_bite = (src_width - x );
566 rle_remainder -= rle_this_bite;
567 rlelen -= rle_this_bite;
568 my_clut = (clut_t*) img_overl->color;
569 my_trans = img_overl->trans;
570 xmask = 0;
571 } else {
572 /* no cutting needed, starts outside, ends outside */
573#ifdef LOG_BLEND_YUV
574 printf("Outside clip right %d, ending outside\n", clip_right);
575#endif
576 rle_this_bite = rle_remainder;
577 rle_remainder = 0;
578 rlelen -= rle_this_bite;
579 my_clut = (clut_t*) img_overl->color;
580 my_trans = img_overl->trans;
581 xmask = 0;
582 }
583 }
584 } else {
585 /* Outside clip are due to y */
586 /* no cutting needed, starts outside, ends outside */
587 rle_this_bite = rle_remainder;
588 rle_remainder = 0;
589 rlelen -= rle_this_bite;
590 my_clut = (clut_t*) img_overl->color;
591 my_trans = img_overl->trans;
592 xmask = 0;
593 }
594 o = my_trans[clr];
595#ifdef LOG_BLEND_YUV
596 printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y);
597#endif
598 if (o) {
599 if(o >= 15) {
600 memset(dst_y + x, my_clut[clr].y, rle_this_bite);
601 if (y & 1) {
602 memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
603 memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
604 }
605 } else {
606 mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
607 if (y & 1) {
608 /* Blending cr and cb should use a different function, with pre -128 to each sample */
609 mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
610 mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
611 }
612 }
613
614 }
615#ifdef LOG_BLEND_YUV
616 printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x);
617#endif
618 x += rle_this_bite;
619 if (rle >= rle_limit) {
620#ifdef LOG_BLEND_YUV
621 printf("x-rle_limit\n");
622#endif
623 break;
624 }
625 }
626 if (rle >= rle_limit) {
627#ifdef LOG_BLEND_YUV
628 printf("x-rle_limit\n");
629#endif
630 break;
631 }
632
633 dst_y += dst_width;
634
635 if (y & 1) {
636 dst_cr += (dst_width + 1) / 2;
637 dst_cb += (dst_width + 1) / 2;
638 }
639 }
640#ifdef LOG_BLEND_YUV
641 printf("overlay_blend ended\n");
642#endif
643}
644
645void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
646 int dst_width, int dst_height)
647{
648 clut_t *my_clut;
649 uint8_t *my_trans;
650
651 int src_width = img_overl->width;
652 int src_height = img_overl->height;
653 rle_elem_t *rle = img_overl->rle;
654 rle_elem_t *rle_limit = rle + img_overl->num_rle;
655 int x_off = img_overl->x;
656 int y_off = img_overl->y;
657 int mask;
658 int x, y;
659 int l;
660 int clip_right;
661 uint32_t yuy2;
662
663 uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off);
664 uint8_t *dst;
665
666 my_clut = (clut_t*) img_overl->clip_color;
667 my_trans = img_overl->clip_trans;
668
669 /* avoid wraping overlay if drawing to small image */
670 if( (x_off + img_overl->clip_right) < dst_width )
671 clip_right = img_overl->clip_right;
672 else
673 clip_right = dst_width - 1 - x_off;
674
675 /* avoid buffer overflow */
676 if( (src_height + y_off) >= dst_height )
677 src_height = dst_height - 1 - y_off;
678
679 for (y = 0; y < src_height; y++) {
680 mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
681
682 dst = dst_y;
683 for (x = 0; x < src_width;) {
684 uint8_t clr;
685 uint16_t o;
686 int rlelen;
687
688 clr = rle->color;
689 o = my_trans[clr];
690 rlelen = rle->len;
691
692 if (o && mask) {
693 /* threat cases where clipping border is inside rle->len pixels */
694 if ( img_overl->clip_left > x ) {
695 if( img_overl->clip_left < x + rlelen ) {
696 rlelen -= img_overl->clip_left - x;
697 x += img_overl->clip_left - x;
698 } else {
699 o = 0;
700 }
701 } else if( clip_right < x + rlelen ) {
702 if( clip_right > x ) {
703 /* fixme: case not implemented */
704 o = 0;
705 } else {
706 o = 0;
707 }
708 }
709 }
710
711
712 if (o && mask) {
713 l = rlelen>>1;
714 if( !(x & 1) ) {
715 yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) +
716 (my_clut[clr].y << 16) + (my_clut[clr].cr << 24);
717 } else {
718 yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) +
719 (my_clut[clr].y << 16) + (my_clut[clr].cb << 24);
720 }
721
722 if (o >= 15) {
723 while(l--) {
724 *((uint32_t *)dst)++ = yuy2;
725 }
726 if(rlelen & 1)
727 *((uint16_t *)dst)++ = yuy2 & 0xffff;
728 } else {
729 if( l ) {
730 mem_blend32(dst, (uint8_t *)&yuy2, o, l);
731 dst += 4*l;
732 }
733
734 if(rlelen & 1) {
735 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o);
736 dst++;
737 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o);
738 dst++;
739 }
740 }
741 } else {
742 dst += rlelen*2;
743 }
744
745 x += rlelen;
746 rle++;
747 if (rle >= rle_limit) break;
748 }
749 if (rle >= rle_limit) break;
750
751 dst_y += dst_width*2;
752 }
753}