From 6471cfc5978df78a423581d27669352426925ce9 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 23 May 2012 20:23:10 +0100 Subject: [PATCH 01/47] + unnamed args in image-filters #1222 --- include/mapnik/image_filter_parser.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/mapnik/image_filter_parser.hpp b/include/mapnik/image_filter_parser.hpp index 2192c96dc..91d4d6969 100644 --- a/include/mapnik/image_filter_parser.hpp +++ b/include/mapnik/image_filter_parser.hpp @@ -34,7 +34,7 @@ namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; template -struct image_filter_grammar : +struct image_filter_grammar : qi::grammar { image_filter_grammar() @@ -59,7 +59,7 @@ struct image_filter_grammar : ; #endif - filter = + filter = lit("emboss")[push_back(_val,construct())] | lit("blur")[push_back(_val,construct())] @@ -76,16 +76,16 @@ struct image_filter_grammar : | lit("y-gradient")[push_back(_val,construct())] | - (lit("agg-stack-blur")[_a = 1, _b = 1] - >> -( lit(':') >> lit("rx") >> lit('=') >> radius_[_a = _1] - >> lit(',') - >> lit("ry") >> lit('=') >> radius_[_b = _1]) + (lit("agg-stack-blur")[_a = 1, _b = 1] + >> -( lit(':') >> radius_[_a = _1] + >> lit(',') + >> radius_[_b = _1]) [push_back(_val,construct(_a,_b))]) | lit("invert")[push_back(_val,construct())] ; } - // + // qi::rule start; qi::rule, qi::ascii::space_type> filter; qi::uint_parser< unsigned, 10, 1, 3 > radius_; From fb34c7ef5a8852e7f16250ed21fff01e66064756 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 23 May 2012 20:26:24 +0100 Subject: [PATCH 02/47] + handle boundary cases in 3x3 convolution --- include/mapnik/image_filter.hpp | 291 ++++++++++++++++++++++---------- 1 file changed, 204 insertions(+), 87 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 8988b2ccf..cd67325bd 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -29,14 +29,14 @@ // boost #include #include -// agg +// agg #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_scanline_u.h" #include "agg_blur.h" - + // 8-bit YUV //Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16 //U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128 @@ -51,48 +51,48 @@ // c3 c4 c5 // c6 c7 c8 -//sharpen +//sharpen // 0 -1 0 // -1 5 -1 -// 0 -1 0 -//bits_type out_value = -c1 - c3 + 5.0*c4 - c5 - c7; - +// 0 -1 0 +//bits_type out_value = -c1 - c3 + 5.0*c4 - c5 - c7; + // edge detect // 0 1 0 // 1 -4 1 -// 0 1 0 -//bits_type out_value = c1 + c3 - 4.0*c4 + c5 + c7; - -// +// 0 1 0 +//bits_type out_value = c1 + c3 - 4.0*c4 + c5 + c7; + +// //if (out_value < 0) out_value = 0; //if (out_value > 255) out_value = 255; - + // emboss // -2 -1 0 // -1 1 1 // 0 1 2 - -// bits_type out_value = -2*c0 - c1 - c3 + c4 + c5 + c7 + 2*c8; - + +// bits_type out_value = -2*c0 - c1 - c3 + c4 + c5 + c7 + 2*c8; + // blur //float out_value = (0.1f*c0 + 0.1f*c1 + 0.1f*c2 + // 0.1f*c3 + 0.1f*c4 + 0.1f*c5 + // 0.1f*c6 + 0.1f*c7 + 0.1f*c8); - - + + //float out_value = std::sqrt(std::pow(x_gradient,2) + std::pow(y_gradient,2)); //float theta = std::atan2(x_gradient,y_gradient); //if (out_value < 0.0) out_value = 0.0; //if (out_value < 1.0) out_value = 1.0; - - - + + + //float conv_matrix[]={1/3.0,1/3.0,1/3.0}; //float gaussian_1[]={0.00022923296f,0.0059770769f,0.060597949f,0.24173197f,0.38292751f, // 0.24173197f,0.060597949f,0.0059770769f,0.00022923296f}; - + //float gaussian_2[]={ // 0.00048869418f,0.0024031631f,0.0092463447f, // 0.027839607f,0.065602221f,0.12099898f,0.17469721f, @@ -102,16 +102,16 @@ //}; // kernel_1d_fixed kernel(conv,4); - + // color_converted_view(src_view); //typedef kth_channel_view_type< 0, const rgba8_view_t>::type view_t; //view_t red = kth_channel_view<0>(const_view(src_view)); - + //kernel_1d_fixed kernel(sharpen,0); -//convolve_rows_fixed(src_view,kernel,src_view); +//convolve_rows_fixed(src_view,kernel,src_view); // convolve_cols_fixed(src_view,kernel,dst_view); - + using namespace boost::gil; namespace mapnik { namespace filter { namespace detail { @@ -127,20 +127,20 @@ static const float edge_detect_matrix[] = {0,1,0,1,-4,1,0,1,0 }; template void process_channel_impl (Src const& src, Dst & dst, Conv const& k) { - using namespace boost::gil; + using namespace boost::gil; typedef boost::gil::bits32f bits_type; - bits32f out_value = + bits32f out_value = k[0]*src[0] + k[1]*src[1] + k[2]*src[2] + k[3]*src[3] + k[4]*src[4] + k[5]*src[5] + k[6]*src[6] + k[7]*src[7] + k[8]*src[8] ; if (out_value < 0) out_value = 0; - if (out_value > 255) out_value = 255; + if (out_value > 255) out_value = 255; dst = out_value; } template -void process_channel (Src const& src, Dst & dst, Conv const& k) +void process_channel (Src const& src, Dst & dst, Conv const& k) { boost::ignore_unused_variable_warning(src); boost::ignore_unused_variable_warning(dst); @@ -175,19 +175,19 @@ void process_channel (Src const& src, Dst & dst, mapnik::filter::edge_detect) template void process_channel (Src const& src, Dst & dst, mapnik::filter::sobel) { - using namespace boost::gil; + using namespace boost::gil; typedef boost::gil::bits32f bits_type; - + bits32f x_gradient = (src[2] + 2*src[5] + src[8]) - (src[0] + 2*src[3] + src[6]); - + bits32f y_gradient = (src[0] + 2*src[1] + src[2]) - (src[6] + 2*src[7] + src[8]); - - bits32f out_value = std::sqrt(std::pow(x_gradient,2) + std::pow(y_gradient,2)); - //bts32f theta = std::atan2(x_gradient,y_gradient); + + bits32f out_value = std::sqrt(std::pow(x_gradient,2) + std::pow(y_gradient,2)); + //bts32f theta = std::atan2(x_gradient,y_gradient); if (out_value < 0) out_value = 0; - if (out_value > 255) out_value = 255; + if (out_value > 255) out_value = 255; dst = out_value; } @@ -196,47 +196,164 @@ void process_channel (Src const& src, Dst & dst, mapnik::filter::sobel) template void apply_convolution_3x3(Src const& src_view, Dst & dst_view, FilterTag filter_tag) { - typename Src::xy_locator src_loc = src_view.xy_at(1,1); + // p0 p1 p2 + // p3 p4 p5 + // p6 p7 p8 + + typename Src::xy_locator src_loc = src_view.xy_at(0,0); typename Src::xy_locator::cached_location_t loc00 = src_loc.cache_location(-1,-1); typename Src::xy_locator::cached_location_t loc10 = src_loc.cache_location( 0,-1); - typename Src::xy_locator::cached_location_t loc20 = src_loc.cache_location( 1,-1); + typename Src::xy_locator::cached_location_t loc20 = src_loc.cache_location( 1,-1); typename Src::xy_locator::cached_location_t loc01 = src_loc.cache_location(-1, 0); typename Src::xy_locator::cached_location_t loc11 = src_loc.cache_location( 0, 0); - typename Src::xy_locator::cached_location_t loc21 = src_loc.cache_location( 1, 0); + typename Src::xy_locator::cached_location_t loc21 = src_loc.cache_location( 1, 0); typename Src::xy_locator::cached_location_t loc02 = src_loc.cache_location(-1, 1); typename Src::xy_locator::cached_location_t loc12 = src_loc.cache_location( 0, 1); typename Src::xy_locator::cached_location_t loc22 = src_loc.cache_location( 1, 1); - - for (int y = 1; y(-src_view.width(),1); + + // 1... height-1 rows + for (int y = 1; y(-src_view.width(),1); } + + // bottom row + //src_loc = src_view.xy_at(0,src_view.height()-1); + for (int x = 0 ; x < src_view.width(); ++x) + { + *dst_it = src_loc[loc11]; + for (int i = 0; i < 3; ++i) + { + bits32f p[9]; + + p[1] = src_loc[loc10][i]; + p[4] = src_loc[loc11][i]; + + if (x == 0) + { + p[0] = p[1]; + p[3] = p[4]; + } + else + { + p[0] = src_loc[loc00][i]; + p[3] = src_loc[loc01][i]; + } + + if ( x == src_view.width()-1) + { + p[2] = p[1]; + p[5] = p[4]; + + } + else + { + p[2] = src_loc[loc20][i]; + p[5] = src_loc[loc21][i]; + } + + p[6] = p[0]; + p[7] = p[1]; + p[8] = p[2]; + + process_channel(p, (*dst_it)[i], filter_tag); + } + ++src_loc.x(); + ++dst_it; + } } - -template +template void apply_filter(Src const& src, Dst & dst, FilterTag filter_tag) { using namespace boost::gil; @@ -245,63 +362,63 @@ void apply_filter(Src const& src, Dst & dst, FilterTag filter_tag) src.width()*4); rgba8_view_t dst_view = interleaved_view(dst.width(),dst.height(), (rgba8_pixel_t*) dst.raw_data(), - dst.width()*4); + dst.width()*4); typedef boost::mpl::vector channels; - + apply_convolution_3x3(src_view,dst_view,filter_tag); } -template +template void apply_filter(Src & src, FilterTag filter_tag) { using namespace boost::gil; rgba8_view_t src_view = interleaved_view(src.width(),src.height(), (rgba8_pixel_t*) src.raw_data(), - src.width()*4); + src.width()*4); rgba8_image_t temp_buffer(src_view.dimensions()); apply_convolution_3x3(src_view,boost::gil::view(temp_buffer), filter_tag); - boost::gil::copy_pixels(view(temp_buffer), src_view); + boost::gil::copy_pixels(view(temp_buffer), src_view); } -template +template void apply_filter(Src & src, agg_stack_blur const& op) { agg::rendering_buffer buf(src.raw_data(),src.width(),src.height(), src.width() * 4); agg::pixfmt_rgba32 pixf(buf); - agg::stack_blur_rgba32(pixf,op.rx,op.ry); + agg::stack_blur_rgba32(pixf,op.rx,op.ry); } -template +template void apply_filter(Src & src, gray) { using namespace boost::gil; - typedef pixel::type, gray_layout_t> gray_pixel_t; - + typedef pixel::type, gray_layout_t> gray_pixel_t; + rgba8_view_t src_view = interleaved_view(src.width(),src.height(), (rgba8_pixel_t*) src.raw_data(), src.width()*4); - boost::gil::copy_and_convert_pixels(color_converted_view(src_view), src_view); + boost::gil::copy_and_convert_pixels(color_converted_view(src_view), src_view); } -template +template void apply_filter(Src & src, x_gradient) { using namespace boost::gil; - + rgba8_view_t src_view = interleaved_view(src.width(),src.height(), (rgba8_pixel_t*) src.raw_data(), src.width()*4); rgba8_image_t temp_buffer(src_view.dimensions()); rgba8_view_t dst_view = view(temp_buffer); - for (int y=0; y +template void apply_filter(Src & src, y_gradient) { using namespace boost::gil; - + rgba8_view_t in = interleaved_view(src.width(),src.height(), (rgba8_pixel_t*) src.raw_data(), src.width()*4); rgba8_image_t temp_buffer(in.dimensions()); dynamic_xy_step_type::type src_view = rotated90ccw_view(in); dynamic_xy_step_type::type dst_view = rotated90ccw_view(view(temp_buffer)); - - for (int y=0; y::type::x_iterator src_it = src_view.row_begin(y); dynamic_xy_step_type::type::x_iterator dst_it = dst_view.row_begin(y); - + for (int x=1; x +template void apply_filter(Src & src, invert) -{ +{ using namespace boost::gil; - + rgba8_view_t src_view = interleaved_view(src.width(),src.height(), (rgba8_pixel_t*) src.raw_data(), - src.width()*4); - for (int y=0; y struct filter_visitor : boost::static_visitor { filter_visitor(Src & src) - : src_(src) {} - + : src_(src) {} + template void operator () (T filter_tag) { apply_filter(src_,filter_tag); - } - + } + Src & src_; }; From 4fc4535c95dd5e1ab0d98f47d4bdbf3564d40c2f Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 23 May 2012 20:29:07 +0100 Subject: [PATCH 03/47] + initialise blur radius's to 1 in default ctor --- include/mapnik/image_filter_types.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index 6ac407ba6..5502f66c1 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -41,7 +41,7 @@ struct agg_stack_blur { agg_stack_blur(unsigned rx_, unsigned ry_) : rx(rx_),ry(ry_) {} - // an attemp to support older boost spirit (< 1.46) + // an attempt to support older boost spirit (< 1.46) agg_stack_blur() : rx(0),ry(0) {} unsigned rx; From f76c6ee25f13c140195aa476990a58062f44ab43 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 23 May 2012 20:37:31 +0100 Subject: [PATCH 04/47] initialise blur radius's to 1 for real this time --- bindings/python/mapnik_text_placement.cpp | 3 ++- demo/viewer/viewer.pro | 27 ++++++++++++++++------- include/mapnik/image_filter_types.hpp | 3 ++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 13de8478b..e22eb26b8 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -193,7 +193,8 @@ struct ListNodeWrap: formatting::list_node, wrapper ListNodeWrap(object l) : formatting::list_node(), wrapper() { stl_input_iterator begin(l), end; - children_.insert(children_.end(), begin, end); + // FIXME c++11 : error: call to 'make_move_iterator' is ambiguous + // children_.insert(children_.end(), begin, end); } /* TODO: Add constructor taking variable number of arguments. diff --git a/demo/viewer/viewer.pro b/demo/viewer/viewer.pro index 538419e49..6d112c1bb 100644 --- a/demo/viewer/viewer.pro +++ b/demo/viewer/viewer.pro @@ -1,18 +1,29 @@ ###################################################################### # Mapnik viewer - Copyright (C) 2007 Artem Pavlenko ###################################################################### -CC = g++ +QMAKE_CXX = /opt/llvm/bin/clang++ TEMPLATE = app -INCLUDEPATH += /usr/local/include/ -INCLUDEPATH += /usr/boost/include/ -INCLUDEPATH += /usr/X11/include/ -INCLUDEPATH += /usr/X11/include/freetype2 +INCLUDEPATH += /opt/mapnik/include/ +INCLUDEPATH += /opt/boost_1_49_0/include/ +INCLUDEPATH += /opt/mapnik_deps/include/ +INCLUDEPATH += /opt/mapnik_deps/include/freetype2 + +### Cairo backend +INCLUDEPATH += /opt/mapnik_deps/include/cairo +INCLUDEPATH += /opt/mapnik_deps/include/cairomm-1.0 +INCLUDEPATH += /opt/mapnik_deps/include/sigc++-2.0 +INCLUDEPATH += /opt/mapnik_deps/lib/sigc++-2.0/include +### + +INCLUDEPATH += /Users/artem/Projects/mapnik/deps/agg/include INCLUDEPATH += . -QMAKE_CXXFLAGS +=' -DDARWIN -Wno-missing-field-initializers -ansi' -unix:LIBS = -L/usr/local/lib -L/usr/X11/lib -lmapnik -lfreetype -unix:LIBS += -lboost_system -licuuc -lboost_filesystem -lboost_regex +QMAKE_CXXFLAGS +='-DDARWIN -Wno-missing-field-initializers -fno-inline -ansi' +QMAKE_CXXFLAGS +=' -DHAVE_CAIRO' +unix:LIBS = -L/opt/mapnik/lib -L/opt/mapnik_deps/lib -lmapnik -lfreetype -L/opt/mapnik/lib +unix:LIBS += -lboost_system -licuuc -lboost_filesystem -lboost_regex -L/opt/boost_1_49_0/lib +unix:LIBS += -lcairo -lcairomm-1.0 # Input diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index 5502f66c1..d4e073263 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -43,7 +43,8 @@ struct agg_stack_blur : rx(rx_),ry(ry_) {} // an attempt to support older boost spirit (< 1.46) agg_stack_blur() - : rx(0),ry(0) {} + : rx(1),ry(1) {} + unsigned rx; unsigned ry; }; From 0e5dcbd81035bf7a59de7f5b4cadc8058517472f Mon Sep 17 00:00:00 2001 From: kunitoki Date: Thu, 24 May 2012 00:02:43 +0200 Subject: [PATCH 05/47] - fixed unwanted behaviour with default log severity in SConstruct #937 --- SConstruct | 276 ++++++++++++++++++++++++++--------------------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/SConstruct b/SConstruct index d7c15f752..0b793578a 100644 --- a/SConstruct +++ b/SConstruct @@ -81,7 +81,7 @@ pretty_dep_names = { 'sqlite_rtree':'The SQLite plugin requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)', 'pgsql2sqlite_rtree':'The pgsql2sqlite program requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)' } - + # Core plugin build configuration # opts.AddVariables still hardcoded however... PLUGINS = { # plugins with external dependencies @@ -94,7 +94,7 @@ PLUGINS = { # plugins with external dependencies 'occi': {'default':False,'path':'OCCI','inc':'occi.h','lib':'ociei','lang':'C++'}, 'sqlite': {'default':True,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'}, 'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','lang':'C'}, - + # todo: osm plugin does also depend on libxml2 (but there is a separate check for that) 'osm': {'default':True,'path':None,'inc':'curl/curl.h','lib':'curl','lang':'C'}, @@ -156,7 +156,7 @@ def create_uninstall_target(env, path, is_glob=False): Delete("$SOURCE"), ]) env.Alias("uninstall", "uninstall-"+path) - + def shortest_name(libs): name = '-'*200 for lib in libs: @@ -168,20 +168,20 @@ def shortest_name(libs): def sort_paths(items,priority): """Sort paths such that compiling and linking will globally prefer custom or local libs over system libraries by fixing up the order libs are passed to gcc and the linker. - + Ideally preference could be by-target instead of global, but our SCons implementation is not currently utilizing different SCons build env()'s as we should. - + Overally the current approach within these scripts is to prepend paths of preference and append all others, but this does not give enough control (particularly due to the approach of assuming /usr/LIBSCHEMA and letting paths be parsed and added by pkg-config). - + In effect /usr/lib is likely to come before /usr/local/lib which makes linking against custom built icu or boost impossible when those libraries are available in both places. - + Sorting using a priority list allows this to be controlled, and fine tuned. """ - + new = [] path_types = {'internal':[],'other':[],'frameworks':[],'user':[],'system':[]} # parse types of paths into logical/meaningful groups @@ -235,7 +235,7 @@ def sort_paths(items,priority): if platform.dist()[0] in ('Ubuntu','debian'): LIBDIR_SCHEMA='lib' elif platform.uname()[4] == 'x86_64' and platform.system() == 'Linux': - LIBDIR_SCHEMA='lib64' + LIBDIR_SCHEMA='lib64' elif platform.uname()[4] == 'ppc64': LIBDIR_SCHEMA='lib64' else: @@ -274,7 +274,7 @@ opts.AddVariables( BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'), ListVariable('INPUT_PLUGINS','Input drivers to include',DEFAULT_PLUGINS,PLUGINS.keys()), ('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''), - + # SCons build behavior options ('CONFIG', "The path to the python file in which to save user configuration options. Currently : '%s'" % SCONS_LOCAL_CONFIG,SCONS_LOCAL_CONFIG), BoolVariable('USE_CONFIG', "Use SCons user '%s' file (will also write variables after successful configuration)", 'True'), @@ -282,8 +282,8 @@ opts.AddVariables( # http://stackoverflow.com/questions/1318863/how-to-optimize-an-scons-script BoolVariable('FAST', "Make SCons faster at the cost of less precise dependency tracking", 'False'), BoolVariable('PRIORITIZE_LINKING', 'Sort list of lib and inc directories to ensure preferential compiling and linking (useful when duplicate libs)', 'True'), - ('LINK_PRIORITY','Priority list in which to sort library and include paths (default order is internal, other, frameworks, user, then system - see source of `sort_paths` function for more detail)',','.join(DEFAULT_LINK_PRIORITY)), - + ('LINK_PRIORITY','Priority list in which to sort library and include paths (default order is internal, other, frameworks, user, then system - see source of `sort_paths` function for more detail)',','.join(DEFAULT_LINK_PRIORITY)), + # Install Variables ('PREFIX', 'The install path "prefix"', '/usr/local'), ('PYTHON_PREFIX','Custom install path "prefix" for python bindings (default of no prefix)',''), @@ -291,7 +291,7 @@ opts.AddVariables( ('PATH', 'A custom path (or multiple paths divided by ":") to append to the $PATH env to prioritize usage of command line programs (if multiple are present on the system)', ''), ('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths', ''), ('PATH_REPLACE', 'Two path prefixes (divided with a :) to search/replace from all known command and compile paths', ''), - + # Boost variables # default is '/usr/include', see FindBoost method below ('BOOST_INCLUDES', 'Search path for boost include files', '',False), @@ -301,7 +301,7 @@ opts.AddVariables( ('BOOST_ABI', 'Specify boost ABI, e.g., d.','',False), ('BOOST_VERSION','Specify boost version, e.g., 1_35.','',False), ('BOOST_PYTHON_LIB','Specify library name to specific Boost Python lib (e.g. "boost_python-py26")',''), - + # Variables for required dependencies ('FREETYPE_CONFIG', 'The path to the freetype-config executable.', 'freetype-config'), ('XML2_CONFIG', 'The path to the xml2-config executable.', 'xml2-config'), @@ -310,7 +310,7 @@ opts.AddVariables( ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc'), PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include', PathVariable.PathAccept), PathVariable('PNG_LIBS','Search path for libpng include files','/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), - BoolVariable('JPEG', 'Build Mapnik with JPEG read and write support', 'True'), + BoolVariable('JPEG', 'Build Mapnik with JPEG read and write support', 'True'), PathVariable('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include', PathVariable.PathAccept), PathVariable('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include', PathVariable.PathAccept), @@ -318,15 +318,15 @@ opts.AddVariables( PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/local/include', PathVariable.PathAccept), PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/local/' + LIBDIR_SCHEMA, PathVariable.PathAccept), ('PKG_CONFIG_PATH', 'Use this path to point pkg-config to .pc files instead of the PKG_CONFIG_PATH environment setting',''), - + # Variables affecting rendering back-ends - + BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'), BoolVariable('INTERNAL_LIBAGG', 'Use provided libagg', 'True'), BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'), - + # Variables for optional dependencies ('GEOS_CONFIG', 'The path to the geos-config executable.', 'geos-config'), # Note: cairo, cairomm, and pycairo all optional but configured automatically through pkg-config @@ -447,7 +447,7 @@ HELP_REQUESTED = False if ('-h' in command_line_args) or ('--help' in command_line_args): HELP_REQUESTED = True - + if 'configure' in command_line_args and not HELP_REQUESTED: force_configure = True @@ -482,10 +482,10 @@ for opt in pickle_store: # if custom arguments are supplied make sure to accept them if opts.args: - # since we have custom arguments update environment with all opts to + # since we have custom arguments update environment with all opts to # make sure to absorb the custom ones opts.Update(env) - # now since we've got custom arguments we'll disregard any + # now since we've got custom arguments we'll disregard any # pickled environment and force another configuration preconfigured = False @@ -504,7 +504,7 @@ color_print(4,'\nWelcome to Mapnik...\n') #### Custom Configure Checks ### -def prioritize_paths(context,silent=True): +def prioritize_paths(context,silent=True): env = context.env prefs = env['LINK_PRIORITY'].split(',') if not silent: @@ -572,7 +572,7 @@ def parse_config(context, config, checks='--libs --cflags'): env['SKIPPED_DEPS'].append(tool) conf.rollback_option(config) else: # freetype and libxml2, not optional - env['MISSING_DEPS'].append(tool) + env['MISSING_DEPS'].append(tool) context.Result( ret ) return ret @@ -637,18 +637,18 @@ def rollback_option(context,variable): def FindBoost(context, prefixes, thread_flag): """Routine to auto-find boost header dir, lib dir, and library naming structure. - + """ context.Message( 'Searching for boost libs and headers... ' ) env = context.env - + BOOST_LIB_DIR = None BOOST_INCLUDE_DIR = None BOOST_APPEND = None env['BOOST_APPEND'] = str() - + if env['THREADING'] == 'multi': - search_lib = 'libboost_thread' + search_lib = 'libboost_thread' else: search_lib = 'libboost_filesystem' @@ -669,23 +669,23 @@ def FindBoost(context, prefixes, thread_flag): if hasattr(match,'groups'): BOOST_APPEND = match.groups()[0] break - + msg = str() - + if BOOST_LIB_DIR: msg += '\n *libs found: %s' % BOOST_LIB_DIR env['BOOST_LIBS'] = BOOST_LIB_DIR else: env['BOOST_LIBS'] = '/usr/' + LIBDIR_SCHEMA msg += '\n *using default boost lib dir: %s' % env['BOOST_LIBS'] - + if BOOST_INCLUDE_DIR: msg += '\n *headers found: %s' % BOOST_INCLUDE_DIR env['BOOST_INCLUDES'] = BOOST_INCLUDE_DIR else: env['BOOST_INCLUDES'] = '/usr/include' - msg += '\n *using default boost include dir: %s' % env['BOOST_INCLUDES'] - + msg += '\n *using default boost include dir: %s' % env['BOOST_INCLUDES'] + if not env['BOOST_TOOLKIT'] and not env['BOOST_ABI'] and not env['BOOST_VERSION']: if BOOST_APPEND: msg += '\n *lib naming extension found: %s' % BOOST_APPEND @@ -704,12 +704,12 @@ def FindBoost(context, prefixes, thread_flag): # Constructing the BOOST_APPEND setting that will be used to find the # Boost libraries. - if len(append_params) > 1: + if len(append_params) > 1: env['BOOST_APPEND'] = '-'.join(append_params) msg += '\n *using boost lib naming: %s' % env['BOOST_APPEND'] env.AppendUnique(CPPPATH = os.path.realpath(env['BOOST_INCLUDES'])) - env.AppendUnique(LIBPATH = os.path.realpath(env['BOOST_LIBS'])) + env.AppendUnique(LIBPATH = os.path.realpath(env['BOOST_LIBS'])) if env['COLOR_PRINT']: msg = "\033[94m%s\033[0m" % (msg) ret = context.Result(msg) @@ -725,14 +725,14 @@ def CheckBoost(context, version, silent=False): version_n += int(v_arr[1])*100 if len(v_arr) > 2: version_n += int(v_arr[2]) - + if not silent: context.Message('Checking for Boost version >= %s... ' % (version)) ret = context.TryRun(""" #include -int main() +int main() { return BOOST_VERSION >= %d ? 0 : 1; } @@ -749,7 +749,7 @@ def GetBoostLibVersion(context): #include #include -int main() +int main() { std::cout << BOOST_LIB_VERSION << std::endl; @@ -768,7 +768,7 @@ def GetMapnikLibVersion(context): #include #include -int main() +int main() { std::cout << MAPNIK_VERSION_STRING << std::endl; return 0; @@ -788,7 +788,7 @@ def icu_at_least_four_two(context): #include #include -int main() +int main() { std::cout << U_ICU_VERSION_MAJOR_NUM << "." << U_ICU_VERSION_MINOR_NUM << std::endl; return 0; @@ -802,12 +802,12 @@ int main() if not result: context.Result('error, could not get major and minor version from unicode/uversion.h') return False - + major, minor = map(int,result.split('.')) if major >= 4 and minor >= 0: color_print(4,'found: icu %s' % result) return True - + color_print(1,'\nFound insufficient icu version... %s' % result) return False @@ -820,10 +820,10 @@ def boost_regex_has_icu(context): #include #include -int main() +int main() { UnicodeString ustr; - try { + try { boost::u32regex pattern = boost::make_u32regex(ustr); } // an exception is fine, still indicates support is @@ -843,17 +843,17 @@ int main() def sqlite_has_rtree(context): """ check an sqlite3 install has rtree support. - + PRAGMA compile_options; http://www.sqlite.org/c3ref/compileoption_get.html """ - + ret = context.TryRun(""" #include #include -int main() +int main() { sqlite3* db; int rc; @@ -873,7 +873,7 @@ int main() printf("yes, has rtree!\\n"); return 0; } - + return -1; } @@ -883,7 +883,7 @@ int main() if ret[0]: return True return False - + conf_tests = { 'prioritize_paths' : prioritize_paths, 'CheckPKGConfig' : CheckPKGConfig, 'CheckPKG' : CheckPKG, @@ -909,7 +909,7 @@ if not preconfigured: if not env['FAST']: SetCacheMode('force') - + if env['USE_CONFIG']: if not env['CONFIG'].endswith('.py'): color_print(1,'SCons CONFIG file specified is not a python file, will not be read...') @@ -924,7 +924,7 @@ if not preconfigured: optfile = file(conf) #print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=") optfile.close() - + elif not conf == SCONS_LOCAL_CONFIG: # if default missing, no worries # but if the default is overridden and the file is not found, give warning @@ -933,18 +933,18 @@ if not preconfigured: env = Environment(ENV=os.environ,options=opts) env['USE_CONFIG'] = True else: - color_print(4,'SCons USE_CONFIG specified as false, will not inherit variables python config file...') + color_print(4,'SCons USE_CONFIG specified as false, will not inherit variables python config file...') conf = Configure(env, custom_tests = conf_tests) - + if env['DEBUG']: mode = 'debug mode' else: mode = 'release mode' - + env['PLATFORM'] = platform.uname()[0] color_print(4,"Configuring on %s in *%s*..." % (env['PLATFORM'],mode)) - + env['MISSING_DEPS'] = [] env['SKIPPED_DEPS'] = [] env['HAS_CAIRO'] = False @@ -964,7 +964,7 @@ if not preconfigured: # now strip it to ensure expected behavior if env['LIB_DIR_NAME'].startswith(os.path.sep): env['LIB_DIR_NAME'] = strip_first(env['LIB_DIR_NAME'],os.path.sep) - + # base install location env['MAPNIK_LIB_BASE'] = os.path.join(env['PREFIX'],env['LIBDIR_SCHEMA']) # directory for plugins and fonts @@ -976,8 +976,8 @@ if not preconfigured: env['MAPNIK_FONTS'] = os.path.normpath(env['SYSTEM_FONTS']) else: env['MAPNIK_FONTS'] = os.path.join(env['MAPNIK_LIB_DIR'],'fonts') - - # install prefix is a pre-pended base location to + + # install prefix is a pre-pended base location to # re-route the install and only intended for package building # we normalize to ensure no trailing slash and proper pre-pending to the absolute prefix install_prefix = os.path.normpath(os.path.realpath(env['DESTDIR'])) + os.path.realpath(env['PREFIX']) @@ -991,12 +991,12 @@ if not preconfigured: env['MAPNIK_FONTS_DEST'] = os.path.normpath(env['SYSTEM_FONTS']) else: env['MAPNIK_FONTS_DEST'] = os.path.join(env['MAPNIK_LIB_DIR_DEST'],'fonts') - + if env['LINKING'] == 'static': env['MAPNIK_LIB_NAME'] = '${LIBPREFIX}mapnik${LIBSUFFIX}' else: env['MAPNIK_LIB_NAME'] = '${SHLIBPREFIX}mapnik${SHLIBSUFFIX}' - + if env['PKG_CONFIG_PATH']: env['ENV']['PKG_CONFIG_PATH'] = os.path.realpath(env['PKG_CONFIG_PATH']) # otherwise this variable == os.environ["PKG_CONFIG_PATH"] @@ -1008,11 +1008,11 @@ if not preconfigured: if not os.path.isdir(env['SYSTEM_FONTS']): color_print(1,'Warning: Directory specified for SYSTEM_FONTS does not exist!') #### Libraries and headers dependency checks #### - + # Set up for libraries and headers dependency checks env['CPPPATH'] = ['#include', '#'] env['LIBPATH'] = ['#src'] - + # set any custom cxxflags to come first env.Append(CXXFLAGS = env['CUSTOM_CXXFLAGS']) @@ -1027,7 +1027,7 @@ if not preconfigured: # set if the `CXX` option begins with `CC`) SOLARIS = env['PLATFORM'] == 'SunOS' env['SUNCC'] = SOLARIS and env['CXX'].startswith('CC') - + # If the Sun Studio C++ compiler (`CC`) is used instead of GCC. if env['SUNCC']: env['CC'] = 'cc' @@ -1050,7 +1050,7 @@ if not preconfigured: if os.path.exists(env['ICU_LIB_NAME']): #-sICU_LINK=" -L/usr/lib -licucore env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','') - + # Adding the required prerequisite library directories to the include path for # compiling and the library path for linking, respectively. for required in ('PNG', 'JPEG', 'TIFF','PROJ','ICU', 'SQLITE'): @@ -1094,8 +1094,8 @@ if not preconfigured: # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: - conf.prioritize_paths(silent=False) - + conf.prioritize_paths(silent=False) + for libname, headers, required, lang in LIBSHEADERS: if not conf.CheckLibWithHeader(libname, headers, lang): if required: @@ -1109,16 +1109,16 @@ if not preconfigured: if not conf.icu_at_least_four_two(): # expression_string.cpp and map.cpp use fromUTF* function only available in >= ICU 4.2 env['MISSING_DEPS'].append(env['ICU_LIB_NAME']) - + if env['THREADING'] == 'multi': thread_flag = thread_suffix else: thread_flag = '' - + conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag) - + env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion() - + # The other required boost headers. BOOST_LIBSHEADERS = [ ['system', 'boost/system/system_error.hpp', True], @@ -1126,11 +1126,11 @@ if not preconfigured: ['regex', 'boost/regex.hpp', True], ['program_options', 'boost/program_options.hpp', False] ] - + if env['THREADING'] == 'multi': BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True]) # on solaris the configure checks for boost_thread - # require the -pthreads flag to be able to check for + # require the -pthreads flag to be able to check for # threading support, so we add as a global library instead # of attaching to cxxflags after configure if env['PLATFORM'] == 'SunOS': @@ -1138,17 +1138,17 @@ if not preconfigured: # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: - conf.prioritize_paths() - + conf.prioritize_paths() + # if the user is not setting custom boost configuration # enforce boost version greater than or equal to BOOST_MIN_VERSION if not conf.CheckBoost(BOOST_MIN_VERSION): - color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION) + color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION) if not env['BOOST_VERSION']: env['MISSING_DEPS'].append('boost version >=%s' % BOOST_MIN_VERSION) else: color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') ) - + for count, libinfo in enumerate(BOOST_LIBSHEADERS): if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'): if libinfo[2]: @@ -1167,7 +1167,7 @@ if not preconfigured: env['SKIPPED_DEPS'].append('boost_regex_icu') env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] - + if len(env['REQUESTED_PLUGINS']): color_print(4,'Checking for requested plugins dependencies...') for plugin in env['REQUESTED_PLUGINS']: @@ -1232,7 +1232,7 @@ if not preconfigured: elif details['lib'] and details['inc']: if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']): env['SKIPPED_DEPS'].append(details['lib']) - + # re-append the local paths for mapnik sources to the beginning of the list # to make sure they come before any plugins that were 'prepended' env.PrependUnique(CPPPATH = '#include', delete_existing=True) @@ -1247,7 +1247,7 @@ if not preconfigured: # Decide which libagg to use # if we are using internal agg, then prepend to make sure # we link locally - + if env['INTERNAL_LIBAGG']: env.Prepend(CPPPATH = '#deps/agg/include') env.Prepend(LIBPATH = '#deps/agg') @@ -1260,7 +1260,7 @@ if not preconfigured: if env['CAIRO_LIBS']: env["CAIROMM_LIBPATHS"].append(os.path.realpath(env['CAIRO_LIBS'])) if not env['CAIRO_INCLUDES']: - c_inc = env['CAIRO_LIBS'].replace('lib','',1) + c_inc = env['CAIRO_LIBS'].replace('lib','',1) if c_inc: c_inc = os.path.normpath(os.path.realpath(env['CAIRO_INCLUDES'])) if c_inc.endswith('include'): @@ -1323,17 +1323,17 @@ if not preconfigured: env['SKIPPED_DEPS'].append('cairo') env['SKIPPED_DEPS'].append('cairomm') color_print(1,'pkg-config reported: %s' % e) - + else: color_print(4,'Not building with cairo support, pass CAIRO=True to enable') - + if 'python' in env['BINDINGS']: # checklibwithheader does not work for boost_python since we can't feed it # multiple header files, so we fall back on a simple check for boost_python headers if not conf.CheckHeader(header='boost/python/detail/config.hpp',language='C++'): color_print(1,'Could not find required header files for boost python') env['MISSING_DEPS'].append('boost python') - + if env['CAIRO']: if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('pycairo'): env['HAS_PYCAIRO'] = True @@ -1341,10 +1341,10 @@ if not preconfigured: env['SKIPPED_DEPS'].extend(['pycairo']) else: color_print(4,'Not building with pycairo support, pass CAIRO=True to enable') - - + + #### End Config Stage for Required Dependencies #### - + if env['MISSING_DEPS']: # if required dependencies are missing, print warnings and then let SCons finish without building or saving local config color_print(1,'\nExiting... the following required dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['MISSING_DEPS']])) @@ -1367,7 +1367,7 @@ if not preconfigured: if env['USE_CONFIG']: if os.path.exists(SCONS_LOCAL_CONFIG): action = 'Overwriting and re-saving' - os.unlink(SCONS_LOCAL_CONFIG) + os.unlink(SCONS_LOCAL_CONFIG) else: action = 'Saving new' color_print(4,"%s file '%s'..." % (action,SCONS_LOCAL_CONFIG)) @@ -1409,25 +1409,25 @@ if not preconfigured: # common_cxx_flags += '-DOSX_LEOPARD ' else: pthread = '-pthread' - + # Common debugging flags. # http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html debug_flags = '-g -fno-omit-frame-pointer -DDEBUG -DMAPNIK_DEBUG' ndebug_flags = '-DNDEBUG' # Enable logging in debug mode (always) and release mode (when specified) + severities = ['info', 'debug', 'warn', 'error', 'fatal', 'none'] if env['DEFAULT_LOG_SEVERITY']: - severities = ['info', 'debug', 'warn', 'error', 'fatal', 'none'] if env['DEFAULT_LOG_SEVERITY'] not in severities: - color_print(1,"Cannot set default logger severity to '%s', available options are 'info', 'debug', 'warn', 'error', 'fatal', 'none'." % env['DEFAULT_LOG_SEVERITY']) + severities_list = ', '.join(["'%s'" % s for s in severities]) + color_print(1,"Cannot set default logger severity to '%s', available options are %s." % (env['DEFAULT_LOG_SEVERITY'], severities_list)) Exit(1) else: log_severity = severities.index(env['DEFAULT_LOG_SEVERITY']) else: - if env['DEBUG']: - log_severity = 1 # debug - else: - log_severity = 3 # error + severities_list = ', '.join(["'%s'" % s for s in severities]) + color_print(1,"No logger severity specified, available options are %s." % severities_list) + Exit(1) log_enabled = ' -DMAPNIK_LOG -DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity @@ -1447,7 +1447,7 @@ if not preconfigured: if env['PLATFORM'] != 'Darwin' and env['CXX'] == 'g++': env.MergeFlags('-rdynamic') - # Customizing the C++ compiler flags depending on: + # Customizing the C++ compiler flags depending on: # (1) the C++ compiler used; and # (2) whether debug binaries are requested. if env['SUNCC']: @@ -1457,10 +1457,10 @@ if not preconfigured: env.Append(CXXFLAGS = common_cxx_flags + '-O %s' % ndebug_flags) else: # Common flags for GCC. - gcc_cxx_flags = '-ansi -Wall %s %s -ftemplate-depth-300 %s' % (env['WARNING_CXXFLAGS'], pthread, common_cxx_flags) + gcc_cxx_flags = '-ansi -Wall %s %s -ftemplate-depth-300 %s' % (env['WARNING_CXXFLAGS'], pthread, common_cxx_flags) if env['DEBUG']: env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags) - else: + else: env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags)) if env['DEBUG_UNDEFINED']: @@ -1470,44 +1470,44 @@ if not preconfigured: if not os.access(env['PYTHON'], os.X_OK): color_print(1,"Cannot run python interpreter at '%s', make sure that you have the permissions to execute it." % env['PYTHON']) Exit(1) - + py3 = 'True' in os.popen('''%s -c "import sys as s;s.stdout.write(str(s.version_info[0] == 3))"''' % env['PYTHON']).read().strip() if py3: sys_prefix = '''%s -c "import sys; print(sys.prefix)"''' % env['PYTHON'] else: - sys_prefix = '''%s -c "import sys; print sys.prefix"''' % env['PYTHON'] + sys_prefix = '''%s -c "import sys; print sys.prefix"''' % env['PYTHON'] env['PYTHON_SYS_PREFIX'] = call(sys_prefix) - - if HAS_DISTUTILS: + + if HAS_DISTUTILS: if py3: sys_version = '''%s -c "from distutils.sysconfig import get_python_version; print(get_python_version())"''' % env['PYTHON'] else: - sys_version = '''%s -c "from distutils.sysconfig import get_python_version; print get_python_version()"''' % env['PYTHON'] + sys_version = '''%s -c "from distutils.sysconfig import get_python_version; print get_python_version()"''' % env['PYTHON'] env['PYTHON_VERSION'] = call(sys_version) - + if py3: - py_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())"''' % env['PYTHON'] + py_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())"''' % env['PYTHON'] else: py_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print get_python_inc()"''' % env['PYTHON'] env['PYTHON_INCLUDES'] = call(py_includes) - + # Note: we use the plat_specific argument here to make sure to respect the arch-specific site-packages location if py3: site_packages = '''%s -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=True))"''' % env['PYTHON'] else: - site_packages = '''%s -c "from distutils.sysconfig import get_python_lib; print get_python_lib(plat_specific=True)"''' % env['PYTHON'] + site_packages = '''%s -c "from distutils.sysconfig import get_python_lib; print get_python_lib(plat_specific=True)"''' % env['PYTHON'] env['PYTHON_SITE_PACKAGES'] = call(site_packages) else: env['PYTHON_SYS_PREFIX'] = os.popen('''%s -c "import sys; print sys.prefix"''' % env['PYTHON']).read().strip() env['PYTHON_VERSION'] = os.popen('''%s -c "import sys; print sys.version"''' % env['PYTHON']).read()[0:3] env['PYTHON_INCLUDES'] = env['PYTHON_SYS_PREFIX'] + '/include/python' + env['PYTHON_VERSION'] env['PYTHON_SITE_PACKAGES'] = env['DESTDIR'] + os.path.sep + env['PYTHON_SYS_PREFIX'] + os.path.sep + env['LIBDIR_SCHEMA'] + '/python' + env['PYTHON_VERSION'] + '/site-packages/' - - # if user-requested custom prefix fall back to manual concatenation for building subdirectories + + # if user-requested custom prefix fall back to manual concatenation for building subdirectories if env['PYTHON_PREFIX']: - py_relative_install = env['LIBDIR_SCHEMA'] + '/python' + env['PYTHON_VERSION'] + '/site-packages/' - env['PYTHON_INSTALL_LOCATION'] = env['DESTDIR'] + os.path.sep + env['PYTHON_PREFIX'] + os.path.sep + py_relative_install + py_relative_install = env['LIBDIR_SCHEMA'] + '/python' + env['PYTHON_VERSION'] + '/site-packages/' + env['PYTHON_INSTALL_LOCATION'] = env['DESTDIR'] + os.path.sep + env['PYTHON_PREFIX'] + os.path.sep + py_relative_install else: env['PYTHON_INSTALL_LOCATION'] = env['DESTDIR'] + os.path.sep + env['PYTHON_SITE_PACKAGES'] @@ -1515,27 +1515,27 @@ if not preconfigured: is_64_bit = '''%s -c "import sys; print(sys.maxsize == 9223372036854775807)"''' % env['PYTHON'] else: is_64_bit = '''%s -c "import sys; print sys.maxint == 9223372036854775807"''' % env['PYTHON'] - + if is_64_bit: env['PYTHON_IS_64BIT'] = True else: - env['PYTHON_IS_64BIT'] = False - + env['PYTHON_IS_64BIT'] = False + majver, minver = env['PYTHON_VERSION'].split('.') - + # we don't want the includes it in the main environment... # as they are later set in the python build.py # ugly hack needed until we have env specific conf backup = env.Clone().Dictionary() env.AppendUnique(CPPPATH = os.path.realpath(env['PYTHON_INCLUDES'])) - + if not conf.CheckHeader(header='Python.h',language='C'): color_print(1,'Could not find required header files for the Python language (version %s)' % env['PYTHON_VERSION']) env.Replace(**backup) Exit(1) else: env.Replace(**backup) - + if (int(majver), int(minver)) < (2, 2): color_print(1,"Python version 2.2 or greater required") Exit(1) @@ -1557,7 +1557,7 @@ if not preconfigured: # if requested, sort LIBPATH and CPPPATH one last time before saving... if env['PRIORITIZE_LINKING']: conf.prioritize_paths() - + # finish config stage and pickle results env = conf.Finish() env_cache = open(SCONS_CONFIGURE_CACHE, 'w') @@ -1606,7 +1606,7 @@ if not HELP_REQUESTED: if env['PKG_CONFIG_PATH']: env['ENV']['PKG_CONFIG_PATH'] = os.path.realpath(env['PKG_CONFIG_PATH']) # otherwise this variable == os.environ["PKG_CONFIG_PATH"] - + if env['PATH']: env['ENV']['PATH'] = os.path.realpath(env['PATH']) + ':' + env['ENV']['PATH'] @@ -1640,10 +1640,10 @@ if not HELP_REQUESTED: replace_path('CXXFLAGS',search,replace) replace_path('CAIROMM_LIBPATHS',search,replace) replace_path('CAIROMM_CPPPATHS',search,replace) - + # export env so it is available in build.py files Export('env') - + plugin_base = env.Clone() # for this to work you need: # if __GNUC__ >= 4 @@ -1659,7 +1659,7 @@ if not HELP_REQUESTED: env['_CPPDEFFLAGS'] = None plugin_base['_CPPDEFFLAGS'] = None - + if env['FAST']: # caching is 'auto' by default in SCons # But let's also cache implicit deps... @@ -1667,22 +1667,22 @@ if not HELP_REQUESTED: SetOption('implicit_cache', 1) env.Decider('MD5-timestamp') SetOption('max_drift', 1) - + else: # Set the cache mode to 'force' unless requested, avoiding hidden caching of Scons 'opts' in '.sconsign.dblite' # This allows for a SCONS_LOCAL_CONFIG, if present, to be used as the primary means of storing paths to successful build dependencies SetCacheMode('force') - + if env['JOBS'] > 1: - SetOption("num_jobs", env['JOBS']) - + SetOption("num_jobs", env['JOBS']) + # Build agg first, doesn't need anything special if env['RUNTIME_LINK'] == 'shared' and env['INTERNAL_LIBAGG']: SConscript('deps/agg/build.py') - + # Build the core library SConscript('src/build.py') - + # Build the requested and able-to-be-compiled input plug-ins GDAL_BUILT = False OGR_BUILT = False @@ -1702,7 +1702,7 @@ if not HELP_REQUESTED: SConscript('plugins/input/%s/build.py' % plugin) else: color_print(1,"Notice: dependencies not met for plugin '%s', not building..." % plugin) - + create_uninstall_target(env, env['MAPNIK_LIB_DIR_DEST'], False) create_uninstall_target(env, env['MAPNIK_INPUT_PLUGINS_DEST'] , False) create_uninstall_target(env, env['MAPNIK_INPUT_PLUGINS_DEST'] , False) @@ -1716,43 +1716,43 @@ if not HELP_REQUESTED: if os.path.exists(plugin_path): color_print(1,"Notice: removing out of date plugin: '%s'" % plugin_path) os.unlink(plugin_path) - + # Build the c++ rundemo app if requested if env['DEMO']: SConscript('demo/c++/build.py') - + # Build the pgsql2psqlite app if requested if env['PGSQL2SQLITE']: SConscript('utils/pgsql2sqlite/build.py') - + # Build shapeindex and remove its dependency from the LIBS if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']: SConscript('utils/shapeindex/build.py') - - # devtools not ready for public + + # devtools not ready for public #SConscript('utils/ogrindex/build.py') SConscript('utils/svg2png/build.py') env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND']) else : color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' won't be available") - + # Build the Python bindings if 'python' in env['BINDINGS']: SConscript('bindings/python/build.py') - + # Install the python speed testing scripts if python bindings will be available SConscript('utils/performance/build.py') # Install the mapnik upgrade script SConscript('utils/upgrade_map_xml/build.py') - + # Configure fonts and if requested install the bundled DejaVu fonts SConscript('fonts/build.py') - + # build C++ tests # not ready for release SConscript('tests/cpp_tests/build.py') - + # not ready for release #if env['SVG_RENDERER']: # SConscript('tests/cpp_tests/svg_renderer_tests/build.py') @@ -1762,7 +1762,7 @@ if not HELP_REQUESTED: # write the viewer.ini file SConscript('demo/viewer/build.py') - + # if requested, build the sample input plugins if env['SAMPLE_INPUT_PLUGINS']: SConscript('plugins/input/templates/helloworld/build.py') From 975242e597ab55d92fd649f25519615035cd94a1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 23 May 2012 15:40:25 -0700 Subject: [PATCH 06/47] disable non-critical failing test on ubuntu --- tests/python_tests/map_deepcopy_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/python_tests/map_deepcopy_test.py b/tests/python_tests/map_deepcopy_test.py index a2dc5f7a9..bd5eaeda9 100644 --- a/tests/python_tests/map_deepcopy_test.py +++ b/tests/python_tests/map_deepcopy_test.py @@ -33,8 +33,10 @@ def test_map_deepcopy1(): eq_(id(m2.parameters),id(m1.parameters)) eq_(id(m2.layers),id(m1.layers)) eq_(id(m2.layers),id(m1.layers)) - eq_(id(m2.find_style('style')),id(m2.find_style('style'))) eq_(id(m2.find_fontset('fontset')),id(m2.find_fontset('fontset'))) + # fails for some reason on linux (not osx) + # but non-critical for now + #eq_(id(m2.find_style('style')),id(m2.find_style('style'))) if __name__ == "__main__": From 1077b79a632453dc1c9fa7fb9930ccc03c0c326d Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 24 May 2012 11:37:24 +0100 Subject: [PATCH 07/47] Revert "initialise blur radius's to 1 for real this time" This reverts commit f76c6ee25f13c140195aa476990a58062f44ab43. --- bindings/python/mapnik_text_placement.cpp | 3 +-- demo/viewer/viewer.pro | 27 +++++++---------------- include/mapnik/image_filter_types.hpp | 3 +-- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index e22eb26b8..13de8478b 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -193,8 +193,7 @@ struct ListNodeWrap: formatting::list_node, wrapper ListNodeWrap(object l) : formatting::list_node(), wrapper() { stl_input_iterator begin(l), end; - // FIXME c++11 : error: call to 'make_move_iterator' is ambiguous - // children_.insert(children_.end(), begin, end); + children_.insert(children_.end(), begin, end); } /* TODO: Add constructor taking variable number of arguments. diff --git a/demo/viewer/viewer.pro b/demo/viewer/viewer.pro index 6d112c1bb..538419e49 100644 --- a/demo/viewer/viewer.pro +++ b/demo/viewer/viewer.pro @@ -1,29 +1,18 @@ ###################################################################### # Mapnik viewer - Copyright (C) 2007 Artem Pavlenko ###################################################################### -QMAKE_CXX = /opt/llvm/bin/clang++ +CC = g++ TEMPLATE = app -INCLUDEPATH += /opt/mapnik/include/ -INCLUDEPATH += /opt/boost_1_49_0/include/ -INCLUDEPATH += /opt/mapnik_deps/include/ -INCLUDEPATH += /opt/mapnik_deps/include/freetype2 - -### Cairo backend -INCLUDEPATH += /opt/mapnik_deps/include/cairo -INCLUDEPATH += /opt/mapnik_deps/include/cairomm-1.0 -INCLUDEPATH += /opt/mapnik_deps/include/sigc++-2.0 -INCLUDEPATH += /opt/mapnik_deps/lib/sigc++-2.0/include -### - -INCLUDEPATH += /Users/artem/Projects/mapnik/deps/agg/include +INCLUDEPATH += /usr/local/include/ +INCLUDEPATH += /usr/boost/include/ +INCLUDEPATH += /usr/X11/include/ +INCLUDEPATH += /usr/X11/include/freetype2 INCLUDEPATH += . -QMAKE_CXXFLAGS +='-DDARWIN -Wno-missing-field-initializers -fno-inline -ansi' -QMAKE_CXXFLAGS +=' -DHAVE_CAIRO' -unix:LIBS = -L/opt/mapnik/lib -L/opt/mapnik_deps/lib -lmapnik -lfreetype -L/opt/mapnik/lib -unix:LIBS += -lboost_system -licuuc -lboost_filesystem -lboost_regex -L/opt/boost_1_49_0/lib -unix:LIBS += -lcairo -lcairomm-1.0 +QMAKE_CXXFLAGS +=' -DDARWIN -Wno-missing-field-initializers -ansi' +unix:LIBS = -L/usr/local/lib -L/usr/X11/lib -lmapnik -lfreetype +unix:LIBS += -lboost_system -licuuc -lboost_filesystem -lboost_regex # Input diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index d4e073263..5502f66c1 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -43,8 +43,7 @@ struct agg_stack_blur : rx(rx_),ry(ry_) {} // an attempt to support older boost spirit (< 1.46) agg_stack_blur() - : rx(1),ry(1) {} - + : rx(0),ry(0) {} unsigned rx; unsigned ry; }; From 0542994c4da32babc19da00c3b240fdb98f4a8da Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 24 May 2012 12:11:55 +0100 Subject: [PATCH 08/47] + implement y-gradient in terms of x-gradient --- include/mapnik/image_filter.hpp | 63 +++++++++++---------------- include/mapnik/image_filter_types.hpp | 2 +- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index cd67325bd..4045cabe8 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -402,6 +402,23 @@ void apply_filter(Src & src, gray) boost::gil::copy_and_convert_pixels(color_converted_view(src_view), src_view); } +template +void x_gradient_impl(Src const& src_view, Dst const& dst_view) +{ + for (int y=0; y void apply_filter(Src & src, x_gradient) @@ -414,20 +431,8 @@ void apply_filter(Src & src, x_gradient) rgba8_image_t temp_buffer(src_view.dimensions()); rgba8_view_t dst_view = view(temp_buffer); - for (int y=0; y void apply_filter(Src & src, y_gradient) { using namespace boost::gil; - - rgba8_view_t in = interleaved_view(src.width(),src.height(), - (rgba8_pixel_t*) src.raw_data(), - src.width()*4); - rgba8_image_t temp_buffer(in.dimensions()); - dynamic_xy_step_type::type src_view = rotated90ccw_view(in); - dynamic_xy_step_type::type dst_view = rotated90ccw_view(view(temp_buffer)); - - for (int y=0; y::type::x_iterator src_it = src_view.row_begin(y); - dynamic_xy_step_type::type::x_iterator dst_it = dst_view.row_begin(y); - - for (int x=1; x diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index 5502f66c1..f39d8a722 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -43,7 +43,7 @@ struct agg_stack_blur : rx(rx_),ry(ry_) {} // an attempt to support older boost spirit (< 1.46) agg_stack_blur() - : rx(0),ry(0) {} + : rx(1),ry(1) {} unsigned rx; unsigned ry; }; From bd25a9af92c7b988298597dea358d0d2d66123a5 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 24 May 2012 12:44:07 +0100 Subject: [PATCH 09/47] + handle boundary pixels in x/y gradients --- include/mapnik/image_filter.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 4045cabe8..6ff7b997b 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -409,7 +409,17 @@ void x_gradient_impl(Src const& src_view, Dst const& dst_view) { typename Src::x_iterator src_it = src_view.row_begin(y); typename Dst::x_iterator dst_it = dst_view.row_begin(y); - + + dst_it[0][0] = 127 + (src_it[0][0] - src_it[1][0]) / 2; + dst_it[0][1] = 127 + (src_it[0][1] - src_it[1][1]) / 2; + dst_it[0][2] = 127 + (src_it[0][2] - src_it[1][2]) / 2; + + dst_it[dst_view.width()-1][0] = 127 + (src_it[src_view.width()-2][0] - src_it[src_view.width()-1][0]) / 2; + dst_it[dst_view.width()-1][1] = 127 + (src_it[src_view.width()-2][1] - src_it[src_view.width()-1][1]) / 2; + dst_it[dst_view.width()-1][2] = 127 + (src_it[src_view.width()-2][2] - src_it[src_view.width()-1][2]) / 2; + + dst_it[0][3] = dst_it[src_view.width()-1][3] = 255; + for (int x=1; x From 181c470bd61a4d7b13f770a175bec6e1b39a598c Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 24 May 2012 12:51:12 +0100 Subject: [PATCH 10/47] + correct calculations --- include/mapnik/image_filter.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 6ff7b997b..a92b91fc7 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -410,21 +410,21 @@ void x_gradient_impl(Src const& src_view, Dst const& dst_view) typename Src::x_iterator src_it = src_view.row_begin(y); typename Dst::x_iterator dst_it = dst_view.row_begin(y); - dst_it[0][0] = 127 + (src_it[0][0] - src_it[1][0]) / 2; - dst_it[0][1] = 127 + (src_it[0][1] - src_it[1][1]) / 2; - dst_it[0][2] = 127 + (src_it[0][2] - src_it[1][2]) / 2; + dst_it[0][0] = 128 + (src_it[0][0] - src_it[1][0]) / 2; + dst_it[0][1] = 128 + (src_it[0][1] - src_it[1][1]) / 2; + dst_it[0][2] = 128 + (src_it[0][2] - src_it[1][2]) / 2; - dst_it[dst_view.width()-1][0] = 127 + (src_it[src_view.width()-2][0] - src_it[src_view.width()-1][0]) / 2; - dst_it[dst_view.width()-1][1] = 127 + (src_it[src_view.width()-2][1] - src_it[src_view.width()-1][1]) / 2; - dst_it[dst_view.width()-1][2] = 127 + (src_it[src_view.width()-2][2] - src_it[src_view.width()-1][2]) / 2; + dst_it[dst_view.width()-1][0] = 128 + (src_it[src_view.width()-2][0] - src_it[src_view.width()-1][0]) / 2; + dst_it[dst_view.width()-1][1] = 128 + (src_it[src_view.width()-2][1] - src_it[src_view.width()-1][1]) / 2; + dst_it[dst_view.width()-1][2] = 128 + (src_it[src_view.width()-2][2] - src_it[src_view.width()-1][2]) / 2; dst_it[0][3] = dst_it[src_view.width()-1][3] = 255; for (int x=1; x Date: Thu, 24 May 2012 11:05:17 -0700 Subject: [PATCH 11/47] Revert "update test images used for validating compositing" This reverts commit ac2d935c2825ae5c2c6b54c0c16f9578da2c3f88. --- .../images/composited/color_burn.png | Bin 3892 -> 3951 bytes .../images/composited/color_dodge.png | Bin 3590 -> 3608 bytes .../images/composited/contrast.png | Bin 3185 -> 3099 bytes .../python_tests/images/composited/darken.png | Bin 3906 -> 3950 bytes .../images/composited/difference.png | Bin 3678 -> 3971 bytes .../images/composited/dst_atop.png | Bin 3085 -> 3130 bytes .../images/composited/dst_over.png | Bin 3414 -> 3455 bytes .../images/composited/exclusion.png | Bin 3665 -> 3998 bytes .../images/composited/hard_light.png | Bin 3989 -> 3950 bytes .../images/composited/invert_rgb.png | Bin 3818 -> 3806 bytes .../images/composited/lighten.png | Bin 3643 -> 3911 bytes .../python_tests/images/composited/minus.png | Bin 3488 -> 3745 bytes .../images/composited/multiply.png | Bin 3905 -> 3950 bytes .../images/composited/overlay.png | Bin 3963 -> 3995 bytes tests/python_tests/images/composited/plus.png | Bin 3562 -> 3834 bytes .../python_tests/images/composited/screen.png | Bin 3641 -> 3912 bytes .../images/composited/soft_light.png | Bin 3951 -> 3991 bytes tests/python_tests/images/composited/src.png | Bin 2230 -> 2273 bytes .../images/composited/src_atop.png | Bin 3148 -> 3174 bytes .../python_tests/images/composited/src_in.png | Bin 2116 -> 2049 bytes .../images/composited/src_out.png | Bin 2189 -> 2196 bytes .../images/composited/src_over.png | Bin 3390 -> 3479 bytes tests/python_tests/images/composited/xor.png | Bin 4159 -> 4165 bytes 23 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/python_tests/images/composited/color_burn.png b/tests/python_tests/images/composited/color_burn.png index 3e9c919ec3e5fd97808d5485af7b82bedf71a04d..89339a678d085c0c49b14cf9f3d7c2450732e1f2 100644 GIT binary patch literal 3951 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 Ymf=v|3}ZUz^37bnbj707-0k6i0hXML9smFU literal 3892 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 H`?3E8CeC;{ diff --git a/tests/python_tests/images/composited/color_dodge.png b/tests/python_tests/images/composited/color_dodge.png index e7efa061fb0b6bde319c6c840d165355ab1d0269..19363cc50257f3dac2a6786ef15c2d20d42fe886 100644 GIT binary patch delta 3380 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 Buj~K- diff --git a/tests/python_tests/images/composited/contrast.png b/tests/python_tests/images/composited/contrast.png index bbac2c41a97212efcdcb5f6b921b14083545aeb0..e594597053b04e72aead74109a00052f09472b71 100644 GIT binary patch delta 2981 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 VkVAD!{P$mwz3o}_UpD?X{}0$?-Z=mO literal 3185 zcmb_e`6CnjAD>NP&RWb-CWWNXwdC56R7#gh^%x?guq2!984E)#O)1nID@S@FL{SVW z#Dh7q9NB@GYcs65X5Z=iFFc=LKKJYMet+J_>wWLEn~N$~7YqOZRF54!d=>zZlMUqn ziVCvsudo7t06@j+*kK2EY{vAUS76WBmL{Ra&AfLG17y?Pc@2uY`)~HbwJuW)4>$_{ zlDFmbZtO5Rx>b{;tF4{9=kbS6yYsrsA$G^prmlK>pLlW6pYxIDyoWSeuRMHGkJn&4 z?~fs62}|#!(~h+-N*3)IbNE^gsDVi~W{5M`g2kw4217+A$$!zjHPsP*dME-Dmk`l6 zvk*nKy4{hV?{afAyJ>2+XBdtl)Q^U`^$$h2_fHE}{dYS{3lYmhc2_DR>Yp!#iZJt- zQ>!g*^!H6_0{(}ZBucNbK#BnTCcLPv?8CY9cAnLozW6G5Jmd^ili#vkwz%_S6`X{^9!T~tbY*kAb8 ztmlDs z^W*NKTB%R;8<9;_sJXP?{6|*lb1_2?{R;oF`-#=-KnMW$t59$>SEQ{qwj;AdJu^U#Cid`jUDer&E@O33j4ij+fwArqF zEtX_j)R5YQ=N>vg5`G5^w$OrMh)#QUW?4`U#=KO;9byDqK z*U*8k8D;pCWLci+EMC<8S7iRPuu~x$w}6uEJ~#5t(Qp{38Vo9BkC_FHM?zO(Uou~a z1v(x_sDGPI@o(TlM@NYGN5xM+g5XWYTVrTSHJkXN(2T*$6UJW5z?71jwh2~kw0m#q z^CTQJgc+Dn`+$i$bLQVL`pw&FQcpO6Dx;Vj>Y0&Xs}Zf~zFc z@qECAJo{*HQO%R(l}leT0DMidMF&KshtZ%5YtjGB%|7Xc~(dIE#hMw6-(HIpNDQfkTv-kQa-YB9Imjan79$KCSk z3ekqR#q~#-+76!@C|>E%Ist%0=XP6e)jmX6#zRB&Ki&x;h2N-ozeua&wm^_gaEA=#n~9*7 zTf=FdJ<)Ts1yAr*U5kH=aP-mmEpw?8nPtSG*OY?IrN=tCa0Bnx84F*0vbph)SYRU` zVQL)?0;bk0+us>U6C0YmN!a!U_@rfqkyLhN5NdVFP857Wj1qYG1g5Ftp`rR8_g=c~ z#qksEUn=6#S*4EPGAVevcE-uZ5?L-i`s~FP?PPbiRqiSxt3+KxBTHg(Eny!J7*^%#TiwA>Qc*#Z9d}13`ri_o`j+$NirOpD8SLAD3g;uk= zAu>v5bnRxp(hZ#Kgb>x5TZS!`w)m=~W8-gm2OKmB?yMq~#m6FtRoBN^4}*v^a;JTM z0yP+DWzK_>$RV9IuyVP37Xv{GLjAa*DjTuV?xBH{K|sj`Ge`DsrziOu=}V z8c=mp04Vuo_vUx`V(TVQ^-`f|?PsoM@$Y!?MpktQ4M*rd4(W5a2{%F0$g_Td(slf< zGgOf|$JWutvbtlHTvz9&Ckr>*+2-ZYN(<~e+j9q~vnaL)s6sBc0KEuP`XskqP_hhr zij-EEbM@B`<8Tl=3vaGgcuw?TQAGqyXtQQP1@&v*w(_#nEAxL1o&+ zIIi_m^^d*Qbys4KGG~5gC+3Bn?I^l^<)`wCf5s=@*$eJGPzh9e?B+CSA@>P<)W?!H zsZ6PY9`5N{Bco!k5h674al{ug0`gMG`4jkcmz-Q^)g^P;=>(fXzGq$J$i({MDyYlE zq4!O0k;NA`asD_5n#ucSnGYh9^H;5A&Ca~e(4HTEmNuwt)Po*6H6$wu8fAWRgrPWN z*tt@M{i^kB@l-~CjOhc#Zmm{Cxn$>6Oob>Ciq_}ObgbykETf!!x0Z$?$dOtZX=qeMNj{ zt)Pj4LO#7+qr^Q6x-j)+3%^0@vRbWQ0{sWnurBAzILYPjPObjf@wf<>_1+q`akaA5 zjqmz}v!z4UOsZ@xwf-s5Uj84fQ3tO=p@GtRwhvO!b)ylR2@T8RBf-1tcZRR;op#x} z-z2%d)=Zos&u>o ziGG)Xz||bE<74J4AM$mhKF8Cevym?G5q;>XFHRGict+c=g=`E;Ib|{FodE0XHs%VW z^vHy0BsK0@xk^vJZ;E*!WH!XiTg1i1&&EVq#|1)!i3NHp(W0g!g6b21>`wcyHzJ5Rcoz<9^ z1An7cVBb+4{Sdh^oJxzhnuu4>#dS62E70aY|B{peALko(uaALmIFHpum=EuCVDmrO zov}GrvD12IQfQ=s1_q%WzF6ejcD|r{8$3r{QIjuHqShX|P8NSK5HXhaNo+hld9^+4 rPIgZM8SKfP+GPD-l-e?kg8Ndr;mWJ2|ITBeYmmpB-44HX^p5!-pJ68y diff --git a/tests/python_tests/images/composited/darken.png b/tests/python_tests/images/composited/darken.png index 5a288f0a4d98e0b83a25ee84a3ec4922d8560101..f3d8be583cbb61595e4307d4dd85c2226928eb69 100644 GIT binary patch delta 3759 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 VOlH(ubKSoOdfG->pEMj}{|hi+o(2E_ delta 3687 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 diff --git a/tests/python_tests/images/composited/difference.png b/tests/python_tests/images/composited/difference.png index be0863c6e62ca507d54338db35aa985b47a075e8..58ae797ee9c9951e5af9b51a27572ab4fa7ab951 100644 GIT binary patch literal 3971 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 diff --git a/tests/python_tests/images/composited/dst_atop.png b/tests/python_tests/images/composited/dst_atop.png index 83f9b08f43f581060da69fee8e666c7e82b73096..53a56f13a7fb9606d97f601d13c51e8976ce582d 100644 GIT binary patch literal 3130 zcmb_edpr|*8{f=zZgXoLm)znC1A9Qrp4%q1sKjdTO4x92a+P2_99!?(Ppps70)@w84z$Q8-dbkf+W~TY%%)gL z*zk8N5WLayg8k?F@Yjd{71YDfgvl49%(CWJ^Ec-wp;bcv2vc3 z2K-Q(b7Jg=(cwhGv@g5fN!uo|pV1?g%EKG$$TSSkP5<0y6*d{{c)c}iv)C-8!x%cx z+DTPN-cfR-ZjyZC8bdx{izZ~AMHApUL zcF@Wy`|H=HisM@Q0B zi-z^C&8_;IBZNc2eO(u-03Ye7t>W?*%C8rBmzGak^N)hI^xUlqkAfUH-;85Ct@yBA zg9H*m*s?iI*Df2&C5@en`wkODx##MhM-sDJLDJ7IPCe@UVKV6EkwLXUnv#b$mu9nZ zxP#_`7uLu)Mm*Ru&B&CfhmD^??bGZvWRp6fGX*Z zK#*IQjnN!Eq*1qeB|Ti(Xm&@VbGGNsxfe}(7VA%)%F|J=8(N_e{g=a&RWh*mwFG+J zxOm5X9RpSp$8Y}pf@_dK=PIl`i@e@Kq&Klt6(Co#Wi-+a9XJwmc{2t=54wKaH1r4- zCi18cq}?bqw&viVAsFWXKbx#91ab0r9>O+tL2f{cqt|KWColI(fdM7^&N^eBbKUTybE|Nf!3H;j|UATZuf1|_^o4Nx4w^#-cnD4x9U$=^QM^3g+w+3pusKspfxPnK484Cb~;>apw zu&1R#^$y)>@kUtX;5BC~+@o z;3WFsRg;WTu`;u7Kgz@n}Qrto~a!4_I z>#L`uSJ8e9F%>Sjs=;(r#ZiRcLbug?U8l&qJgVPko0A9z#cX9|j!5`G-Yb1-6$f>_ z>O8>&Rw`DTmsolytvfVJoQ%7M?Q`-XGYliqQv|E?C@}PDMID)QGygwK#E5$TnChPjx<3$amml4H4< zA717)#5aU%rdA2RyBggDGJ`d<{0D;KJKpMi%O4dkWrhJF|0wih5-K$Bsyb!PocG{7 z&ri&a9xmaD8Dvd6^P;z_tsqg{^U2kRiy8m67{Ywi3JuTht3NVHW;RL9Q3-2`aI^ZN0c_Dy$LdeDR)jqE^+jF`9k_DM@Bv-*E_nu0!|4yNr-%gcGe>UJP z6akdZBp@ecq1k#n!-O|rBkJk?B|wPZU30`J!NP%Gk8i_mc`>IFhgUE?wa+)PLRTJ3 zzED@gdle%rrs-C%EiFx4*%o_ zrzKCy(^3k5Nwb-B1%vFSL&AnzC5`eFljAz100$Kg6;G;;&+ z9c9!ltN@tkN~YgN?v)cGhqknk7zl+oA<0Wq8z^Rs$jL8_DUO`ze9%EB;sm+pqhOss zRE-ls?T{5?j@%Ui7)tprKaW&RjqzW%+fd9n`#(SxA?Lq972gH=bO)UzsA^O(ATuoT zQ^IWG+ZT{vT1n$lI@iyz;(>U?#S(m!#2Iie{-v0S-52RaMUJ4ObKT+xDHe#fu8JOs zhB1ky&96eY*%T36;P-M%YT<7hO8-N{@NBbngUDy%1jTw}k(1ZM=y<5ZUrTk%_B>Xn zx`JSLx~v017K*QlVoR&uLB|NzS5aSB>H89(M`zb#SUKBSIks9(kugdoPMHx1Gb+2! z53Eo98yNL^2Fr{PW~;lWtC0%6YiQ7v6P;7R)&iO;%U9h|L>WX(;s5z_oP5l#dtTlc zZN^z?^8b|1%*y<1q0iZ-(PBI59oEhaXUWaFJQD)&OU+A9-q7jS@L+vPbelo<*1#XU z)Sn5^GlR?P8HytWi{L&^P&;hZygxLM>3F*T@C;=ELppmuc5`s0ixF%~>e5v?hU7?M2N`37sc zT-z2sQ`Urjvdk*gwmo&vs-QiL>YeywRUf*yO6AzS?gslKE9-^El{-(&3^eBR9$?#1 zG~A(yEIamSiYi9us|i)LYZW!vhnOU}8%9f?4jameRca|m$MA8)ASP~Kb^9|Iq*p&B zY3bo2siA5!chPAt`)lFP%z7M@=Mmq}KEYbb7twnv8dKy}3ftv8!BTj>R>CBB_L4z9 ziXop{$MK(+rGkDRVE2k^!}*ZB(#P=T<_lJsj0U=|A4V$zHbSKLVJJV9_C$lDWSk4j z(}%wGUes#hEY7*3Ikg=I>p04waQl8SnpB=e9mZ(f-- zjjNVOFn!{acxmK4V`YBE_X91@JC6T=f!>wG0s-p^4$e4fTuM-S-}-^KaocMnzlvuA zT)F10EzQ4Dzgh}z%=VMv$1s}CB|@&Kpd`9m4!bM!{d?$V6V2+5{hTnndjGMJcj7Vj z<@t)vP@$m1PPDB)6uNepuXN9j(W#G{h7#oN^=vQl|H63_u?cmI(qFL%jSbp1=j`a_ J@WjqP^*_|Fx7>yW^BYz9jNklb>{5OmdOVD{1$g_kCvO{eIvF!HI(t&GY`5XWkhR0Fk0de|Sk=n#t16vR0GY zR+gPCyLG8QZb;)`N~R8*(mZ-iUVHYLd^XhRU+b@Bf3KhYbNl+w>hE#CcO(0Et!7!u zGHw0e2S9!;^d(p5J6hboE$X5&Ez<*cf!J~vh6OGRK*6-g^vym3zkye0rM zugc8&by+{UFGr&a|74!uzcBpfdVBcSSN~*Q%z2_6hwMVIf5IyQDraF<7IyzAyXP(X zQTfLw^TP+TADb6*p6J|$>nOC0e=I<;F1;z2PJ7IsH2Qk*w>LjAFXp__b|&)#NRB@0 z_ijticj2E*|IX#;Uk&t$z_k;3H9*{^UzTZ|(SPqP9S-e}9I+L{_iL>R?+2WflI({Ivbb@T;rK=7pR$y68z4Kw1AhfpgIbKJDRK z75>TST7uXo3N^a?nE3$&OS(HwhlYDujlZ1~JZ#>9gRq@V$GP>c2 zbpi7vfYNQ?td{ z)mRF93g`|))?*I=pxrlqXb&O@D_3O2x|m|k->-Dc3)s^|fJwnB(rvtW@1Hz69}xSY zr5blc8QY6h&B0&fz`BTH&kvuzWnREOqDPZik4KcKyDVMn;z=cX2#Iw8`v|)YSA_1{ ze{WqhsU?MT2i*DqT7xO0HI@V!8y^n_k!{fmos z1yWcb)R4x3^;ks#_{6vP@aZsuq&GaZtpnysfu&bX#%j;`MX^=vt3s zOn{kx`=rtlupY~pK$VX33N;BGGscHPG0`>utopN$t`1D$8v(Wtiwrycgp-7J4r&<> zYn&IYzi>iJ5T(*BzO4s6Ii3`@5@%shBzA7ej`e^i$MgNIcg+jfN3sjRiuL%$e;Eeb zGO!--o87 zJ>GEw?Z5CtI}nAS{TEMY2f{nvfB)l2Lh}IZ6ch@+{f{T?5diP@?#iC^z$WL*KkxqD zym&ob0M@O?Jsb}Fj3-YwFPayxkJO~rvmW=5pLhSU9@J#Kq_9iSluY%l$3BD(K#ZXi z0B_j-E55Kz7`&ka5MSs7z#9(!j4vD@3U4_5C%$lM5WHazfcWyHJ8NFNe?C%^+J^P` zue|;}>01wIGG2bX_l9}#db$AYSdah8V-Zk%d4B(bdGUI>0PI?i|H|VCu=t`!hFKS{ zk8osI0IUZynJm`D>mvQ+5Krg;z`M?(bgTz9IbR+v-Y_p-PZxk0f9r7%hfY8|p#y+I z47O!pJ-Er~`DyzV^Wyc9y43fq$2(5w-Ikv904JxXf9JA!@%l*i_`hmB-f;r+0O2R0 z_y3mhaK}k(5E_0`*a&n=rVg#gI!0h`fN=A}r*D}TuaDHEwq-reF+z7)y4C}oyg1)n zZ<`mdk7SSkOV;BYeiK-;u6gn1O;egj)?*nH;?y9!aQY9-f3@eOZCwae&6jU~XkNUY zE&%NO6Ej+Z<%iZEg0V0w3)TfuwLF;p*t~f2hJ`-~;Q-O{!oi;i4jqB=lFH0KcmKp} z-IOis;z&K;-MnI6yq@m<9qaK5&veT$RtFXrUGOar#Ur1uje@$w;)?*X}qb=w^DYX5jWqQD(pNe4fP=EP$`91UE z^$|Y!sTfuW<_|0W5G`FBKv!V$=&XMVJ^v}0>eKVDD0U8-JPGaebIE!f!Vt@Z#}CVW zkqlac<3;!QPod?tEXVMR&tzDBf>tYKnUtfFQym)2R}7}KY*?4~rm(`#E$?j^4-Zs< zemjuD2SmD;UkYpc>r&rmJ1>+9K!xeNKuoU$`pBQc`@VbR zXA5uG(?du0yRvUx+-K!UcQ%Q`J8Dwf;d5RDe<$RFM^ZSr!?pO>y%*uqa|aGL<XZXJ!Ya0(OA7ItAlMBSQWl*-SySgW%I(#8@FpOcYVZ1I|X_ONtu&`I?1Pp zb;Lfy?-uo}SpN)x+;oz#jFzFc_F|vpbMN_GCi##YT|iXCC&v2eZVK=DZg!vde56e$ ze+qqkW~_Jo*bnB^JH8&x#WG%0j=mab>u{W9#kzb~TY9lS>NliupzruR>I0efytGey zJtLTA1mFFxEvr;x6Ci@g69FK2GZeK_9KPeWnFi z##4gc-E~>6o4MCXyan#^Kp@k zgcPGRjAe=}$5@83`;K${-hbZfdfxSVpZmU_`yD-VcqZjMaMS39j#XIhzj->|*0yJQ z+n>4_RDAf5_T&fDF|nA-Xh^?E4;{Q38|xwX9OCw>#ElPnsw}A&-eQP4&C9LKe?{nl zzqE&laEt6nTw!(B$-k1KrOyhP=nUzrH4JRk*?HXbp|#G@7~?^J_Lfc}F5Tb@mZ3hk zJBaNE9ksOCV|D<$f0Q6W_3K^b3?-?13~UGFIJbD4C|EWHVn&xIFk}0hF+?>HKl+#% zz6sZ>TKZ^|Fo7c3lpzpNl( z7@)QhVoWii+^=XeI7oQ;0ywzKypf5LT|2zgaagFf_~W+NomY*&&(fBq??J1Tn|?-I z(fEqp>d@LMroE-BwmI}rk-sjw{)op&G!oqVj~Bp&l(HRqw=x-{<=;1bYo8wC){}nz zgGb-Xlkl!A@=Rh~i|!d>I$^>YE(25m_=5OB3M!dK^xISVqdYl0bbWq*EKsosr(!5` zNv&$_NW9lNruATkJ;CZ@;rDQ{i-InnnIkm@VqSISGgV94<>6|W&4{D%5n8;eDsgfe z*(PPt*k-%auQBCj{h83t$O(ka*2w35(gN?rm+cr&u6~@%hF#b-ZvT4-_y;wABa=tC zoSpisr7Lc$+G>aOIN;aF?A~U33nWM+!`O;%1TU`JSs``v!xdVzRVeU&^;rfUYyWE zGp$fo(t1F3IWs5LVvGY&g_~1$DTq13CGEJZq^KhLv$(Def3K( zIn-S^8))>?O^K>I!GF>4D|8cUn_OM+^XwP(I;Yg->7IR(`3@%{a0T;68>B`B&KRmU zemQ=7LlD91z+y&$#XbrVbKqwhju03QrYRAD727w>OKh~y|eSI^UBdlIWZDNs!soM``}?Hru8n^v%S%3;mOsXNg+|SvulWmQwiFG zk-rcf(jycPT7WfQaN~FUkn7!r6DJt#)xbpjWVFSjU%RVjW&Vt)1x`bOgX3)S&mf1C z%qe%2;?fAks^L_P!J^pfKtz_@UCp!ViYq*$v%UlPDA#d$g%sWBp;$A`mE`7%sYJzx z*2%{�MUTB{fYW>+3bk&|*q{!_O)Nl=>py1j(H==PKR5Mt?T(Le~LJ=9EYB0|hg% z)(pPR)Z*rLmQ+{ZE@hg387$sqECM0ktoeDo)F5=g==VT^Cjsk={y|Ea%0o9-DWS94IxG zaGAvPJ(An&)HE&32wRKOd8*?R2Ec?&hb1o~f?!kdO$SW3hIx>C$VVG8gs-e}`NYa` z8a$c0RfWx+#sXMx-e)k#9L{-Y|-PFk>rMOJj7P}D*CxY%O zOyu`O@!UA)wOAuzZk2?Zd8AVP8Lixju>AEVBhamW7;|`U|hvS)bA5s%0*=#H?7B-5^$YZFgXhU z2Mu_AwwCkwzX+1FIPoj>C@ju-Q!&Kz1v^jmBewCc2gb5lsE&mN36gYf{bR_{jC62u zc{-;?!y9ig8Ua-8!zZ9y?zi(Cz=~r9U?65XBue=rc*rsnG*}N!d=(DC@S2dJhG*d9 z^8%;9LL7xzLLB;_(vCker5%DDu2Rg@Zj@k0fD1E~-XVz6gELd(r36tXO3c(u7eSOI znweTw@Emo=pPAA$^&F+H6mEFh|GdA-DUnOI1bwb7g4@?Xb?+M~P@tnoh7&GGbhKGV z!0j&mr$8j>@%tJ+v{f;#t6;kl571eHd#7D``*_&o(Q7}XSJMK-{+UftAwzgyklASst}`pyR8{EM=Z zLt~Wt&>0#h_b@Xdsdt>97E2zbt|SkSyPS@~z3gKG?27q?4dOUoP<-aZ;R&7F@c7J4 zXBk2R_>{3DI8&FEZ{Z9cm1FXDpaVDCO90LHuD3`KSmvbS1Lft;9LoKiN59zI>VB>B z!usK%+?8Oyu9`<7TQO|>DZL!j&eJu9w`Pnub9jrOT;ZYgfmgTKm#EH=-NT9Am3orb z_aPrzxHk1vpSpsuvO`#oZP)El4~5+g{QB`|SM|Mvy#n@5D+Lnb>&dMZb~!+U3ZpYF zpt`DE$l(#&9&j?kl8#^JnQk>LrGIgvQW+AM+i$OWD$oeW=*;bzz(X$}g?02*Ny{j-h-7MQEXUK?ZB;%R6 z_!TefdwXNd&(J~slEtHf!_N76%;r;Q^6~Nu1`&nl3}I#GfO)MyPuQM|g&@5!BW{>W zPhh{958`|EWL*D3J4u>v$_Va}w)0$X6-1N;=85_o7@|X?gk054U7MXNwL*8#>4k6z z@qh5+!#xt-PMLd_{wjL|tty@`&oC?Oy7ilEwWXij7td&3YGW1jW>sZ5^AY!toL1wy zykNsUzfl0cVmo0Kx&!fb8O3Yri85Js+9okGlyvR5jkdDA#+A$J4-}h%zh;sMMeP4iaPJlp)$L$=z+eo!Wj!+NLl$5J@Fshw)vLH&+JrQf zS>Qb1eMvNE;b~p< zds%wirQ%W@HbZ=Znr0+*R33ZdtEyOVAxUp)-;Ax3a9I{B6A0 zkr5PsTZZs<5M|jeolDa}^aDmOc(Tg4dNJ|1yWq*CYwz$HZW+$s5zBc{9RIn zZO4b(E8oW-*yMk`N3pr{8O|Y*Hhs+T3<%WJ1%N54-9bKK#UV!@2qS&-8@0MFG5-TD CYi~aQ delta 3239 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 P9H5s?txR5B#Kis&Tu5Al diff --git a/tests/python_tests/images/composited/exclusion.png b/tests/python_tests/images/composited/exclusion.png index 1ccb4eb22e7f0f882ad865b03b3ac293c2fb1528..3391778b34a313514be3b1fbbae27a5154aa09cd 100644 GIT binary patch literal 3998 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 diff --git a/tests/python_tests/images/composited/hard_light.png b/tests/python_tests/images/composited/hard_light.png index a55ce1aee61bc0d664dbfda8769f6e708402dc70..4332e44973f09b06e7df65f18f1ab3da3aa3d924 100644 GIT binary patch literal 3950 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 literal 3818 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 F{{xSgD;fX* diff --git a/tests/python_tests/images/composited/lighten.png b/tests/python_tests/images/composited/lighten.png index 60f9eecce9a1543ffa37ff281e5dbf2e6ce4ee48..8b0b23744b091d85c4298fd1fa4467510f4344fb 100644 GIT binary patch literal 3911 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 literal 3643 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 delta 3311 zcmVF=$oU7KT^x5Up&6R4Ec(VG#?NU}c0b;uOjt zq!8pbazh$@V3FNU3cb&8L z-sk(^15twr=ig`Vz1G>=43jYqSdp*?f8Y!*U$V1zcJ`mx{_Ayn z{bpcqMq4&I+P0$)zuJe-zu9N0U+eb{pWETVh8^hd>Sy$`FCN*8r+4k?o$GdI=BmxK z_+Qb#^>gLZ$`_S8m3x)1E8kWgR=%tJQ2F`94=2Ajs{H-r@9v%a>}KU^Cy(4I~;IG%#qenQ~yz&nlD(x`L{3e;Mkg{KJk1 z2n{Y87#59z0a8YRA3U&u-qKA6eOxtr&_JY_f(EBE{u>IJ-s}pV-r`LMeOxsF4eWS8 z0Ek0x)|H#Kvb$!xZM@w*X9>e+e>Ut_vy+qA!JHkxWrxobHC@`8@ zr}&m1$3H9oSNW-O<+*+S+ruhQGvR^um>p=T(&k!&!U6t5&W~J`IA~N4`#!I z?4in;>=VE-n(C{3#~c4*&aPPrO9RaaR8C}R&}I6|*3YSgcUJKK)k64B{l~9Wh#pj4 z3J>zMs+73u{aiufs3Atpe=*VF^$7pR7K8t_t1qh%Er*BLLp449?ERcUVrZSOw%q98 zdIbMdVDP_Iy#xhp6iT%pvp-NG_ios|+}HW1;g1gd_pD2Y@gbg8?GG>;C?j0PedV!{St%BYQ(DSvv_OM+|R0rpT! zf;s2M7Ccy(wT0Z9dQQV19oVKUWM4qdLkr%|FHC_Ndnobcq1_D+u!kxYE_px4FabK1 zCpx$u=DgWAuJr*VfAJyqaK-z1hB46TJki0O*4%gcC$*po!Bh7K8_q|^YDb6HBm6lu z_cUewiE$Z&z^3~H4&SGQH^1!SoBwO;14rTm%uFB`So4?Xl}F*>^^!e-CecL~(ZThw z3%mW}T1a(3QXOal)%hv)m2Dw?0xA*GC*X-X{Alv&hJ|ztf2vt%&N&9%M7{mA_jbp+ zZMckY2h=vqw*%8s$_YLteAv^L^-*JGoGI|yJrG@ja$k3)JlJux=@%Vb4_Wt5uH6a` zua|5Jj)RWz8g1DqI=mj?XWc)!^?pG9mzGLhQO5CN7e!ZdMTghJ|0EEi-2G`IJiK1M z@Xkq*=+oZlf8ct^)Zfqg5|a1;d&p_SXQ7fG^?v-8h1@%!{s2mY-(&xY?MH`qS}FN8 zV|}(@8D9?Wxd*2N=<~<(Eac)5$@c12aNwP<imGuzS(r^^l$acni8_tUDhHm2%7%U4QY`-GOC%BhZcG!*s%Lba*{v`k#&kog6gh z9JlnKfAojmQWDGrwf)lggH2e-QQ~Dc2K8=PukEllA)9~c`NQMz@Os(v&RsGLpV_eO zur}ex1Ri+&tMy$1@!|Dw=$*SHVET_uThKC~JUHY+9-T2~)}ipV1FF zo^2sVh8?;GFcO-7ur2LoczC^>bBWoYhH;e8`!6Z~ zr7z{c1fl$gZAv*XAvpO5+qR&6fc#Gi;@f|0Th0hbi1qun-c%^tl%v1$@%ppy;Ci|4 zoyXSMU9;V$LfNKV_?eF@&%=Z3^!y| z?=VLADS-zX$Mcu1@Zfs6ch>==+csMoAek0cZrmC}{*r09t`DN?L&v zfRBMNN@Rr z2gV3#15O042E(@HYOsXha!_nrE(c8rDgoHGQ~(lU=Bmv!70NbcA0Qv?W_WPDobk?M z2vh>FO{oARMk${Ke@x)v#;t6l>{@tmy zVp|rp{-1M>VJwHw?Xc;9HZ21{fBF`35a^+M0Hfh-0BqWyHo}AJ zm2vt{zE^;a3ugqNmwfx5Deqs}`{)2qE6ad*Z6-Xp9=>xASn6v;X z_3+?&S;omf<3dRgCzaA)0caLLV-QZF&4&lq!}1${&Vvg?aa_6hvmn$Se6(#x(E*-T zW&!P4(9VCi-~Okp+_aVGe*k;PETDO>JPHr4mn+^m%9?`>JBSYOw9*~etaaC48ApD- zbq`SPaAFXiXF(_aEPCgs2=<@YesqARRRaJQiTc~ywo-cj_uPY13MvcIB8=a%kh0$& z*43t;i*o0>-H8schYSLa;eQYwTra!z!Ox`7A&95a@z+7r8!+0ke^GRRr26oKy;9DwV;!J7QFM(31}1UuC)6?O)1BRQ5w9s^%?(Vl>EAL z%vV#WG+4^TqU;BpZ@um>tnskDEDo;Kj3gaCCmgg2y}5KFuPVv_<8e3!k$2W7Id8#YyK2ab$}9K9u~6OuTmeo z{VAb70h)!@f)Byg69VPXD_50}9QvIB$zA3EH=w@|UsR*OZ?l zymLm!i|stNo#+sI3<5bc4c#7CDVKNb7@zZ&!@V1Jk5XZ?7IJZiN_?E&TO!&ZEailu zPYDG6)RpH}f67LmPVix)uXJ?xKq-3z9|MD5AKkSa9$F7|YA-{DtNPtW_gf{f56;oyM{a^D|lt7KT0_VVB4(>i}(Z1TY=+8>}=@O|q~ zcgtAkYj>Y@K71Rs6YFX+W&~fn@$5g&5qZ_ ztCd4Le|~#L2l=9^gr_&XPUT^W53y*OpmJi0dj@KH(#ED5pfqru@!wF8bkdDB%=95l zbjZK;mRI?X={=;2LZ$&hn}`aY+K=0qCFt$0<%!CfTB_)%w3D~|r08cgAZTi>@|gnI z#w^5%44=vUKk9c!+jRqj8reGL!_?r6(KN85JvWeHNh*6-=h zG`rB>)z9c>HMl6~db3X%^l{O@rPf&u3<{|RhdnzEtp*9T*1og94i+Cyeoue)`^n$k tJNa21tF2`SK?jpD4p@<}1{i>I`9BLMTO`F^EsFpE002ovPDHLkV1gYVrZE5j diff --git a/tests/python_tests/images/composited/multiply.png b/tests/python_tests/images/composited/multiply.png index 78fa3e7daad6cf28870eb24a0abf63f246ccf71a..f3d8be583cbb61595e4307d4dd85c2226928eb69 100644 GIT binary patch literal 3950 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 diff --git a/tests/python_tests/images/composited/overlay.png b/tests/python_tests/images/composited/overlay.png index d13a1c6281f0e3edd254cad78872a23c2b8f42cd..64367a3425912d064b5937cf7a63201f6166f64b 100644 GIT binary patch literal 3995 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 diff --git a/tests/python_tests/images/composited/plus.png b/tests/python_tests/images/composited/plus.png index 499ffe01bedbdaf1cfded03c9f3c9c862ff0b836..d43b2d414a9f13959245ea918be58d4ea9a8163f 100644 GIT binary patch literal 3834 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 literal 3562 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 LNkvXXu0mjfb}?dU delta 2138 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 Qy#N3J07*qoM6N<$f|j34=>Px# diff --git a/tests/python_tests/images/composited/src_atop.png b/tests/python_tests/images/composited/src_atop.png index 6ed75a76f18f517ca45dd40508c39d755eba6c16..7ef1234bead888bb065752d6687f1c0f30188fdb 100644 GIT binary patch delta 3043 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 delta 3015 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 literal 2189 zcmb7F`y-S4AAe9AVT+t1np@e?SvJQ>%w;$(_0^G*V<(qwcHC+eNs)=;a#mS{;&*S_32hQ`$^L#$f`}KamU+?$(^ZH!&_w&)+ zw0#o*0J;bEdmaG*HSkjn(1d}nkTZ`X0YLNU0Z;d%iG|Z22$y~i+6sKx;tjXj;10L& zXx7VeOE)rXiafY!qc-27y2ao*(Se+2joE4a-oW~x-u@VL%+81Q+Mj7VPttgQUfbQt zQv}akgrj_KWhD(S&QI0L7Be)$O>E&^DKcf!gf|%TA3Z{@(`?sDc6G%i{tM#D4ACUH z4mEjbID1i9Wpo>hZO$Tbs4EK-v&)3W%cqq^d5vAePR3EBBIY01xo%1K$8H;Cj!$;u zBv~(LTgBlu6}&lB+a-Grr@c3OCD&{1QTV=dsoiQ8@O%onnnq6Bhsnm=nffJh*&wwy z%hmo2aBOu2B}wxy`tB3&enHio^-DeD?jb>MN;@ZWEN=Ccc=+Prpc>}$*}{hTU+9Xr zD{(50^nUTk^azf%r_V9VD#g%L8ADK{me@!Fsfl*DpVA@skq!1vwd zqKtkPY}p$}L*LrYCCUUZZ@(S;$|1GBRY8#~IQsG0mH0b754OaKGlJtL8B&k1y>mSQ zsI-zU^bgkE`jrj-1$nKxWk~L|Gn4GvOF>sDDcnH-Ge$3L?Eh*(5wL^Fd7B08Uc7oy za#(0{seo-i;%Sbt}>y@&(YvlP=*m);=u8zjAHcx%42+f&(6UNTs&t?k=wV?`L!AO zFi3A9tslFm)3E&8-Y^{je%pj=nazl`#WSl?C>5;v6L96hp%9NC7ZExW8Z=!VaUht@ zz{1~B*J2WE?j3LmalSU1tVZ;h*)$*P7Hwxw`gubC*2i8-K@F-4Mr&1^h|(ZyT(Z$aWfM(pr3hj^4^W=40rZ}@8ZVUwP~zNEdZNTV&BF}HilZ=0hJqDDs(oeWx`0{C%~NbraUu{6nd@$Rek87QLQx&#q6j z!jwSJ@wFnL!1g4MESTEBW!AVEL<-B?any;i)fW(;KYaQy6eCJ3^h=oa(`yxrpxKD` zYk890*W%>$wDoH*w4Q5cL*^kyFy9iJA?xtkxzhl!N6DnKtTm$ zi&5w4(=>QYN6ig(l5cUsg52N80y;v+?vc5su;5QJj(RJd$BfZN*hvg=!t13?WI+gG zlU*bnh@@c^#X;)@SOM8cL~3a_@p@?2$53QT`{F>bqtCZE!Jz~(VJc|uJ3mJ&8v_gf z6@3VK)eRD%Qn_ZQeV>M;F@4v|vVtSmW-8lm#NcGy?ZN zBSuE<4q8hV$qAs$4#*jKcnu@*t;N{`~~Q_5yL*wCd|q1>ewRN{(dEr{w&@h zPirlo?WWf7+f!`Bp^EDa)fPTC))M|Z=8cI-Kd59|Pa^b_D$hApkyLT)HqwM_Jhelz teK|@VH5c`~?3~|^2Kaw;X#+s4fl5s@eq&lp=G8*b173cf%ANc?P diff --git a/tests/python_tests/images/composited/src_over.png b/tests/python_tests/images/composited/src_over.png index 57415c5f0275255dbaa8b13971f5875a3c4eef56..9efe5be5ad96be8b33d8390803b7aababf5fd5c6 100644 GIT binary patch literal 3479 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 O8hz~>S_K-mLH_}M=9N_d literal 3390 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 f{%5MWwQ|vjZ2x)hcLEQzgfOA_aXcbVlzxW diff --git a/tests/python_tests/images/composited/xor.png b/tests/python_tests/images/composited/xor.png index e2bde97db4de0a2590b68e06b1f20c2dc7d22432..af5bb3351fe92e1cb867c04b1bb53209117fbbd8 100644 GIT binary patch literal 4165 zcmcIn_ghn0*G)($QHT^@hYpSgh#(3h2FXxE(J)j+MhMM_0t!Lt2!uAEBIt~viP8}S z0Z|YT2vtx)i3A9p&|3%zQbGxNZ{~ZxKjA&U-1|J|+`IO(_StK%{m|ChLhO+2ArJ^8 zcIl$2JqQE_Ucn#{A>e_#S8@{s5*NK>YJ4U1#p+8dFIP|5gtcpGJ~F92Py3u!pceAw zLYLkq9a#C^`9)&%l7;$iqtF*L`IwbkM<@wm8Sk32tSyp$` z^OHVG;Lw(;+eYR65#Hn%+j|o^0WSW=uf;GK0XYE^+hN~-VgdaB=_>Q@9shWXHZw9X zRyN;X^6IARKo0}?ElMlz3^}`>mPB>J=~Wgf@rsm)2T!6t9K7c-M=U;m@HanvP6m}ez<$Xhcmq1HAD29sZ5DvT*S3AM6Fj<-IXhw zw`XLV4=N_OY)mBQ{bmj~L^bFhyCfxQj<}M;?qyQRufbxC9~_)R#)}%5tAlG`iiG?| ztAW`0^f=~Iy=s)fkL0X8CW(BFV?Lb~M-U|sU#Zv9U4$3KF?03Cn&Cmk5zYkSnp`|V zldN@TaNgKY^yxYH{_Jt9UF7&uZf)75V#JB{tXP6|d6aNsk4>;}uMOK;xXC3FGEzSN zjC?%sC(k*0lCHWkbt{O|cGqRGld3=K+&1R@O(%WQdLR9Ji7;=rm{DTB@R1#OWGBtv zR@gAo#72I874$I{GUK>%G-rL4Gv2k!R3cJ^Z3qrLb6>_}fxgmriQB280am$D`>5 zj>UnSsV;h@Itk>|ZgBWqyfrRaVg6J&py26yQ9oHEJYLzK^mYyi0GcYR8$SOS%ZG_RR^srYA_Fx;o$l z2bavy5)0@4BKjng`;j+=(c8GjP<9-!vhj;v?yM1(VCzl#)&s#g5LopIl^0u^UA84> z$#!1jQ9TDnd7_2|Q)9H9L4-a+d^a_4>1^vRsD{*WZHF0gQl|XHg zY^MWiOkmKOXW=3G{EzJOEQjgh%)7%*-L(!yHYcfegcZO6{nvk=-9VCn;c|+ zAvP%LN}^jDVK+>Xw+}+x`tM_vqmgx&(UVCEbn$np6psjs8G!m0-oRaTG6`z2S6CFU z_?d3ItX}`!Z9sAtiu<+DM)@q0rJnbtOCbuY?1gkT>B`OeYf)M>{{Eh&*IE#Pcxkoi zWuI?5A_7hS;6YXpF@i}&;F#)D?b&`yc6db3QC583rt7xy*T|r>b@y-VS8f0#>*wWN z91MEO;>ZeXp$Z~za$az>1K)V8xJDY?=&&h$W{|r=+XL4tIr&7I%FKKkX|V|S1Sg1W z@0$@F1dP89TWoyJ9sRVh!R?21jE)S5Kko|G2?6 zqk2~z1zM3`B)=>86G26-4jKAI!$VW$rx4BG7l&gJ5f^mx|4v#h%2y%vE#$1XD%3l- zwVp^@6TIp^_4wHJ#M)AWymS}d_oY%Jn3xG(wqeZr{G&vhh`Z(MOa2~p^UZ;-mi)^? z+fOwzT6TvufdK`yCPaH}f7&XtsuRa;sZYrfzebJM#=pzGCEUMzIy%J=R~aaBGbQJs zDo(D=a&6@wNfA?p&9F#-i#Dh8!d8lXHyEshx8Lzi_?4>Zs&=`y@e%#{w4S48u+zx>^F@F}%G}_mY@SQ%JdA3MAd2u(XvH@brG0#0e)BgJu3OMq) zFegyM^PcT#71-t7c8a}Z544t>M&ZmzOk(M6UCwD|v5lP0+)itq>xrm%0)v)?rRR4! z`_Z;gcwyamKz80_=ReLwm)8$XiA`bjNAjVX;f+PTk`ELn#8Z3%{Wgz!9;)OGd0So+ zdXrXg2kAL|q}_m;`p_8G&NK{mDh0zXw}EpMcZ#5zfp>giC)y+4daa!Fyomf}2vn&n z3^zM8azamA3EgsBqZC;J$PFK;Y9SE!?-p20J_$h5j|2}RgA^bgNMoxQRDVJX2a2Fh8j0HjX ziwI>fb_sN2-!V#CMFU&{a@TkbJqZ#fUe~x_bPlY`6~=#gZ47G>1wHo6*-hZnx>rr` znG5u6=_z~u5Wsl?xZ~s5re^W13hupOBJ`Y5AQOY)It7M^y&%*
cOT72v8>pVRT~%+L6%-)Ytn7XrbtXszT8W z&^ZAQ4R0tG`1GDIr7r@FAFWO79;V;2#B#{^xy8%mgcbt5XM+5 zO;ped+8K)%l{uU(QVqe2dPA(CDMIaj-9Ox6ty8%}z8B=r9WQ~p*A@vp6>mCH@^8Sr zwE5JQPst%$4^n!%fFMv_7(yA&Q!o|8cy$FNSwQNIRa*XW4B;Pxzr9A|9^s#{(9xsm z*=7D1E4vBs#u^IHtAJ|WyR#ZCl)~4Ebm9}5(;O0wT@tyWq#S8^jdyDj9EzqH^wkW3 zD^5X7sI~FNxqP!y{)~j|5o)pCd!RTh1yDLx$-U*+ZJ)*n$2IUXMlE=LRp1x&!5~D> zUz2}p0OL}gR-{qC;5UxBAdW`PHFx}56kz!Axt5K>{d92hOCO-^iA)YvqEcJTp45(2 ztP=R-?hQ=-sc$CJt_?zaA}e_zOBMGWZS3Z4#abxu_HrbO&IxL%Xeh|=Qe_Yka&)Az zyv#8-CGgd@jhr`6K(~Ln33XT7*)qKB7m+Vl1;Guh84QMCm7zgf)z(BgKs6O;oK3Xq ztFyW~B4uBf3}r5VEzJEtWx*)umlnA3c}dFLr)rX*cbn{Y)j`dIB#Lxk5Y{o(NNsr* z_OebE_)EFjOz%rN$nK6K{6IsbR`|?Inmq&LnEJ?QTf=jqdCP{EB_DM)kuM2r+T3+CEy4-GyD;QTp-u)0Vy63EVM_JhO~< z?xB`ydrjrF&6U2?UMHDwEQa4V5)u;vE@G(s0w0NFy?0#{@5t(7J7UJ<-s+Zr0&-n? zA5wDYjoaF8y6sQH*Uysr_eXDx9`ogQKd1Y}!@Ob=+k+%T ztGKnFZo6JKkWpzp)#nZqP6{XK?tw!FR}Li2BleyFCJpO{F{>W z`!EW@39S2lr{kBA*md^{_RP2-EuGTW{P?@$f)v%6RTBu(-j?^|l?S(FM+)On;7RB* zN9Am83?31mqe{Gi9hNGgYT=9I7d|~Vl)x#d<(dAOxNHP#;A(DGjpj%*rPT7SmCPE% zNG|XDt>=BuQHyL^R?qVtQiwy;h&43T#={M3xBI5jb^YWH!tLF<;CCIkt41&-@vt;E zSQFPE@#$Sx87+3K%Jsy$(h70;`_^5lMo(#YB$|t^#^+1X)B-aA6QB0>B#UfhZ7I;a zp8j@XTix(P<8NIvpBft!(H#z(c_%P7OJN9c)&S%3q%ABlq|T{zp;1t4|8at)+J9a} zur9)cL+U!ZHYQBiLLM-wga~E})p?*2YC=Hy;E6D~$ZUGMxtkbk7=mDk;dCnwAKCOu z`c-hUpaH%_;Tv2Bo7K73ZkXry2YQ;qKBo#One=_LG9j$*yiFMk;f(iFD-X=mHBlEO z2$I%7k7e#bCQdTUzfg*r#!x$r-zR|q;m&&NnNVVGyibhW13mV`D#P*99xvC%BL{aV zlC@HMUhl>xMH=m-r+>p6vI7h=s5TKw-^}FBypcI0CW{{UQ@7wRzEMvX(p30By~@~f zN#D3f98jVTc~-K+1`@G#1r#(BFv0dM_)!TbNJItKZ*Ut(u1~17qf{&=g(M`u5$W#HQ;D%xKr$8iXVHFqh1%O)E^?WB&`W0IOGXFN`j@ur7q>$Pc;qI8UqvHT2bO~v+ZnzQ?Tq5~*ROi=M%P*I&04DrTFT~1r^~Uzs_00P@b`R%{ zo-M5}O6?bM;rf`!V=D`7FQk3=6mE0VgKO@A<)X0xT)+K^adsGby7I!FH}@QGSe4qJ znyfKD#S+OJXCoI+4A7^wkRQp@@17pB&hOQ=B3dSEnZ9o04s^;`4+#)<-vvChj)bNwl9bSc^X0=Lum1NnFobY~|1&CUWd z94n1xKeL7UrBw|q8D?!ScR_ni=y%yZog0YY~KB_zY+|`GyhWOo{K2tH-x)x_@P(}5aH$&c0+HQ_yf1VhSHZB zwsUD~y}Sz-$xQsP!-9N8v+LmemzY7wtUOh<`susW-Em%r(LzV@SvPJs&ZY>pA|K&8 z-I>+%u9!NwOnnUhX;3@WFu$xrnaoCe%2Zynn?#dvPgruf#E$r4!xU9kk)N$5f5~8%ZR+^DyWk`X~g*en0ywV~8f7s8* zh;6ILK@a@3h32uD;$mHB=j_*LmgL}vkrTPEH7$N~?=fXf4)i1Tnw1yDtkOh7$w!91 zpDfq>)9=Wk7+ubu4TiNc&@YChR4uA-#Ya&zQGC{J$p$&FylbUUMJOj?V~e6@?f&&U<~!Az4YR_O{h=J2 zE8e63t+Yiv*sa)sVO^st&1t%m+`9Gln5r6gPDKu^ZIdh<&@>0$_;J zD?jyqd`zv-G)U`fzbKMXF;dZd;^ZD-J52W&Hz^pJ9MhJWSo7v~8YzfbZBxH)R3iAa zMO@PseB8bru`lmFaMMa5MkUg^ZQ>Dp(l{CP5KL$hbOW{)dRab7FIKuPSY#eE->49j zMI}0Tdh>4>zVtS5i$H{!T!Qqacz+S>VD@UA{XYh-0RtFGMhidsH*P|3zC+*fAzLc z*$_jFu`0j7v{JaDzgv=xltVNsZghK5&g8{z_f8Boi80nxUH$;`{l`S!6b6iWjjWss z`a&i~Q<+<;v6Cb(C{z48mydL)t|Ho`xT5){qZN+O{aygI9TIf?wQe-Z+)TNk)942Q z5mHSgSg6rO{F__v1{`1+YpPMlBlO;gg~{EtZFY)?J-(aWF(eZwzge!P=d zT~@ZE8XKe21dHZBeLgB>0@S^fOhLU2QmkP)(sX$wZbBgRZj*0>acB;BcDor@V5S+0 zVW+^yBquO8byJNMGH0E$xOx#WW<&q}%>CT!@)$lLc_FFMWn)vd`uz9<@Q_pHb*(0+S}k^^ zxHG!I&OUrjvoDJMYjEy^o`46k+ZibUrw6fC5&%HRhjrYz;Q#-KoHMeTq_vLUq>*xg zcJ>Kdq#Y*=YJFy93?}vP{ku)x^RjjV+wnCzIY6&~#Ca`FAu&GSAdW=qU)Kn*nBySn z4yeu7R`Ea~3!Ta;Y_0aKA2$FR2o!pITBj7E?mI@YU6`8#Y^(y6_~(>~I#F`_fj31P z;~o97Rpvo>U&~M`fQ7lF&KP~Lni1B^2{2Q0;Z*Ylb-z;)k!FPubsyIFft%^A4+7Fk z)pEt8J*^NyULVWut472uv@3LB&fYej%|E?-FnWuxF})IWDZvr+ScMFFep^b?QwB)t z*J!C{+6t|IY2N~O2@xyu4=eNe2(&u&2)_bhM2QtMp1F|8&|8m{a`?}H_)Rolh(atu zm*Z}$9f!UEi3)sn(mtYdSX$(%mX})O$u9B7TKQsnhxKGc6VF-@lpu+Osq!B|UBp~i zO!Et2V^h{{_SR=02!p>;U$fes-JP-dD+sKG7sVw9(@4U`cSvi_E9a&Sav|zLtfhli za)1fs$om1LeMa}iya*r;D`S>fj^JbZ5ooJxzoM1Zwm(?=Lj_?qC*&osfE9_}HyTp9 z8WqAujz57<)@m#0U{TT#4k^2K6ls}3^9RXRbLWem2mM55~Vw?|;4O-2PV^wV+K!a7v+IFHP@PNi-_v%cf_O_O)}vtxFFQ@%h+h z0<30s^+d}2?1}$diuVIbM3l^@r;Li)TUGn2&9xVyvwnM5_7+}_Y~j(aJd~Q zukIuj(W_##+7OOyD@j{r_UCBrI|!}oQs+FY4Y0w7PuX+LmTU)W!4+&cf^fphd0MmI z|5{RxwbS|XOF}S8{Z7f?%iwQb`BkDD%1FjH-p@e+K-nSo94=>u*^Z$Zz}NCM3_ zO^28Ne2VEFdXqD*y&HGWQ&5j6Dj~)!xtDfOy-#*0-+IhSw(Rz-4jPZ0DF0OQZHTX| z_#uCx@CF&pMHTKW_fOdP@{l33G2)-agM>0<`=|mo9Q{5ENX!MsPpdkOy)=i`M0=Sr zO7^OU=@+uSXTza*6hTQ=ZQg#0C1~hEWv6LQjS6DcCglHg;P5~27zj|3tRw{#V-Y~x za_Qfd*oykp91(e~oH)$45a{a$g`742r9V~%K5$xdY^Wx7?QF0r+1DHjQCDK>RKtLp zQ(N<*lO}r^YcoEb*63|TjbaB!O z-*fMs)UHvwbIZkhuN*J`B2&e(VpRz9>U=#+D8%Tus$S|Z`ScY~@~B9ql?LOhWC(6X zgMp<+&v+Bj-y`eO(E!8NlwAz-+7jRbq78E(+HTSq@KZ9*jL?a=bi_ZOU{>)e@`ety zCisn{lsSshlo$*?Uy zqntWZP`JM0WnyJru>w386yv>u0fe}laiHAWIE5BCAl`)JKa#lN| nOFnv-2^suP|C2!=R>D500^ug!pD~tmaFnI_)k|fjx8nW_yF2c0 From 6fd92dcc3e564c3a8099e96c24790d98c55147bd Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 13:41:00 -0700 Subject: [PATCH 12/47] do not premultiply the image mask being composited to the target buffer - fixes #1211 --- bindings/python/mapnik_image.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 9107aa881..3884b5c2e 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -149,7 +149,7 @@ void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float op void composite(image_32 & im, image_32 & im2, mapnik::composite_mode_e mode, float opacity) { - mapnik::composite(im.data(),im2.data(),mode,opacity,0,0,true,true); + mapnik::composite(im.data(),im2.data(),mode,opacity,0,0,false,true); } #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) From 225678eccbc887e774e16dd127031784d7678f87 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 14:10:52 -0700 Subject: [PATCH 13/47] restore pristine agg2.4 agg:span_image_resample_rgba_affine - refs #1227 --- include/mapnik/span_image_filter.hpp | 79 ++++++++++++---------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/include/mapnik/span_image_filter.hpp b/include/mapnik/span_image_filter.hpp index e32b5a249..a4f81593f 100644 --- a/include/mapnik/span_image_filter.hpp +++ b/include/mapnik/span_image_filter.hpp @@ -27,9 +27,9 @@ namespace mapnik { using namespace agg; -template -class span_image_resample_rgba_affine : - public span_image_resample_affine +template +class span_image_resample_rgba_affine : +public span_image_resample_affine { public: typedef Source source_type; @@ -48,17 +48,17 @@ public: //-------------------------------------------------------------------- span_image_resample_rgba_affine() {} - span_image_resample_rgba_affine(source_type& src, + span_image_resample_rgba_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(src, inter, filter) + base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[4]; @@ -67,11 +67,11 @@ public: int filter_scale = diameter << image_subpixel_shift; int radius_x = (diameter * base_type::m_rx) >> 1; int radius_y = (diameter * base_type::m_ry) >> 1; - int len_x_lr = - (diameter * base_type::m_rx + image_subpixel_mask) >> - image_subpixel_shift; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; - const boost::int16_t* weight_array = base_type::filter().weight_array(); + const int16* weight_array = base_type::filter().weight_array(); do { @@ -83,17 +83,17 @@ public: fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; - int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; int x_hr2 = x_hr; - const value_type* fg_ptr = + const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { @@ -101,15 +101,14 @@ public: x_hr = x_hr2; for(;;) { - int weight = (weight_y * weight_array[x_hr] + - image_filter_scale / 2) >> - downscale_shift; - + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr * weight; - + fg[3] += *fg_ptr++ * weight; total_weight += weight; x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; @@ -120,31 +119,21 @@ public: fg_ptr = (const value_type*)base_type::source().next_y(); } - if (total_weight) - { - fg[3] /= total_weight; - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - } - else - { - fg[0] = 0; - fg[1] = 0; - fg[2] = 0; - fg[3] = 0; - } + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; - if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; - if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; - if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; From 28b9729ae740b5b6a04a3992cf548b22a0d7fef1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 14:11:42 -0700 Subject: [PATCH 14/47] Revert "restore pristine agg2.4 agg:span_image_resample_rgba_affine - refs #1227" This reverts commit 225678eccbc887e774e16dd127031784d7678f87. --- include/mapnik/span_image_filter.hpp | 79 ++++++++++++++++------------ 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/include/mapnik/span_image_filter.hpp b/include/mapnik/span_image_filter.hpp index a4f81593f..e32b5a249 100644 --- a/include/mapnik/span_image_filter.hpp +++ b/include/mapnik/span_image_filter.hpp @@ -27,9 +27,9 @@ namespace mapnik { using namespace agg; -template -class span_image_resample_rgba_affine : -public span_image_resample_affine +template +class span_image_resample_rgba_affine : + public span_image_resample_affine { public: typedef Source source_type; @@ -48,17 +48,17 @@ public: //-------------------------------------------------------------------- span_image_resample_rgba_affine() {} - span_image_resample_rgba_affine(source_type& src, + span_image_resample_rgba_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(src, inter, filter) + base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[4]; @@ -67,11 +67,11 @@ public: int filter_scale = diameter << image_subpixel_shift; int radius_x = (diameter * base_type::m_rx) >> 1; int radius_y = (diameter * base_type::m_ry) >> 1; - int len_x_lr = - (diameter * base_type::m_rx + image_subpixel_mask) >> - image_subpixel_shift; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; - const int16* weight_array = base_type::filter().weight_array(); + const boost::int16_t* weight_array = base_type::filter().weight_array(); do { @@ -83,17 +83,17 @@ public: fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; - int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; int x_hr2 = x_hr; - const value_type* fg_ptr = + const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { @@ -101,14 +101,15 @@ public: x_hr = x_hr2; for(;;) { - int weight = (weight_y * weight_array[x_hr] + - image_filter_scale / 2) >> - downscale_shift; - + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr++ * weight; + fg[3] += *fg_ptr * weight; + total_weight += weight; x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; @@ -119,21 +120,31 @@ public: fg_ptr = (const value_type*)base_type::source().next_y(); } - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; + if (total_weight) + { + fg[3] /= total_weight; + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + } + else + { + fg[0] = 0; + fg[1] = 0; + fg[2] = 0; + fg[3] = 0; + } + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - + span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; From 19631e50e2bf295af87d186c2de6417d0df4a25b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 14:12:04 -0700 Subject: [PATCH 15/47] restore pristine agg2.4 agg:span_image_resample_rgba_affine - refs #1227 --- deps/agg/include/agg_span_image_filter_rgba.h | 45 ++++++------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/deps/agg/include/agg_span_image_filter_rgba.h b/deps/agg/include/agg_span_image_filter_rgba.h index 77949f9d8..134a80255 100644 --- a/deps/agg/include/agg_span_image_filter_rgba.h +++ b/deps/agg/include/agg_span_image_filter_rgba.h @@ -725,7 +725,6 @@ namespace agg base_type::m_ry_inv) >> image_subpixel_shift; int total_weight = 0; - int total_weight_alpha = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * base_type::m_rx_inv) >> @@ -740,21 +739,15 @@ namespace agg x_hr = x_hr2; for(;;) { - int weight = (weight_y * weight_array[x_hr] + + int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; - int weight_alpha = (weight_y * weight_array[x_hr] / base_mask * fg_ptr[3] + - image_filter_scale / 2) >> - downscale_shift; - fg[0] += *fg_ptr++ * weight_alpha; - fg[1] += *fg_ptr++ * weight_alpha; - fg[2] += *fg_ptr++ * weight_alpha; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; fg[3] += *fg_ptr++ * weight; - total_weight += weight; - total_weight_alpha += weight_alpha; - x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); @@ -763,26 +756,16 @@ namespace agg if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } - - if (total_weight && total_weight_alpha) - { - fg[3] /= total_weight; - fg[0] = fg[0] / total_weight_alpha * fg[3] / base_mask; - fg[1] = fg[1] / total_weight_alpha * fg[3] / base_mask; - fg[2] = fg[2] / total_weight_alpha * fg[3] / base_mask; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - } - else - { - fg[0] = 0; - fg[1] = 0; - fg[2] = 0; - fg[3] = 0; - } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; From e1fa732f9049b6365e5e49edaa676056b09335b3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 16:39:24 -0700 Subject: [PATCH 16/47] add test for alpha blending during bilinear scaling - refs #997 --- tests/data/good_maps/raster-alpha.xml | 19 ++++++++++++ tests/data/raster/white-alpha.tiff | Bin 0 -> 1001391 bytes .../images/support/raster-alpha.png | Bin 0 -> 4442 bytes tests/python_tests/raster_alpha_test.py | 29 ++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/data/good_maps/raster-alpha.xml create mode 100644 tests/data/raster/white-alpha.tiff create mode 100644 tests/python_tests/images/support/raster-alpha.png create mode 100644 tests/python_tests/raster_alpha_test.py diff --git a/tests/data/good_maps/raster-alpha.xml b/tests/data/good_maps/raster-alpha.xml new file mode 100644 index 000000000..163bd463c --- /dev/null +++ b/tests/data/good_maps/raster-alpha.xml @@ -0,0 +1,19 @@ + + + + + + + white + + ../raster/white-alpha.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/data/raster/white-alpha.tiff b/tests/data/raster/white-alpha.tiff new file mode 100644 index 0000000000000000000000000000000000000000..b25998986c861480a78fdb45e4d04dcd8ec95c5c GIT binary patch literal 1001391 zcmeIy&5Koa7{Kx8zRbOMX70>nVKo#vqEQ)oh=g7s8j)V4jMB(jRD{~1f>ZXo&=zV8 zMpP6L2iPFX#N8@9&&@7MBla z-MSUgi-^-A8m(yLbTm(m1#>g!cJ3d@qcy)jxUVxmH*;RpXvdCR_h&4g-yi(u%mwpV z^Yon8{*IJN$RG7VJABkHvg#pZ}|XZ9P}pJxA_4+lZ$*7cD~elMQ9js;>bdN9vkzqdp51Rp zeQ`UA8`@Fc*N$pW_S@NCX8)4i8H)P+p(w5yigL?PRJ*d@%>FFabtlTZ zI#KP&el7c>?C-LVWlwgaxS|{7?cJyz??(M{_6OPDWFO5wqZh@cy(l;IqI#$o_4C>9 zWq+OhNA}oo6f1|Lym2_H`-h``I(u*SSJ}U2cSoYQU?j?GN21y~67}xvx3WLa{yDob z8pYDlD5poGx_dP0C$nGA{y6*l?0>S)=|_2GKdL+WQ9sd-;+5=u*@v_L%3eGc$c7JJW_7ke&WLR zn46os*Wo{4fB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz U7+`<_1{h#~0R|Xg;M6qmAM%Fyi2wiq literal 0 HcmV?d00001 diff --git a/tests/python_tests/images/support/raster-alpha.png b/tests/python_tests/images/support/raster-alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..a84c88eaf333db3b6a5806402442bcb922800ca5 GIT binary patch literal 4442 zcmeAS@N?(olHy`uVBq!ia0y~yV2WU1V4T3g1{5hWm7Br9AgJi+;uumf=k2wHyv&R| zEC=6z`@LS_ARl*Bw3NY}CtK?5&VNpv_?@-k|JA=q6|b0o1oDeC%zjm8Sg~Q-N_MUT zzNPymY$9%7VP<`>Y*##w+?w21jZ6i>clFu$ubF*yVBE3top>{Q_Ux(!40l4lcOPut z>T4Uokhkjh(FX@_EtAt=FbA6ZAt5(-)Y#EL7)=SI* Date: Thu, 24 May 2012 16:57:17 -0700 Subject: [PATCH 17/47] add partial test files for second case of #997 --- .../data/good_maps/raster-alpha-gradient.xml | 19 ++++++++++++++++++ tests/data/raster/transp.tiff | Bin 0 -> 264370 bytes 2 files changed, 19 insertions(+) create mode 100644 tests/data/good_maps/raster-alpha-gradient.xml create mode 100644 tests/data/raster/transp.tiff diff --git a/tests/data/good_maps/raster-alpha-gradient.xml b/tests/data/good_maps/raster-alpha-gradient.xml new file mode 100644 index 000000000..a3638cf87 --- /dev/null +++ b/tests/data/good_maps/raster-alpha-gradient.xml @@ -0,0 +1,19 @@ + + + + + + + white + + ../raster/transp.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/data/raster/transp.tiff b/tests/data/raster/transp.tiff new file mode 100644 index 0000000000000000000000000000000000000000..f8a098b42b66052c2af6660c24ae00b20a116d34 GIT binary patch literal 264370 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 Date: Thu, 24 May 2012 17:05:51 -0700 Subject: [PATCH 18/47] remove option to link againt external AGG - our local copy has critical fixes and is required --- SConstruct | 17 +++++------------ src/build.py | 5 +---- utils/mapnik-config/build.py | 4 ++-- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/SConstruct b/SConstruct index 0b793578a..c35e77aaf 100644 --- a/SConstruct +++ b/SConstruct @@ -323,8 +323,6 @@ opts.AddVariables( BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'), - BoolVariable('INTERNAL_LIBAGG', 'Use provided libagg', 'True'), - BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'), # Variables for optional dependencies @@ -1244,15 +1242,10 @@ if not preconfigured: env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree') env['PGSQL2SQLITE'] = False - # Decide which libagg to use - # if we are using internal agg, then prepend to make sure - # we link locally - - if env['INTERNAL_LIBAGG']: - env.Prepend(CPPPATH = '#deps/agg/include') - env.Prepend(LIBPATH = '#deps/agg') - else: - env.ParseConfig('pkg-config --libs --cflags libagg') + # we rely on an internal, patched copy of agg with critical fixes + # prepend to make sure we link locally + env.Prepend(CPPPATH = '#deps/agg/include') + env.Prepend(LIBPATH = '#deps/agg') if env['CAIRO']: if env['CAIRO_LIBS'] or env['CAIRO_INCLUDES']: @@ -1677,7 +1670,7 @@ if not HELP_REQUESTED: SetOption("num_jobs", env['JOBS']) # Build agg first, doesn't need anything special - if env['RUNTIME_LINK'] == 'shared' and env['INTERNAL_LIBAGG']: + if env['RUNTIME_LINK'] == 'shared': SConscript('deps/agg/build.py') # Build the core library diff --git a/src/build.py b/src/build.py index 2a13f18e6..7df2f8eb5 100644 --- a/src/build.py +++ b/src/build.py @@ -75,10 +75,7 @@ if env['RUNTIME_LINK'] == 'static': lib_env['LIBS'].append('icudata') lib_env['LIBS'].append('icui18n') else: - if env['INTERNAL_LIBAGG']: - lib_env['LIBS'].insert(0, 'agg') - else: - lib_env['LIBS'].append([lib for lib in env['LIBS'] if lib.startswith('agg')]) + lib_env['LIBS'].insert(0, 'agg') if env['PLATFORM'] == 'Darwin': mapnik_libname = env.subst(env['MAPNIK_LIB_NAME']) diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index 8519051e0..22f23bfc8 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -56,8 +56,8 @@ ldflags = config_env['CUSTOM_LDFLAGS'] + ''.join([' -L%s' % i for i in config_en dep_libs = ''.join([' -l%s' % i for i in env['LIBMAPNIK_LIBS']]) -if env['INTERNAL_LIBAGG']: - dep_libs = dep_libs.replace('-lagg','') +# remove local agg from public linking +dep_libs = dep_libs.replace('-lagg','') git_revision = os.popen("git rev-list --max-count=1 HEAD").read() From b7052029d8a3f06d2afe53839b9a3e53f5174e9f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 24 May 2012 17:07:56 -0700 Subject: [PATCH 19/47] start requiring >= boost 1.47 to enable things like the carto parser to be integrated soon --- INSTALL.md | 5 +---- SConstruct | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 386d6afd3..d525be56a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -37,10 +37,7 @@ Build dependencies are: Mapnik Core depends on: * Boost - - >= 1.46 is recommended - - >= 1.45 is required if compiling with clang++ - - >= 1.42 works on most systems and most compilers - - >= 1.47 is required to support wkt/wkb geometry output (optional) + - >= 1.47 is required. - These libraries are required: - filesystem - system diff --git a/SConstruct b/SConstruct index c35e77aaf..3efef7ad2 100644 --- a/SConstruct +++ b/SConstruct @@ -44,7 +44,7 @@ SCONS_CONFIGURE_CACHE = 'config.cache' SCONF_TEMP_DIR = '.sconf_temp' # auto-search directories for boost libs/headers BOOST_SEARCH_PREFIXES = ['/usr/local','/opt/local','/sw','/usr',] -BOOST_MIN_VERSION = '1.41' +BOOST_MIN_VERSION = '1.47' CAIROMM_MIN_VERSION = '1.8.0' DEFAULT_LINK_PRIORITY = ['internal','other','frameworks','user','system'] From 6bea57d690e9497a52f41386417aa922fb45efb9 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 25 May 2012 10:35:43 +0100 Subject: [PATCH 20/47] + implement grain-merge blending mode (GIMP) --- deps/agg/include/agg_pixfmt_rgba.h | 4770 +++++++++++++------------- include/mapnik/image_compositing.hpp | 3 +- src/cairo_renderer.cpp | 1 + src/image_compositing.cpp | 4 +- 4 files changed, 2413 insertions(+), 2365 deletions(-) diff --git a/deps/agg/include/agg_pixfmt_rgba.h b/deps/agg/include/agg_pixfmt_rgba.h index 22db11802..e973da6d7 100644 --- a/deps/agg/include/agg_pixfmt_rgba.h +++ b/deps/agg/include/agg_pixfmt_rgba.h @@ -1,9 +1,10 @@ + //---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // @@ -13,12 +14,12 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Adaptation for high precision colors has been sponsored by +// Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGBA_INCLUDED @@ -36,88 +37,88 @@ namespace agg //=========================================================multiplier_rgba template struct multiplier_rgba { - typedef typename ColorT::value_type value_type; - typedef typename ColorT::calc_type calc_type; + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; - //-------------------------------------------------------------------- - static AGG_INLINE void premultiply(value_type* p) - { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) - { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); + } + } - //-------------------------------------------------------------------- - static AGG_INLINE void demultiply(value_type* p) - { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) - { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; - calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; - calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; - p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); - p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); - p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; + calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; + calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; + p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); + p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); + p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); + } + } }; //=====================================================apply_gamma_dir_rgba template class apply_gamma_dir_rgba { public: - typedef typename ColorT::value_type value_type; + typedef typename ColorT::value_type value_type; - apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.dir(p[Order::R]); - p[Order::G] = m_gamma.dir(p[Order::G]); - p[Order::B] = m_gamma.dir(p[Order::B]); - } + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } private: - const GammaLut& m_gamma; + const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_rgba template class apply_gamma_inv_rgba { public: - typedef typename ColorT::value_type value_type; + typedef typename ColorT::value_type value_type; - apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.inv(p[Order::R]); - p[Order::G] = m_gamma.inv(p[Order::G]); - p[Order::B] = m_gamma.inv(p[Order::B]); - } + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } private: - const GammaLut& m_gamma; + const GammaLut& m_gamma; }; - + @@ -128,99 +129,99 @@ namespace agg //=============================================================blender_rgba template struct blender_rgba { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover=0) - { - calc_type r = p[Order::R]; - calc_type g = p[Order::G]; - calc_type b = p[Order::B]; - calc_type a = p[Order::A]; - p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); - p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); - p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); - p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + calc_type r = p[Order::R]; + calc_type g = p[Order::G]; + calc_type b = p[Order::B]; + calc_type a = p[Order::A]; + p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); + p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); + p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); + p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + } }; //=========================================================blender_rgba_pre template struct blender_rgba_pre { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - alpha = color_type::base_mask - alpha; - cover = (cover + 1) << (base_shift - 8); - p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) - { - alpha = color_type::base_mask - alpha; - p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); - p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); - p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } }; //======================================================blender_rgba_plain template struct blender_rgba_plain { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e { base_shift = color_type::base_shift }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned /*cover*/=0) - { - if(alpha == 0) return; - calc_type a = p[Order::A]; - calc_type r = p[Order::R] * a; - calc_type g = p[Order::G] * a; - calc_type b = p[Order::B] * a; - a = ((alpha + a) << base_shift) - alpha * a; - p[Order::A] = (value_type)(a >> base_shift); - p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); - p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); - p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned /*cover*/=0) + { + if(alpha == 0) return; + calc_type a = p[Order::A]; + calc_type r = p[Order::R] * a; + calc_type g = p[Order::G] * a; + calc_type b = p[Order::B] * a; + a = ((alpha + a) << base_shift) - alpha * a; + p[Order::A] = (value_type)(a >> base_shift); + p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); + p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); + p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + } }; @@ -236,612 +237,612 @@ namespace agg //=========================================================comp_op_rgba_clear template struct comp_op_rgba_clear { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, unsigned, - unsigned cover) - { - if(cover < 255) - { - cover = 255 - cover; - p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); - p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); - p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); - p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); - } - else - { - p[0] = p[1] = p[2] = p[3] = 0; - } - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, unsigned, + unsigned cover) + { + if(cover < 255) + { + cover = 255 - cover; + p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); + p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); + p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); + p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); + } + else + { + p[0] = p[1] = p[2] = p[3] = 0; + } + } }; //===========================================================comp_op_rgba_src template struct comp_op_rgba_src { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - } - else - { - p[Order::R] = sr; - p[Order::G] = sg; - p[Order::B] = sb; - p[Order::A] = sa; - } - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + } + else + { + p[Order::R] = sr; + p[Order::G] = sg; + p[Order::B] = sb; + p[Order::A] = sa; + } + } }; //===========================================================comp_op_rgba_dst template struct comp_op_rgba_dst { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; - static AGG_INLINE void blend_pix(value_type*, - unsigned, unsigned, unsigned, - unsigned, unsigned) - { - } + static AGG_INLINE void blend_pix(value_type*, + unsigned, unsigned, unsigned, + unsigned, unsigned) + { + } }; //======================================================comp_op_rgba_src_over template struct comp_op_rgba_src_over { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } + // Dca' = Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } }; //======================================================comp_op_rgba_dst_over template struct comp_op_rgba_dst_over { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca + Sca.(1 - Da) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } }; //======================================================comp_op_rgba_src_in template struct comp_op_rgba_src_in { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Da - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } }; //======================================================comp_op_rgba_dst_in template struct comp_op_rgba_dst_in { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.Sa - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); - } - p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); - } + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); + } + p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); + } }; //======================================================comp_op_rgba_src_out template struct comp_op_rgba_src_out { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.(1 - Da) - // Da' = Sa.(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } }; //======================================================comp_op_rgba_dst_out template struct comp_op_rgba_dst_out { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.(1 - Sa) - // Da' = Da.(1 - Sa) - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = (sa * cover + 255) >> 8; - } - sa = base_mask - sa; - p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); - } + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = (sa * cover + 255) >> 8; + } + sa = base_mask - sa; + p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); + } }; //=====================================================comp_op_rgba_src_atop template struct comp_op_rgba_src_atop { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Da + Dca.(1 - Sa) - // Da' = Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type da = p[Order::A]; - sa = base_mask - sa; - p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); - } + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type da = p[Order::A]; + sa = base_mask - sa; + p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); + } }; //=====================================================comp_op_rgba_dst_atop template struct comp_op_rgba_dst_atop { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.Sa + Sca.(1 - Da) - // Da' = Sa - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; - sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; - sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; + sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; + sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)sa; - } - } + } + else + { + p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)sa; + } + } }; //=========================================================comp_op_rgba_xor template struct comp_op_rgba_xor { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - 2.Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); - } - } + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + } + } }; //=========================================================comp_op_rgba_plus template struct comp_op_rgba_plus { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - // Da' = Sa + Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R] + sr; - calc_type dg = p[Order::G] + sg; - calc_type db = p[Order::B] + sb; - calc_type da = p[Order::A] + sa; - p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; - p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; - p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; - p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; - } - } + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] + sr; + calc_type dg = p[Order::G] + sg; + calc_type db = p[Order::B] + sb; + calc_type da = p[Order::A] + sa; + p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; + p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; + p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; + p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; + } + } }; //========================================================comp_op_rgba_minus template struct comp_op_rgba_minus { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca - Sca - // Da' = 1 - (1 - Sa).(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R] - sr; - calc_type dg = p[Order::G] - sg; - calc_type db = p[Order::B] - sb; - p[Order::R] = (dr > base_mask) ? 0 : dr; - p[Order::G] = (dg > base_mask) ? 0 : dg; - p[Order::B] = (db > base_mask) ? 0 : db; - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); - } - } + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] - sr; + calc_type dg = p[Order::G] - sg; + calc_type db = p[Order::B] - sb; + p[Order::R] = (dr > base_mask) ? 0 : dr; + p[Order::G] = (dg > base_mask) ? 0 : dg; + p[Order::B] = (db > base_mask) ? 0 : db; + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_multiply template struct comp_op_rgba_multiply { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } - } + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_screen template struct comp_op_rgba_screen { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - Sca.Dca - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_overlay template struct comp_op_rgba_overlay { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Dca < Da - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * p[Order::A]; + // if 2.Dca < Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * p[Order::A]; - p[Order::R] = (value_type)(((2*dr < da) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((2*dr < da) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((2*dg < da) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((2*dg < da) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((2*db < da) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((2*db < da) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; @@ -851,634 +852,678 @@ namespace agg //=====================================================comp_op_rgba_darken template struct comp_op_rgba_darken { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_lighten template struct comp_op_rgba_lighten { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_color_dodge template struct comp_op_rgba_color_dodge { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if Sca.Da + Dca.Sa >= Sa.Da - // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + // if Sca.Da + Dca.Sa >= Sa.Da + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; - p[Order::R] = (value_type)((srda + drsa >= sada) ? - (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : - drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); + p[Order::R] = (value_type)((srda + drsa >= sada) ? + (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : + drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)((sgda + dgsa >= sada) ? - (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : - dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)((sgda + dgsa >= sada) ? + (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : + dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)((sbda + dbsa >= sada) ? - (sada + sb * d1a + db * s1a + base_mask) >> base_shift : - dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)((sbda + dbsa >= sada) ? + (sada + sb * d1a + db * s1a + base_mask) >> base_shift : + dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_color_burn template struct comp_op_rgba_color_burn { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if Sca.Da + Dca.Sa <= Sa.Da - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + // if Sca.Da + Dca.Sa <= Sa.Da + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; - p[Order::R] = (value_type)(((srda + drsa <= sada) ? - sr * d1a + dr * s1a : - sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((srda + drsa <= sada) ? + sr * d1a + dr * s1a : + sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? - sg * d1a + dg * s1a : - sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? + sg * d1a + dg * s1a : + sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? - sb * d1a + db * s1a : - sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? + sb * d1a + db * s1a : + sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_hard_light template struct comp_op_rgba_hard_light { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Sca < Sa - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * da; + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * da; - p[Order::R] = (value_type)(((2*sr < sa) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((2*sr < sa) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((2*sg < sa) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((2*sg < sa) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((2*sb < sa) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((2*sb < sa) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_soft_light template struct comp_op_rgba_soft_light { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Sca < Sa - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise if 8.Dca <= Da - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da + // if 2.Sca < Sa + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 8.Dca <= Da + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned r, unsigned g, unsigned b, - unsigned a, unsigned cover) - { - double sr = double(r * cover) / (base_mask * 255); - double sg = double(g * cover) / (base_mask * 255); - double sb = double(b * cover) / (base_mask * 255); - double sa = double(a * cover) / (base_mask * 255); - if(sa > 0) - { - double dr = double(p[Order::R]) / base_mask; - double dg = double(p[Order::G]) / base_mask; - double db = double(p[Order::B]) / base_mask; - double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; - if(cover < 255) - { - a = (a * cover + 255) >> 8; - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned r, unsigned g, unsigned b, + unsigned a, unsigned cover) + { + double sr = double(r * cover) / (base_mask * 255); + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); + if(sa > 0) + { + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; + if(cover < 255) + { + a = (a * cover + 255) >> 8; + } - if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); - else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); + else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); - else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); + else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); - else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); + else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - p[Order::R] = (value_type)uround(dr * base_mask); - p[Order::G] = (value_type)uround(dg * base_mask); - p[Order::B] = (value_type)uround(db * base_mask); - p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)uround(dr * base_mask); + p[Order::G] = (value_type)uround(dg * base_mask); + p[Order::B] = (value_type)uround(db * base_mask); + p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_difference template struct comp_op_rgba_difference { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_exclusion template struct comp_op_rgba_exclusion { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_contrast template struct comp_op_rgba_contrast { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - long_type dr = p[Order::R]; - long_type dg = p[Order::G]; - long_type db = p[Order::B]; - int da = p[Order::A]; - long_type d2a = da >> 1; - unsigned s2a = sa >> 1; + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; - int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); - int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); - int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); - r = (r < 0) ? 0 : r; - g = (g < 0) ? 0 : g; - b = (b < 0) ? 0 : b; + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; - p[Order::R] = (value_type)((r > da) ? da : r); - p[Order::G] = (value_type)((g > da) ? da : g); - p[Order::B] = (value_type)((b > da) ? da : b); - } + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } }; //=====================================================comp_op_rgba_invert template struct comp_op_rgba_invert { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, - unsigned sa, unsigned cover) - { - sa = (sa * cover + 255) >> 8; - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=================================================comp_op_rgba_invert_rgb template struct comp_op_rgba_invert_rgb { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; + // merge grain (GIMP) + // E = I + M - 128 + + template + struct comp_op_rgba_grain_merge + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa) + { + calc_type da = p[Order::A]; + + p[Order::R] = (sr + p[Order::R] > 128) ? sr + p[Order::R]-128 : 0; + p[Order::G] = (sg + p[Order::G] > 128) ? sg + p[Order::G]-128 : 0; + p[Order::B] = (sb + p[Order::B] > 128) ? sb + p[Order::B]-128 : 0; + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + if (p[Order::R] > 255) p[Order::R] = 255; + if (p[Order::G] > 255) p[Order::G] = 255; + if (p[Order::B] > 255) p[Order::B] = 255; + } + } + }; //======================================================comp_op_table_rgba template struct comp_op_table_rgba { - typedef typename ColorT::value_type value_type; - typedef void (*comp_op_func_type)(value_type* p, - unsigned cr, - unsigned cg, - unsigned cb, - unsigned ca, - unsigned cover); - static comp_op_func_type g_comp_op_func[]; + typedef typename ColorT::value_type value_type; + typedef void (*comp_op_func_type)(value_type* p, + unsigned cr, + unsigned cg, + unsigned cb, + unsigned ca, + unsigned cover); + static comp_op_func_type g_comp_op_func[]; }; //==========================================================g_comp_op_func - template + template typename comp_op_table_rgba::comp_op_func_type - comp_op_table_rgba::g_comp_op_func[] = + comp_op_table_rgba::g_comp_op_func[] = { - comp_op_rgba_clear ::blend_pix, - comp_op_rgba_src ::blend_pix, - comp_op_rgba_dst ::blend_pix, - comp_op_rgba_src_over ::blend_pix, - comp_op_rgba_dst_over ::blend_pix, - comp_op_rgba_src_in ::blend_pix, - comp_op_rgba_dst_in ::blend_pix, - comp_op_rgba_src_out ::blend_pix, - comp_op_rgba_dst_out ::blend_pix, - comp_op_rgba_src_atop ::blend_pix, - comp_op_rgba_dst_atop ::blend_pix, - comp_op_rgba_xor ::blend_pix, - comp_op_rgba_plus ::blend_pix, - comp_op_rgba_minus ::blend_pix, - comp_op_rgba_multiply ::blend_pix, - comp_op_rgba_screen ::blend_pix, - comp_op_rgba_overlay ::blend_pix, - comp_op_rgba_darken ::blend_pix, - comp_op_rgba_lighten ::blend_pix, - comp_op_rgba_color_dodge::blend_pix, - comp_op_rgba_color_burn ::blend_pix, - comp_op_rgba_hard_light ::blend_pix, - comp_op_rgba_soft_light ::blend_pix, - comp_op_rgba_difference ::blend_pix, - comp_op_rgba_exclusion ::blend_pix, - comp_op_rgba_contrast ::blend_pix, - comp_op_rgba_invert ::blend_pix, - comp_op_rgba_invert_rgb ::blend_pix, - 0 + comp_op_rgba_clear ::blend_pix, + comp_op_rgba_src ::blend_pix, + comp_op_rgba_dst ::blend_pix, + comp_op_rgba_src_over ::blend_pix, + comp_op_rgba_dst_over ::blend_pix, + comp_op_rgba_src_in ::blend_pix, + comp_op_rgba_dst_in ::blend_pix, + comp_op_rgba_src_out ::blend_pix, + comp_op_rgba_dst_out ::blend_pix, + comp_op_rgba_src_atop ::blend_pix, + comp_op_rgba_dst_atop ::blend_pix, + comp_op_rgba_xor ::blend_pix, + comp_op_rgba_plus ::blend_pix, + comp_op_rgba_minus ::blend_pix, + comp_op_rgba_multiply ::blend_pix, + comp_op_rgba_screen ::blend_pix, + comp_op_rgba_overlay ::blend_pix, + comp_op_rgba_darken ::blend_pix, + comp_op_rgba_lighten ::blend_pix, + comp_op_rgba_color_dodge::blend_pix, + comp_op_rgba_color_burn ::blend_pix, + comp_op_rgba_hard_light ::blend_pix, + comp_op_rgba_soft_light ::blend_pix, + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + comp_op_rgba_contrast ::blend_pix, + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::blend_pix, + comp_op_rgba_grain_merge::blend_pix, + 0 }; //==============================================================comp_op_e enum comp_op_e { - comp_op_clear, //----comp_op_clear - comp_op_src, //----comp_op_src - comp_op_dst, //----comp_op_dst - comp_op_src_over, //----comp_op_src_over - comp_op_dst_over, //----comp_op_dst_over - comp_op_src_in, //----comp_op_src_in - comp_op_dst_in, //----comp_op_dst_in - comp_op_src_out, //----comp_op_src_out - comp_op_dst_out, //----comp_op_dst_out - comp_op_src_atop, //----comp_op_src_atop - comp_op_dst_atop, //----comp_op_dst_atop - comp_op_xor, //----comp_op_xor - comp_op_plus, //----comp_op_plus - comp_op_minus, //----comp_op_minus - comp_op_multiply, //----comp_op_multiply - comp_op_screen, //----comp_op_screen - comp_op_overlay, //----comp_op_overlay - comp_op_darken, //----comp_op_darken - comp_op_lighten, //----comp_op_lighten - comp_op_color_dodge, //----comp_op_color_dodge - comp_op_color_burn, //----comp_op_color_burn - comp_op_hard_light, //----comp_op_hard_light - comp_op_soft_light, //----comp_op_soft_light - comp_op_difference, //----comp_op_difference - comp_op_exclusion, //----comp_op_exclusion - comp_op_contrast, //----comp_op_contrast - comp_op_invert, //----comp_op_invert - comp_op_invert_rgb, //----comp_op_invert_rgb - - end_of_comp_op_e + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + comp_op_contrast, //----comp_op_contrast + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb + comp_op_grain_merge, //----comp_op_grain_merge_rgb + end_of_comp_op_e }; @@ -1490,186 +1535,186 @@ namespace agg //====================================================comp_op_adaptor_rgba template struct comp_op_adaptor_rgba { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } }; //=========================================comp_op_adaptor_clip_to_dst_rgba template struct comp_op_adaptor_clip_to_dst_rgba { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //================================================comp_op_adaptor_rgba_pre template struct comp_op_adaptor_rgba_pre { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } }; //=====================================comp_op_adaptor_clip_to_dst_rgba_pre template struct comp_op_adaptor_clip_to_dst_rgba_pre { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //=======================================================comp_adaptor_rgba template struct comp_adaptor_rgba { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - BlenderPre::blend_pix(p, - (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + BlenderPre::blend_pix(p, + (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } }; //==========================================comp_adaptor_clip_to_dst_rgba template struct comp_adaptor_clip_to_dst_rgba { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //======================================comp_adaptor_clip_to_dst_rgba_pre template struct comp_adaptor_clip_to_dst_rgba_pre { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; @@ -1680,724 +1725,724 @@ namespace agg //===============================================copy_or_blend_rgba_wrapper template struct copy_or_blend_rgba_wrapper { - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) - { - if(alpha) - { - if(alpha == base_mask) - { - p[order_type::R] = cr; - p[order_type::G] = cg; - p[order_type::B] = cb; - p[order_type::A] = base_mask; - } - else - { - Blender::blend_pix(p, cr, cg, cb, alpha); - } - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + if(alpha) + { + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha); + } + } + } - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - if(cover == 255) - { - copy_or_blend_pix(p, cr, cg, cb, alpha); - } - else - { - if(alpha) - { - alpha = (alpha * (cover + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = cr; - p[order_type::G] = cg; - p[order_type::B] = cb; - p[order_type::A] = base_mask; - } - else - { - Blender::blend_pix(p, cr, cg, cb, alpha, cover); - } - } - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + if(cover == 255) + { + copy_or_blend_pix(p, cr, cg, cb, alpha); + } + else + { + if(alpha) + { + alpha = (alpha * (cover + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha, cover); + } + } + } + } }; - + //=================================================pixfmt_alpha_blend_rgba - template + template class pixfmt_alpha_blend_rgba { public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef PixelT pixel_type; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef copy_or_blend_rgba_wrapper cob_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(pixel_type) - }; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef PixelT pixel_type; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef copy_or_blend_rgba_wrapper cob_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) + }; - //-------------------------------------------------------------------- - pixfmt_alpha_blend_rgba() : m_rbuf(0) {} - explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; - } + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - AGG_INLINE const int8u* pix_ptr(int x, int y) const - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) - { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const - { - const value_type* p = (const value_type*)m_rbuf->row_ptr(y); - if(p) - { - p += x << 2; - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } - return color_type::no_color(); - } + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + const value_type* p = (const value_type*)m_rbuf->row_ptr(y); + if(p) + { + p += x << 2; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + return color_type::no_color(); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_pixel(int x, int y, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - cob_type::copy_or_blend_pix( - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + cob_type::copy_or_blend_pix( + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_hline(int x, int y, - unsigned len, - const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_vline(int x, int y, - unsigned len, - const color_type& c) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_hline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - p += 4; - } - while(--len); - } - else - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p += 4; - } - while(--len); - } - } - } - } + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + p += 4; + } + while(--len); + } + else + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 4; + } + while(--len); + } + } + } + } - //-------------------------------------------------------------------- - void blend_vline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p; - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - } - while(--len); - } - } - } - } + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + } - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } - p += 4; - ++covers; - } - while(--len); - } - } + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 4; + ++covers; + } + while(--len); + } + } - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } - ++covers; - } - while(--len); - } - } + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + ++covers; + } + while(--len); + } + } - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - if(covers) - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - *covers++); - p += 4; - ++colors; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); - p += 4; - ++colors; - } - while(--len); - } - else - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); - p += 4; - ++colors; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + if(covers) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + p += 4; + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + p += 4; + ++colors; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + p += 4; + ++colors; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p; - if(covers) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - *covers++); - ++colors; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); - ++colors; - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); - ++colors; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + ++colors; + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + ++colors; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } - if(cover == 255) - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A]); - psrc += incp; - pdst += incp; - } - while(--len); - } - else - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); - psrc += incp; - pdst += incp; - } - while(--len); - } - } - } + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A]); + psrc += incp; + pdst += incp; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - if(cover == 255) - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a); - ++psrc; - pdst += 4; - } - while(--len); - } - else - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - cover); - ++psrc; - pdst += 4; - } - while(--len); - } - } - } + if(cover == 255) + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 4; + } + while(--len); + } + else + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } + } private: - rbuf_type* m_rbuf; + rbuf_type* m_rbuf; }; @@ -2407,436 +2452,436 @@ namespace agg template class pixfmt_custom_blend_rgba { public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(value_type) * 4 - }; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 4 + }; - //-------------------------------------------------------------------- - pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} - explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : - m_rbuf(&rb), - m_comp_op(comp_op) - {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; - } + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - AGG_INLINE const int8u* pix_ptr(int x, int y) const - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - //-------------------------------------------------------------------- - void comp_op(unsigned op) { m_comp_op = op; } - unsigned comp_op() const { return m_comp_op; } + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) - { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - color_type pixel(int x, int y) const - { - const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); - p += 4; - } - while(--len); - } + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } - while(--len); - } + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, c.r, c.g, c.b, c.a, - *covers++); - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, c.r, c.g, c.b, c.a, + *covers++); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - *covers++); - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + *covers++); + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - p += 4; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + p += 4; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - ++colors; - } - while(--len); + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + ++colors; + } + while(--len); - } + } - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (const value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } - do - { - blender_type::blend_pix(m_comp_op, - pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); - psrc += incp; - pdst += incp; - } - while(--len); - } - } + do + { + blender_type::blend_pix(m_comp_op, + pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - blender_type::blend_pix(m_comp_op, - pdst, - color.r, color.g, color.b, color.a, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - const color_type& color = color_lut[*psrc]; - blender_type::blend_pix(m_comp_op, - pdst, - color.r, color.g, color.b, color.a, - cover); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + const color_type& color = color_lut[*psrc]; + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } private: - rbuf_type* m_rbuf; - unsigned m_comp_op; + rbuf_type* m_rbuf; + unsigned m_comp_op; }; @@ -2899,4 +2944,3 @@ namespace agg } #endif - diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index b407a52a4..90f621f7b 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -68,7 +68,8 @@ enum composite_mode_e exclusion, contrast, invert, - invert_rgb + invert_rgb, + grain_merge }; MAPNIK_DECL boost::optional comp_op_from_string(std::string const& name); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index bf81cc532..5b0b1caeb 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -382,6 +382,7 @@ public: case minus: case invert: case invert_rgb: + case grain_merge: break; } } diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index cb3d59b54..680cfd4a1 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -67,7 +67,9 @@ static const comp_op_lookup_type comp_lookup = boost::assign::list_of comp_op_from_string(std::string const& name) { From f692df9337c0459258c0c0b9c2a619cda66081c3 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 25 May 2012 13:28:00 +0100 Subject: [PATCH 21/47] + untabify --- deps/agg/include/agg_pixfmt_rgba.h | 4774 ++++++++++++++-------------- 1 file changed, 2387 insertions(+), 2387 deletions(-) diff --git a/deps/agg/include/agg_pixfmt_rgba.h b/deps/agg/include/agg_pixfmt_rgba.h index e973da6d7..92c0ea5c6 100644 --- a/deps/agg/include/agg_pixfmt_rgba.h +++ b/deps/agg/include/agg_pixfmt_rgba.h @@ -37,84 +37,84 @@ namespace agg //=========================================================multiplier_rgba template struct multiplier_rgba { - typedef typename ColorT::value_type value_type; - typedef typename ColorT::calc_type calc_type; + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; - //-------------------------------------------------------------------- - static AGG_INLINE void premultiply(value_type* p) - { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) - { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); + } + } - //-------------------------------------------------------------------- - static AGG_INLINE void demultiply(value_type* p) - { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) - { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; - calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; - calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; - p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); - p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); - p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; + calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; + calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; + p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); + p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); + p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); + } + } }; //=====================================================apply_gamma_dir_rgba template class apply_gamma_dir_rgba { public: - typedef typename ColorT::value_type value_type; + typedef typename ColorT::value_type value_type; - apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.dir(p[Order::R]); - p[Order::G] = m_gamma.dir(p[Order::G]); - p[Order::B] = m_gamma.dir(p[Order::B]); - } + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } private: - const GammaLut& m_gamma; + const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_rgba template class apply_gamma_inv_rgba { public: - typedef typename ColorT::value_type value_type; + typedef typename ColorT::value_type value_type; - apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.inv(p[Order::R]); - p[Order::G] = m_gamma.inv(p[Order::G]); - p[Order::B] = m_gamma.inv(p[Order::B]); - } + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } private: - const GammaLut& m_gamma; + const GammaLut& m_gamma; }; @@ -129,99 +129,99 @@ namespace agg //=============================================================blender_rgba template struct blender_rgba { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover=0) - { - calc_type r = p[Order::R]; - calc_type g = p[Order::G]; - calc_type b = p[Order::B]; - calc_type a = p[Order::A]; - p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); - p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); - p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); - p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + calc_type r = p[Order::R]; + calc_type g = p[Order::G]; + calc_type b = p[Order::B]; + calc_type a = p[Order::A]; + p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); + p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); + p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); + p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + } }; //=========================================================blender_rgba_pre template struct blender_rgba_pre { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - alpha = color_type::base_mask - alpha; - cover = (cover + 1) << (base_shift - 8); - p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) - { - alpha = color_type::base_mask - alpha; - p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); - p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); - p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } }; //======================================================blender_rgba_plain template struct blender_rgba_plain { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e { base_shift = color_type::base_shift }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned /*cover*/=0) - { - if(alpha == 0) return; - calc_type a = p[Order::A]; - calc_type r = p[Order::R] * a; - calc_type g = p[Order::G] * a; - calc_type b = p[Order::B] * a; - a = ((alpha + a) << base_shift) - alpha * a; - p[Order::A] = (value_type)(a >> base_shift); - p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); - p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); - p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); - } + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned /*cover*/=0) + { + if(alpha == 0) return; + calc_type a = p[Order::A]; + calc_type r = p[Order::R] * a; + calc_type g = p[Order::G] * a; + calc_type b = p[Order::B] * a; + a = ((alpha + a) << base_shift) - alpha * a; + p[Order::A] = (value_type)(a >> base_shift); + p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); + p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); + p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + } }; @@ -237,612 +237,612 @@ namespace agg //=========================================================comp_op_rgba_clear template struct comp_op_rgba_clear { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, unsigned, - unsigned cover) - { - if(cover < 255) - { - cover = 255 - cover; - p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); - p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); - p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); - p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); - } - else - { - p[0] = p[1] = p[2] = p[3] = 0; - } - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, unsigned, + unsigned cover) + { + if(cover < 255) + { + cover = 255 - cover; + p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); + p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); + p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); + p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); + } + else + { + p[0] = p[1] = p[2] = p[3] = 0; + } + } }; //===========================================================comp_op_rgba_src template struct comp_op_rgba_src { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - } - else - { - p[Order::R] = sr; - p[Order::G] = sg; - p[Order::B] = sb; - p[Order::A] = sa; - } - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + } + else + { + p[Order::R] = sr; + p[Order::G] = sg; + p[Order::B] = sb; + p[Order::A] = sa; + } + } }; //===========================================================comp_op_rgba_dst template struct comp_op_rgba_dst { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; - static AGG_INLINE void blend_pix(value_type*, - unsigned, unsigned, unsigned, - unsigned, unsigned) - { - } + static AGG_INLINE void blend_pix(value_type*, + unsigned, unsigned, unsigned, + unsigned, unsigned) + { + } }; //======================================================comp_op_rgba_src_over template struct comp_op_rgba_src_over { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } + // Dca' = Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } }; //======================================================comp_op_rgba_dst_over template struct comp_op_rgba_dst_over { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca + Sca.(1 - Da) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } }; //======================================================comp_op_rgba_src_in template struct comp_op_rgba_src_in { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Da - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } }; //======================================================comp_op_rgba_dst_in template struct comp_op_rgba_dst_in { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.Sa - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); - } - p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); - } + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); + } + p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); + } }; //======================================================comp_op_rgba_src_out template struct comp_op_rgba_src_out { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.(1 - Da) - // Da' = Sa.(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } }; //======================================================comp_op_rgba_dst_out template struct comp_op_rgba_dst_out { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.(1 - Sa) - // Da' = Da.(1 - Sa) - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = (sa * cover + 255) >> 8; - } - sa = base_mask - sa; - p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); - } + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = (sa * cover + 255) >> 8; + } + sa = base_mask - sa; + p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); + } }; //=====================================================comp_op_rgba_src_atop template struct comp_op_rgba_src_atop { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Da + Dca.(1 - Sa) - // Da' = Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type da = p[Order::A]; - sa = base_mask - sa; - p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); - } + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type da = p[Order::A]; + sa = base_mask - sa; + p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); + } }; //=====================================================comp_op_rgba_dst_atop template struct comp_op_rgba_dst_atop { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca.Sa + Sca.(1 - Da) - // Da' = Sa - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; - sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; - sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; + sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; + sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)sa; - } - } + } + else + { + p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)sa; + } + } }; //=========================================================comp_op_rgba_xor template struct comp_op_rgba_xor { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - 2.Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); - } - } + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + } + } }; //=========================================================comp_op_rgba_plus template struct comp_op_rgba_plus { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - // Da' = Sa + Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R] + sr; - calc_type dg = p[Order::G] + sg; - calc_type db = p[Order::B] + sb; - calc_type da = p[Order::A] + sa; - p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; - p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; - p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; - p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; - } - } + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] + sr; + calc_type dg = p[Order::G] + sg; + calc_type db = p[Order::B] + sb; + calc_type da = p[Order::A] + sa; + p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; + p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; + p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; + p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; + } + } }; //========================================================comp_op_rgba_minus template struct comp_op_rgba_minus { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Dca - Sca - // Da' = 1 - (1 - Sa).(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R] - sr; - calc_type dg = p[Order::G] - sg; - calc_type db = p[Order::B] - sb; - p[Order::R] = (dr > base_mask) ? 0 : dr; - p[Order::G] = (dg > base_mask) ? 0 : dg; - p[Order::B] = (db > base_mask) ? 0 : db; - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); - } - } + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] - sr; + calc_type dg = p[Order::G] - sg; + calc_type db = p[Order::B] - sb; + p[Order::R] = (dr > base_mask) ? 0 : dr; + p[Order::G] = (dg > base_mask) ? 0 : dg; + p[Order::B] = (db > base_mask) ? 0 : db; + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_multiply template struct comp_op_rgba_multiply { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } - } + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_screen template struct comp_op_rgba_screen { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - Sca.Dca - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_overlay template struct comp_op_rgba_overlay { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Dca < Da - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * p[Order::A]; + // if 2.Dca < Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * p[Order::A]; - p[Order::R] = (value_type)(((2*dr < da) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((2*dr < da) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((2*dg < da) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((2*dg < da) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((2*db < da) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((2*db < da) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; @@ -852,545 +852,545 @@ namespace agg //=====================================================comp_op_rgba_darken template struct comp_op_rgba_darken { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_lighten template struct comp_op_rgba_lighten { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_color_dodge template struct comp_op_rgba_color_dodge { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if Sca.Da + Dca.Sa >= Sa.Da - // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + // if Sca.Da + Dca.Sa >= Sa.Da + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; - p[Order::R] = (value_type)((srda + drsa >= sada) ? - (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : - drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); + p[Order::R] = (value_type)((srda + drsa >= sada) ? + (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : + drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)((sgda + dgsa >= sada) ? - (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : - dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)((sgda + dgsa >= sada) ? + (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : + dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)((sbda + dbsa >= sada) ? - (sada + sb * d1a + db * s1a + base_mask) >> base_shift : - dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)((sbda + dbsa >= sada) ? + (sada + sb * d1a + db * s1a + base_mask) >> base_shift : + dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_color_burn template struct comp_op_rgba_color_burn { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if Sca.Da + Dca.Sa <= Sa.Da - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + // if Sca.Da + Dca.Sa <= Sa.Da + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; - p[Order::R] = (value_type)(((srda + drsa <= sada) ? - sr * d1a + dr * s1a : - sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((srda + drsa <= sada) ? + sr * d1a + dr * s1a : + sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? - sg * d1a + dg * s1a : - sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? + sg * d1a + dg * s1a : + sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? - sb * d1a + db * s1a : - sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? + sb * d1a + db * s1a : + sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_hard_light template struct comp_op_rgba_hard_light { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Sca < Sa - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * da; + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * da; - p[Order::R] = (value_type)(((2*sr < sa) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::R] = (value_type)(((2*sr < sa) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)(((2*sg < sa) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)(((2*sg < sa) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)(((2*sb < sa) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)(((2*sb < sa) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_soft_light template struct comp_op_rgba_soft_light { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // if 2.Sca < Sa - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise if 8.Dca <= Da - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da + // if 2.Sca < Sa + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 8.Dca <= Da + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned r, unsigned g, unsigned b, - unsigned a, unsigned cover) - { - double sr = double(r * cover) / (base_mask * 255); - double sg = double(g * cover) / (base_mask * 255); - double sb = double(b * cover) / (base_mask * 255); - double sa = double(a * cover) / (base_mask * 255); - if(sa > 0) - { - double dr = double(p[Order::R]) / base_mask; - double dg = double(p[Order::G]) / base_mask; - double db = double(p[Order::B]) / base_mask; - double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; - if(cover < 255) - { - a = (a * cover + 255) >> 8; - } + static AGG_INLINE void blend_pix(value_type* p, + unsigned r, unsigned g, unsigned b, + unsigned a, unsigned cover) + { + double sr = double(r * cover) / (base_mask * 255); + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); + if(sa > 0) + { + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; + if(cover < 255) + { + a = (a * cover + 255) >> 8; + } - if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); - else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); + else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); - else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); + else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); - else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); + else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - p[Order::R] = (value_type)uround(dr * base_mask); - p[Order::G] = (value_type)uround(dg * base_mask); - p[Order::B] = (value_type)uround(db * base_mask); - p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); - } - } + p[Order::R] = (value_type)uround(dr * base_mask); + p[Order::G] = (value_type)uround(dg * base_mask); + p[Order::B] = (value_type)uround(db * base_mask); + p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_difference template struct comp_op_rgba_difference { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; - // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_exclusion template struct comp_op_rgba_exclusion { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=====================================================comp_op_rgba_contrast template struct comp_op_rgba_contrast { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - long_type dr = p[Order::R]; - long_type dg = p[Order::G]; - long_type db = p[Order::B]; - int da = p[Order::A]; - long_type d2a = da >> 1; - unsigned s2a = sa >> 1; + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; - int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); - int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); - int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); - r = (r < 0) ? 0 : r; - g = (g < 0) ? 0 : g; - b = (b < 0) ? 0 : b; + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; - p[Order::R] = (value_type)((r > da) ? da : r); - p[Order::G] = (value_type)((g > da) ? da : g); - p[Order::B] = (value_type)((b > da) ? da : b); - } + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } }; //=====================================================comp_op_rgba_invert template struct comp_op_rgba_invert { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, - unsigned sa, unsigned cover) - { - sa = (sa * cover + 255) >> 8; - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; //=================================================comp_op_rgba_invert_rgb template struct comp_op_rgba_invert_rgb { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } }; @@ -1400,42 +1400,42 @@ namespace agg template struct comp_op_rgba_grain_merge { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if (sa) - { - calc_type da = p[Order::A]; + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa) + { + calc_type da = p[Order::A]; - p[Order::R] = (sr + p[Order::R] > 128) ? sr + p[Order::R]-128 : 0; - p[Order::G] = (sg + p[Order::G] > 128) ? sg + p[Order::G]-128 : 0; - p[Order::B] = (sb + p[Order::B] > 128) ? sb + p[Order::B]-128 : 0; - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - if (p[Order::R] > 255) p[Order::R] = 255; - if (p[Order::G] > 255) p[Order::G] = 255; - if (p[Order::B] > 255) p[Order::B] = 255; - } - } + p[Order::R] = (sr + p[Order::R] > 128) ? sr + p[Order::R]-128 : 0; + p[Order::G] = (sg + p[Order::G] > 128) ? sg + p[Order::G]-128 : 0; + p[Order::B] = (sb + p[Order::B] > 128) ? sb + p[Order::B]-128 : 0; + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + if (p[Order::R] > 255) p[Order::R] = 255; + if (p[Order::G] > 255) p[Order::G] = 255; + if (p[Order::B] > 255) p[Order::B] = 255; + } + } }; @@ -1443,14 +1443,14 @@ namespace agg //======================================================comp_op_table_rgba template struct comp_op_table_rgba { - typedef typename ColorT::value_type value_type; - typedef void (*comp_op_func_type)(value_type* p, - unsigned cr, - unsigned cg, - unsigned cb, - unsigned ca, - unsigned cover); - static comp_op_func_type g_comp_op_func[]; + typedef typename ColorT::value_type value_type; + typedef void (*comp_op_func_type)(value_type* p, + unsigned cr, + unsigned cg, + unsigned cb, + unsigned ca, + unsigned cover); + static comp_op_func_type g_comp_op_func[]; }; //==========================================================g_comp_op_func @@ -1458,72 +1458,72 @@ namespace agg typename comp_op_table_rgba::comp_op_func_type comp_op_table_rgba::g_comp_op_func[] = { - comp_op_rgba_clear ::blend_pix, - comp_op_rgba_src ::blend_pix, - comp_op_rgba_dst ::blend_pix, - comp_op_rgba_src_over ::blend_pix, - comp_op_rgba_dst_over ::blend_pix, - comp_op_rgba_src_in ::blend_pix, - comp_op_rgba_dst_in ::blend_pix, - comp_op_rgba_src_out ::blend_pix, - comp_op_rgba_dst_out ::blend_pix, - comp_op_rgba_src_atop ::blend_pix, - comp_op_rgba_dst_atop ::blend_pix, - comp_op_rgba_xor ::blend_pix, - comp_op_rgba_plus ::blend_pix, - comp_op_rgba_minus ::blend_pix, - comp_op_rgba_multiply ::blend_pix, - comp_op_rgba_screen ::blend_pix, - comp_op_rgba_overlay ::blend_pix, - comp_op_rgba_darken ::blend_pix, - comp_op_rgba_lighten ::blend_pix, - comp_op_rgba_color_dodge::blend_pix, - comp_op_rgba_color_burn ::blend_pix, - comp_op_rgba_hard_light ::blend_pix, - comp_op_rgba_soft_light ::blend_pix, - comp_op_rgba_difference ::blend_pix, - comp_op_rgba_exclusion ::blend_pix, - comp_op_rgba_contrast ::blend_pix, - comp_op_rgba_invert ::blend_pix, - comp_op_rgba_invert_rgb ::blend_pix, - comp_op_rgba_grain_merge::blend_pix, - 0 + comp_op_rgba_clear ::blend_pix, + comp_op_rgba_src ::blend_pix, + comp_op_rgba_dst ::blend_pix, + comp_op_rgba_src_over ::blend_pix, + comp_op_rgba_dst_over ::blend_pix, + comp_op_rgba_src_in ::blend_pix, + comp_op_rgba_dst_in ::blend_pix, + comp_op_rgba_src_out ::blend_pix, + comp_op_rgba_dst_out ::blend_pix, + comp_op_rgba_src_atop ::blend_pix, + comp_op_rgba_dst_atop ::blend_pix, + comp_op_rgba_xor ::blend_pix, + comp_op_rgba_plus ::blend_pix, + comp_op_rgba_minus ::blend_pix, + comp_op_rgba_multiply ::blend_pix, + comp_op_rgba_screen ::blend_pix, + comp_op_rgba_overlay ::blend_pix, + comp_op_rgba_darken ::blend_pix, + comp_op_rgba_lighten ::blend_pix, + comp_op_rgba_color_dodge::blend_pix, + comp_op_rgba_color_burn ::blend_pix, + comp_op_rgba_hard_light ::blend_pix, + comp_op_rgba_soft_light ::blend_pix, + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + comp_op_rgba_contrast ::blend_pix, + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::blend_pix, + comp_op_rgba_grain_merge::blend_pix, + 0 }; //==============================================================comp_op_e enum comp_op_e { - comp_op_clear, //----comp_op_clear - comp_op_src, //----comp_op_src - comp_op_dst, //----comp_op_dst - comp_op_src_over, //----comp_op_src_over - comp_op_dst_over, //----comp_op_dst_over - comp_op_src_in, //----comp_op_src_in - comp_op_dst_in, //----comp_op_dst_in - comp_op_src_out, //----comp_op_src_out - comp_op_dst_out, //----comp_op_dst_out - comp_op_src_atop, //----comp_op_src_atop - comp_op_dst_atop, //----comp_op_dst_atop - comp_op_xor, //----comp_op_xor - comp_op_plus, //----comp_op_plus - comp_op_minus, //----comp_op_minus - comp_op_multiply, //----comp_op_multiply - comp_op_screen, //----comp_op_screen - comp_op_overlay, //----comp_op_overlay - comp_op_darken, //----comp_op_darken - comp_op_lighten, //----comp_op_lighten - comp_op_color_dodge, //----comp_op_color_dodge - comp_op_color_burn, //----comp_op_color_burn - comp_op_hard_light, //----comp_op_hard_light - comp_op_soft_light, //----comp_op_soft_light - comp_op_difference, //----comp_op_difference - comp_op_exclusion, //----comp_op_exclusion - comp_op_contrast, //----comp_op_contrast - comp_op_invert, //----comp_op_invert - comp_op_invert_rgb, //----comp_op_invert_rgb - comp_op_grain_merge, //----comp_op_grain_merge_rgb - end_of_comp_op_e + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + comp_op_contrast, //----comp_op_contrast + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb + comp_op_grain_merge, //----comp_op_grain_merge_rgb + end_of_comp_op_e }; @@ -1535,186 +1535,186 @@ namespace agg //====================================================comp_op_adaptor_rgba template struct comp_op_adaptor_rgba { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } }; //=========================================comp_op_adaptor_clip_to_dst_rgba template struct comp_op_adaptor_clip_to_dst_rgba { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //================================================comp_op_adaptor_rgba_pre template struct comp_op_adaptor_rgba_pre { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } }; //=====================================comp_op_adaptor_clip_to_dst_rgba_pre template struct comp_op_adaptor_clip_to_dst_rgba_pre { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //=======================================================comp_adaptor_rgba template struct comp_adaptor_rgba { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - BlenderPre::blend_pix(p, - (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + BlenderPre::blend_pix(p, + (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } }; //==========================================comp_adaptor_clip_to_dst_rgba template struct comp_adaptor_clip_to_dst_rgba { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; //======================================comp_adaptor_clip_to_dst_rgba_pre template struct comp_adaptor_clip_to_dst_rgba_pre { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } }; @@ -1725,67 +1725,67 @@ namespace agg //===============================================copy_or_blend_rgba_wrapper template struct copy_or_blend_rgba_wrapper { - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) - { - if(alpha) - { - if(alpha == base_mask) - { - p[order_type::R] = cr; - p[order_type::G] = cg; - p[order_type::B] = cb; - p[order_type::A] = base_mask; - } - else - { - Blender::blend_pix(p, cr, cg, cb, alpha); - } - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + if(alpha) + { + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha); + } + } + } - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - if(cover == 255) - { - copy_or_blend_pix(p, cr, cg, cb, alpha); - } - else - { - if(alpha) - { - alpha = (alpha * (cover + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = cr; - p[order_type::G] = cg; - p[order_type::B] = cb; - p[order_type::A] = base_mask; - } - else - { - Blender::blend_pix(p, cr, cg, cb, alpha, cover); - } - } - } - } + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + if(cover == 255) + { + copy_or_blend_pix(p, cr, cg, cb, alpha); + } + else + { + if(alpha) + { + alpha = (alpha * (cover + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha, cover); + } + } + } + } }; @@ -1798,651 +1798,651 @@ namespace agg class pixfmt_alpha_blend_rgba { public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef PixelT pixel_type; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef copy_or_blend_rgba_wrapper cob_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(pixel_type) - }; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef PixelT pixel_type; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef copy_or_blend_rgba_wrapper cob_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) + }; - //-------------------------------------------------------------------- - pixfmt_alpha_blend_rgba() : m_rbuf(0) {} - explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; - } + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - AGG_INLINE const int8u* pix_ptr(int x, int y) const - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) - { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const - { - const value_type* p = (const value_type*)m_rbuf->row_ptr(y); - if(p) - { - p += x << 2; - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } - return color_type::no_color(); - } + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + const value_type* p = (const value_type*)m_rbuf->row_ptr(y); + if(p) + { + p += x << 2; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + return color_type::no_color(); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_pixel(int x, int y, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - cob_type::copy_or_blend_pix( - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + cob_type::copy_or_blend_pix( + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_hline(int x, int y, - unsigned len, - const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_vline(int x, int y, - unsigned len, - const color_type& c) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_hline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - p += 4; - } - while(--len); - } - else - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p += 4; - } - while(--len); - } - } - } - } + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + p += 4; + } + while(--len); + } + else + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 4; + } + while(--len); + } + } + } + } - //-------------------------------------------------------------------- - void blend_vline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p; - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - } - while(--len); - } - } - } - } + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + } - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } - p += 4; - ++covers; - } - while(--len); - } - } + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 4; + ++covers; + } + while(--len); + } + } - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } - ++covers; - } - while(--len); - } - } + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + ++covers; + } + while(--len); + } + } - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - if(covers) - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - *covers++); - p += 4; - ++colors; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); - p += 4; - ++colors; - } - while(--len); - } - else - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); - p += 4; - ++colors; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + if(covers) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + p += 4; + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + p += 4; + ++colors; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + p += 4; + ++colors; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p; - if(covers) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - *covers++); - ++colors; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); - ++colors; - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); - ++colors; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + ++colors; + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + ++colors; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } - if(cover == 255) - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A]); - psrc += incp; - pdst += incp; - } - while(--len); - } - else - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); - psrc += incp; - pdst += incp; - } - while(--len); - } - } - } + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A]); + psrc += incp; + pdst += incp; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - if(cover == 255) - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a); - ++psrc; - pdst += 4; - } - while(--len); - } - else - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - cover); - ++psrc; - pdst += 4; - } - while(--len); - } - } - } + if(cover == 255) + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 4; + } + while(--len); + } + else + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } + } private: - rbuf_type* m_rbuf; + rbuf_type* m_rbuf; }; @@ -2452,436 +2452,436 @@ namespace agg template class pixfmt_custom_blend_rgba { public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(value_type) * 4 - }; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 4 + }; - //-------------------------------------------------------------------- - pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} - explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : - m_rbuf(&rb), - m_comp_op(comp_op) - {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; - } + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - AGG_INLINE const int8u* pix_ptr(int x, int y) const - { - return m_rbuf->row_ptr(y) + x * pix_width; - } + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } - //-------------------------------------------------------------------- - void comp_op(unsigned op) { m_comp_op = op; } - unsigned comp_op() const { return m_comp_op; } + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) - { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } - //-------------------------------------------------------------------- - color_type pixel(int x, int y) const - { - const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); - p += 4; - } - while(--len); - } + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } - while(--len); - } + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, c.r, c.g, c.b, c.a, - *covers++); - p += 4; - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, c.r, c.g, c.b, c.a, + *covers++); + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - *covers++); - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + *covers++); + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - p += 4; - ++colors; - } - while(--len); - } + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + p += 4; + ++colors; + } + while(--len); + } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - ++colors; - } - while(--len); + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + ++colors; + } + while(--len); - } + } - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (const value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } - do - { - blender_type::blend_pix(m_comp_op, - pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); - psrc += incp; - pdst += incp; - } - while(--len); - } - } + do + { + blender_type::blend_pix(m_comp_op, + pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - blender_type::blend_pix(m_comp_op, - pdst, - color.r, color.g, color.b, color.a, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - const color_type& color = color_lut[*psrc]; - blender_type::blend_pix(m_comp_op, - pdst, - color.r, color.g, color.b, color.a, - cover); - ++psrc; - pdst += 4; - } - while(--len); - } - } + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + const color_type& color = color_lut[*psrc]; + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } private: - rbuf_type* m_rbuf; - unsigned m_comp_op; + rbuf_type* m_rbuf; + unsigned m_comp_op; }; From 0697461488d1aa09bdb52a60b4ad885a2b25574f Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Sun, 27 May 2012 01:14:26 +0200 Subject: [PATCH 22/47] Add compatiblity layer for C++ code. --- src/text_symbolizer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/text_symbolizer.cpp b/src/text_symbolizer.cpp index aee3720cd..29142249c 100644 --- a/src/text_symbolizer.cpp +++ b/src/text_symbolizer.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // boost @@ -137,7 +138,9 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other) expression_ptr text_symbolizer::get_name() const { - return expression_ptr(); + formatting::text_node *node = dynamic_cast(placement_options_->defaults.format_tree().get()); + if (!node) return expression_ptr(); + return node->get_text(); } void text_symbolizer::set_name(expression_ptr name) From 472e81fe68f67b68d6b2276a1ad4b4897e70ea00 Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Mon, 28 May 2012 02:46:04 +0200 Subject: [PATCH 23/47] Correctly transform marker bounding box. Refs #1119. --- src/markers_placement.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/markers_placement.cpp b/src/markers_placement.cpp index d55f3ce28..572a0e42b 100644 --- a/src/markers_placement.cpp +++ b/src/markers_placement.cpp @@ -7,6 +7,7 @@ // agg #include "agg_basics.h" #include "agg_conv_clip_polyline.h" +#include "agg_trans_affine.h" // stl #include @@ -191,18 +192,23 @@ bool markers_placement::get_point( template box2d markers_placement::perform_transform(double angle, double dx, double dy) { - double c = cos(angle), s = sin(angle); double x1 = size_.minx(); double x2 = size_.maxx(); double y1 = size_.miny(); double y2 = size_.maxy(); - double x1_ = dx + x1 * c - y1 * s; - double y1_ = dy + x1 * s + y1 * c; - double x2_ = dx + x2 * c - y2 * s; - double y2_ = dy + x2 * s + y2 * c; + agg::trans_affine tr = agg::trans_affine_rotation(angle).translate(dx, dy); - return box2d(x1_, y1_, x2_, y2_); + double xA = x1, yA = y1, xB = x2, yB = y1, xC = x2, yC = y2, xD = x1, yD = y2; + tr.transform(&xA, &yA); + tr.transform(&xB, &yB); + tr.transform(&xC, &yC); + tr.transform(&xD, &yD); + + box2d result(xA, yA, xB, yB); + result.expand_to_include(xC, yC); + result.expand_to_include(xD, yD); + return result; } template From d85605eba1841ac076ce441cb70c6bce9179327b Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 29 May 2012 11:54:12 +0100 Subject: [PATCH 24/47] + avoid unnecessary mapnik::feature_ptr copying --- src/feature_style_processor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 58bd1ef39..e7cff4fa7 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -106,7 +106,7 @@ struct feature_style_processor::symbol_dispatch : public boost::stati } Processor & output_; - mapnik::feature_ptr f_; + mapnik::feature_ptr const& f_; proj_transform const& prj_trans_; }; From 9dc4cb34ccf6e91a88ed57c651215ca83e087f9e Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 29 May 2012 12:03:14 +0100 Subject: [PATCH 25/47] + point symbolizer needs 'image-transform' via @lightmare --- src/load_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/load_map.cpp b/src/load_map.cpp index ad95400c2..3944db538 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -936,7 +936,7 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym) } boost::array matrix; tr.store_to(&matrix[0]); - symbol.set_transform(matrix); + symbol.set_image_transform(matrix); } } catch (image_reader_exception const & ex) From e7ae5121a2551763e81aa19fe8a4db66226e829e Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 29 May 2012 12:38:10 +0100 Subject: [PATCH 26/47] + correct image_width padding calc - via @lightmare --- include/mapnik/png_io.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index 7bcd3d8f4..39bd4dd0e 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -428,7 +428,7 @@ void save_as_png8_oct(T1 & file, T2 const& image, const unsigned max_colors = 25 else if (palette.size() == 1) { // 1 color image -> write 1-bit color depth PNG - unsigned image_width = width > 7 ? (int(0.125*width) + 1)&~1 : 1; + unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary unsigned image_height = height; image_data_8 reduced_image(image_width,image_height); reduce_1(image,reduced_image,trees, limits, alphaTable); @@ -441,7 +441,7 @@ void save_as_png8_oct(T1 & file, T2 const& image, const unsigned max_colors = 25 else { // <=16 colors -> write 4-bit color depth PNG - unsigned image_width = width > 3 ? (int(0.5*width) + 3)&~3 : 4; + unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary unsigned image_height = height; image_data_8 reduced_image(image_width,image_height); reduce_4(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable); @@ -478,7 +478,7 @@ void save_as_png8(T1 & file, T2 const& image, T3 const & tree, else if (palette.size() == 1) { // 1 color image -> write 1-bit color depth PNG - unsigned image_width = width > 7 ? (int(0.125*width) + 1)&~1 : 1; + unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary unsigned image_height = height; image_data_8 reduced_image(image_width, image_height); reduced_image.set(0); @@ -487,7 +487,7 @@ void save_as_png8(T1 & file, T2 const& image, T3 const & tree, else { // <=16 colors -> write 4-bit color depth PNG - unsigned image_width = width > 3 ? (int(0.5*width) + 3)&~3 : 4; + unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary unsigned image_height = height; image_data_8 reduced_image(image_width, image_height); for (unsigned y = 0; y < height; ++y) From f3c774baa435a365d36a3eb358c1dd7dd0269682 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 29 May 2012 15:09:33 +0100 Subject: [PATCH 27/47] + add grain-extract blending mode (gimp) --- deps/agg/include/agg_pixfmt_rgba.h | 70 +++++++++++++++++++++------- include/mapnik/image_compositing.hpp | 3 +- src/cairo_renderer.cpp | 1 + src/image_compositing.cpp | 1 + 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/deps/agg/include/agg_pixfmt_rgba.h b/deps/agg/include/agg_pixfmt_rgba.h index 92c0ea5c6..7d2ef4f0a 100644 --- a/deps/agg/include/agg_pixfmt_rgba.h +++ b/deps/agg/include/agg_pixfmt_rgba.h @@ -117,15 +117,6 @@ namespace agg const GammaLut& m_gamma; }; - - - - - - - - - //=============================================================blender_rgba template struct blender_rgba { @@ -1416,28 +1407,69 @@ namespace agg unsigned sa, unsigned cover) { - if(cover < 255) + if (cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - if (sa) + if (sa > 0) { calc_type da = p[Order::A]; - - p[Order::R] = (sr + p[Order::R] > 128) ? sr + p[Order::R]-128 : 0; - p[Order::G] = (sg + p[Order::G] > 128) ? sg + p[Order::G]-128 : 0; - p[Order::B] = (sb + p[Order::B] > 128) ? sb + p[Order::B]-128 : 0; + int dr = sr + p[Order::R] - 128; + int dg = sg + p[Order::G] - 128; + int db = sb + p[Order::B] - 128; + p[Order::R] = dr < 0 ? 0 : (dr > 255 ? 255 : dr); + p[Order::G] = dg < 0 ? 0 : (dg > 255 ? 255 : dg); + p[Order::B] = db < 0 ? 0 : (db > 255 ? 255 : db); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - if (p[Order::R] > 255) p[Order::R] = 255; - if (p[Order::G] > 255) p[Order::G] = 255; - if (p[Order::B] > 255) p[Order::B] = 255; } } }; + // grain extract (GIMP) + // E = I - M + 128 + + template + struct comp_op_rgba_grain_extract + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa > 0) + { + calc_type da = p[Order::A]; + int dr = p[Order::R] - sr + 128; + int dg = p[Order::G] - sg + 128; + int db = p[Order::B] - sb + 128; + + p[Order::R] = dr < 0 ? 0 : (dr > 255 ? 255 : dr); + p[Order::G] = dg < 0 ? 0 : (dg > 255 ? 255 : dg); + p[Order::B] = db < 0 ? 0 : (db > 255 ? 255 : db); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; //======================================================comp_op_table_rgba @@ -1487,6 +1519,7 @@ namespace agg comp_op_rgba_invert ::blend_pix, comp_op_rgba_invert_rgb ::blend_pix, comp_op_rgba_grain_merge::blend_pix, + comp_op_rgba_grain_extract::blend_pix, 0 }; @@ -1523,6 +1556,7 @@ namespace agg comp_op_invert, //----comp_op_invert comp_op_invert_rgb, //----comp_op_invert_rgb comp_op_grain_merge, //----comp_op_grain_merge_rgb + comp_op_grain_extract, //----comp_op_grain_extract_rgb end_of_comp_op_e }; diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index 90f621f7b..09c9e0db1 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -69,7 +69,8 @@ enum composite_mode_e contrast, invert, invert_rgb, - grain_merge + grain_merge, + grain_extract }; MAPNIK_DECL boost::optional comp_op_from_string(std::string const& name); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 5b0b1caeb..15d23feee 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -383,6 +383,7 @@ public: case invert: case invert_rgb: case grain_merge: + case grain_extract: break; } } diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index 680cfd4a1..fb2fc61f7 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -69,6 +69,7 @@ static const comp_op_lookup_type comp_lookup = boost::assign::list_of comp_op_from_string(std::string const& name) From 44538e29d4a9db46a6d0cdc3383c8e97ed6fa02f Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Sun, 27 May 2012 09:11:46 +0200 Subject: [PATCH 28/47] agg::conv_transform: changed transformer to non-const reference (replaces ba270e0) --- deps/agg/include/agg_conv_transform.h | 15 ++++++--------- include/mapnik/vertex_converters.hpp | 13 +++++++++---- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/deps/agg/include/agg_conv_transform.h b/deps/agg/include/agg_conv_transform.h index 84eb736cc..b57fb07fa 100644 --- a/deps/agg/include/agg_conv_transform.h +++ b/deps/agg/include/agg_conv_transform.h @@ -29,11 +29,8 @@ namespace agg template class conv_transform { public: - explicit conv_transform(VertexSource& source) : - m_source(&source), m_trans() {} - - conv_transform(VertexSource& source, const Transformer& tr) : - m_source(&source), m_trans(tr) {} + conv_transform(VertexSource& source, Transformer& tr) : + m_source(&source), m_trans(&tr) {} void attach(VertexSource& source) { m_source = &source; } @@ -47,14 +44,14 @@ namespace agg unsigned cmd = m_source->vertex(x, y); if(is_vertex(cmd)) { - m_trans.transform(x, y); + m_trans->transform(x, y); } return cmd; } - void transformer(const Transformer& tr) + void transformer(Transformer& tr) { - m_trans = tr; + m_trans = &tr; } private: @@ -63,7 +60,7 @@ namespace agg operator = (const conv_transform&); VertexSource* m_source; - Transformer m_trans; + const Transformer* m_trans; }; diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index ddfc69728..c6a75f409 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -190,16 +190,21 @@ template struct converter_traits { typedef T geometry_type; - typedef typename agg::conv_transform conv_type; + + struct conv_type : public agg::conv_transform + { + agg::trans_affine trans_; + + conv_type(geometry_type& geom) + : agg::conv_transform(geom, trans_) {} + }; template static void setup(geometry_type & geom, Args & args) { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); - agg::trans_affine tr; boost::array const& m = sym.get_transform(); - tr.load_from(&m[0]); - geom.transformer(tr); + geom.trans_.load_from(&m[0]); } }; From 09b05b48b0dc01e28ebea327c812cf02fd292fb5 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Tue, 29 May 2012 22:53:39 +0200 Subject: [PATCH 29/47] fix/prevent to_expression_string misuse #985 --- bindings/python/mapnik_expression.cpp | 7 ++++++- include/mapnik/expression_string.hpp | 27 +++++++++++++++++++++++++++ include/mapnik/rule.hpp | 2 +- src/formatting/expression.cpp | 2 +- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp index b75281394..b39c4c069 100644 --- a/bindings/python/mapnik_expression.cpp +++ b/bindings/python/mapnik_expression.cpp @@ -46,6 +46,11 @@ expression_ptr parse_expression_(std::string const& wkt) return parse_expression(wkt,"utf8"); } +std::string expression_to_string_(mapnik::expr_node const& expr) +{ + return mapnik::to_expression_string(expr); +} + mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::Feature const& f) { // will be auto-converted to proper python type by `mapnik_value_to_python` @@ -75,7 +80,7 @@ void export_expression() "TODO" "",no_init) .def("evaluate", &expression_evaluate_) - .def("__str__",&to_expression_string); + .def("__str__",&expression_to_string_); ; def("Expression",&parse_expression_,(arg("expr")),"Expression string"); diff --git a/include/mapnik/expression_string.hpp b/include/mapnik/expression_string.hpp index 14f687719..b69899f3a 100644 --- a/include/mapnik/expression_string.hpp +++ b/include/mapnik/expression_string.hpp @@ -33,6 +33,33 @@ namespace mapnik { MAPNIK_DECL std::string to_expression_string(expr_node const& node); + +// Dummy types that are used to trigger nice (with gcc at least) +// compilation error when to_expression_string is misused. +enum expr_node_ref_ {}; +enum expr_node_ptr_ {}; + +// The following two templates should prevent accidentally passing +// a pointer (either raw or shared) as the argument. Without them, +// the compiler would construct a temporary expr_node(bool) using +// implicit pointer-to-bool conversion, thus any non-null pointer +// would yield "true". + +template +std::string to_expression_string(T const* x) +{ + expr_node_ref_ invalid_argument_type = expr_node_ptr_(); + throw std::logic_error("to_expression_string() called with pointer argument"); + return std::string(); +} + +template +std::string to_expression_string(boost::shared_ptr const& x) +{ + expr_node_ref_ invalid_argument_type = expr_node_ptr_(); + throw std::logic_error("to_expression_string() called with pointer argument"); + return std::string(); +} } #endif // MAPNIK_EXPRESSION_STRING_HPP diff --git a/include/mapnik/rule.hpp b/include/mapnik/rule.hpp index 62c5d45c8..c073de1ef 100644 --- a/include/mapnik/rule.hpp +++ b/include/mapnik/rule.hpp @@ -206,7 +206,7 @@ private: template void copy_height_ptr(T & sym) const { - std::string height_expr = to_expression_string(sym.height()); + std::string height_expr = to_expression_string(*sym.height()); sym.set_height(parse_expression(height_expr,"utf8")); } }; diff --git a/src/formatting/expression.cpp b/src/formatting/expression.cpp index e2e184884..86d418e13 100644 --- a/src/formatting/expression.cpp +++ b/src/formatting/expression.cpp @@ -40,7 +40,7 @@ void expression_format::to_xml(boost::property_tree::ptree &xml) const ptree &new_node = xml.push_back(ptree::value_type("ExpressionFormat", ptree()))->second; if (face_name) set_attr(new_node, "face-name", to_expression_string(*face_name)); if (text_size) set_attr(new_node, "size", to_expression_string(*text_size)); - if (character_spacing) set_attr(new_node, "character-spacing", to_expression_string*character_spacing); + if (character_spacing) set_attr(new_node, "character-spacing", to_expression_string(*character_spacing)); if (line_spacing) set_attr(new_node, "line-spacing", to_expression_string(*line_spacing)); if (text_opacity) set_attr(new_node, "opacity", to_expression_string(*text_opacity)); if (wrap_before) set_attr(new_node, "wrap-before", to_expression_string(*wrap_before)); From e8e8ba1f962db2e39c4e55b41e1ab31d28fd0d0e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 May 2012 14:06:23 -0700 Subject: [PATCH 30/47] Revert "followup to b42e4988e, fix svg transforms for svg render as well as render_id - refs #1204" This reverts commit ac9dc4762a6b71b395d0ee84c91ad2b2652949f6. --- include/mapnik/svg/svg_renderer.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/mapnik/svg/svg_renderer.hpp b/include/mapnik/svg/svg_renderer.hpp index 7d7820c3c..47dfaf858 100644 --- a/include/mapnik/svg/svg_renderer.hpp +++ b/include/mapnik/svg/svg_renderer.hpp @@ -269,8 +269,6 @@ public: transform *= mtx; double scl = transform.scale(); - curved_stroked_trans.transformer(transform); - curved_trans.transformer(transform); //curved_.approximation_method(curve_inc); curved_.approximation_scale(scl); curved_.angle_tolerance(0.0); From 109081bef3ebcaf2302bb151c873399b1cc5ee21 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 May 2012 14:06:47 -0700 Subject: [PATCH 31/47] Revert "fix transform (patch from #1204)" This reverts commit b42e4988ecd43628dd2c253dfd55ff5e5bf8a871. --- include/mapnik/svg/svg_renderer.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/mapnik/svg/svg_renderer.hpp b/include/mapnik/svg/svg_renderer.hpp index 47dfaf858..666bbacb1 100644 --- a/include/mapnik/svg/svg_renderer.hpp +++ b/include/mapnik/svg/svg_renderer.hpp @@ -375,8 +375,6 @@ public: transform *= mtx; double scl = transform.scale(); - curved_stroked_trans.transformer(transform); - curved_trans.transformer(transform); //curved_.approximation_method(curve_inc); curved_.approximation_scale(scl); curved_.angle_tolerance(0.0); From a6b4bb88ce4cbe9746866ee47d89043d0d73e4b4 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Tue, 29 May 2012 23:45:13 +0200 Subject: [PATCH 32/47] unary minus operator on mapnik::value and in expression_grammar --- include/mapnik/expression_evaluator.hpp | 6 ++++++ include/mapnik/expression_grammar.hpp | 14 +++++++++---- include/mapnik/expression_node.hpp | 15 +++++++++++++ include/mapnik/value.hpp | 28 +++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/include/mapnik/expression_evaluator.hpp b/include/mapnik/expression_evaluator.hpp index b2155f9da..a4d199012 100644 --- a/include/mapnik/expression_evaluator.hpp +++ b/include/mapnik/expression_evaluator.hpp @@ -73,6 +73,12 @@ struct evaluate : boost::static_visitor template value_type operator() (unary_node const& x) const + { + typename make_op::type func; + return func(boost::apply_visitor(*this, x.expr)); + } + + value_type operator() (unary_node const& x) const { return ! (boost::apply_visitor(evaluate(feature_),x.expr).to_bool()); } diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index c62b537cf..c74b70d47 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -198,21 +198,26 @@ struct expression_grammar : qi::grammar | ( (lit('>') | lit("gt") ) >> additive_expr [ _val > _1 ]) ) ; + additive_expr = multiplicative_expr [_val = _1] >> * ( '+' >> multiplicative_expr[_val += _1] | '-' >> multiplicative_expr[_val -= _1] ) ; - multiplicative_expr = primary_expr [_val = _1] - >> *( '*' >> primary_expr [_val *= _1] - | '/' >> primary_expr [_val /= _1] - | '%' >> primary_expr [_val %= _1] + multiplicative_expr = unary_expr [_val = _1] + >> *( '*' >> unary_expr [_val *= _1] + | '/' >> unary_expr [_val /= _1] + | '%' >> unary_expr [_val %= _1] | regex_match_expr[_val = regex_match_(_val, _1)] | regex_replace_expr(_val) [_val = _1] ) ; + unary_expr = primary_expr [_val = _1] + | '+' >> primary_expr [_val = _1] + | '-' >> primary_expr [_val = -_1] + ; primary_expr = strict_double [_val = _1] | int_ [_val = _1] @@ -256,6 +261,7 @@ struct expression_grammar : qi::grammar rule_type logical_expr; rule_type additive_expr; rule_type multiplicative_expr; + rule_type unary_expr; rule_type not_expr; rule_type primary_expr; qi::rule regex_match_expr; diff --git a/include/mapnik/expression_node.hpp b/include/mapnik/expression_node.hpp index 97608ec3b..a123297c5 100644 --- a/include/mapnik/expression_node.hpp +++ b/include/mapnik/expression_node.hpp @@ -40,6 +40,14 @@ namespace mapnik { namespace tags { +struct negate +{ + static const char* str() + { + return "-"; + } +}; + struct plus { static const char* str() @@ -166,6 +174,7 @@ typedef mapnik::value value_type; typedef boost::variant < value_type, attribute, +boost::recursive_wrapper >, boost::recursive_wrapper >, boost::recursive_wrapper >, boost::recursive_wrapper >, @@ -185,6 +194,7 @@ boost::recursive_wrapper > expr_node; template struct make_op; +template <> struct make_op { typedef std::negate type;}; template <> struct make_op { typedef std::plus type;}; template <> struct make_op { typedef std::minus type;}; template <> struct make_op { typedef std::multiplies type;}; @@ -289,6 +299,11 @@ struct function_call // ops +inline expr_node& operator- (expr_node& expr) +{ + return expr = unary_node(expr); +} + inline expr_node & operator += ( expr_node &left ,const expr_node &right) { return left = binary_node(left,right); diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index ab892d63f..06b1bdc30 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -524,6 +524,29 @@ struct mod: public boost::static_visitor } }; +template +struct negate : public boost::static_visitor +{ + typedef V value_type; + + template + value_type operator() (T val) const + { + return -val; + } + + value_type operator() (value_null const& val) const + { + return val; + } + + value_type operator() (UnicodeString const& ustr) const + { + UnicodeString inplace(ustr); + return inplace.reverse(); + } +}; + struct to_bool : public boost::static_visitor { bool operator() (bool val) const @@ -763,6 +786,11 @@ public: return boost::apply_visitor(impl::less_or_equal(),base_,other.base_); } + value operator- () const + { + return boost::apply_visitor(impl::negate(), base_); + } + value_base const& base() const { return base_; From 5feb9750e5aa5e17d39328ce8bde5c1f5113a892 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 May 2012 15:28:35 -0700 Subject: [PATCH 33/47] amend eaa53b0 and #1232 to compile with clang++ by avoiding first pass instanciation of intentionally invalid templates - refs #985 --- include/mapnik/expression_string.hpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/include/mapnik/expression_string.hpp b/include/mapnik/expression_string.hpp index b69899f3a..aae6fa09e 100644 --- a/include/mapnik/expression_string.hpp +++ b/include/mapnik/expression_string.hpp @@ -34,21 +34,19 @@ namespace mapnik { MAPNIK_DECL std::string to_expression_string(expr_node const& node); -// Dummy types that are used to trigger nice (with gcc at least) -// compilation error when to_expression_string is misused. -enum expr_node_ref_ {}; -enum expr_node_ptr_ {}; - -// The following two templates should prevent accidentally passing -// a pointer (either raw or shared) as the argument. Without them, -// the compiler would construct a temporary expr_node(bool) using -// implicit pointer-to-bool conversion, thus any non-null pointer -// would yield "true". +/* +The following two templates are intentionally invalid and will prompt +a compile error if ever instanciated. This should prevent accidentally +passing a pointer (either raw or shared) as the argument. Without them, +the compiler could construct a temporary expr_node(bool) using +implicit pointer-to-bool conversion, thus any non-null pointer +would yield "true". +*/ template std::string to_expression_string(T const* x) { - expr_node_ref_ invalid_argument_type = expr_node_ptr_(); + x = 0; throw std::logic_error("to_expression_string() called with pointer argument"); return std::string(); } @@ -56,7 +54,7 @@ std::string to_expression_string(T const* x) template std::string to_expression_string(boost::shared_ptr const& x) { - expr_node_ref_ invalid_argument_type = expr_node_ptr_(); + x = 0; throw std::logic_error("to_expression_string() called with pointer argument"); return std::string(); } From a359c602362a43f40860bd8026c2b66fbe09d001 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 May 2012 16:57:58 -0700 Subject: [PATCH 34/47] include cairo-version header explicitly --- src/cairo_renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 15d23feee..7fc86441c 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -46,6 +46,7 @@ #include #include #include +#include // boost #include From 9a18cb2cf6d3f21374c7259d9c2c7aa44d8cfebb Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 May 2012 17:10:41 -0700 Subject: [PATCH 35/47] amend 733c2df0a8589 - graphics.hpp is needed on windows --- include/mapnik/image_util.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index 6b7d1df8f..bb5a563f3 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -27,6 +27,10 @@ #include #include +#ifdef _MSC_VER +#include +#endif + // boost #include #include From 9ae70c4823ecc5381897e2d6ee9baaf666f560da Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 30 May 2012 16:26:34 +0100 Subject: [PATCH 36/47] + take into account opacity from fill and stroke rgba8 colour --- src/cairo_renderer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 7fc86441c..8b2c2e715 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -1075,12 +1075,13 @@ void cairo_renderer_base::start_map_processing(Map const& map) } else if(attr.fill_flag) { - context.set_color(attr.fill_color.r,attr.fill_color.g,attr.fill_color.b,attr.opacity*opacity); + double fill_opacity = attr.opacity * opacity * attr.fill_color.opacity(); + context.set_color(attr.fill_color.r,attr.fill_color.g,attr.fill_color.b, fill_opacity); context.fill(); } } - if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) + if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) { context.add_agg_path(svg_path,attr.index); if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) @@ -1093,9 +1094,10 @@ void cairo_renderer_base::start_map_processing(Map const& map) context.set_gradient(g,bbox); context.stroke(); } - else if(attr.stroke_flag) + else if (attr.stroke_flag) { - context.set_color(attr.stroke_color.r,attr.stroke_color.g,attr.stroke_color.b,attr.opacity*opacity); + double stroke_opacity = attr.opacity * opacity * attr.stroke_color.opacity(); + context.set_color(attr.stroke_color.r,attr.stroke_color.g,attr.stroke_color.b, stroke_opacity); context.set_line_width(attr.stroke_width); context.set_line_cap(line_cap_enum(attr.line_cap)); context.set_line_join(line_join_enum(attr.line_join)); From f4539474fc945a9d0f1b4c82fb4aa03dccc73797 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 30 May 2012 16:27:55 +0100 Subject: [PATCH 37/47] + scale_factor is 1.0 in cairo renderer TODO: should consider using variable scale_factor as in AGG --- src/cairo_renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 8b2c2e715..b071e1d5b 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -867,7 +867,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) if (height_expr) { value_type result = boost::apply_visitor(evaluate(*feature), *height_expr); - height = 0.7071 * result.to_double(); + height = result.to_double(); //scale_factor is always 1.0 atm } for (unsigned i = 0; i < feature->num_geometries(); ++i) From 6e23b64244be1288a63f27d2a7c0fab50c2ed440 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 30 May 2012 16:29:39 +0100 Subject: [PATCH 38/47] + don't draw 'frame' to match AGG renderer output --- src/cairo_renderer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index b071e1d5b..4612aa356 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -949,11 +949,11 @@ void cairo_renderer_base::start_map_processing(Map const& map) } } - path_type path(t_, *frame, prj_trans); - context.set_color(128, 128, 128, sym.get_opacity()); - context.add_path(path); - context.stroke(); - + //path_type path(t_, *frame, prj_trans); + //context.set_color(128, 128, 128, sym.get_opacity()); + //context.add_path(path); + //context.stroke(); + path_type roof_path(t_, *roof, prj_trans); context.set_color(sym.get_fill(), sym.get_opacity()); context.add_path(roof_path); From de71db7d388cd3af7f99b18a984871cf7ab754f8 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 09:33:55 +0100 Subject: [PATCH 39/47] + avoid copying --- include/mapnik/vertex_converters.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index c6a75f409..328c3e8f6 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -105,7 +105,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type box = boost::fusion::at_c<0>(args); + typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); } }; @@ -120,7 +120,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); double scale_factor = boost::fusion::at_c<5>(args); stroke const& stroke_ = sym.get_stroke(); dash_array const& d = stroke_.get_dash_array(); @@ -144,7 +144,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); stroke const& stroke_ = sym.get_stroke(); set_join_caps(stroke_,geom); geom.generator().miter_limit(stroke_.get_miterlimit()); @@ -163,7 +163,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type box = boost::fusion::at_c<0>(args); + typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); } }; @@ -178,8 +178,8 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type tr = boost::fusion::at_c<3>(args); - typename boost::mpl::at >::type prj_trans = boost::fusion::at_c<4>(args); + typename boost::mpl::at >::type const& tr = boost::fusion::at_c<3>(args); + typename boost::mpl::at >::type const& prj_trans = boost::fusion::at_c<4>(args); geom.set_proj_trans(prj_trans); geom.set_trans(tr); } @@ -202,7 +202,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); boost::array const& m = sym.get_transform(); geom.trans_.load_from(&m[0]); } @@ -217,7 +217,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); geom.set_offset(sym.offset()); } }; From 7eb8d175daf67da0d5112d5dfc14b7140e11ee23 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 09:37:00 +0100 Subject: [PATCH 40/47] + cleanup --- include/mapnik/vertex_converters.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index 328c3e8f6..fa9d37191 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -121,7 +121,7 @@ struct converter_traits static void setup(geometry_type & geom, Args & args) { typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); - double scale_factor = boost::fusion::at_c<5>(args); + double scale_factor = boost::fusion::at_c<5>(args); stroke const& stroke_ = sym.get_stroke(); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); @@ -213,10 +213,10 @@ struct converter_traits { typedef T geometry_type; typedef offset_converter conv_type; - + template static void setup(geometry_type & geom, Args & args) - { + { typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); geom.set_offset(sym.offset()); } @@ -320,23 +320,20 @@ struct vertex_converter : private boost::noncopyable proj_trans_type const&, double //scale-factor > args_type; - + vertex_converter(bbox_type const& b, rasterizer_type & ras, - symbolizer_type const& sym, trans_type & tr, + symbolizer_type const& sym, trans_type & tr, proj_trans_type const& prj_trans, double scale_factor) : disp_(args_type(boost::cref(b),boost::ref(ras), boost::cref(sym),boost::cref(tr), boost::cref(prj_trans),scale_factor)) {} - + template void apply(Geometry & geom) { typedef Geometry geometry_type; - //BOOST_FOREACH(geometry_type & geom, cont) - { - disp_.template apply(geom); - } + disp_.template apply(geom); } template From 6190cf22f1951f0a307db1a91fc14ad09406b7a2 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 10:40:23 +0100 Subject: [PATCH 41/47] + pass Args by const-ref --- include/mapnik/vertex_converters.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index fa9d37191..23ef76c77 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -76,7 +76,7 @@ struct converter_traits typedef T0 geometry_type; typedef geometry_type conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { throw "BOOM!"; } @@ -89,7 +89,7 @@ struct converter_traits typedef typename agg::conv_smooth_poly1_curve conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { geom.smooth_value(boost::fusion::at_c<2>(args).smooth()); } @@ -103,7 +103,7 @@ struct converter_traits typedef typename agg::conv_clip_polyline conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); @@ -118,7 +118,7 @@ struct converter_traits typedef typename agg::conv_dash conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); double scale_factor = boost::fusion::at_c<5>(args); @@ -142,7 +142,7 @@ struct converter_traits typedef typename agg::conv_stroke conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); stroke const& stroke_ = sym.get_stroke(); @@ -161,7 +161,7 @@ struct converter_traits typedef typename agg::conv_clip_polygon conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); @@ -176,7 +176,7 @@ struct converter_traits typedef coord_transform2 conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& tr = boost::fusion::at_c<3>(args); typename boost::mpl::at >::type const& prj_trans = boost::fusion::at_c<4>(args); @@ -215,7 +215,7 @@ struct converter_traits typedef offset_converter conv_type; template - static void setup(geometry_type & geom, Args & args) + static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); geom.set_offset(sym.offset()); @@ -226,7 +226,7 @@ template struct converter_fwd { template - static void forward(Base& base, T0 & geom,T1 & args) + static void forward(Base& base, T0 & geom,T1 const& args) { typedef T0 geometry_type; typedef T2 conv_tag; @@ -241,7 +241,7 @@ template <> struct converter_fwd { template - static void forward(Base& base, T0 & geom,T1 & args) + static void forward(Base& base, T0 & geom,T1 const& args) { base.template dispatch(geom, typename boost::is_same::type()); } @@ -254,7 +254,7 @@ struct dispatcher typedef A args_type; typedef C conv_types; - dispatcher(args_type args) + dispatcher(args_type const& args) : args_(args) { std::memset(&vec_[0], 0, sizeof(unsigned)*vec_.size()); @@ -296,7 +296,7 @@ struct dispatcher } boost::array::value> vec_; - args_type args_; + args_type args_; }; } From 500f57cf608565750cb775cba865510cf0fee300 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 12:13:09 +0100 Subject: [PATCH 42/47] + make vertex() and rewind() methods const + remove unused coord_transforms + rename coord_transform2 to coord_transform --- demo/viewer/mapwidget.cpp | 2 +- include/mapnik/ctrans.hpp | 71 ++----------------- include/mapnik/metawriter.hpp | 2 +- include/mapnik/placement_finder.hpp | 4 +- include/mapnik/svg/svg_generator.hpp | 2 +- include/mapnik/svg/svg_output_grammars.hpp | 2 +- include/mapnik/svg/svg_path_iterator.hpp | 2 +- include/mapnik/vertex_converters.hpp | 2 +- src/agg/process_building_symbolizer.cpp | 2 +- src/agg/process_markers_symbolizer.cpp | 2 +- .../process_polygon_pattern_symbolizer.cpp | 2 +- src/cairo_renderer.cpp | 8 +-- src/grid/grid_renderer.cpp | 2 +- src/grid/process_building_symbolizer.cpp | 2 +- src/grid/process_line_pattern_symbolizer.cpp | 2 +- src/grid/process_line_symbolizer.cpp | 2 +- src/grid/process_markers_symbolizer.cpp | 2 +- .../process_polygon_pattern_symbolizer.cpp | 2 +- src/grid/process_polygon_symbolizer.cpp | 2 +- src/markers_placement.cpp | 4 +- src/svg/process_symbolizers.cpp | 2 +- src/symbolizer_helpers.cpp | 2 +- 22 files changed, 30 insertions(+), 93 deletions(-) diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index f9b7ae396..0ad0f28ce 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -194,7 +194,7 @@ void MapWidget::mousePressEvent(QMouseEvent* e) boost::get<1>(*itr).to_string().c_str())); } - typedef mapnik::coord_transform2 path_type; + typedef mapnik::coord_transform path_type; for (unsigned i=0; inum_geometries();++i) { diff --git a/include/mapnik/ctrans.hpp b/include/mapnik/ctrans.hpp index 6b8917136..c1cc2f926 100644 --- a/include/mapnik/ctrans.hpp +++ b/include/mapnik/ctrans.hpp @@ -38,45 +38,20 @@ namespace mapnik typedef coord_array CoordinateArray; - template struct MAPNIK_DECL coord_transform -{ - coord_transform(Transform const& t, Geometry& geom) - : t_(t), geom_(geom) {} - - unsigned vertex(double *x, double *y) const - { - unsigned command = geom_.vertex(x, y); - t_.forward(x, y); - return command; - } - - void rewind(unsigned pos) - { - geom_.rewind(pos); - } - -private: - Transform const& t_; - Geometry& geom_; -}; - - -template -struct MAPNIK_DECL coord_transform2 { typedef std::size_t size_type; //typedef typename Geometry::value_type value_type; - coord_transform2(Transform const& t, + coord_transform(Transform const& t, Geometry & geom, proj_transform const& prj_trans) : t_(&t), geom_(geom), prj_trans_(&prj_trans) {} - explicit coord_transform2(Geometry & geom) + explicit coord_transform(Geometry & geom) : t_(0), geom_(geom), prj_trans_(0) {} @@ -91,7 +66,7 @@ struct MAPNIK_DECL coord_transform2 t_ = &t; } - unsigned vertex(double *x, double *y) + unsigned vertex(double *x, double *y) const { unsigned command = SEG_MOVETO; bool ok = false; @@ -113,7 +88,7 @@ struct MAPNIK_DECL coord_transform2 return command; } - void rewind(unsigned pos) + void rewind(unsigned pos) const { geom_.rewind(pos); } @@ -129,44 +104,6 @@ private: proj_transform const* prj_trans_; }; - -template -struct MAPNIK_DECL coord_transform3 -{ - coord_transform3(Transform const& t, - Geometry const& geom, - proj_transform const& prj_trans, - int dx, int dy) - : t_(t), - geom_(geom), - prj_trans_(prj_trans), - dx_(dx), dy_(dy) {} - - unsigned vertex(double *x, double *y) const - { - unsigned command = geom_.vertex(x, y); - double z = 0; - prj_trans_.backward(*x, *y, z); - t_.forward(x, y); - *x += dx_; - *y += dy_; - return command; - } - - void rewind(unsigned pos) - { - geom_.rewind(pos); - } - -private: - Transform const& t_; - Geometry const& geom_; - proj_transform const& prj_trans_; - int dx_; - int dy_; -}; - - class CoordTransform { private: diff --git a/include/mapnik/metawriter.hpp b/include/mapnik/metawriter.hpp index 523a71822..738137c31 100644 --- a/include/mapnik/metawriter.hpp +++ b/include/mapnik/metawriter.hpp @@ -93,7 +93,7 @@ public: class metawriter { public: - typedef coord_transform2 path_type; + typedef coord_transform path_type; metawriter(metawriter_properties dflt_properties) : dflt_properties_(dflt_properties), width_(0), diff --git a/include/mapnik/placement_finder.hpp b/include/mapnik/placement_finder.hpp index bf8844808..dcc207ade 100644 --- a/include/mapnik/placement_finder.hpp +++ b/include/mapnik/placement_finder.hpp @@ -47,8 +47,8 @@ class string_info; class text_path; typedef agg::conv_clip_polyline clipped_geometry_type; -typedef coord_transform2 ClippedPathType; -typedef coord_transform2 PathType; +typedef coord_transform ClippedPathType; +typedef coord_transform PathType; typedef label_collision_detector4 DetectorType; diff --git a/include/mapnik/svg/svg_generator.hpp b/include/mapnik/svg/svg_generator.hpp index 73cce0199..bb3eabb5f 100644 --- a/include/mapnik/svg/svg_generator.hpp +++ b/include/mapnik/svg/svg_generator.hpp @@ -44,7 +44,7 @@ namespace mapnik { namespace svg { template class svg_generator : private boost::noncopyable { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef svg::svg_root_attributes_grammar root_attributes_grammar; typedef svg::svg_rect_attributes_grammar rect_attributes_grammar; diff --git a/include/mapnik/svg/svg_output_grammars.hpp b/include/mapnik/svg/svg_output_grammars.hpp index 016d8edd0..121ca2aae 100644 --- a/include/mapnik/svg/svg_output_grammars.hpp +++ b/include/mapnik/svg/svg_output_grammars.hpp @@ -94,7 +94,7 @@ BOOST_FUSION_ADAPT_STRUCT( */ namespace boost { namespace spirit { namespace traits { - typedef mapnik::coord_transform2 path_type; + typedef mapnik::coord_transform path_type; template <> struct is_container diff --git a/include/mapnik/svg/svg_path_iterator.hpp b/include/mapnik/svg/svg_path_iterator.hpp index bd8e0c082..6132f2a84 100644 --- a/include/mapnik/svg/svg_path_iterator.hpp +++ b/include/mapnik/svg/svg_path_iterator.hpp @@ -174,7 +174,7 @@ private: * Each coordinate is stored twice to match the needs of the grammar. */ typedef path_iterator, - coord_transform2 > path_iterator_type; + coord_transform > path_iterator_type; }} diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index 23ef76c77..48282c747 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -173,7 +173,7 @@ template struct converter_traits { typedef T geometry_type; - typedef coord_transform2 conv_type; + typedef coord_transform conv_type; template static void setup(geometry_type & geom, Args const& args) diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 05aced20d..435f79568 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -47,7 +47,7 @@ void agg_renderer::process(building_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_aa_solid renderer; diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index bced49428..9e02e2f01 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -54,7 +54,7 @@ void agg_renderer::process(markers_symbolizer const& sym, proj_transform const& prj_trans) { typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::rgba8 color_type; typedef agg::order_rgba order_type; typedef agg::pixel32_type pixel_type; diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 50693063a..6049a99ca 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -53,7 +53,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, proj_transform const& prj_trans) { typedef agg::conv_clip_polygon clipped_geometry_type; - typedef coord_transform2 path_type; + typedef coord_transform path_type; agg::rendering_buffer buf(current_buffer_->raw_data(), width_, height_, width_ * 4); ras_ptr->reset(); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 4612aa356..8b4bab54c 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -857,7 +857,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; cairo_context context(context_); context.set_operator(sym.comp_op()); @@ -1026,7 +1026,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) mtx.translate(pos.x+0.5 * marker.width(), pos.y+0.5 * marker.height()); } - typedef coord_transform2 path_type; + typedef coord_transform path_type; agg::trans_affine transform; mapnik::path_ptr vmarker = *marker.get_vector_data(); using namespace mapnik::svg; @@ -1207,7 +1207,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) proj_transform const& prj_trans) { typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform2 path_type; + typedef coord_transform path_type; std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature); boost::optional marker = mapnik::marker_cache::instance()->find(filename,true); @@ -1368,7 +1368,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) double scale_factor_ = 1; typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform2 path_type; + typedef coord_transform path_type; agg::trans_affine tr; boost::array const& m = sym.get_image_transform(); diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 07bfeaad4..16e4c8e1c 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -104,7 +104,7 @@ void grid_renderer::render_marker(mapnik::feature_ptr const& feature, unsigne { if (marker.is_vector()) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index cedefb5ea..52b1edd69 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -46,7 +46,7 @@ void grid_renderer::process(building_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index afde3412b..2ab1ad8a5 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -45,7 +45,7 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index 4a87184a1..be3519586 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -45,7 +45,7 @@ void grid_renderer::process(line_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 0d675f5f4..2170ff039 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -55,7 +55,7 @@ void grid_renderer::process(markers_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index 45328b27c..855694df4 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -44,7 +44,7 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/grid/process_polygon_symbolizer.cpp b/src/grid/process_polygon_symbolizer.cpp index a3e2a42d7..649366bd8 100644 --- a/src/grid/process_polygon_symbolizer.cpp +++ b/src/grid/process_polygon_symbolizer.cpp @@ -44,7 +44,7 @@ void grid_renderer::process(polygon_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; + typedef coord_transform path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; diff --git a/src/markers_placement.cpp b/src/markers_placement.cpp index 572a0e42b..a52b2caf2 100644 --- a/src/markers_placement.cpp +++ b/src/markers_placement.cpp @@ -232,8 +232,8 @@ void markers_placement::set_spacing_left(double sl, bool allo } typedef agg::conv_clip_polyline clipped_geometry_type; -typedef coord_transform2 path_type; -typedef coord_transform2 clipped_path_type; +typedef coord_transform path_type; +typedef coord_transform clipped_path_type; template class markers_placement; template class markers_placement; diff --git a/src/svg/process_symbolizers.cpp b/src/svg/process_symbolizers.cpp index be2138e09..1619b6caa 100644 --- a/src/svg/process_symbolizers.cpp +++ b/src/svg/process_symbolizers.cpp @@ -32,7 +32,7 @@ bool svg_renderer::process(rule::symbolizers const& syms, { // svg renderer supports processing of multiple symbolizers. - typedef coord_transform2 path_type; + typedef coord_transform path_type; // process each symbolizer to collect its (path) information. // path information (attributes from line_ and polygon_ symbolizers) diff --git a/src/symbolizer_helpers.cpp b/src/symbolizer_helpers.cpp index 22e77b3f0..f2a3f2be0 100644 --- a/src/symbolizer_helpers.cpp +++ b/src/symbolizer_helpers.cpp @@ -53,7 +53,7 @@ bool text_symbolizer_helper::next_line_placement() } typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform2 path_type; + typedef coord_transform path_type; clipped_geometry_type clipped(**geo_itr_); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); path_type path(t_, clipped, prj_trans_); From 90c3415d9b516cf14a8928b5b97e148d0c8bc737 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 13:26:16 +0100 Subject: [PATCH 43/47] + don't premultiply pattern source + cleanup --- .../process_polygon_pattern_symbolizer.cpp | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 6049a99ca..62a382174 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -54,7 +54,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, { typedef agg::conv_clip_polygon clipped_geometry_type; typedef coord_transform path_type; - + agg::rendering_buffer buf(current_buffer_->raw_data(), width_, height_, width_ * 4); ras_ptr->reset(); set_gamma_method(sym,ras_ptr); @@ -80,71 +80,71 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, } boost::optional pat = (*marker)->get_bitmap_data(); - + if (!pat) return; typedef agg::rgba8 color; typedef agg::order_rgba order; - typedef agg::pixel32_type pixel_type; - typedef agg::comp_op_adaptor_rgba blender_type; + typedef agg::pixel32_type pixel_type; + typedef agg::comp_op_adaptor_rgba blender_type; typedef agg::wrap_mode_repeat wrap_x_type; - typedef agg::wrap_mode_repeat wrap_y_type; - typedef agg::pixfmt_custom_blend_rgba pixfmt_type; + typedef agg::wrap_mode_repeat wrap_y_type; + typedef agg::pixfmt_custom_blend_rgba pixfmt_type; typedef agg::image_accessor_wrap img_source_type; + wrap_y_type> img_source_type; typedef agg::span_pattern_rgba span_gen_type; typedef agg::renderer_base ren_base; - + typedef agg::renderer_scanline_aa, span_gen_type> renderer_type; - + pixfmt_type pixf(buf); pixf.comp_op(static_cast(sym.comp_op())); ren_base renb(pixf); - + unsigned w=(*pat)->width(); unsigned h=(*pat)->height(); agg::rendering_buffer pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4); agg::pixfmt_rgba32 pixf_pattern(pattern_rbuf); - pixf_pattern.premultiply(); img_source_type img_src(pixf_pattern); - unsigned num_geometries = feature->num_geometries(); + pattern_alignment_e align = sym.get_alignment(); unsigned offset_x=0; unsigned offset_y=0; - + if (align == LOCAL_ALIGNMENT) { - double x0=0,y0=0; - if (num_geometries>0) + double x0 = 0; + double y0 = 0; + if (feature->num_geometries() > 0) { clipped_geometry_type clipped(feature->get_geometry(0)); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); path_type path(t_,clipped,prj_trans); path.vertex(&x0,&y0); } - offset_x = unsigned(width_-x0); - offset_y = unsigned(height_-y0); + offset_x = unsigned(width_ - x0); + offset_y = unsigned(height_ - y0); } span_gen_type sg(img_src, offset_x, offset_y); agg::span_allocator sa; - renderer_type rp(renb,sa, sg); - + renderer_type rp(renb,sa, sg); + box2d inflated_extent = query_extent_ * 1.0; typedef boost::mpl::vector conv_types; vertex_converter,rasterizer,polygon_pattern_symbolizer, proj_transform, CoordTransform,conv_types> converter(inflated_extent,*ras_ptr,sym,t_,prj_trans, scale_factor_); - + if (sym.clip()) converter.set(); //optional clip (default: true) converter.set(); //always transform if (sym.smooth() > 0.0) converter.set(); // optional smooth converter - + BOOST_FOREACH( geometry_type & geom, feature->paths()) { if (geom.num_points() > 2) @@ -162,4 +162,3 @@ template void agg_renderer::process(polygon_pattern_symbolizer const&, proj_transform const&); } - From 404ddf329da0e3d068c01112ed7c42ff199a23df Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 31 May 2012 15:55:20 +0100 Subject: [PATCH 44/47] Revert "+ avoid copying" This reverts commit de71db7d388cd3af7f99b18a984871cf7ab754f8. Conflicts: include/mapnik/vertex_converters.hpp --- include/mapnik/vertex_converters.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index 48282c747..9a6aaa420 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -105,7 +105,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); + typename boost::mpl::at >::type box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); } }; @@ -120,7 +120,8 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); + + typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); double scale_factor = boost::fusion::at_c<5>(args); stroke const& stroke_ = sym.get_stroke(); dash_array const& d = stroke_.get_dash_array(); @@ -144,7 +145,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); stroke const& stroke_ = sym.get_stroke(); set_join_caps(stroke_,geom); geom.generator().miter_limit(stroke_.get_miterlimit()); @@ -163,7 +164,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& box = boost::fusion::at_c<0>(args); + typename boost::mpl::at >::type box = boost::fusion::at_c<0>(args); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); } }; @@ -178,8 +179,8 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& tr = boost::fusion::at_c<3>(args); - typename boost::mpl::at >::type const& prj_trans = boost::fusion::at_c<4>(args); + typename boost::mpl::at >::type tr = boost::fusion::at_c<3>(args); + typename boost::mpl::at >::type prj_trans = boost::fusion::at_c<4>(args); geom.set_proj_trans(prj_trans); geom.set_trans(tr); } @@ -202,7 +203,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args & args) { - typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); boost::array const& m = sym.get_transform(); geom.trans_.load_from(&m[0]); } @@ -217,7 +218,7 @@ struct converter_traits template static void setup(geometry_type & geom, Args const& args) { - typename boost::mpl::at >::type const& sym = boost::fusion::at_c<2>(args); + typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); geom.set_offset(sym.offset()); } }; From 963cd83f98d63d2e2e2b69a23b71620275c610c3 Mon Sep 17 00:00:00 2001 From: Carl Simonson Date: Thu, 31 May 2012 18:09:12 -0500 Subject: [PATCH 45/47] viewer: show more exception messages When trying to render the map widget in the viewer, we catch exceptions and print out the message to stderr. The only exceptions that are printed are mapnik::config_error messages. mapnik can throw more errors, so this change makes it catch all std::exceptions. --- demo/viewer/mapwidget.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index 0ad0f28ce..8717cf4a8 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -486,6 +486,10 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix) { std::cerr << ex.what() << std::endl; } + catch (const std::exception & ex) + { + std::cerr << "exception: " << ex.what() << std::endl; + } catch (...) { std::cerr << "Unknown exception caught!\n"; @@ -522,6 +526,10 @@ void render_grid(mapnik::Map const& map, double scaling_factor, QPixmap & pix) { std::cerr << ex.what() << std::endl; } + catch (const std::exception & ex) + { + std::cerr << "exception: " << ex.what() << std::endl; + } catch (...) { std::cerr << "Unknown exception caught!\n"; From c696c85dd4e93c8523bfb868dd4f668b97e964f0 Mon Sep 17 00:00:00 2001 From: Carl Simonson Date: Thu, 31 May 2012 18:16:19 -0500 Subject: [PATCH 46/47] viewer: add mouse wheel zooming This change makes the viewer zoom in and out when using the scroll wheel. The zoom tracks the position of the mouse pointer when zooming in so that the map will be centered under the mouse after a zoom. --- demo/viewer/mapwidget.cpp | 26 ++++++++++++++++++++++++++ demo/viewer/mapwidget.hpp | 1 + 2 files changed, 27 insertions(+) diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index 8717cf4a8..102dfe030 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -289,6 +289,32 @@ void MapWidget::mouseReleaseEvent(QMouseEvent* e) } } +void MapWidget::wheelEvent(QWheelEvent* e) +{ + if (!map_) + { + return; + } + + QPoint corner(map_->width(), map_->height()); + QPoint zoomCoords; + double zoom; + if (e->delta() > 0) + { + zoom = 0.5; + QPoint center = corner / 2; + QPoint delta = e->pos() - center; + zoomCoords = zoom * delta + center; + } + else + { + zoom = 2.0; + zoomCoords = corner - e->pos(); + } + + map_->pan_and_zoom(zoomCoords.x(), zoomCoords.y(), zoom); + updateMap(); +} void MapWidget::keyPressEvent(QKeyEvent *e) { diff --git a/demo/viewer/mapwidget.hpp b/demo/viewer/mapwidget.hpp index e440ce2c2..671cc5ab4 100644 --- a/demo/viewer/mapwidget.hpp +++ b/demo/viewer/mapwidget.hpp @@ -99,6 +99,7 @@ protected: void mousePressEvent(QMouseEvent* e); void mouseMoveEvent(QMouseEvent* e); void mouseReleaseEvent(QMouseEvent* e); + void wheelEvent(QWheelEvent* e); void keyPressEvent(QKeyEvent *e); void export_to_file(unsigned width, unsigned height, From 024ebfdfe3bf019269db901f15342e3ecd146270 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 1 Jun 2012 12:19:42 +0100 Subject: [PATCH 47/47] + better not to use errno (via perror) for std::iostreams (it works with gcc and friends but non-standard) --- src/metawriter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/metawriter.cpp b/src/metawriter.cpp index d3d43c48f..f55298807 100644 --- a/src/metawriter.cpp +++ b/src/metawriter.cpp @@ -33,7 +33,6 @@ // STL #include -#include namespace mapnik { @@ -334,7 +333,10 @@ void metawriter_json::start(metawriter_property_map const& properties) void metawriter_json::write_header() { f_.open(filename_.c_str(), std::fstream::out | std::fstream::trunc); - if (f_.fail()) perror((std::string("Metawriter JSON: Failed to open file ") + filename_).c_str()); + if (f_.fail()) + { + MAPNIK_LOG_DEBUG(metawriter) << "metawriter_json: Failed to open file " << filename_; + } set_stream(&f_); metawriter_json_stream::write_header(); }