Created
April 5, 2015 14:15
-
-
Save loentar/bb7ccdda021f33b63516 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/blending.hpp b/lib/blending.hpp | |
index d61c741..0c800ff 100644 | |
--- a/lib/blending.hpp | |
+++ b/lib/blending.hpp | |
@@ -107,6 +107,32 @@ class BufferCombineFunc <DSTALPHA, BUFSIZE, BlendNormal, CompositeDestinationOut | |
// Da' = Da × (1 - Sa) | |
+template <bool DSTALPHA, unsigned int BUFSIZE> | |
+class BufferCombineFunc <DSTALPHA, BUFSIZE, BlendNormal, CompositeDestinationAtop> | |
+{ | |
+ // Partial specialization for normal lainting layers, | |
+ // working in premultiplied alpha for speed. | |
+ public: | |
+ inline void operator() (const fix15_short_t * const src, | |
+ fix15_short_t * const dst, | |
+ const fix15_short_t opac) const | |
+ { | |
+ for (unsigned int i=0; i<BUFSIZE; i+=4) { | |
+ const fix15_t as = fix15_mul(src[i+3], opac); | |
+ const fix15_t one_minus_ab = fix15_one - dst[i+3]; | |
+ const fix15_t ab_mul_as = fix15_mul(dst[i+3], as); | |
+ const fix15_t as_mul_one_minus_ab = fix15_mul(as, one_minus_ab); | |
+ dst[i+0] = fix15_sumprods(src[i+0], as_mul_one_minus_ab, dst[i+0], ab_mul_as); | |
+ dst[i+1] = fix15_sumprods(src[i+1], as_mul_one_minus_ab, dst[i+1], ab_mul_as); | |
+ dst[i+2] = fix15_sumprods(src[i+2], as_mul_one_minus_ab, dst[i+2], ab_mul_as); | |
+ if (DSTALPHA) { | |
+ dst[i+3] = fix15_short_clamp(fix15_mul(as, one_minus_ab) + ab_mul_as); | |
+ } | |
+ } | |
+ } | |
+}; | |
+ | |
+ | |
// Multiply: http://www.w3.org/TR/compositing/#blendingmultiply | |
class BlendMultiply : public BlendFunc | |
diff --git a/lib/compositing.hpp b/lib/compositing.hpp | |
index 5d983f7..dc956f4 100644 | |
--- a/lib/compositing.hpp | |
+++ b/lib/compositing.hpp | |
@@ -269,6 +269,33 @@ class CompositeDestinationOut : public CompositeFunc | |
}; | |
+// Destination-Atop: Destination which overlaps the source replaces the source. | |
+// Source is placed elsewhere. | |
+// http://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop | |
+ | |
+class CompositeDestinationAtop : public CompositeFunc | |
+{ | |
+ public: | |
+ inline void operator() (const fix15_t Rs, const fix15_t Gs, | |
+ const fix15_t Bs, const fix15_t as, | |
+ fix15_short_t &rb, fix15_short_t &gb, | |
+ fix15_short_t &bb, fix15_short_t &ab) const | |
+ { | |
+ const fix15_t one_minus_ab = fix15_one - ab; | |
+ const fix15_t as_mul_one_minus_ab = fix15_mul(as, one_minus_ab); | |
+ const fix15_t ab_mul_as = fix15_mul(as, ab); | |
+ | |
+ rb = fix15_short_clamp(fix15_sumprods(as_mul_one_minus_ab, Rs, ab_mul_as, rb)); | |
+ gb = fix15_short_clamp(fix15_sumprods(as_mul_one_minus_ab, Gs, ab_mul_as, gb)); | |
+ bb = fix15_short_clamp(fix15_sumprods(as_mul_one_minus_ab, Bs, ab_mul_as, bb)); | |
+ ab = fix15_short_clamp(as_mul_one_minus_ab + ab_mul_as); | |
+ } | |
+ | |
+ static const bool zero_alpha_has_effect = true; | |
+ static const bool can_decrease_alpha = true; | |
+}; | |
+ | |
+ | |
// W3C "Lighter", a.k.a. Porter-Duff "plus", a.k.a. "svg:plus". This just adds | |
// together corresponding channels of the destination and source. | |
// Ref: http://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus | |
diff --git a/lib/layer/consts.py b/lib/layer/consts.py | |
index f50b95f..701db19 100644 | |
--- a/lib/layer/consts.py | |
+++ b/lib/layer/consts.py | |
@@ -113,6 +113,10 @@ MODE_STRINGS = { | |
_("Destination Out"), | |
_("Uses the backdrop only where this layer doesn't cover it. " | |
"Everything else is ignored.")), | |
+ lib.mypaintlib.CombineDestinationAtop: ( | |
+ _("Destination Atop"), | |
+ _("Destination which overlaps the source replaces the source. " | |
+ "Source is placed elsewhere.")), | |
} | |
for mode in STANDARD_MODES + STACK_MODES: | |
assert mode in MODE_STRINGS | |
diff --git a/lib/pixops.cpp b/lib/pixops.cpp | |
index 794ce4b..e0a9e54 100644 | |
--- a/lib/pixops.cpp | |
+++ b/lib/pixops.cpp | |
@@ -675,7 +675,8 @@ static const TileDataCombineOp * combine_mode_info[NumCombineModes] = | |
// Normal blend mode + various compositing operators | |
new TileDataCombine<BlendNormal, CompositeLighter>("svg:plus"), | |
new TileDataCombine<BlendNormal, CompositeDestinationIn>("svg:dst-in"), | |
- new TileDataCombine<BlendNormal, CompositeDestinationOut>("svg:dst-out") | |
+ new TileDataCombine<BlendNormal, CompositeDestinationOut>("svg:dst-out"), | |
+ new TileDataCombine<BlendNormal, CompositeDestinationAtop>("svg:dst-atop") | |
}; | |
diff --git a/lib/pixops.hpp b/lib/pixops.hpp | |
index 1e12c9f..972cf35 100644 | |
--- a/lib/pixops.hpp | |
+++ b/lib/pixops.hpp | |
@@ -110,6 +110,7 @@ enum CombineMode { | |
CombineLighter, // normal blend mode, and W3C lightER (Porter-Duff PLUS) | |
CombineDestinationIn, | |
CombineDestinationOut, | |
+ CombineDestinationAtop, | |
NumCombineModes | |
}; | |
diff --git a/lib/tiledsurface.py b/lib/tiledsurface.py | |
index 931873f..3be1678 100644 | |
--- a/lib/tiledsurface.py | |
+++ b/lib/tiledsurface.py | |
@@ -319,7 +319,7 @@ class MyPaintSurface (object): | |
""" | |
if opacity == 0: | |
- if mode == mypaintlib.CombineDestinationIn: | |
+ if mode == mypaintlib.CombineDestinationIn or mode == mypaintlib.CombineDestinationAtop: | |
if dst_has_alpha: | |
mypaintlib.tile_clear_rgba16(dst) | |
return | |
@@ -333,7 +333,7 @@ class MyPaintSurface (object): | |
with self.tile_request(tx, ty, readonly=True) as src: | |
if src is transparent_tile.rgba: | |
- if mode == mypaintlib.CombineDestinationIn: | |
+ if mode == mypaintlib.CombineDestinationIn or mode == mypaintlib.CombineDestinationAtop: | |
if dst_has_alpha: | |
mypaintlib.tile_clear_rgba16(dst) | |
return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment