aboutsummaryrefslogtreecommitdiff
path: root/pixman/pixman/pixman-combine32.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman/pixman-combine32.c')
-rw-r--r--pixman/pixman/pixman-combine32.c671
1 files changed, 374 insertions, 297 deletions
diff --git a/pixman/pixman/pixman-combine32.c b/pixman/pixman/pixman-combine32.c
index 3ac7576bd..450114a52 100644
--- a/pixman/pixman/pixman-combine32.c
+++ b/pixman/pixman/pixman-combine32.c
@@ -142,12 +142,12 @@ combine_mask (const uint32_t *src, const uint32_t *mask, int i)
static void
combine_clear (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
- memset (dest, 0, width * sizeof(uint32_t));
+ memset (dest, 0, width * sizeof (uint32_t));
}
static void
@@ -155,7 +155,7 @@ combine_dst (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
- const uint32_t * mask,
+ const uint32_t * mask,
int width)
{
return;
@@ -164,9 +164,9 @@ combine_dst (pixman_implementation_t *imp,
static void
combine_src_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -189,9 +189,9 @@ combine_src_u (pixman_implementation_t *imp,
static void
combine_over_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -254,9 +254,9 @@ combine_over_u (pixman_implementation_t *imp,
static void
combine_over_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -274,9 +274,9 @@ combine_over_reverse_u (pixman_implementation_t *imp,
static void
combine_in_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -293,9 +293,9 @@ combine_in_u (pixman_implementation_t *imp,
static void
combine_in_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -313,9 +313,9 @@ combine_in_reverse_u (pixman_implementation_t *imp,
static void
combine_out_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -332,9 +332,9 @@ combine_out_u (pixman_implementation_t *imp,
static void
combine_out_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -352,9 +352,9 @@ combine_out_reverse_u (pixman_implementation_t *imp,
static void
combine_atop_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -374,9 +374,9 @@ combine_atop_u (pixman_implementation_t *imp,
static void
combine_atop_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -396,9 +396,9 @@ combine_atop_reverse_u (pixman_implementation_t *imp,
static void
combine_xor_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -418,9 +418,9 @@ combine_xor_u (pixman_implementation_t *imp,
static void
combine_add_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -437,9 +437,9 @@ combine_add_u (pixman_implementation_t *imp,
static void
combine_saturate_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -463,39 +463,66 @@ combine_saturate_u (pixman_implementation_t *imp,
}
}
+
/*
* PDF blend modes:
+ *
* The following blend modes have been taken from the PDF ISO 32000
* specification, which at this point in time is available from
- * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
- * The relevant chapters are 11.3.5 and 11.3.6.
+ *
+ * http://www.adobe.com/devnet/pdf/pdf_reference.html
+ *
+ * The specific documents of interest are the PDF spec itself:
+ *
+ * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
+ *
+ * chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat
+ * 9.1 and Reader 9.1:
+ *
+ * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf
+ *
+ * that clarifies the specifications for blend modes ColorDodge and
+ * ColorBurn.
+ *
* The formula for computing the final pixel color given in 11.3.6 is:
- * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
- * with B() being the blend function.
- * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
- *
- * These blend modes should match the SVG filter draft specification, as
- * it has been designed to mirror ISO 32000. Note that at the current point
- * no released draft exists that shows this, as the formulas have not been
- * updated yet after the release of ISO 32000.
- *
- * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
- * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
- * argument. Note that this implementation operates on premultiplied colors,
- * while the PDF specification does not. Therefore the code uses the formula
- * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
+ *
+ * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
+ *
+ * with B() is the blend function. When B(Cb, Cs) = Cs, this formula
+ * reduces to the regular OVER operator.
+ *
+ * Cs and Cb are not premultiplied, so in our implementation we instead
+ * use:
+ *
+ * cr = (1 – αs) × cb + (1 – αb) × cs + αb × αs × B (cb/αb, cs/αs)
+ *
+ * where cr, cs, and cb are premultiplied colors, and where the
+ *
+ * αb × αs × B(cb/αb, cs/αs)
+ *
+ * part is first arithmetically simplified under the assumption that αb
+ * and αs are not 0, and then updated to produce a meaningful result when
+ * they are.
+ *
+ * For all the blend mode operators, the alpha channel is given by
+ *
+ * αr = αs + αb + αb × αs
*/
/*
* Multiply
- * B(Dca, ad, Sca, as) = Dca.Sca
+ *
+ * ad * as * B(d / ad, s / as)
+ * = ad * as * d/ad * s/as
+ * = d * s
+ *
*/
static void
combine_multiply_u (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -519,9 +546,9 @@ combine_multiply_u (pixman_implementation_t *imp,
static void
combine_multiply_ca (pixman_implementation_t *imp,
pixman_op_t op,
- uint32_t * dest,
- const uint32_t * src,
- const uint32_t * mask,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
int width)
{
int i;
@@ -548,13 +575,14 @@ combine_multiply_ca (pixman_implementation_t *imp,
static void \
combine_ ## name ## _u (pixman_implementation_t *imp, \
pixman_op_t op, \
- uint32_t * dest, \
- const uint32_t * src, \
- const uint32_t * mask, \
+ uint32_t * dest, \
+ const uint32_t * src, \
+ const uint32_t * mask, \
int width) \
{ \
int i; \
- for (i = 0; i < width; ++i) { \
+ for (i = 0; i < width; ++i) \
+ { \
uint32_t s = combine_mask (src, mask, i); \
uint32_t d = *(dest + i); \
uint8_t sa = ALPHA_8 (s); \
@@ -577,13 +605,14 @@ combine_multiply_ca (pixman_implementation_t *imp,
static void \
combine_ ## name ## _ca (pixman_implementation_t *imp, \
pixman_op_t op, \
- uint32_t * dest, \
- const uint32_t * src, \
- const uint32_t * mask, \
- int width) \
+ uint32_t * dest, \
+ const uint32_t * src, \
+ const uint32_t * mask, \
+ int width) \
{ \
int i; \
- for (i = 0; i < width; ++i) { \
+ for (i = 0; i < width; ++i) \
+ { \
uint32_t m = *(mask + i); \
uint32_t s = *(src + i); \
uint32_t d = *(dest + i); \
@@ -608,49 +637,69 @@ combine_multiply_ca (pixman_implementation_t *imp,
/*
* Screen
- * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
+ *
+ * ad * as * B(d/ad, s/as)
+ * = ad * as * (d/ad + s/as - s/as * d/ad)
+ * = ad * s + as * d - s * d
*/
static inline uint32_t
-blend_screen (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_screen (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- return DIV_ONE_UN8 (sca * da + dca * sa - sca * dca);
+ return DIV_ONE_UN8 (s * ad + d * as - s * d);
}
PDF_SEPARABLE_BLEND_MODE (screen)
/*
* Overlay
- * B(Dca, Da, Sca, Sa) =
- * if 2.Dca < Da
- * 2.Sca.Dca
- * otherwise
- * Sa.Da - 2.(Da - Dca).(Sa - Sca)
+ *
+ * ad * as * B(d/ad, s/as)
+ * = ad * as * Hardlight (s, d)
+ * = if (d / ad < 0.5)
+ * as * ad * Multiply (s/as, 2 * d/ad)
+ * else
+ * as * ad * Screen (s/as, 2 * d / ad - 1)
+ * = if (d < 0.5 * ad)
+ * as * ad * s/as * 2 * d /ad
+ * else
+ * as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1))
+ * = if (2 * d < ad)
+ * 2 * s * d
+ * else
+ * ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1)
+ * = if (2 * d < ad)
+ * 2 * s * d
+ * else
+ * as * ad - 2 * (ad - d) * (as - s)
*/
static inline uint32_t
-blend_overlay (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_overlay (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- uint32_t rca;
+ uint32_t r;
- if (2 * dca < da)
- rca = 2 * sca * dca;
+ if (2 * d < ad)
+ r = 2 * s * d;
else
- rca = sa * da - 2 * (da - dca) * (sa - sca);
- return DIV_ONE_UN8 (rca);
+ r = as * ad - 2 * (ad - d) * (as - s);
+
+ return DIV_ONE_UN8 (r);
}
PDF_SEPARABLE_BLEND_MODE (overlay)
/*
* Darken
- * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
+ *
+ * ad * as * B(d/ad, s/as)
+ * = ad * as * MIN(d/ad, s/as)
+ * = MIN (as * d, ad * s)
*/
static inline uint32_t
-blend_darken (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_darken (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- uint32_t s, d;
+ s = ad * s;
+ d = as * d;
- s = sca * da;
- d = dca * sa;
return DIV_ONE_UN8 (s > d ? d : s);
}
@@ -658,15 +707,17 @@ PDF_SEPARABLE_BLEND_MODE (darken)
/*
* Lighten
- * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
+ *
+ * ad * as * B(d/ad, s/as)
+ * = ad * as * MAX(d/ad, s/as)
+ * = MAX (as * d, ad * s)
*/
static inline uint32_t
-blend_lighten (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_lighten (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- uint32_t s, d;
-
- s = sca * da;
- d = dca * sa;
+ s = ad * s;
+ d = as * d;
+
return DIV_ONE_UN8 (s > d ? s : d);
}
@@ -674,152 +725,197 @@ PDF_SEPARABLE_BLEND_MODE (lighten)
/*
* Color dodge
- * B(Dca, Da, Sca, Sa) =
- * if Dca == 0
- * 0
- * if Sca == Sa
- * Sa.Da
- * otherwise
- * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
+ *
+ * ad * as * B(d/ad, s/as)
+ * = if d/ad = 0
+ * ad * as * 0
+ * else if (d/ad >= (1 - s/as)
+ * ad * as * 1
+ * else
+ * ad * as * ((d/ad) / (1 - s/as))
+ * = if d = 0
+ * 0
+ * elif as * d >= ad * (as - s)
+ * ad * as
+ * else
+ * as * (as * d / (as - s))
+ *
*/
static inline uint32_t
-blend_color_dodge (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
-{
- if (sca >= sa)
- {
- return dca == 0 ? 0 : DIV_ONE_UN8 (sa * da);
- }
+blend_color_dodge (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+{
+ if (d == 0)
+ return 0;
+ else if (as * d >= ad * (as - s))
+ return DIV_ONE_UN8 (as * ad);
+ else if (as - s == 0)
+ return DIV_ONE_UN8 (as * ad);
else
- {
- uint32_t rca = dca * sa / (sa - sca);
- return DIV_ONE_UN8 (sa * MIN (rca, da));
- }
+ return DIV_ONE_UN8 (as * ((d * as) / ((as - s))));
}
PDF_SEPARABLE_BLEND_MODE (color_dodge)
/*
* Color burn
- * B(Dca, Da, Sca, Sa) =
- * if Dca == Da
- * Sa.Da
- * if Sca == 0
- * 0
- * otherwise
- * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
+ *
+ * We modify the first clause "if d = 1" to "if d >= 1" since with
+ * premultiplied colors d > 1 can actually happen.
+ *
+ * ad * as * B(d/ad, s/as)
+ * = if d/ad >= 1
+ * ad * as * 1
+ * elif (1 - d/ad) >= s/as
+ * ad * as * 0
+ * else
+ * ad * as * (1 - ((1 - d/ad) / (s/as)))
+ * = if d >= ad
+ * ad * as
+ * elif as * ad - as * d >= ad * s
+ * 0
+ * else
+ * ad * as - as * as * (ad - d) / s
*/
static inline uint32_t
-blend_color_burn (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
-{
- if (sca == 0)
- {
- return dca < da ? 0 : DIV_ONE_UN8 (sa * da);
- }
+blend_color_burn (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+{
+ if (d >= ad)
+ return DIV_ONE_UN8 (ad * as);
+ else if (as * ad - as * d >= ad * s)
+ return 0;
+ else if (s == 0)
+ return 0;
else
- {
- uint32_t rca = (da - dca) * sa / sca;
- return DIV_ONE_UN8 (sa * (MAX (rca, da) - rca));
- }
+ return DIV_ONE_UN8 (ad * as - (as * as * (ad - d)) / s);
}
PDF_SEPARABLE_BLEND_MODE (color_burn)
/*
* Hard light
- * B(Dca, Da, Sca, Sa) =
- * if 2.Sca < Sa
- * 2.Sca.Dca
- * otherwise
- * Sa.Da - 2.(Da - Dca).(Sa - Sca)
+ *
+ * ad * as * B(d/ad, s/as)
+ * = if (s/as <= 0.5)
+ * ad * as * Multiply (d/ad, 2 * s/as)
+ * else
+ * ad * as * Screen (d/ad, 2 * s/as - 1)
+ * = if 2 * s <= as
+ * ad * as * d/ad * 2 * s / as
+ * else
+ * ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1))
+ * = if 2 * s <= as
+ * 2 * s * d
+ * else
+ * as * ad - 2 * (ad - d) * (as - s)
*/
static inline uint32_t
-blend_hard_light (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_hard_light (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- if (2 * sca < sa)
- return DIV_ONE_UN8 (2 * sca * dca);
+ if (2 * s < as)
+ return DIV_ONE_UN8 (2 * s * d);
else
- return DIV_ONE_UN8 (sa * da - 2 * (da - dca) * (sa - sca));
+ return DIV_ONE_UN8 (as * ad - 2 * (ad - d) * (as - s));
}
PDF_SEPARABLE_BLEND_MODE (hard_light)
/*
* Soft light
- * B(Dca, Da, Sca, Sa) =
- * if (2.Sca <= Sa)
- * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
- * otherwise if Dca.4 <= Da
- * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
- * otherwise
- * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
+ *
+ * ad * as * B(d/ad, s/as)
+ * = if (s/as <= 0.5)
+ * ad * as * (d/ad - (1 - 2 * s/as) * d/ad * (1 - d/ad))
+ * else if (d/ad <= 0.25)
+ * ad * as * (d/ad + (2 * s/as - 1) * ((((16 * d/ad - 12) * d/ad + 4) * d/ad) - d/ad))
+ * else
+ * ad * as * (d/ad + (2 * s/as - 1) * sqrt (d/ad))
+ * = if (2 * s <= as)
+ * d * as - d * (ad - d) * (as - 2 * s) / ad;
+ * else if (4 * d <= ad)
+ * (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
+ * else
+ * d * as + (sqrt (d * ad) - d) * (2 * s - as);
*/
static inline uint32_t
-blend_soft_light (uint32_t dca_org,
- uint32_t da_org,
- uint32_t sca_org,
- uint32_t sa_org)
-{
- double dca = dca_org * (1.0 / MASK);
- double da = da_org * (1.0 / MASK);
- double sca = sca_org * (1.0 / MASK);
- double sa = sa_org * (1.0 / MASK);
- double rca;
-
- if (2 * sca < sa)
+blend_soft_light (uint32_t d_org,
+ uint32_t ad_org,
+ uint32_t s_org,
+ uint32_t as_org)
+{
+ double d = d_org * (1.0 / MASK);
+ double ad = ad_org * (1.0 / MASK);
+ double s = s_org * (1.0 / MASK);
+ double as = as_org * (1.0 / MASK);
+ double r;
+
+ if (2 * s < as)
{
- if (da == 0)
- rca = dca * sa;
+ if (ad == 0)
+ r = d * as;
else
- rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
+ r = d * as - d * (ad - d) * (as - 2 * s) / ad;
}
- else if (da == 0)
+ else if (ad == 0)
{
- rca = 0;
+ r = 0;
}
- else if (4 * dca <= da)
+ else if (4 * d <= ad)
{
- rca = dca * sa +
- (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
+ r = d * as +
+ (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
}
else
{
- rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
+ r = d * as + (sqrt (d * ad) - d) * (2 * s - as);
}
- return rca * MASK + 0.5;
+ return r * MASK + 0.5;
}
PDF_SEPARABLE_BLEND_MODE (soft_light)
/*
* Difference
- * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
+ *
+ * ad * as * B(s/as, d/ad)
+ * = ad * as * abs (s/as - d/ad)
+ * = if (s/as <= d/ad)
+ * ad * as * (d/ad - s/as)
+ * else
+ * ad * as * (s/as - d/ad)
+ * = if (ad * s <= as * d)
+ * as * d - ad * s
+ * else
+ * ad * s - as * d
*/
static inline uint32_t
-blend_difference (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_difference (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- uint32_t dcasa = dca * sa;
- uint32_t scada = sca * da;
+ uint32_t das = d * as;
+ uint32_t sad = s * ad;
- if (scada < dcasa)
- return DIV_ONE_UN8 (dcasa - scada);
+ if (sad < das)
+ return DIV_ONE_UN8 (das - sad);
else
- return DIV_ONE_UN8 (scada - dcasa);
+ return DIV_ONE_UN8 (sad - das);
}
PDF_SEPARABLE_BLEND_MODE (difference)
/*
* Exclusion
- * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
+ *
+ * ad * as * B(s/as, d/ad)
+ * = ad * as * (d/ad + s/as - 2 * d/ad * s/as)
+ * = as * d + ad * s - 2 * s * d
*/
/* This can be made faster by writing it directly and not using
* PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
static inline uint32_t
-blend_exclusion (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
+blend_exclusion (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
{
- return DIV_ONE_UN8 (sca * da + dca * sa - 2 * dca * sca);
+ return DIV_ONE_UN8 (s * ad + d * as - 2 * d * s);
}
PDF_SEPARABLE_BLEND_MODE (exclusion)
@@ -834,103 +930,70 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
* LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
*
* clip_color (C):
- * l = LUM (C)
- * min = Cmin
- * max = Cmax
- * if n < 0.0
- * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) )
- * if x > 1.0
- * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
- * return C
+ * l = LUM (C)
+ * min = Cmin
+ * max = Cmax
+ * if n < 0.0
+ * C = l + (((C – l) × l) ⁄ (l – min))
+ * if x > 1.0
+ * C = l + (((C – l) × (1 – l) ) ⁄ (max – l))
+ * return C
*
* set_lum (C, l):
- * d = l – LUM (C)
- * C += d
- * return clip_color (C)
+ * d = l – LUM (C)
+ * C += d
+ * return clip_color (C)
*
* SAT (C) = CH_MAX (C) - CH_MIN (C)
*
* set_sat (C, s):
- * if Cmax > Cmin
- * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
- * Cmax = s
- * else
- * Cmid = Cmax = 0.0
- * Cmin = 0.0
- * return C
+ * if Cmax > Cmin
+ * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
+ * Cmax = s
+ * else
+ * Cmid = Cmax = 0.0
+ * Cmin = 0.0
+ * return C
*/
/* For premultiplied colors, we need to know what happens when C is
* multiplied by a real number. LUM and SAT are linear:
*
- * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
+ * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
*
* If we extend clip_color with an extra argument a and change
*
- * if x >= 1.0
+ * if x >= 1.0
*
* into
*
- * if x >= a
+ * if x >= a
*
* then clip_color is also linear:
*
- * r * clip_color (C, a) = clip_color (r_c, ra);
+ * r * clip_color (C, a) = clip_color (r * C, r * a);
*
* for positive r.
*
* Similarly, we can extend set_lum with an extra argument that is just passed
* on to clip_color:
*
- * r * set_lum ( C, l, a)
+ * r * set_lum (C, l, a)
*
- * = r × clip_color ( C + l - LUM (C), a)
+ * = r × clip_color (C + l - LUM (C), a)
*
- * = clip_color ( r * C + r × l - r * LUM (C), r * a)
+ * = clip_color (r * C + r × l - r * LUM (C), r * a)
*
- * = set_lum ( r * C, r * l, r * a)
+ * = set_lum (r * C, r * l, r * a)
*
* Finally, set_sat:
*
- * r * set_sat (C, s) = set_sat (x * C, r * s)
+ * r * set_sat (C, s) = set_sat (x * C, r * s)
*
* The above holds for all non-zero x, because the x'es in the fraction for
* C_mid cancel out. Specifically, it holds for x = r:
*
- * r * set_sat (C, s) = set_sat (r_c, rs)
- *
- */
-
-/* So, for the non-separable PDF blend modes, we have (using s, d for
- * non-premultiplied colors, and S, D for premultiplied:
- *
- * Color:
- *
- * a_s * a_d * B(s, d)
- * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
- * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
- *
- *
- * Luminosity:
- *
- * a_s * a_d * B(s, d)
- * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
- * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
- *
- *
- * Saturation:
- *
- * a_s * a_d * B(s, d)
- * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
- * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
- * a_s * LUM (D), a_s * a_d)
- * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
- *
- * Hue:
- *
- * a_s * a_d * B(s, d)
- * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
- * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
+ * r * set_sat (C, s) = set_sat (r * C, r * s)
*
*/
@@ -942,11 +1005,11 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
#define PDF_NON_SEPARABLE_BLEND_MODE(name) \
static void \
combine_ ## name ## _u (pixman_implementation_t *imp, \
- pixman_op_t op, \
- uint32_t *dest, \
- const uint32_t *src, \
- const uint32_t *mask, \
- int width) \
+ pixman_op_t op, \
+ uint32_t * dest, \
+ const uint32_t * src, \
+ const uint32_t * mask, \
+ int width) \
{ \
int i; \
for (i = 0; i < width; ++i) \
@@ -958,7 +1021,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
uint8_t da = ALPHA_8 (d); \
uint8_t ida = ~da; \
uint32_t result; \
- uint32_t sc[3], dc[3], c[3]; \
+ uint32_t sc[3], dc[3], c[3]; \
\
result = d; \
UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \
@@ -1104,80 +1167,94 @@ set_sat (uint32_t dest[3], uint32_t src[3], uint32_t sat)
}
}
-/*
- * Hue:
- * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
+/* Hue:
+ *
+ * as * ad * B(s/as, d/as)
+ * = as * ad * set_lum (set_sat (s/as, SAT (d/ad)), LUM (d/ad), 1)
+ * = set_lum (set_sat (ad * s, as * SAT (d)), as * LUM (d), as * ad)
+ *
*/
static inline void
-blend_hsl_hue (uint32_t c[3],
- uint32_t dc[3],
- uint32_t da,
- uint32_t sc[3],
- uint32_t sa)
+blend_hsl_hue (uint32_t r[3],
+ uint32_t d[3],
+ uint32_t ad,
+ uint32_t s[3],
+ uint32_t as)
{
- c[0] = sc[0] * da;
- c[1] = sc[1] * da;
- c[2] = sc[2] * da;
- set_sat (c, c, SAT (dc) * sa);
- set_lum (c, c, sa * da, LUM (dc) * sa);
+ r[0] = s[0] * ad;
+ r[1] = s[1] * ad;
+ r[2] = s[2] * ad;
+ set_sat (r, r, SAT (d) * as);
+ set_lum (r, r, as * ad, LUM (d) * as);
}
PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
-/*
- * Saturation:
- * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
+/*
+ * Saturation
+ *
+ * as * ad * B(s/as, d/ad)
+ * = as * ad * set_lum (set_sat (d/ad, SAT (s/as)), LUM (d/ad), 1)
+ * = set_lum (as * ad * set_sat (d/ad, SAT (s/as)),
+ * as * LUM (d), as * ad)
+ * = set_lum (set_sat (as * d, ad * SAT (s), as * LUM (d), as * ad))
*/
static inline void
-blend_hsl_saturation (uint32_t c[3],
- uint32_t dc[3],
- uint32_t da,
- uint32_t sc[3],
- uint32_t sa)
+blend_hsl_saturation (uint32_t r[3],
+ uint32_t d[3],
+ uint32_t ad,
+ uint32_t s[3],
+ uint32_t as)
{
- c[0] = dc[0] * sa;
- c[1] = dc[1] * sa;
- c[2] = dc[2] * sa;
- set_sat (c, c, SAT (sc) * da);
- set_lum (c, c, sa * da, LUM (dc) * sa);
+ r[0] = d[0] * as;
+ r[1] = d[1] * as;
+ r[2] = d[2] * as;
+ set_sat (r, r, SAT (s) * ad);
+ set_lum (r, r, as * ad, LUM (d) * as);
}
PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
-/*
- * Color:
- * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
+/*
+ * Color
+ *
+ * as * ad * B(s/as, d/as)
+ * = as * ad * set_lum (s/as, LUM (d/ad), 1)
+ * = set_lum (s * ad, as * LUM (d), as * ad)
*/
static inline void
-blend_hsl_color (uint32_t c[3],
- uint32_t dc[3],
- uint32_t da,
- uint32_t sc[3],
- uint32_t sa)
+blend_hsl_color (uint32_t r[3],
+ uint32_t d[3],
+ uint32_t ad,
+ uint32_t s[3],
+ uint32_t as)
{
- c[0] = sc[0] * da;
- c[1] = sc[1] * da;
- c[2] = sc[2] * da;
- set_lum (c, c, sa * da, LUM (dc) * sa);
+ r[0] = s[0] * ad;
+ r[1] = s[1] * ad;
+ r[2] = s[2] * ad;
+ set_lum (r, r, as * ad, LUM (d) * as);
}
PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
/*
- * Luminosity:
- * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
+ * Luminosity
+ *
+ * as * ad * B(s/as, d/ad)
+ * = as * ad * set_lum (d/ad, LUM (s/as), 1)
+ * = set_lum (as * d, ad * LUM (s), as * ad)
*/
static inline void
-blend_hsl_luminosity (uint32_t c[3],
- uint32_t dc[3],
- uint32_t da,
- uint32_t sc[3],
- uint32_t sa)
+blend_hsl_luminosity (uint32_t r[3],
+ uint32_t d[3],
+ uint32_t ad,
+ uint32_t s[3],
+ uint32_t as)
{
- c[0] = dc[0] * sa;
- c[1] = dc[1] * sa;
- c[2] = dc[2] * sa;
- set_lum (c, c, sa * da, LUM (sc) * da);
+ r[0] = d[0] * as;
+ r[1] = d[1] * as;
+ r[2] = d[2] * as;
+ set_lum (r, r, as * ad, LUM (s) * ad);
}
PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
@@ -1194,7 +1271,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
* come from each of the four areas of the picture -- areas covered by neither
* A nor B, areas covered only by A, areas covered only by B and finally
* areas covered by both A and B.
- *
+ *
* Disjoint Conjoint
* Fa Fb Fa Fb
* (0,0,0,0) 0 0 0 0