LCOV - code coverage report
Current view: top level - evg - raster_argb.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 349 429 81.4 %
Date: 2021-04-29 23:48:07 Functions: 26 26 100.0 %

          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             : }

Generated by: LCOV version 1.13