Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2019
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / software 2D rasterizer
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : *
25 : */
26 :
27 : #include "rast_soft.h"
28 :
29 :
30 : static GFINLINE s32
31 : mul255(s32 a, s32 b)
32 : {
33 2552436 : return ((a+1) * b) >> 8;
34 : }
35 :
36 :
37 : /*
38 : 32 bit ARGB/BGRA/RGBA
39 : */
40 :
41 7947778 : u32 do_composite_mode(GF_EVGCompositeMode comp_mode, s32 *srca, s32 *dsta)
42 : {
43 7947778 : switch (comp_mode) {
44 0 : case GF_EVG_SRC_ATOP:
45 0 : if (*srca && *dsta) {}
46 0 : else if (*dsta) { *srca = 0; }
47 0 : else { *dsta = *srca = 0; }
48 : break;
49 0 : case GF_EVG_SRC_IN:
50 0 : if (*srca && *dsta) {}
51 0 : else { *dsta = *srca = 0; }
52 : break;
53 0 : case GF_EVG_SRC_OUT:
54 0 : if (*srca && !*dsta) {}
55 0 : else { *dsta = *srca = 0; }
56 : break;
57 0 : case GF_EVG_DST_ATOP:
58 0 : if (*srca && *dsta) { *srca = 0;}
59 0 : else if (*srca) { *dsta = 0; }
60 0 : else { *dsta = *srca = 0; }
61 : break;
62 0 : case GF_EVG_DST_IN:
63 0 : if (*srca && *dsta) { *srca = 0; }
64 0 : else { *dsta = *srca = 0; }
65 : break;
66 0 : case GF_EVG_DST_OUT:
67 0 : if (!*srca && *dsta) {*srca = 0;}
68 0 : else { *dsta = *srca = 0; }
69 : break;
70 0 : case GF_EVG_DST_OVER:
71 0 : if (*dsta) {*srca = 0;}
72 0 : else { *dsta = *srca = 0; }
73 : break;
74 : case GF_EVG_LIGHTER:
75 : return 1;
76 0 : case GF_EVG_COPY:
77 0 : *dsta = 0;
78 0 : break;
79 0 : case GF_EVG_XOR:
80 0 : return 2;
81 7947778 : case GF_EVG_SRC_OVER:
82 7947778 : return 0;
83 : }
84 : return 0;
85 : }
86 :
87 1988357 : GFINLINE static void overmask_argb(u32 src, u8 *dst, u32 alpha, GF_EVGSurface *surf)
88 : {
89 : u32 cmode;
90 1988357 : s32 srca = GF_COL_A(src);
91 1988357 : s32 srcr = GF_COL_R(src);
92 1988357 : s32 srcg = GF_COL_G(src);
93 1988357 : s32 srcb = GF_COL_B(src);
94 1988357 : s32 dsta = dst[surf->idx_a];
95 :
96 3976714 : srca = mul255(srca, alpha);
97 :
98 1988357 : cmode = do_composite_mode(surf->comp_mode, &srca, &dsta);
99 1988357 : if (cmode==1) {
100 0 : u8 dstr = dst[surf->idx_r];
101 0 : u8 dstg = dst[surf->idx_g];
102 0 : u8 dstb = dst[surf->idx_b];
103 : // dsta += srca;
104 : // if (srca>0xFF) srca = 0xFF;
105 0 : dstr += srcr;
106 : if (dstr>0xFF) dstr = 0xFF;
107 0 : dstg += srcg;
108 : if (dstg>0xFF) dstg = 0xFF;
109 0 : dstb += srcb;
110 : if (dstb>0xFF) dstb = 0xFF;
111 0 : dst[surf->idx_a] = (u8) srca;
112 0 : dst[surf->idx_r] = (u8) dstr;
113 0 : dst[surf->idx_g] = (u8) dstg;
114 0 : dst[surf->idx_b] = (u8) dstb;
115 0 : return;
116 : }
117 1988357 : if (cmode==2) {
118 0 : u8 dstr = dst[surf->idx_r];
119 0 : u8 dstg = dst[surf->idx_g];
120 0 : u8 dstb = dst[surf->idx_b];
121 0 : dst[surf->idx_a] = (u8) srca;
122 0 : dst[surf->idx_r] = (u8) (dstr^srcr);
123 0 : dst[surf->idx_g] = (u8) (dstg^srcg);
124 0 : dst[surf->idx_b] = (u8) (dstb^srcb);
125 0 : return;
126 : }
127 :
128 : /*special case for RGBA:
129 : if dst alpha is 0, consider the surface is empty and copy pixel
130 : if source alpha is 0xFF erase the entire pixel
131 : */
132 1988357 : if (dsta && (srca!=0xFF) ) {
133 : s32 final_a;
134 35308 : s32 dstr = dst[surf->idx_r];
135 35308 : s32 dstg = dst[surf->idx_g];
136 35308 : s32 dstb = dst[surf->idx_b];
137 :
138 : //do the maths , so that the result of the blend follows the same DST = SRC*apha + DST(1-alpha)
139 : //it gives a transform alpha of Fa = SRCa + DSTa - SRCa*DSTa
140 : //and an RGB Fc = (SRCa*SRCc + DSTa*DSTc - DSTc*(DSTa-SRCa)) / Fa
141 70616 : final_a = dsta + srca - mul255(dsta, srca);
142 35308 : if (final_a) {
143 : s32 res;
144 35308 : dst[surf->idx_a] = final_a;
145 35308 : res = (srcr*srca + dstr*(dsta-srca)) / final_a;
146 35308 : if (res<0) res=0;
147 35308 : dst[surf->idx_r] = (u8) (res);
148 35308 : res = (srcg*srca + dstg*(dsta-srca)) / final_a;
149 35308 : if (res<0) res=0;
150 35308 : dst[surf->idx_g] = (u8) (res);
151 35308 : res = (srcb*srca + dstb*(dsta-srca)) / final_a;
152 35308 : if (res<0) res=0;
153 35308 : dst[surf->idx_b] = (u8) (res);
154 : }
155 : } else {
156 1953049 : dst[surf->idx_a] = (u8) srca;
157 1953049 : dst[surf->idx_r] = (u8) srcr;
158 1953049 : dst[surf->idx_g] = (u8) srcg;
159 1953049 : dst[surf->idx_b] = (u8) srcb;
160 : }
161 : }
162 :
163 1997790 : GFINLINE static void overmask_argb_const_run(u32 src, u8 *dst, s32 dst_pitch_x, u32 count, GF_EVGSurface *surf)
164 : {
165 1997790 : u8 const_srca = GF_COL_A(src);
166 1997790 : s32 srcr = GF_COL_R(src);
167 1997790 : s32 srcg = GF_COL_G(src);
168 1997790 : s32 srcb = GF_COL_B(src);
169 :
170 9955001 : while (count) {
171 5959421 : s32 srca = const_srca;
172 5959421 : s32 dsta = dst[surf->idx_a];
173 :
174 5959421 : do_composite_mode(surf->comp_mode, &srca, &dsta);
175 :
176 : /*special case for RGBA:
177 : if dst alpha is 0, consider the surface is empty and copy pixel
178 : if source alpha is 0xFF erase the entire pixel
179 : */
180 5959421 : if ((dsta != 0) && (srca != 0xFF)) {
181 : s32 final_a;
182 357280 : s32 dstr = dst[surf->idx_r];
183 357280 : s32 dstg = dst[surf->idx_g];
184 357280 : s32 dstb = dst[surf->idx_b];
185 :
186 : //do the maths , so that the result of the blend follows the same DST = SRC*apha + DST(1-alpha)
187 : //it gives a transform alpha of Fa = SRCa + DSTa - SRCa*DSTa
188 : //and an RGB Fc = (SRCa*SRCc + DSTa*DSTc - DSTc*(DSTa-SRCa)) / Fa
189 714560 : final_a = dsta + srca - mul255(dsta, srca);
190 357280 : if (final_a) {
191 : s32 res;
192 357280 : dst[surf->idx_a] = final_a;
193 357280 : res = (srcr*srca + dstr*(dsta-srca)) / final_a;
194 357280 : if (res<0) res=0;
195 357280 : dst[surf->idx_r] = (u8) (res);
196 357280 : res = (srcg*srca + dstg*(dsta-srca)) / final_a;
197 357280 : if (res<0) res=0;
198 357280 : dst[surf->idx_g] = (u8) (res);
199 357280 : res = (srcb*srca + dstb*(dsta-srca)) / final_a;
200 357280 : if (res<0) res=0;
201 357280 : dst[surf->idx_b] = (u8) (res);
202 : }
203 : } else {
204 5602141 : dst[surf->idx_a] = (u8) srca;
205 5602141 : dst[surf->idx_r] = (u8) srcr;
206 5602141 : dst[surf->idx_g] = (u8) srcg;
207 5602141 : dst[surf->idx_b] = (u8) srcb;
208 : }
209 5959421 : dst+=dst_pitch_x;
210 5959421 : count--;
211 : }
212 1997790 : }
213 :
214 33640 : void evg_argb_fill_single(s32 y, s32 x, u32 col, GF_EVGSurface *surf)
215 : {
216 33640 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
217 33640 : overmask_argb(col, dst, 0xFF, surf);
218 33640 : }
219 :
220 3168 : void evg_argb_fill_single_a(s32 y, s32 x, u8 coverage, u32 col, GF_EVGSurface *surf)
221 : {
222 3168 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
223 3168 : overmask_argb(col, dst, coverage, surf);
224 3168 : }
225 :
226 :
227 283674 : void evg_argb_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
228 : {
229 283674 : u32 col = surf->fill_col;
230 : u32 col_no_a;
231 283674 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
232 : s32 i;
233 :
234 283674 : col_no_a = col & 0x00FFFFFF;
235 :
236 2262691 : for (i=0; i<count; i++) {
237 : u32 new_a, fin;
238 : u8 *p;
239 : u32 len;
240 1979017 : p = dst + spans[i].x*surf->pitch_x;
241 1979017 : len = spans[i].len;
242 :
243 1979017 : new_a = spans[i].coverage;
244 1979017 : fin = (new_a<<24) | col_no_a;
245 : //we must blend in all cases since we have to merge with the dst alpha
246 1979017 : overmask_argb_const_run(fin, p, surf->pitch_x, len, surf);
247 : }
248 283674 : }
249 :
250 12614 : void evg_argb_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
251 : {
252 12614 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
253 : u32 a, fin, col_no_a;
254 : s32 i;
255 :
256 12614 : a = GF_COL_A(surf->fill_col);
257 12614 : col_no_a = surf->fill_col & 0x00FFFFFF;
258 12614 : if (surf->get_alpha) {
259 : u32 j;
260 0 : for (i=0; i<count; i++) {
261 0 : for (j=0; j<spans[i].len; j++) {
262 0 : s32 x = spans[i].x+j;
263 0 : u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
264 0 : fin = mul255(aa, spans[i].coverage);
265 0 : fin = (fin<<24) | col_no_a;
266 0 : overmask_argb_const_run(fin, dst + x * surf->pitch_x, surf->pitch_x, 1, surf);
267 : }
268 : }
269 : } else {
270 18773 : for (i=0; i<count; i++) {
271 37546 : fin = mul255(a, spans[i].coverage);
272 18773 : fin = (fin<<24) | col_no_a;
273 18773 : overmask_argb_const_run(fin, dst + spans[i].x*surf->pitch_x, surf->pitch_x, spans[i].len, surf);
274 : }
275 : }
276 12614 : }
277 :
278 10258 : void evg_argb_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
279 : {
280 10258 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
281 : s32 i;
282 :
283 36680 : for (i=0; i<count; i++) {
284 : u8 *p;
285 : u8 spanalpha;
286 : u32 len;
287 : u32 *col;
288 26422 : p = dst + spans[i].x * surf->pitch_x;
289 26422 : len = spans[i].len;
290 26422 : spanalpha = spans[i].coverage;
291 26422 : evg_fill_run(surf->sten, surf, spans[i].x, y, len);
292 26422 : col = surf->stencil_pix_run;
293 2004393 : while (len--) {
294 : //we must blend in all cases since we have to merge with the dst alpha
295 1951549 : overmask_argb(*col, p, spanalpha, surf);
296 1951549 : col++;
297 1951549 : p += surf->pitch_x;
298 : }
299 : }
300 10258 : }
301 :
302 :
303 22125 : void evg_argb_fill_erase(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
304 : {
305 22125 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
306 : s32 i;
307 :
308 108414 : for (i=0; i<count; i++) {
309 : u8 *p;
310 : u32 len;
311 86289 : p = dst + spans[i].x*surf->pitch_x;
312 86289 : len = spans[i].len;
313 86289 : if (spans[i].coverage != 0xFF) {
314 : } else {
315 1850150 : while (len--) {
316 1828338 : *(u32 *)p = 0;
317 1828338 : p += surf->pitch_x;
318 : }
319 : }
320 : }
321 22125 : }
322 :
323 2386 : GF_Err evg_surface_clear_argb(GF_EVGSurface *surf, GF_IRect rc, GF_Color col)
324 : {
325 : u8 *data, *o_data;
326 : u8 a, r, g, b;
327 : u32 x, y, w, h, sy;
328 : s32 st;
329 : GF_EVGSurface *_this = (GF_EVGSurface *)surf;
330 2386 : st = _this->pitch_y;
331 :
332 2386 : h = rc.height;
333 2386 : w = rc.width;
334 2386 : sy = rc.y;
335 :
336 2386 : if (sy+h > _this->height) {
337 0 : h = _this->height - sy;
338 : }
339 2386 : if (rc.x + w > _this->width) {
340 0 : w = _this->width - rc.x;
341 : }
342 :
343 2386 : a = GF_COL_A(col);
344 2386 : r = GF_COL_R(col);
345 2386 : g = GF_COL_G(col);
346 2386 : b = GF_COL_B(col);
347 :
348 : o_data = NULL;
349 193786 : for (y = 0; y < h; y++) {
350 191400 : data = (u8 *) _this ->pixels + (sy+y)* st + _this->pitch_x * rc.x;
351 191400 : if (!y) {
352 : o_data = data;
353 318157 : for (x = 0; x < w; x++) {
354 318157 : data[surf->idx_a] = a;
355 318157 : data[surf->idx_r] = r;
356 318157 : data[surf->idx_g] = g;
357 318157 : data[surf->idx_b] = b;
358 318157 : data += 4;
359 : }
360 : } else {
361 189014 : memcpy(data, o_data, w*4);
362 : }
363 : }
364 2386 : return GF_OK;
365 : }
366 :
367 : /*
368 : 32 bit RGBX/XRGB/BGRX/XBGR
369 : */
370 :
371 15346 : static void overmask_rgbx(u32 src, u8 *dst, u32 alpha, GF_EVGSurface *surf)
372 : {
373 15346 : s32 srca = (src >> 24) & 0xff;
374 15346 : s32 srcr = (src >> 16) & 0xff;
375 15346 : s32 srcg = (src >> 8) & 0xff;
376 15346 : s32 srcb = (src >> 0) & 0xff;
377 :
378 15346 : s32 dstr = dst[surf->idx_r];
379 15346 : s32 dstg = dst[surf->idx_g];
380 15346 : s32 dstb = dst[surf->idx_b];
381 :
382 15346 : srca = mul255(srca, alpha);
383 30692 : dst[surf->idx_r] = mul255(srca, srcr - dstr) + dstr;
384 30692 : dst[surf->idx_g] = mul255(srca, srcg - dstg) + dstg;
385 30692 : dst[surf->idx_b] = mul255(srca, srcb - dstb) + dstb;
386 15346 : }
387 :
388 6688 : GFINLINE static void overmask_rgbx_const_run(u32 src, u8 *dst, s32 dst_pitch_x, u32 count, GF_EVGSurface *surf)
389 : {
390 6688 : s32 srca = (src>>24) & 0xff;
391 13376 : u32 srcr = mul255(srca, ((src >> 16) & 0xff)) ;
392 13376 : u32 srcg = mul255(srca, ((src >> 8) & 0xff)) ;
393 13376 : u32 srcb = mul255(srca, ((src) & 0xff)) ;
394 23264 : while (count) {
395 : u32 dstc;
396 9888 : dstc = dst[surf->idx_r];
397 19776 : dst[surf->idx_r] = mul255(srca, srcr - dstc) + dstc;
398 9888 : dstc = dst[surf->idx_g];
399 19776 : dst[surf->idx_g] = mul255(srca, srcg - dstc) + dstc;
400 9888 : dstc = dst[surf->idx_b];
401 19776 : dst[surf->idx_b] = mul255(srca, srcb - dstc) + dstc;
402 9888 : dst += dst_pitch_x;
403 9888 : count--;
404 : }
405 6688 : }
406 :
407 :
408 33640 : void evg_rgbx_fill_single(s32 y, s32 x, u32 col, GF_EVGSurface *surf)
409 : {
410 33640 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
411 33640 : u8 r = GF_COL_R(col);
412 33640 : u8 g = GF_COL_G(col);
413 33640 : u8 b = GF_COL_B(col);
414 33640 : dst[surf->idx_r] = r;
415 33640 : dst[surf->idx_g] = g;
416 33640 : dst[surf->idx_b] = b;
417 33640 : }
418 :
419 3168 : void evg_rgbx_fill_single_a(s32 y, s32 x, u8 coverage, u32 col, GF_EVGSurface *surf)
420 : {
421 3168 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
422 3168 : overmask_rgbx(col, dst, coverage, surf);
423 3168 : }
424 :
425 1228 : void evg_rgbx_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
426 : {
427 1228 : u32 col = surf->fill_col;
428 : u32 fin, col_no_a, spana;
429 1228 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
430 : u8 r, g, b;
431 : s32 i, x;
432 : u32 len;
433 :
434 1228 : col_no_a = col & 0x00FFFFFF;
435 1228 : r = GF_COL_R(col);
436 1228 : g = GF_COL_G(col);
437 1228 : b = GF_COL_B(col);
438 :
439 8128 : for (i=0; i<count; i++) {
440 6900 : spana = spans[i].coverage;
441 6900 : x = spans[i].x * surf->pitch_x;
442 6900 : len = spans[i].len;
443 :
444 6900 : if (spana != 0xFF) {
445 5712 : fin = (spana<<24) | col_no_a;
446 5712 : overmask_rgbx_const_run(fin, dst + x, surf->pitch_x, len, surf);
447 : } else {
448 12904 : while (len--) {
449 11716 : dst[x+surf->idx_r] = r;
450 11716 : dst[x+surf->idx_g] = g;
451 11716 : dst[x+surf->idx_b] = b;
452 11716 : x += surf->pitch_x;
453 : }
454 : }
455 : }
456 1228 : }
457 :
458 224 : void evg_rgbx_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
459 : {
460 224 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
461 224 : u32 col = surf->fill_col;
462 : u32 a, fin, col_no_a;
463 : s32 i;
464 :
465 224 : a = (col>>24)&0xFF;
466 224 : col_no_a = col & 0x00FFFFFF;
467 224 : if (surf->get_alpha) {
468 0 : for (i=0; i<count; i++) {
469 : u32 j;
470 0 : for (j=0; j<spans[i].len; j++) {
471 0 : s32 x = spans[i].x + j;
472 0 : u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
473 0 : fin = mul255(aa, spans[i].coverage);
474 0 : fin = (fin<<24) | col_no_a;
475 0 : overmask_rgbx_const_run(fin, dst + surf->pitch_x * x, surf->pitch_x, 1, surf);
476 : }
477 : }
478 : } else {
479 976 : for (i=0; i<count; i++) {
480 1952 : fin = mul255(a, spans[i].coverage);
481 976 : fin = (fin<<24) | col_no_a;
482 976 : overmask_rgbx_const_run(fin, dst + surf->pitch_x*spans[i].x, surf->pitch_x, spans[i].len, surf);
483 : }
484 : }
485 224 : }
486 :
487 :
488 3244 : void evg_rgbx_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
489 : {
490 3244 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
491 : s32 i;
492 :
493 9368 : for (i=0; i<count; i++) {
494 : u8 spanalpha, col_a;
495 : s32 x;
496 : u32 len;
497 : u32 *col, _col;
498 6124 : len = spans[i].len;
499 6124 : spanalpha = spans[i].coverage;
500 6124 : evg_fill_run(surf->sten, surf, spans[i].x, y, len);
501 6124 : col = surf->stencil_pix_run;
502 6124 : x = spans[i].x * surf->pitch_x;
503 :
504 327124 : while (len--) {
505 314876 : _col = *col;
506 314876 : col_a = GF_COL_A(_col);
507 314876 : if (col_a) {
508 287548 : if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
509 12178 : overmask_rgbx(*col, dst+x, spanalpha, surf);
510 : } else {
511 275370 : dst[x+surf->idx_r] = GF_COL_R(_col);
512 275370 : dst[x+surf->idx_g] = GF_COL_G(_col);
513 275370 : dst[x+surf->idx_b] = GF_COL_B(_col);
514 : }
515 : }
516 314876 : col++;
517 314876 : x += surf->pitch_x;
518 : }
519 : }
520 3244 : }
521 :
522 20 : GF_Err evg_surface_clear_rgbx(GF_EVGSurface *surf, GF_IRect rc, GF_Color col)
523 : {
524 : u32 x, y, w, h, sx, sy;
525 : u8 r,g,b;
526 : s32 st;
527 : char *o_data;
528 : GF_EVGSurface *_this = (GF_EVGSurface *)surf;
529 20 : st = _this->pitch_x;
530 :
531 20 : h = rc.height;
532 20 : w = rc.width;
533 20 : sx = rc.x;
534 20 : sy = rc.y;
535 :
536 20 : r = GF_COL_R(col);
537 20 : g = GF_COL_G(col);
538 20 : b = GF_COL_B(col);
539 :
540 : o_data = NULL;
541 3268 : for (y = 0; y < h; y++) {
542 3248 : u8 *data = (u8 *) _this ->pixels + (y + sy) * _this->pitch_y + st*sx;
543 3248 : if (!y) {
544 : o_data = data;
545 3248 : for (x = 0; x < w; x++) {
546 3248 : data[surf->idx_r] = r;
547 3248 : data[surf->idx_g] = g;
548 3248 : data[surf->idx_b] = b;
549 3248 : data[surf->idx_a] = 0xFF;
550 3248 : data += st;
551 : }
552 : } else {
553 3228 : memcpy(data, o_data, w*4);
554 : }
555 : }
556 20 : return GF_OK;
557 : }
558 :
559 :
560 :
561 :
562 : /*
563 : alpha grey
564 : */
565 :
566 10046 : static void overmask_alphagrey(u32 src, u8 *dst, u32 alpha, u32 grey_type, u32 idx_g, u32 idx_a)
567 : {
568 10046 : s32 srca = (src >> 24) & 0xff;
569 : s32 srcc;
570 10046 : s32 dsta = dst[idx_a];
571 :
572 10046 : if (grey_type==0) srcc = (src >> 16) & 0xff;
573 0 : else if (grey_type==1) srcc = (src >> 8) & 0xff;
574 0 : else srcc = (src >> 0) & 0xff;
575 10046 : srca = mul255(srca, alpha);
576 :
577 10046 : if (dsta) {
578 6902 : s32 dstc = dst[idx_g];
579 13804 : dst[idx_g] = mul255(srca, srcc - dstc) + dstc;
580 13804 : dst[idx_a] = mul255(srca, srca) + mul255(255-srca, dsta);
581 : } else {
582 3144 : dst[idx_g] = srcc;
583 3144 : dst[idx_a] = srca;
584 : }
585 10046 : }
586 :
587 3344 : static void overmask_alphagrey_const_run(u32 src_a, u32 src_c, u8 *dst, s32 dst_pitch_x, u32 count, u32 idx_g, u32 idx_a)
588 : {
589 11632 : while (count) {
590 4944 : s32 dsta = dst[idx_a];
591 : /*special case : if dst alpha is 0, consider the surface is empty and copy pixel*/
592 4944 : if (dsta) {
593 2178 : s32 dstc = dst[idx_g];
594 4356 : dst[idx_g] = mul255(src_a, src_c - dstc) + dstc;
595 4356 : dst[idx_a] = mul255(src_a, src_a) + mul255(255-src_a, dsta);
596 : } else {
597 2766 : dst[idx_g] = src_c;
598 2766 : dst[idx_a] = src_a;
599 : }
600 4944 : dst += dst_pitch_x;
601 4944 : count--;
602 : }
603 3344 : }
604 :
605 :
606 16820 : void evg_alphagrey_fill_single(s32 y, s32 x, u32 col, GF_EVGSurface *surf)
607 : {
608 16820 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
609 : u8 col_c;
610 :
611 16820 : if (surf->grey_type==0) col_c = GF_COL_R(col);
612 0 : else if (surf->grey_type==1) col_c = GF_COL_G(col);
613 0 : else col_c = GF_COL_B(col);
614 16820 : dst[surf->idx_g] = col_c;
615 16820 : }
616 :
617 1584 : void evg_alphagrey_fill_single_a(s32 y, s32 x, u8 coverage, u32 col, GF_EVGSurface *surf)
618 : {
619 1584 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
620 1584 : overmask_alphagrey(col, dst, coverage, surf->grey_type, surf->idx_g, surf->idx_a);
621 1584 : }
622 :
623 614 : void evg_alphagrey_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
624 : {
625 614 : u32 col = surf->fill_col;
626 : u32 a;
627 614 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
628 : s32 i, x;
629 : u32 len;
630 : u8 col_a, col_c;
631 :
632 614 : col_a = GF_COL_A(col);
633 614 : if (surf->grey_type==0) col_c = GF_COL_R(col);
634 0 : else if (surf->grey_type==1) col_c = GF_COL_G(col);
635 0 : else col_c = GF_COL_B(col);
636 :
637 4064 : for (i=0; i<count; i++) {
638 3450 : x = spans[i].x * surf->pitch_x;
639 3450 : len = spans[i].len;
640 :
641 3450 : if (spans[i].coverage != 0xFF) {
642 5712 : a = mul255(0xFF, spans[i].coverage);
643 2856 : overmask_alphagrey_const_run(a, col_c, dst + x, surf->pitch_x, len, surf->idx_g, surf->idx_a);
644 : } else {
645 6452 : while (len--) {
646 5858 : dst[x+surf->idx_g] = col_c;
647 5858 : dst[x+surf->idx_a] = col_a;
648 5858 : x += surf->pitch_x;
649 : }
650 : }
651 : }
652 614 : }
653 :
654 112 : void evg_alphagrey_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
655 : {
656 112 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
657 112 : u32 col = surf->fill_col;
658 : u32 a, fin, col_c;
659 : s32 i;
660 :
661 112 : a = GF_COL_A(col);
662 112 : if (surf->grey_type==0) col_c = GF_COL_R(col);
663 0 : else if (surf->grey_type==1) col_c = GF_COL_G(col);
664 : else col_c = GF_COL_B(col);
665 :
666 112 : if (surf->get_alpha) {
667 0 : for (i=0; i<count; i++) {
668 : u32 j;
669 0 : for (j=0; j<spans[i].len; i++) {
670 0 : s32 x = spans[i].x+j;
671 0 : u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
672 0 : fin = mul255(aa, spans[i].coverage);
673 0 : overmask_alphagrey_const_run(fin, col_c, dst + surf->pitch_x * x, surf->pitch_x, 1, surf->idx_g, surf->idx_a);
674 : }
675 : }
676 : } else {
677 488 : for (i=0; i<count; i++) {
678 976 : fin = mul255(a, spans[i].coverage);
679 488 : overmask_alphagrey_const_run(fin, col_c, dst + surf->pitch_x*spans[i].x, surf->pitch_x, spans[i].len, surf->idx_g, surf->idx_a);
680 : }
681 : }
682 112 : }
683 :
684 :
685 2262 : void evg_alphagrey_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
686 : {
687 2262 : u8 *dst = (u8 *) surf->pixels + y * surf->pitch_y;
688 : s32 i;
689 :
690 5964 : for (i=0; i<count; i++) {
691 : u8 spanalpha, col_a;
692 : s32 x;
693 : u32 len;
694 : u32 *col, _col;
695 3702 : len = spans[i].len;
696 3702 : spanalpha = spans[i].coverage;
697 3702 : evg_fill_run(surf->sten, surf, spans[i].x, y, len);
698 3702 : x = spans[i].x * surf->pitch_x;
699 3702 : col = surf->stencil_pix_run;
700 246762 : while (len--) {
701 239358 : _col = *col;
702 239358 : col_a = GF_COL_A(_col);
703 239358 : if (col_a) {
704 215958 : if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
705 8462 : overmask_alphagrey(*col, (dst + x) , spanalpha, surf->grey_type, surf->idx_g, surf->idx_a);
706 : } else {
707 : u8 dstc;
708 :
709 207496 : if (surf->grey_type==0) dstc = GF_COL_R(_col);
710 0 : else if (surf->grey_type==1) dstc = GF_COL_G(_col);
711 0 : else dstc = GF_COL_B(_col);
712 :
713 207496 : dst[x+surf->idx_g] = dstc;
714 207496 : dst[x+surf->idx_a] = col_a;
715 : }
716 : }
717 239358 : col++;
718 239358 : x += surf->pitch_x;
719 : }
720 : }
721 2262 : }
722 :
723 10 : GF_Err evg_surface_clear_alphagrey(GF_EVGSurface *surf, GF_IRect rc, GF_Color col)
724 : {
725 : u8 *data, *data_o;
726 : u8 col_a, col_c;
727 : u32 x, y, w, h, sx, sy;
728 : s32 st;
729 : GF_EVGSurface *_this = (GF_EVGSurface *)surf;
730 10 : st = _this->pitch_y;
731 :
732 10 : col_a = GF_COL_A(col);
733 10 : if (surf->grey_type==0) col_c = GF_COL_R(col);
734 0 : else if (surf->grey_type==1) col_c = GF_COL_G(col);
735 0 : else col_c = GF_COL_B(col);
736 :
737 10 : h = rc.height;
738 10 : w = rc.width;
739 10 : sx = rc.x;
740 10 : sy = rc.y;
741 :
742 : data_o = NULL;
743 :
744 1634 : for (y = 0; y < h; y++) {
745 1624 : data = (u8 *) _this ->pixels + (sy+y)* st + _this->pitch_x*sx;
746 1624 : if (!y) {
747 : data_o = data;
748 1624 : for (x = 0; x < w; x++) {
749 1624 : data[surf->idx_a] = col_c;
750 1624 : data[surf->idx_g] = col_a;
751 1624 : data += _this->pitch_x;
752 : }
753 : } else {
754 1614 : memcpy(data, data_o, w*_this->BPP);
755 : }
756 : }
757 10 : return GF_OK;
758 : }
|