LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-combine-float.c (source / functions) Hit Total Coverage
Test: output.info Lines: 108 370 29.2 %
Date: 2017-07-14 16:53:18 Functions: 1 166 0.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
       2             : /*
       3             :  * Copyright © 2010, 2012 Soren Sandmann Pedersen
       4             :  * Copyright © 2010, 2012 Red Hat, Inc.
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7             :  * copy of this software and associated documentation files (the "Software"),
       8             :  * to deal in the Software without restriction, including without limitation
       9             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10             :  * and/or sell copies of the Software, and to permit persons to whom the
      11             :  * Software is furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice (including the next
      14             :  * paragraph) shall be included in all copies or substantial portions of the
      15             :  * Software.
      16             :  *
      17             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      20             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      21             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      22             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      23             :  * DEALINGS IN THE SOFTWARE.
      24             :  *
      25             :  * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk)
      26             :  */
      27             : 
      28             : #ifdef HAVE_CONFIG_H
      29             : #include <config.h>
      30             : #endif
      31             : 
      32             : #include <math.h>
      33             : #include <string.h>
      34             : #include <float.h>
      35             : 
      36             : #include "pixman-private.h"
      37             : 
      38             : /* Workaround for http://gcc.gnu.org/PR54965 */
      39             : /* GCC 4.6 has problems with force_inline, so just use normal inline instead */
      40             : #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 6)
      41             : #undef force_inline
      42             : #define force_inline __inline__
      43             : #endif
      44             : 
      45             : #define IS_ZERO(f)     (-FLT_MIN < (f) && (f) < FLT_MIN)
      46             : 
      47             : typedef float (* combine_channel_t) (float sa, float s, float da, float d);
      48             : 
      49             : static force_inline void
      50             : combine_inner (pixman_bool_t component,
      51             :                float *dest, const float *src, const float *mask, int n_pixels,
      52             :                combine_channel_t combine_a, combine_channel_t combine_c)
      53             : {
      54             :     int i;
      55             : 
      56           0 :     if (!mask)
      57             :     {
      58           0 :         for (i = 0; i < 4 * n_pixels; i += 4)
      59             :         {
      60           0 :             float sa = src[i + 0];
      61           0 :             float sr = src[i + 1];
      62           0 :             float sg = src[i + 2];
      63           0 :             float sb = src[i + 3];
      64             :             
      65           0 :             float da = dest[i + 0];
      66           0 :             float dr = dest[i + 1];
      67           0 :             float dg = dest[i + 2];
      68           0 :             float db = dest[i + 3];                                     
      69             :             
      70           0 :             dest[i + 0] = combine_a (sa, sa, da, da);
      71           0 :             dest[i + 1] = combine_c (sa, sr, da, dr);
      72           0 :             dest[i + 2] = combine_c (sa, sg, da, dg);
      73           0 :             dest[i + 3] = combine_c (sa, sb, da, db);
      74             :         }
      75             :     }
      76             :     else
      77             :     {
      78           0 :         for (i = 0; i < 4 * n_pixels; i += 4)
      79             :         {
      80             :             float sa, sr, sg, sb;
      81             :             float ma, mr, mg, mb;
      82             :             float da, dr, dg, db;
      83             :             
      84           0 :             sa = src[i + 0];
      85           0 :             sr = src[i + 1];
      86           0 :             sg = src[i + 2];
      87           0 :             sb = src[i + 3];
      88             :             
      89           0 :             if (component)
      90             :             {
      91           0 :                 ma = mask[i + 0];
      92           0 :                 mr = mask[i + 1];
      93           0 :                 mg = mask[i + 2];
      94           0 :                 mb = mask[i + 3];
      95             : 
      96           0 :                 sr *= mr;
      97           0 :                 sg *= mg;
      98           0 :                 sb *= mb;
      99             : 
     100           0 :                 ma *= sa;
     101           0 :                 mr *= sa;
     102           0 :                 mg *= sa;
     103           0 :                 mb *= sa;
     104             :                 
     105           0 :                 sa = ma;
     106             :             }
     107             :             else
     108             :             {
     109           0 :                 ma = mask[i + 0];
     110             : 
     111           0 :                 sa *= ma;
     112           0 :                 sr *= ma;
     113           0 :                 sg *= ma;
     114           0 :                 sb *= ma;
     115             : 
     116           0 :                 ma = mr = mg = mb = sa;
     117             :             }
     118             :             
     119           0 :             da = dest[i + 0];
     120           0 :             dr = dest[i + 1];
     121           0 :             dg = dest[i + 2];
     122           0 :             db = dest[i + 3];
     123             :             
     124           0 :             dest[i + 0] = combine_a (ma, sa, da, da);
     125           0 :             dest[i + 1] = combine_c (mr, sr, da, dr);
     126           0 :             dest[i + 2] = combine_c (mg, sg, da, dg);
     127           0 :             dest[i + 3] = combine_c (mb, sb, da, db);
     128             :         }
     129             :     }
     130             : }
     131             : 
     132             : #define MAKE_COMBINER(name, component, combine_a, combine_c)            \
     133             :     static void                                                         \
     134             :     combine_ ## name ## _float (pixman_implementation_t *imp,           \
     135             :                                 pixman_op_t              op,            \
     136             :                                 float                   *dest,          \
     137             :                                 const float             *src,           \
     138             :                                 const float             *mask,          \
     139             :                                 int                      n_pixels)      \
     140             :     {                                                                   \
     141             :         combine_inner (component, dest, src, mask, n_pixels,            \
     142             :                        combine_a, combine_c);                           \
     143             :     }
     144             : 
     145             : #define MAKE_COMBINERS(name, combine_a, combine_c)                      \
     146             :     MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c)              \
     147             :     MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c)
     148             : 
     149             : 
     150             : /*
     151             :  * Porter/Duff operators
     152             :  */
     153             : typedef enum
     154             : {
     155             :     ZERO,
     156             :     ONE,
     157             :     SRC_ALPHA,
     158             :     DEST_ALPHA,
     159             :     INV_SA,
     160             :     INV_DA,
     161             :     SA_OVER_DA,
     162             :     DA_OVER_SA,
     163             :     INV_SA_OVER_DA,
     164             :     INV_DA_OVER_SA,
     165             :     ONE_MINUS_SA_OVER_DA,
     166             :     ONE_MINUS_DA_OVER_SA,
     167             :     ONE_MINUS_INV_DA_OVER_SA,
     168             :     ONE_MINUS_INV_SA_OVER_DA
     169             : } combine_factor_t;
     170             : 
     171             : #define CLAMP(f)                                        \
     172             :     (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f)))
     173             : 
     174             : static force_inline float
     175             : get_factor (combine_factor_t factor, float sa, float da)
     176             : {
     177           0 :     float f = -1;
     178             : 
     179           0 :     switch (factor)
     180             :     {
     181             :     case ZERO:
     182           0 :         f = 0.0f;
     183             :         break;
     184             : 
     185             :     case ONE:
     186           0 :         f = 1.0f;
     187             :         break;
     188             : 
     189             :     case SRC_ALPHA:
     190           0 :         f = sa;
     191             :         break;
     192             : 
     193             :     case DEST_ALPHA:
     194           0 :         f = da;
     195             :         break;
     196             : 
     197             :     case INV_SA:
     198           0 :         f = 1 - sa;
     199             :         break;
     200             : 
     201             :     case INV_DA:
     202           0 :         f = 1 - da;
     203             :         break;
     204             : 
     205             :     case SA_OVER_DA:
     206           0 :         if (IS_ZERO (da))
     207           0 :             f = 1.0f;
     208             :         else
     209           0 :             f = CLAMP (sa / da);
     210             :         break;
     211             : 
     212             :     case DA_OVER_SA:
     213           0 :         if (IS_ZERO (sa))
     214           0 :             f = 1.0f;
     215             :         else
     216           0 :             f = CLAMP (da / sa);
     217             :         break;
     218             : 
     219             :     case INV_SA_OVER_DA:
     220           0 :         if (IS_ZERO (da))
     221           0 :             f = 1.0f;
     222             :         else
     223           0 :             f = CLAMP ((1.0f - sa) / da);
     224             :         break;
     225             : 
     226             :     case INV_DA_OVER_SA:
     227           0 :         if (IS_ZERO (sa))
     228           0 :             f = 1.0f;
     229             :         else
     230           0 :             f = CLAMP ((1.0f - da) / sa);
     231             :         break;
     232             : 
     233             :     case ONE_MINUS_SA_OVER_DA:
     234           0 :         if (IS_ZERO (da))
     235           0 :             f = 0.0f;
     236             :         else
     237           0 :             f = CLAMP (1.0f - sa / da);
     238             :         break;
     239             : 
     240             :     case ONE_MINUS_DA_OVER_SA:
     241           0 :         if (IS_ZERO (sa))
     242           0 :             f = 0.0f;
     243             :         else
     244           0 :             f = CLAMP (1.0f - da / sa);
     245             :         break;
     246             : 
     247             :     case ONE_MINUS_INV_DA_OVER_SA:
     248           0 :         if (IS_ZERO (sa))
     249           0 :             f = 0.0f;
     250             :         else
     251           0 :             f = CLAMP (1.0f - (1.0f - da) / sa);
     252             :         break;
     253             : 
     254             :     case ONE_MINUS_INV_SA_OVER_DA:
     255           0 :         if (IS_ZERO (da))
     256           0 :             f = 0.0f;
     257             :         else
     258           0 :             f = CLAMP (1.0f - (1.0f - sa) / da);
     259             :         break;
     260             :     }
     261             : 
     262           0 :     return f;
     263             : }
     264             : 
     265             : #define MAKE_PD_COMBINERS(name, a, b)                                   \
     266             :     static float force_inline                                           \
     267             :     pd_combine_ ## name (float sa, float s, float da, float d)          \
     268             :     {                                                                   \
     269             :         const float fa = get_factor (a, sa, da);                        \
     270             :         const float fb = get_factor (b, sa, da);                        \
     271             :                                                                         \
     272             :         return MIN (1.0f, s * fa + d * fb);                             \
     273             :     }                                                                   \
     274             :                                                                         \
     275             :     MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name)
     276             : 
     277           0 : MAKE_PD_COMBINERS (clear,                       ZERO,                           ZERO)
     278           0 : MAKE_PD_COMBINERS (src,                         ONE,                            ZERO)
     279           0 : MAKE_PD_COMBINERS (dst,                         ZERO,                           ONE)
     280           0 : MAKE_PD_COMBINERS (over,                        ONE,                            INV_SA)
     281           0 : MAKE_PD_COMBINERS (over_reverse,                INV_DA,                         ONE)
     282           0 : MAKE_PD_COMBINERS (in,                          DEST_ALPHA,                     ZERO)
     283           0 : MAKE_PD_COMBINERS (in_reverse,                  ZERO,                           SRC_ALPHA)
     284           0 : MAKE_PD_COMBINERS (out,                         INV_DA,                         ZERO)
     285           0 : MAKE_PD_COMBINERS (out_reverse,                 ZERO,                           INV_SA)
     286           0 : MAKE_PD_COMBINERS (atop,                        DEST_ALPHA,                     INV_SA)
     287           0 : MAKE_PD_COMBINERS (atop_reverse,                INV_DA,                         SRC_ALPHA)
     288           0 : MAKE_PD_COMBINERS (xor,                         INV_DA,                         INV_SA)
     289           0 : MAKE_PD_COMBINERS (add,                         ONE,                            ONE)
     290             : 
     291           0 : MAKE_PD_COMBINERS (saturate,                    INV_DA_OVER_SA,                 ONE)
     292             : 
     293           0 : MAKE_PD_COMBINERS (disjoint_clear,              ZERO,                           ZERO)
     294           0 : MAKE_PD_COMBINERS (disjoint_src,                ONE,                            ZERO)
     295           0 : MAKE_PD_COMBINERS (disjoint_dst,                ZERO,                           ONE)
     296           0 : MAKE_PD_COMBINERS (disjoint_over,               ONE,                            INV_SA_OVER_DA)
     297           0 : MAKE_PD_COMBINERS (disjoint_over_reverse,       INV_DA_OVER_SA,                 ONE)
     298           0 : MAKE_PD_COMBINERS (disjoint_in,                 ONE_MINUS_INV_DA_OVER_SA,       ZERO)
     299           0 : MAKE_PD_COMBINERS (disjoint_in_reverse,         ZERO,                           ONE_MINUS_INV_SA_OVER_DA)
     300           0 : MAKE_PD_COMBINERS (disjoint_out,                INV_DA_OVER_SA,                 ZERO)
     301           0 : MAKE_PD_COMBINERS (disjoint_out_reverse,        ZERO,                           INV_SA_OVER_DA)
     302           0 : MAKE_PD_COMBINERS (disjoint_atop,               ONE_MINUS_INV_DA_OVER_SA,       INV_SA_OVER_DA)
     303           0 : MAKE_PD_COMBINERS (disjoint_atop_reverse,       INV_DA_OVER_SA,                 ONE_MINUS_INV_SA_OVER_DA)
     304           0 : MAKE_PD_COMBINERS (disjoint_xor,                INV_DA_OVER_SA,                 INV_SA_OVER_DA)
     305             : 
     306           0 : MAKE_PD_COMBINERS (conjoint_clear,              ZERO,                           ZERO)
     307           0 : MAKE_PD_COMBINERS (conjoint_src,                ONE,                            ZERO)
     308           0 : MAKE_PD_COMBINERS (conjoint_dst,                ZERO,                           ONE)
     309           0 : MAKE_PD_COMBINERS (conjoint_over,               ONE,                            ONE_MINUS_SA_OVER_DA)
     310           0 : MAKE_PD_COMBINERS (conjoint_over_reverse,       ONE_MINUS_DA_OVER_SA,           ONE)
     311           0 : MAKE_PD_COMBINERS (conjoint_in,                 DA_OVER_SA,                     ZERO)
     312           0 : MAKE_PD_COMBINERS (conjoint_in_reverse,         ZERO,                           SA_OVER_DA)
     313           0 : MAKE_PD_COMBINERS (conjoint_out,                ONE_MINUS_DA_OVER_SA,           ZERO)
     314           0 : MAKE_PD_COMBINERS (conjoint_out_reverse,        ZERO,                           ONE_MINUS_SA_OVER_DA)
     315           0 : MAKE_PD_COMBINERS (conjoint_atop,               DA_OVER_SA,                     ONE_MINUS_SA_OVER_DA)
     316           0 : MAKE_PD_COMBINERS (conjoint_atop_reverse,       ONE_MINUS_DA_OVER_SA,           SA_OVER_DA)
     317           0 : MAKE_PD_COMBINERS (conjoint_xor,                ONE_MINUS_DA_OVER_SA,           ONE_MINUS_SA_OVER_DA)
     318             : 
     319             : /*
     320             :  * PDF blend modes:
     321             :  *
     322             :  * The following blend modes have been taken from the PDF ISO 32000
     323             :  * specification, which at this point in time is available from
     324             :  * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
     325             :  * The relevant chapters are 11.3.5 and 11.3.6.
     326             :  * The formula for computing the final pixel color given in 11.3.6 is:
     327             :  * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
     328             :  * with B() being the blend function.
     329             :  * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
     330             :  *
     331             :  * These blend modes should match the SVG filter draft specification, as
     332             :  * it has been designed to mirror ISO 32000. Note that at the current point
     333             :  * no released draft exists that shows this, as the formulas have not been
     334             :  * updated yet after the release of ISO 32000.
     335             :  *
     336             :  * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
     337             :  * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
     338             :  * argument. Note that this implementation operates on premultiplied colors,
     339             :  * while the PDF specification does not. Therefore the code uses the formula
     340             :  * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
     341             :  */
     342             : 
     343             : #define MAKE_SEPARABLE_PDF_COMBINERS(name)                              \
     344             :     static force_inline float                                           \
     345             :     combine_ ## name ## _a (float sa, float s, float da, float d)       \
     346             :     {                                                                   \
     347             :         return da + sa - da * sa;                                       \
     348             :     }                                                                   \
     349             :                                                                         \
     350             :     static force_inline float                                           \
     351             :     combine_ ## name ## _c (float sa, float s, float da, float d)       \
     352             :     {                                                                   \
     353             :         float f = (1 - sa) * d + (1 - da) * s;                          \
     354             :                                                                         \
     355             :         return f + blend_ ## name (sa, s, da, d);                       \
     356             :     }                                                                   \
     357             :                                                                         \
     358             :     MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
     359             : 
     360             : static force_inline float
     361             : blend_multiply (float sa, float s, float da, float d)
     362             : {
     363           0 :     return d * s;
     364             : }
     365             : 
     366             : static force_inline float
     367             : blend_screen (float sa, float s, float da, float d)
     368             : {
     369           0 :     return d * sa + s * da - s * d;
     370             : }
     371             : 
     372             : static force_inline float
     373             : blend_overlay (float sa, float s, float da, float d)
     374             : {
     375           0 :     if (2 * d < da)
     376           0 :         return 2 * s * d;
     377             :     else
     378           0 :         return sa * da - 2 * (da - d) * (sa - s);
     379             : }
     380             : 
     381             : static force_inline float
     382             : blend_darken (float sa, float s, float da, float d)
     383             : {
     384           0 :     s = s * da;
     385           0 :     d = d * sa;
     386             : 
     387           0 :     if (s > d)
     388           0 :         return d;
     389             :     else
     390           0 :         return s;
     391             : }
     392             : 
     393             : static force_inline float
     394             : blend_lighten (float sa, float s, float da, float d)
     395             : {
     396           0 :     s = s * da;
     397           0 :     d = d * sa;
     398             : 
     399           0 :     if (s > d)
     400           0 :         return s;
     401             :     else
     402           0 :         return d;
     403             : }
     404             : 
     405             : static force_inline float
     406             : blend_color_dodge (float sa, float s, float da, float d)
     407             : {
     408           0 :     if (IS_ZERO (d))
     409           0 :         return 0.0f;
     410           0 :     else if (d * sa >= sa * da - s * da)
     411           0 :         return sa * da;
     412           0 :     else if (IS_ZERO (sa - s))
     413           0 :         return sa * da;
     414             :     else
     415           0 :         return sa * sa * d / (sa - s);
     416             : }
     417             : 
     418             : static force_inline float
     419             : blend_color_burn (float sa, float s, float da, float d)
     420             : {
     421           0 :     if (d >= da)
     422           0 :         return sa * da;
     423           0 :     else if (sa * (da - d) >= s * da)
     424           0 :         return 0.0f;
     425           0 :     else if (IS_ZERO (s))
     426           0 :         return 0.0f;
     427             :     else
     428           0 :         return sa * (da - sa * (da - d) / s);
     429             : }
     430             : 
     431             : static force_inline float
     432             : blend_hard_light (float sa, float s, float da, float d)
     433             : {
     434           0 :     if (2 * s < sa)
     435           0 :         return 2 * s * d;
     436             :     else
     437           0 :         return sa * da - 2 * (da - d) * (sa - s);
     438             : }
     439             : 
     440             : static force_inline float
     441             : blend_soft_light (float sa, float s, float da, float d)
     442             : {
     443           0 :     if (2 * s < sa)
     444             :     {
     445           0 :         if (IS_ZERO (da))
     446           0 :             return d * sa;
     447             :         else
     448           0 :             return d * sa - d * (da - d) * (sa - 2 * s) / da;
     449             :     }
     450             :     else
     451             :     {
     452           0 :         if (IS_ZERO (da))
     453             :         {
     454           0 :             return 0.0f;
     455             :         }
     456             :         else
     457             :         {
     458           0 :             if (4 * d <= da)
     459           0 :                 return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
     460             :             else
     461           0 :                 return d * sa + (sqrtf (d * da) - d) * (2 * s - sa);
     462             :         }
     463             :     }
     464             : }
     465             : 
     466             : static force_inline float
     467             : blend_difference (float sa, float s, float da, float d)
     468             : {
     469           0 :     float dsa = d * sa;
     470           0 :     float sda = s * da;
     471             : 
     472           0 :     if (sda < dsa)
     473           0 :         return dsa - sda;
     474             :     else
     475           0 :         return sda - dsa;
     476             : }
     477             : 
     478             : static force_inline float
     479             : blend_exclusion (float sa, float s, float da, float d)
     480             : {
     481           0 :     return s * da + d * sa - 2 * d * s;
     482             : }
     483             : 
     484           0 : MAKE_SEPARABLE_PDF_COMBINERS (multiply)
     485           0 : MAKE_SEPARABLE_PDF_COMBINERS (screen)
     486           0 : MAKE_SEPARABLE_PDF_COMBINERS (overlay)
     487           0 : MAKE_SEPARABLE_PDF_COMBINERS (darken)
     488           0 : MAKE_SEPARABLE_PDF_COMBINERS (lighten)
     489           0 : MAKE_SEPARABLE_PDF_COMBINERS (color_dodge)
     490           0 : MAKE_SEPARABLE_PDF_COMBINERS (color_burn)
     491           0 : MAKE_SEPARABLE_PDF_COMBINERS (hard_light)
     492           0 : MAKE_SEPARABLE_PDF_COMBINERS (soft_light)
     493           0 : MAKE_SEPARABLE_PDF_COMBINERS (difference)
     494           0 : MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
     495             : 
     496             : /*
     497             :  * PDF nonseperable blend modes.
     498             :  *
     499             :  * These are implemented using the following functions to operate in Hsl
     500             :  * space, with Cmax, Cmid, Cmin referring to the max, mid and min value
     501             :  * of the red, green and blue components.
     502             :  *
     503             :  * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
     504             :  *
     505             :  * clip_color (C):
     506             :  *   l = LUM (C)
     507             :  *   min = Cmin
     508             :  *   max = Cmax
     509             :  *   if n < 0.0
     510             :  *     C = l + (((C – l) × l) ⁄     (l – min))
     511             :  *   if x > 1.0
     512             :  *     C = l + (((C – l) × (1 – l)) (max – l))
     513             :  *   return C
     514             :  *
     515             :  * set_lum (C, l):
     516             :  *   d = l – LUM (C)
     517             :  *   C += d
     518             :  *   return clip_color (C)
     519             :  *
     520             :  * SAT (C) = CH_MAX (C) - CH_MIN (C)
     521             :  *
     522             :  * set_sat (C, s):
     523             :  *  if Cmax > Cmin
     524             :  *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
     525             :  *    Cmax = s
     526             :  *  else
     527             :  *    Cmid = Cmax = 0.0
     528             :  *  Cmin = 0.0
     529             :  *  return C
     530             :  */
     531             : 
     532             : /* For premultiplied colors, we need to know what happens when C is
     533             :  * multiplied by a real number. LUM and SAT are linear:
     534             :  *
     535             :  *    LUM (r × C) = r × LUM (C)               SAT (r × C) = r × SAT (C)
     536             :  *
     537             :  * If we extend clip_color with an extra argument a and change
     538             :  *
     539             :  *        if x >= 1.0
     540             :  *
     541             :  * into
     542             :  *
     543             :  *        if x >= a
     544             :  *
     545             :  * then clip_color is also linear:
     546             :  *
     547             :  *     r * clip_color (C, a) = clip_color (r_c, ra);
     548             :  *
     549             :  * for positive r.
     550             :  *
     551             :  * Similarly, we can extend set_lum with an extra argument that is just passed
     552             :  * on to clip_color:
     553             :  *
     554             :  *     r × set_lum ( C, l, a)
     555             :  *
     556             :  *   = r × clip_color ( C + l - LUM (C), a)
     557             :  *
     558             :  *   = clip_color ( r * C + r × l - LUM (r × C), r * a)
     559             :  *
     560             :  *   = set_lum ( r * C, r * l, r * a)
     561             :  *
     562             :  * Finally, set_sat:
     563             :  *
     564             :  *     r * set_sat (C, s) = set_sat (x * C, r * s)
     565             :  *
     566             :  * The above holds for all non-zero x because they x'es in the fraction for
     567             :  * C_mid cancel out. Specifically, it holds for x = r:
     568             :  *
     569             :  *     r * set_sat (C, s) = set_sat (r_c, rs)
     570             :  *
     571             :  *
     572             :  *
     573             :  *
     574             :  * So, for the non-separable PDF blend modes, we have (using s, d for
     575             :  * non-premultiplied colors, and S, D for premultiplied:
     576             :  *
     577             :  *   Color:
     578             :  *
     579             :  *     a_s * a_d * B(s, d)
     580             :  *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
     581             :  *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
     582             :  *
     583             :  *
     584             :  *   Luminosity:
     585             :  *
     586             :  *     a_s * a_d * B(s, d)
     587             :  *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
     588             :  *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
     589             :  *
     590             :  *
     591             :  *   Saturation:
     592             :  *
     593             :  *     a_s * a_d * B(s, d)
     594             :  *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
     595             :  *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
     596             :  *                                        a_s * LUM (D), a_s * a_d)
     597             :  *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
     598             :  *
     599             :  *   Hue:
     600             :  *
     601             :  *     a_s * a_d * B(s, d)
     602             :  *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
     603             :  *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
     604             :  *
     605             :  */
     606             : 
     607             : typedef struct
     608             : {
     609             :     float       r;
     610             :     float       g;
     611             :     float       b;
     612             : } rgb_t;
     613             : 
     614             : static force_inline float
     615             : minf (float a, float b)
     616             : {
     617           0 :     return a < b? a : b;
     618             : }
     619             : 
     620             : static force_inline float
     621             : maxf (float a, float b)
     622             : {
     623           0 :     return a > b? a : b;
     624             : }
     625             : 
     626             : static force_inline float
     627             : channel_min (const rgb_t *c)
     628             : {
     629           0 :     return minf (minf (c->r, c->g), c->b);
     630             : }
     631             : 
     632             : static force_inline float
     633             : channel_max (const rgb_t *c)
     634             : {
     635           0 :     return maxf (maxf (c->r, c->g), c->b);
     636             : }
     637             : 
     638             : static force_inline float
     639             : get_lum (const rgb_t *c)
     640             : {
     641           0 :     return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f;
     642             : }
     643             : 
     644             : static force_inline float
     645             : get_sat (const rgb_t *c)
     646             : {
     647           0 :     return channel_max (c) - channel_min (c);
     648             : }
     649             : 
     650             : static void
     651           0 : clip_color (rgb_t *color, float a)
     652             : {
     653           0 :     float l = get_lum (color);
     654           0 :     float n = channel_min (color);
     655           0 :     float x = channel_max (color);
     656             :     float t;
     657             : 
     658           0 :     if (n < 0.0f)
     659             :     {
     660           0 :         t = l - n;
     661           0 :         if (IS_ZERO (t))
     662             :         {
     663           0 :             color->r = 0.0f;
     664           0 :             color->g = 0.0f;
     665           0 :             color->b = 0.0f;
     666             :         }
     667             :         else
     668             :         {
     669           0 :             color->r = l + (((color->r - l) * l) / t);
     670           0 :             color->g = l + (((color->g - l) * l) / t);
     671           0 :             color->b = l + (((color->b - l) * l) / t);
     672             :         }
     673             :     }
     674           0 :     if (x > a)
     675             :     {
     676           0 :         t = x - l;
     677           0 :         if (IS_ZERO (t))
     678             :         {
     679           0 :             color->r = a;
     680           0 :             color->g = a;
     681           0 :             color->b = a;
     682             :         }
     683             :         else
     684             :         {
     685           0 :             color->r = l + (((color->r - l) * (a - l) / t));
     686           0 :             color->g = l + (((color->g - l) * (a - l) / t));
     687           0 :             color->b = l + (((color->b - l) * (a - l) / t));
     688             :         }
     689             :     }
     690           0 : }
     691             : 
     692             : static void
     693           0 : set_lum (rgb_t *color, float sa, float l)
     694             : {
     695           0 :     float d = l - get_lum (color);
     696             : 
     697           0 :     color->r = color->r + d;
     698           0 :     color->g = color->g + d;
     699           0 :     color->b = color->b + d;
     700             : 
     701           0 :     clip_color (color, sa);
     702           0 : }
     703             : 
     704             : static void
     705           0 : set_sat (rgb_t *src, float sat)
     706             : {
     707             :     float *max, *mid, *min;
     708             :     float t;
     709             : 
     710           0 :     if (src->r > src->g)
     711             :     {
     712           0 :         if (src->r > src->b)
     713             :         {
     714           0 :             max = &(src->r);
     715             : 
     716           0 :             if (src->g > src->b)
     717             :             {
     718           0 :                 mid = &(src->g);
     719           0 :                 min = &(src->b);
     720             :             }
     721             :             else
     722             :             {
     723           0 :                 mid = &(src->b);
     724           0 :                 min = &(src->g);
     725             :             }
     726             :         }
     727             :         else
     728             :         {
     729           0 :             max = &(src->b);
     730           0 :             mid = &(src->r);
     731           0 :             min = &(src->g);
     732             :         }
     733             :     }
     734             :     else
     735             :     {
     736           0 :         if (src->r > src->b)
     737             :         {
     738           0 :             max = &(src->g);
     739           0 :             mid = &(src->r);
     740           0 :             min = &(src->b);
     741             :         }
     742             :         else
     743             :         {
     744           0 :             min = &(src->r);
     745             : 
     746           0 :             if (src->g > src->b)
     747             :             {
     748           0 :                 max = &(src->g);
     749           0 :                 mid = &(src->b);
     750             :             }
     751             :             else
     752             :             {
     753           0 :                 max = &(src->b);
     754           0 :                 mid = &(src->g);
     755             :             }
     756             :         }
     757             :     }
     758             : 
     759           0 :     t = *max - *min;
     760             : 
     761           0 :     if (IS_ZERO (t))
     762             :     {
     763           0 :         *mid = *max = 0.0f;
     764             :     }
     765             :     else
     766             :     {
     767           0 :         *mid = ((*mid - *min) * sat) / t;
     768           0 :         *max = sat;
     769             :     }
     770             : 
     771           0 :     *min = 0.0f;
     772           0 : }
     773             : 
     774             : /*
     775             :  * Hue:
     776             :  * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
     777             :  */
     778             : static force_inline void
     779             : blend_hsl_hue (rgb_t *res,
     780             :                const rgb_t *dest, float da,
     781             :                const rgb_t *src, float sa)
     782             : {
     783           0 :     res->r = src->r * da;
     784           0 :     res->g = src->g * da;
     785           0 :     res->b = src->b * da;
     786             : 
     787           0 :     set_sat (res, get_sat (dest) * sa);
     788           0 :     set_lum (res, sa * da, get_lum (dest) * sa);
     789             : }
     790             : 
     791             : /*
     792             :  * Saturation:
     793             :  * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
     794             :  */
     795             : static force_inline void
     796             : blend_hsl_saturation (rgb_t *res,
     797             :                       const rgb_t *dest, float da,
     798             :                       const rgb_t *src, float sa)
     799             : {
     800           0 :     res->r = dest->r * sa;
     801           0 :     res->g = dest->g * sa;
     802           0 :     res->b = dest->b * sa;
     803             : 
     804           0 :     set_sat (res, get_sat (src) * da);
     805           0 :     set_lum (res, sa * da, get_lum (dest) * sa);
     806             : }
     807             : 
     808             : /*
     809             :  * Color:
     810             :  * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
     811             :  */
     812             : static force_inline void
     813             : blend_hsl_color (rgb_t *res,
     814             :                  const rgb_t *dest, float da,
     815             :                  const rgb_t *src, float sa)
     816             : {
     817           0 :     res->r = src->r * da;
     818           0 :     res->g = src->g * da;
     819           0 :     res->b = src->b * da;
     820             : 
     821           0 :     set_lum (res, sa * da, get_lum (dest) * sa);
     822             : }
     823             : 
     824             : /*
     825             :  * Luminosity:
     826             :  * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
     827             :  */
     828             : static force_inline void
     829             : blend_hsl_luminosity (rgb_t *res,
     830             :                       const rgb_t *dest, float da,
     831             :                       const rgb_t *src, float sa)
     832             : {
     833           0 :     res->r = dest->r * sa;
     834           0 :     res->g = dest->g * sa;
     835           0 :     res->b = dest->b * sa;
     836             : 
     837           0 :     set_lum (res, sa * da, get_lum (src) * da);
     838             : }
     839             : 
     840             : #define MAKE_NON_SEPARABLE_PDF_COMBINERS(name)                          \
     841             :     static void                                                         \
     842             :     combine_ ## name ## _u_float (pixman_implementation_t *imp,         \
     843             :                                   pixman_op_t              op,          \
     844             :                                   float                   *dest,        \
     845             :                                   const float             *src,         \
     846             :                                   const float             *mask,        \
     847             :                                   int                      n_pixels)    \
     848             :     {                                                                   \
     849             :         int i;                                                          \
     850             :                                                                         \
     851             :         for (i = 0; i < 4 * n_pixels; i += 4)                                \
     852             :         {                                                               \
     853             :             float sa, da;                                               \
     854             :             rgb_t sc, dc, rc;                                           \
     855             :                                                                         \
     856             :             sa = src[i + 0];                                            \
     857             :             sc.r = src[i + 1];                                          \
     858             :             sc.g = src[i + 2];                                          \
     859             :             sc.b = src[i + 3];                                          \
     860             :                                                                         \
     861             :             da = dest[i + 0];                                           \
     862             :             dc.r = dest[i + 1];                                         \
     863             :             dc.g = dest[i + 2];                                         \
     864             :             dc.b = dest[i + 3];                                         \
     865             :                                                                         \
     866             :             if (mask)                                                   \
     867             :             {                                                           \
     868             :                 float ma = mask[i + 0];                                 \
     869             :                                                                         \
     870             :                 /* Component alpha is not supported for HSL modes */    \
     871             :                 sa *= ma;                                               \
     872             :                 sc.r *= ma;                                             \
     873             :                 sc.g *= ma;                                             \
     874             :                 sc.g *= ma;                                             \
     875             :             }                                                           \
     876             :                                                                         \
     877             :             blend_ ## name (&rc, &dc, da, &sc, sa);                 \
     878             :                                                                         \
     879             :             dest[i + 0] = sa + da - sa * da;                            \
     880             :             dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r;     \
     881             :             dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g;     \
     882             :             dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b;     \
     883             :         }                                                               \
     884             :     }
     885             : 
     886           0 : MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue)
     887           0 : MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation)
     888           0 : MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color)
     889           0 : MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity)
     890             : 
     891             : void
     892           1 : _pixman_setup_combiner_functions_float (pixman_implementation_t *imp)
     893             : {
     894             :     /* Unified alpha */
     895           1 :     imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float;
     896           1 :     imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float;
     897           1 :     imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float;
     898           1 :     imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float;
     899           1 :     imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float;
     900           1 :     imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float;
     901           1 :     imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float;
     902           1 :     imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float;
     903           1 :     imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float;
     904           1 :     imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float;
     905           1 :     imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float;
     906           1 :     imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float;
     907           1 :     imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float;
     908           1 :     imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float;
     909             : 
     910             :     /* Disjoint, unified */
     911           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float;
     912           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float;
     913           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float;
     914           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float;
     915           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float;
     916           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float;
     917           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float;
     918           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float;
     919           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float;
     920           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float;
     921           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float;
     922           1 :     imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float;
     923             : 
     924             :     /* Conjoint, unified */
     925           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float;
     926           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float;
     927           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float;
     928           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float;
     929           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float;
     930           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float;
     931           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float;
     932           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float;
     933           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float;
     934           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float;
     935           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float;
     936           1 :     imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float;
     937             : 
     938             :     /* PDF operators, unified */
     939           1 :     imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float;
     940           1 :     imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float;
     941           1 :     imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float;
     942           1 :     imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float;
     943           1 :     imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float;
     944           1 :     imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float;
     945           1 :     imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float;
     946           1 :     imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float;
     947           1 :     imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float;
     948           1 :     imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float;
     949           1 :     imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float;
     950             : 
     951           1 :     imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float;
     952           1 :     imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float;
     953           1 :     imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float;
     954           1 :     imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float;
     955             : 
     956             :     /* Component alpha combiners */
     957           1 :     imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float;
     958           1 :     imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float;
     959           1 :     imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float;
     960           1 :     imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float;
     961           1 :     imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float;
     962           1 :     imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float;
     963           1 :     imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float;
     964           1 :     imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float;
     965           1 :     imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float;
     966           1 :     imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float;
     967           1 :     imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float;
     968           1 :     imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float;
     969           1 :     imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float;
     970           1 :     imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float;
     971             : 
     972             :     /* Disjoint CA */
     973           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float;
     974           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float;
     975           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float;
     976           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float;
     977           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float;
     978           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float;
     979           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float;
     980           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float;
     981           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float;
     982           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float;
     983           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float;
     984           1 :     imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float;
     985             : 
     986             :     /* Conjoint CA */
     987           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float;
     988           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float;
     989           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float;
     990           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float;
     991           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float;
     992           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float;
     993           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float;
     994           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float;
     995           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float;
     996           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float;
     997           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float;
     998           1 :     imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float;
     999             : 
    1000             :     /* PDF operators CA */
    1001           1 :     imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float;
    1002           1 :     imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float;
    1003           1 :     imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float;
    1004           1 :     imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float;
    1005           1 :     imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float;
    1006           1 :     imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float;
    1007           1 :     imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float;
    1008           1 :     imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float;
    1009           1 :     imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float;
    1010           1 :     imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float;
    1011           1 :     imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float;
    1012             : 
    1013             :     /* It is not clear that these make sense, so make them noops for now */
    1014           1 :     imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float;
    1015           1 :     imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float;
    1016           1 :     imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float;
    1017           1 :     imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float;
    1018           1 : }

Generated by: LCOV version 1.13