Author: Carlos Lopez <[email protected]>
Date:   Sun Oct 14 10:23:34 2012 +0200

Cairo operators: Add support for blend modes not supported by Cairo. Add 
support for MULTIPLY, HUE, SATURATION, LUMINANCE, SCREEN and HARD_LIGHT. The 
transparency is not correctly handled in those cases and could need further 
operations.

---

 synfig-core/src/synfig/cairo_operators.cpp |   96 +++++++++++++++++++++++++++-
 1 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/synfig-core/src/synfig/cairo_operators.cpp 
b/synfig-core/src/synfig/cairo_operators.cpp
index ae93917..cb53a42 100644
--- a/synfig-core/src/synfig/cairo_operators.cpp
+++ b/synfig-core/src/synfig/cairo_operators.cpp
@@ -30,6 +30,7 @@
 #endif
 
 #include "cairo_operators.h"
+#include "surface.h"
 #include "general.h"
 
 
@@ -75,7 +76,7 @@ void cairo_paint_with_alpha_operator(cairo_t* acr, float 
alpha, Color::BlendMeth
                case Color::BLEND_BRIGHTEN:
                {
                        cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
-                       cairo_set_operator(cr, CAIRO_OPERATOR_HSL_LUMINOSITY);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_LIGHTEN);
                        cairo_identity_matrix(cr);
                        cairo_mask_surface(cr, dest, 0,0);
                        cairo_surface_destroy(dest);
@@ -90,6 +91,42 @@ void cairo_paint_with_alpha_operator(cairo_t* acr, float 
alpha, Color::BlendMeth
                        cairo_surface_destroy(dest);
                        break;
                }
+               case Color::BLEND_MULTIPLY:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_MULTIPLY);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
+               case Color::BLEND_HUE:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_HSL_HUE);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
+               case Color::BLEND_SATURATION:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_HSL_SATURATION);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
+               case Color::BLEND_LUMINANCE:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_HSL_LUMINOSITY);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
                case Color::BLEND_BEHIND:
                {
                        cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
@@ -102,6 +139,24 @@ void cairo_paint_with_alpha_operator(cairo_t* acr, float 
alpha, Color::BlendMeth
                        cairo_paint_with_alpha(cr, alpha);
                        break;
                }
+               case Color::BLEND_SCREEN:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_SCREEN);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
+               case Color::BLEND_HARD_LIGHT:
+               {
+                       cairo_surface_t* 
dest=cairo_copy_target_image(cairo_get_target(cr), alpha);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_HARD_LIGHT);
+                       cairo_identity_matrix(cr);
+                       cairo_mask_surface(cr, dest, 0,0);
+                       cairo_surface_destroy(dest);
+                       break;
+               }
                case Color::BLEND_ALPHA_OVER:
                {
                        cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OUT);
@@ -125,10 +180,45 @@ void cairo_paint_with_alpha_operator(cairo_t* acr, float 
alpha, Color::BlendMeth
                        cairo_surface_destroy(source);
                        break;
                }
+               case Color::BLEND_ADD:
+               case Color::BLEND_SUBTRACT:
+               case Color::BLEND_DIVIDE:
+               case Color::BLEND_ALPHA_BRIGHTEN:
+               case Color::BLEND_ALPHA_DARKEN:
+               case Color::BLEND_OVERLAY:
                default:
                {
-                       cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-                       cairo_paint_with_alpha(cr, alpha);
+                       cairo_surface_t* target=cairo_get_target(cr);
+                       cairo_surface_t* dest=cairo_copy_target_image(target);
+                       
+                       cairo_save(cr);
+                       cairo_reset_clip(cr);
+                       cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+                       cairo_paint(cr);
+                       cairo_restore(cr);
+                       
+                       cairo_paint(cr);
+                       
+                       CairoSurface cresult(target);
+                       CairoSurface cdest(dest);
+                       assert(cdest.map_cairo_image());
+                       assert(cresult.map_cairo_image());
+
+                       int w=cresult.get_w();
+                       int h=cresult.get_h();
+                       
+                       for(int y=0;y<h;y++)
+                               for(int x=0;x<w;x++)
+                               {
+                                       Color 
src=Color(cresult[y][x].demult_alpha());
+                                       Color 
dst=Color(cdest[y][x].demult_alpha());
+                                       
cresult[y][x]=CairoColor(Color::blend(src, dst, alpha,  
method).clamped()).premult_alpha();
+                               }
+                       
+                       cresult.unmap_cairo_image();
+                       cdest.unmap_cairo_image();
+
+                       cairo_surface_destroy(dest);
                        break;
                }
        }


------------------------------------------------------------------------------
Don't let slow site performance ruin your business. Deploy New Relic APM
Deploy New Relic app performance management and know exactly
what is happening inside your Ruby, Python, PHP, Java, and .NET app
Try New Relic at no cost today and get our sweet Data Nerd shirt too!
http://p.sf.net/sfu/newrelic-dev2dev
_______________________________________________
Synfig-devl mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl

Reply via email to