Permalink
Browse files

Implement RFC-113 Layer Compositing Framework (#5071)

  • Loading branch information...
tbonfort committed Nov 6, 2014
1 parent 7f20e12 commit 29db335114606f3564e81f3c706f137efdfb3fb2
Showing with 2,809 additions and 2,201 deletions.
  1. +13 −0 CMakeLists.txt
  2. +25 −0 cmake/FindPixman.cmake
  3. +198 −4 mapagg.cpp
  4. +83 −5 mapcairo.c
  5. +5 −1 mapcontext.c
  6. +45 −1 mapcopy.c
  7. +34 −9 mapdraw.c
  8. +1 −1 mapdummyrenderer.c
  9. +131 −5 mapfile.c
  10. +5 −0 mapfile.h
  11. +1 −2 mapkml.cpp
  12. +8 −8 mapkmlrenderer.cpp
  13. +10 −17 maplegend.c
  14. +2,170 −2,130 maplexer.c
  15. +3 −0 maplexer.l
  16. +3 −11 mapogcsld.c
  17. +3 −2 mapscript/php/layer.c
  18. +10 −0 mapscript/swiginc/layer.i
  19. +1 −0 mapserver-config.h.in
  20. +50 −3 mapserver.h
  21. +8 −0 maputil.c
  22. +1 −1 msautotest
  23. +1 −1 renderers/agg/include/agg_pixfmt_rgba.h
View
@@ -137,6 +137,7 @@ option(WITH_SDE "include ArcSDE support. Add -DSDE_VERSION=91 to use 9.1 arcSDE
option(WITH_EXEMPI "include xmp output metadata support" OFF)
option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF)
option(WITH_V8 "include javacript v8 scripting" OFF)
+option(WITH_PIXMAN "use pixman for layer compositing operations" OFF)
option(BUILD_STATIC "Also build a static version of mapserver" OFF)
option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF)
@@ -333,6 +334,17 @@ if(WITH_PROJ)
endif(NOT PROJ_FOUND)
endif (WITH_PROJ)
+if(WITH_PIXMAN)
+ find_package(Pixman)
+ if(PIXMAN_FOUND)
+ include_directories(${PIXMAN_INCLUDE_DIR})
+ ms_link_libraries(${PIXMAN_LIBRARY})
+ set (USE_PIXMAN 1)
+ else(PIXMAN_FOUND)
+ report_optional_not_found(PIXMAN)
+ endif(PIXMAN_FOUND)
+endif (WITH_PIXMAN)
+
if(WITH_WMS)
if(USE_PROJ)
set(USE_WMS_SVR 1)
@@ -878,6 +890,7 @@ status_optional_component("SVGCAIRO" "${USE_SVG_CAIRO}" "${SVGCAIRO_LIBRARY}")
status_optional_component("RSVG" "${USE_RSVG}" "${RSVG_LIBRARY}")
status_optional_component("CURL" "${USE_CURL}" "${CURL_LIBRARY}")
status_optional_component("PROJ" "${USE_PROJ}" "${PROJ_LIBRARY}")
+status_optional_component("PIXMAN" "${USE_PIXMAN}" "${PIXMAN_LIBRARY}")
status_optional_component("LIBXML2" "${USE_LIBXML2}" "${LIBXML2_LIBRARY}")
status_optional_component("POSTGIS" "${USE_POSTGIS}" "${POSTGRESQL_LIBRARY}")
status_optional_component("GEOS" "${USE_GEOS}" "${GEOS_LIBRARY}")
View
@@ -0,0 +1,25 @@
+FIND_PACKAGE(PkgConfig)
+PKG_CHECK_MODULES(PC_PIXMAN pixman)
+if(NOT PC_PIXMAN_FOUND)
+ PKG_CHECK_MODULES(PC_PIXMAN pixman-1)
+endif(NOT PC_PIXMAN_FOUND)
+
+
+FIND_PATH(PIXMAN_INCLUDE_DIR
+ NAMES pixman.h
+ HINTS ${PC_PIXMAN_INCLUDEDIR}
+ ${PC_PIXMAN_INCLUDE_DIR}
+ PATH_SUFFIXES pixman pixman-1
+)
+
+FIND_LIBRARY(PIXMAN_LIBRARY
+ NAMES pixman pixman-1
+ HINTS ${PC_PIXMAN_LIBDIR}
+ ${PC_PIXMAN_LIBRARY_DIRS}
+)
+
+set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR})
+set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY})
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PIXMAN DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
+mark_as_advanced(PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
View
@@ -42,16 +42,15 @@
#include "renderers/agg/include/agg_span_pattern_rgba.h"
#include "renderers/agg/include/agg_span_allocator.h"
#include "renderers/agg/include/agg_span_interpolator_linear.h"
-#include "renderers/agg/include/agg_span_image_filter_rgba.h"
#include "renderers/agg/include/agg_pattern_filters_rgba.h"
-#include "renderers/agg/include/agg_span_image_filter_rgb.h"
#include "renderers/agg/include/agg_image_accessors.h"
#include "renderers/agg/include/agg_conv_stroke.h"
#include "renderers/agg/include/agg_conv_dash.h"
#include "renderers/agg/include/agg_font_freetype.h"
#include "renderers/agg/include/agg_conv_contour.h"
#include "renderers/agg/include/agg_ellipse.h"
#include "renderers/agg/include/agg_gamma_functions.h"
+#include "renderers/agg/include/agg_blur.h"
#include "renderers/agg/include/agg_rasterizer_outline_aa.h"
#include "renderers/agg/include/agg_renderer_outline_aa.h"
@@ -64,6 +63,10 @@
#include "renderers/agg/include/agg_conv_clipper.h"
+#ifdef USE_PIXMAN
+#include <pixman.h>
+#endif
+
#ifdef AGG_ALIASED_ENABLED
#include "renderers/agg/include/agg_renderer_primitives.h"
#include "renderers/agg/include/agg_rasterizer_outline.h"
@@ -78,10 +81,13 @@ typedef mapserver::rgba8 color_type;
typedef mapserver::pixel32_type pixel_type;
typedef mapserver::blender_rgba_pre<color_type, band_order> blender_pre;
+typedef mapserver::comp_op_adaptor_rgba_pre<color_type, band_order> compop_blender_pre;
typedef mapserver::pixfmt_alpha_blend_rgba<blender_pre, mapserver::rendering_buffer, pixel_type> pixel_format;
+typedef mapserver::pixfmt_custom_blend_rgba<compop_blender_pre, mapserver::rendering_buffer> compop_pixel_format;
typedef mapserver::rendering_buffer rendering_buffer;
typedef mapserver::renderer_base<pixel_format> renderer_base;
+typedef mapserver::renderer_base<compop_pixel_format> compop_renderer_base;
typedef mapserver::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
typedef mapserver::rasterizer_scanline_aa<> rasterizer_scanline;
typedef mapserver::font_engine_freetype_int16 font_engine_type;
@@ -136,7 +142,9 @@ class AGG2Renderer
band_type* buffer;
rendering_buffer m_rendering_buffer;
pixel_format m_pixel_format;
+ compop_pixel_format m_compop_pixel_format;
renderer_base m_renderer_base;
+ compop_renderer_base m_compop_renderer_base;
renderer_scanline m_renderer_scanline;
#ifdef AGG_ALIASED_ENABLED
renderer_primitives m_renderer_primitives;
@@ -826,7 +834,9 @@ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorO
}
r->m_rendering_buffer.attach(r->buffer, width, height, width * 4);
r->m_pixel_format.attach(r->m_rendering_buffer);
+ r->m_compop_pixel_format.attach(r->m_rendering_buffer);
r->m_renderer_base.attach(r->m_pixel_format);
+ r->m_compop_renderer_base.attach(r->m_compop_pixel_format);
r->m_renderer_scanline.attach(r->m_renderer_base);
r->default_gamma = atof(msGetOutputFormatOption( format, "GAMMA", "0.75" ));
if(r->default_gamma <= 0.0 || r->default_gamma >= 1.0) {
@@ -1119,7 +1129,7 @@ int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width,
if(patternlength>1) {
- //dash the hatch and render it clipped by the shape
+ //dash the color-hatch and render it clipped by the shape
mapserver::conv_dash<mapserver::path_storage > dash(hatch);
mapserver::conv_stroke<mapserver::conv_dash<mapserver::path_storage> > stroke(dash);
for (int i=0; i<patternlength; i+=2) {
@@ -1146,10 +1156,194 @@ int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width,
return MS_SUCCESS;
}
+#ifdef USE_PIXMAN
+static pixman_op_t ms2pixman_compop(CompositingOperation c) {
+ switch(c) {
+ case MS_COMPOP_CLEAR:
+ return PIXMAN_OP_CLEAR;
+ case MS_COMPOP_SRC:
+ return PIXMAN_OP_SRC;
+ case MS_COMPOP_DST:
+ return PIXMAN_OP_DST;
+ case MS_COMPOP_SRC_OVER:
+ return PIXMAN_OP_OVER;
+ case MS_COMPOP_DST_OVER:
+ return PIXMAN_OP_OVER_REVERSE;
+ case MS_COMPOP_SRC_IN:
+ return PIXMAN_OP_IN;
+ case MS_COMPOP_DST_IN:
+ return PIXMAN_OP_IN_REVERSE;
+ case MS_COMPOP_SRC_OUT:
+ return PIXMAN_OP_OUT;
+ case MS_COMPOP_DST_OUT:
+ return PIXMAN_OP_OUT_REVERSE;
+ case MS_COMPOP_SRC_ATOP:
+ return PIXMAN_OP_ATOP;
+ case MS_COMPOP_DST_ATOP:
+ return PIXMAN_OP_ATOP_REVERSE;
+ case MS_COMPOP_XOR:
+ return PIXMAN_OP_XOR;
+ case MS_COMPOP_PLUS:
+ return PIXMAN_OP_ADD;
+ case MS_COMPOP_MULTIPLY:
+ return PIXMAN_OP_MULTIPLY;
+ case MS_COMPOP_SCREEN:
+ return PIXMAN_OP_SCREEN;
+ case MS_COMPOP_OVERLAY:
+ return PIXMAN_OP_OVERLAY;
+ case MS_COMPOP_DARKEN:
+ return PIXMAN_OP_DARKEN;
+ case MS_COMPOP_LIGHTEN:
+ return PIXMAN_OP_LIGHTEN;
+ case MS_COMPOP_COLOR_DODGE:
+ return PIXMAN_OP_COLOR_DODGE;
+ case MS_COMPOP_COLOR_BURN:
+ return PIXMAN_OP_COLOR_DODGE;
+ case MS_COMPOP_HARD_LIGHT:
+ return PIXMAN_OP_HARD_LIGHT;
+ case MS_COMPOP_SOFT_LIGHT:
+ return PIXMAN_OP_SOFT_LIGHT;
+ case MS_COMPOP_DIFFERENCE:
+ return PIXMAN_OP_DIFFERENCE;
+ case MS_COMPOP_EXCLUSION:
+ return PIXMAN_OP_EXCLUSION;
+ case MS_COMPOP_INVERT:
+ case MS_COMPOP_INVERT_RGB:
+ case MS_COMPOP_MINUS:
+ case MS_COMPOP_CONTRAST:
+ default:
+ return PIXMAN_OP_OVER;
+ }
+}
+#else
+static mapserver::comp_op_e ms2agg_compop(CompositingOperation c) {
+ switch(c) {
+ case MS_COMPOP_CLEAR:
+ return mapserver::comp_op_clear;
+ case MS_COMPOP_SRC:
+ return mapserver::comp_op_src;
+ case MS_COMPOP_DST:
+ return mapserver::comp_op_dst;
+ case MS_COMPOP_SRC_OVER:
+ return mapserver::comp_op_src_over;
+ case MS_COMPOP_DST_OVER:
+ return mapserver::comp_op_dst_over;
+ case MS_COMPOP_SRC_IN:
+ return mapserver::comp_op_src_in;
+ case MS_COMPOP_DST_IN:
+ return mapserver::comp_op_dst_in;
+ case MS_COMPOP_SRC_OUT:
+ return mapserver::comp_op_src_out;
+ case MS_COMPOP_DST_OUT:
+ return mapserver::comp_op_dst_out;
+ case MS_COMPOP_SRC_ATOP:
+ return mapserver::comp_op_src_atop;
+ case MS_COMPOP_DST_ATOP:
+ return mapserver::comp_op_dst_atop;
+ case MS_COMPOP_XOR:
+ return mapserver::comp_op_xor;
+ case MS_COMPOP_PLUS:
+ return mapserver::comp_op_plus;
+ case MS_COMPOP_MINUS:
+ return mapserver::comp_op_minus;
+ case MS_COMPOP_MULTIPLY:
+ return mapserver::comp_op_multiply;
+ case MS_COMPOP_SCREEN:
+ return mapserver::comp_op_screen;
+ case MS_COMPOP_OVERLAY:
+ return mapserver::comp_op_overlay;
+ case MS_COMPOP_DARKEN:
+ return mapserver::comp_op_darken;
+ case MS_COMPOP_LIGHTEN:
+ return mapserver::comp_op_lighten;
+ case MS_COMPOP_COLOR_DODGE:
+ return mapserver::comp_op_color_dodge;
+ case MS_COMPOP_COLOR_BURN:
+ return mapserver::comp_op_color_burn;
+ case MS_COMPOP_HARD_LIGHT:
+ return mapserver::comp_op_hard_light;
+ case MS_COMPOP_SOFT_LIGHT:
+ return mapserver::comp_op_soft_light;
+ case MS_COMPOP_DIFFERENCE:
+ return mapserver::comp_op_difference;
+ case MS_COMPOP_EXCLUSION:
+ return mapserver::comp_op_exclusion;
+ case MS_COMPOP_CONTRAST:
+ return mapserver::comp_op_contrast;
+ case MS_COMPOP_INVERT:
+ return mapserver::comp_op_invert;
+ case MS_COMPOP_INVERT_RGB:
+ return mapserver::comp_op_invert_rgb;
+ default:
+ return mapserver::comp_op_src_over;
+ }
+}
+#endif
+
+int aggCompositeRasterBuffer(imageObj *dest, rasterBufferObj *overlay, CompositingOperation comp, int opacity) {
+ assert(overlay->type == MS_BUFFER_BYTE_RGBA);
+ AGG2Renderer *r = AGG_RENDERER(dest);
+#ifdef USE_PIXMAN
+ pixman_image_t *si = pixman_image_create_bits(PIXMAN_a8r8g8b8,overlay->width,overlay->height,
+ (uint32_t*)overlay->data.rgba.pixels,overlay->data.rgba.row_step);
+ pixman_image_t *bi = pixman_image_create_bits(PIXMAN_a8r8g8b8,dest->width,dest->height,
+ (uint32_t*)r->buffer,dest->width*4);
+ pixman_image_t *alpha_mask_i=NULL, *alpha_mask_i_ptr;
+ pixman_image_set_filter(si,PIXMAN_FILTER_NEAREST, NULL, 0);
+ unsigned char *alpha_mask = NULL;
+ if(opacity > 0) {
+ if(opacity == 100) {
+ alpha_mask_i_ptr = NULL;
+ } else {
+ unsigned char alpha = (unsigned char)(opacity * 2.55);
+ if(!alpha_mask_i) {
+ alpha_mask = (unsigned char*)msSmallMalloc(dest->width * dest->height);
+ alpha_mask_i = pixman_image_create_bits(PIXMAN_a8,dest->width,dest->height,
+ (uint32_t*)alpha_mask,dest->width);
+ }
+ memset(alpha_mask,alpha,dest->width*dest->height);
+ alpha_mask_i_ptr = alpha_mask_i;
+ }
+ pixman_image_composite (ms2pixman_compop(comp), si, alpha_mask_i_ptr, bi,
+ 0, 0, 0, 0, 0, 0, dest->width,dest->height);
+ }
+ pixman_image_unref(si);
+ pixman_image_unref(bi);
+ if(alpha_mask_i) {
+ pixman_image_unref(alpha_mask_i);
+ msFree(alpha_mask);
+ }
+ return MS_SUCCESS;
+#else
+ rendering_buffer b(overlay->data.rgba.pixels, overlay->width, overlay->height, overlay->data.rgba.row_step);
+ pixel_format pf(b);
+ mapserver::comp_op_e comp_op = ms2agg_compop(comp);
+ if(comp == mapserver::comp_op_src_over) {
+ r->m_renderer_base.blend_from(pf,0,0,0,unsigned(opacity * 2.55));
+ } else {
+ compop_pixel_format pixf(r->m_rendering_buffer);
+ compop_renderer_base ren(pixf);
+ pixf.comp_op(comp_op);
+ ren.blend_from(pf,0,0,0,unsigned(opacity * 2.55));
+ }
+ return MS_SUCCESS;
+#endif
+}
+
+rasterBufferObj* msApplyFilterToRasterBuffer(const rasterBufferObj *rb, CompositingFilter *filter) {
+ rasterBufferObj *rbret = (rasterBufferObj*)msSmallCalloc(sizeof(rasterBufferObj),1);
+ msCopyRasterBuffer(rbret,rb);
+ rendering_buffer b(rbret->data.rgba.pixels, rbret->width, rbret->height, rbret->data.rgba.row_step);
+ pixel_format pf(b);
+ /* for now, we only support a blurring filter */
+ int radius = atoi(filter->filter);
+ mapserver::stack_blur_rgba32(pf,radius,radius);
+ return rbret;
+}
int msPopulateRendererVTableAGG(rendererVTableObj * renderer)
{
- renderer->supports_transparent_layers = 0;
+ renderer->compositeRasterBuffer = &aggCompositeRasterBuffer;
renderer->supports_pixel_buffer = 1;
renderer->use_imagecache = 0;
renderer->supports_clipping = 0;
Oops, something went wrong.

0 comments on commit 29db335

Please sign in to comment.