Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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