Skip to content

Commit 29db335

Browse files
committed
Implement RFC-113 Layer Compositing Framework (#5071)
1 parent 7f20e12 commit 29db335

23 files changed

+2809
-2201
lines changed

CMakeLists.txt

+13
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ option(WITH_SDE "include ArcSDE support. Add -DSDE_VERSION=91 to use 9.1 arcSDE
137137
option(WITH_EXEMPI "include xmp output metadata support" OFF)
138138
option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF)
139139
option(WITH_V8 "include javacript v8 scripting" OFF)
140+
option(WITH_PIXMAN "use pixman for layer compositing operations" OFF)
140141

141142
option(BUILD_STATIC "Also build a static version of mapserver" OFF)
142143
option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF)
@@ -333,6 +334,17 @@ if(WITH_PROJ)
333334
endif(NOT PROJ_FOUND)
334335
endif (WITH_PROJ)
335336

337+
if(WITH_PIXMAN)
338+
find_package(Pixman)
339+
if(PIXMAN_FOUND)
340+
include_directories(${PIXMAN_INCLUDE_DIR})
341+
ms_link_libraries(${PIXMAN_LIBRARY})
342+
set (USE_PIXMAN 1)
343+
else(PIXMAN_FOUND)
344+
report_optional_not_found(PIXMAN)
345+
endif(PIXMAN_FOUND)
346+
endif (WITH_PIXMAN)
347+
336348
if(WITH_WMS)
337349
if(USE_PROJ)
338350
set(USE_WMS_SVR 1)
@@ -878,6 +890,7 @@ status_optional_component("SVGCAIRO" "${USE_SVG_CAIRO}" "${SVGCAIRO_LIBRARY}")
878890
status_optional_component("RSVG" "${USE_RSVG}" "${RSVG_LIBRARY}")
879891
status_optional_component("CURL" "${USE_CURL}" "${CURL_LIBRARY}")
880892
status_optional_component("PROJ" "${USE_PROJ}" "${PROJ_LIBRARY}")
893+
status_optional_component("PIXMAN" "${USE_PIXMAN}" "${PIXMAN_LIBRARY}")
881894
status_optional_component("LIBXML2" "${USE_LIBXML2}" "${LIBXML2_LIBRARY}")
882895
status_optional_component("POSTGIS" "${USE_POSTGIS}" "${POSTGRESQL_LIBRARY}")
883896
status_optional_component("GEOS" "${USE_GEOS}" "${GEOS_LIBRARY}")

cmake/FindPixman.cmake

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FIND_PACKAGE(PkgConfig)
2+
PKG_CHECK_MODULES(PC_PIXMAN pixman)
3+
if(NOT PC_PIXMAN_FOUND)
4+
PKG_CHECK_MODULES(PC_PIXMAN pixman-1)
5+
endif(NOT PC_PIXMAN_FOUND)
6+
7+
8+
FIND_PATH(PIXMAN_INCLUDE_DIR
9+
NAMES pixman.h
10+
HINTS ${PC_PIXMAN_INCLUDEDIR}
11+
${PC_PIXMAN_INCLUDE_DIR}
12+
PATH_SUFFIXES pixman pixman-1
13+
)
14+
15+
FIND_LIBRARY(PIXMAN_LIBRARY
16+
NAMES pixman pixman-1
17+
HINTS ${PC_PIXMAN_LIBDIR}
18+
${PC_PIXMAN_LIBRARY_DIRS}
19+
)
20+
21+
set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR})
22+
set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY})
23+
include(FindPackageHandleStandardArgs)
24+
find_package_handle_standard_args(PIXMAN DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
25+
mark_as_advanced(PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)

mapagg.cpp

+198-4
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,15 @@
4242
#include "renderers/agg/include/agg_span_pattern_rgba.h"
4343
#include "renderers/agg/include/agg_span_allocator.h"
4444
#include "renderers/agg/include/agg_span_interpolator_linear.h"
45-
#include "renderers/agg/include/agg_span_image_filter_rgba.h"
4645
#include "renderers/agg/include/agg_pattern_filters_rgba.h"
47-
#include "renderers/agg/include/agg_span_image_filter_rgb.h"
4846
#include "renderers/agg/include/agg_image_accessors.h"
4947
#include "renderers/agg/include/agg_conv_stroke.h"
5048
#include "renderers/agg/include/agg_conv_dash.h"
5149
#include "renderers/agg/include/agg_font_freetype.h"
5250
#include "renderers/agg/include/agg_conv_contour.h"
5351
#include "renderers/agg/include/agg_ellipse.h"
5452
#include "renderers/agg/include/agg_gamma_functions.h"
53+
#include "renderers/agg/include/agg_blur.h"
5554

5655
#include "renderers/agg/include/agg_rasterizer_outline_aa.h"
5756
#include "renderers/agg/include/agg_renderer_outline_aa.h"
@@ -64,6 +63,10 @@
6463

6564
#include "renderers/agg/include/agg_conv_clipper.h"
6665

66+
#ifdef USE_PIXMAN
67+
#include <pixman.h>
68+
#endif
69+
6770
#ifdef AGG_ALIASED_ENABLED
6871
#include "renderers/agg/include/agg_renderer_primitives.h"
6972
#include "renderers/agg/include/agg_rasterizer_outline.h"
@@ -78,10 +81,13 @@ typedef mapserver::rgba8 color_type;
7881
typedef mapserver::pixel32_type pixel_type;
7982

8083
typedef mapserver::blender_rgba_pre<color_type, band_order> blender_pre;
84+
typedef mapserver::comp_op_adaptor_rgba_pre<color_type, band_order> compop_blender_pre;
8185

8286
typedef mapserver::pixfmt_alpha_blend_rgba<blender_pre, mapserver::rendering_buffer, pixel_type> pixel_format;
87+
typedef mapserver::pixfmt_custom_blend_rgba<compop_blender_pre, mapserver::rendering_buffer> compop_pixel_format;
8388
typedef mapserver::rendering_buffer rendering_buffer;
8489
typedef mapserver::renderer_base<pixel_format> renderer_base;
90+
typedef mapserver::renderer_base<compop_pixel_format> compop_renderer_base;
8591
typedef mapserver::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
8692
typedef mapserver::rasterizer_scanline_aa<> rasterizer_scanline;
8793
typedef mapserver::font_engine_freetype_int16 font_engine_type;
@@ -136,7 +142,9 @@ class AGG2Renderer
136142
band_type* buffer;
137143
rendering_buffer m_rendering_buffer;
138144
pixel_format m_pixel_format;
145+
compop_pixel_format m_compop_pixel_format;
139146
renderer_base m_renderer_base;
147+
compop_renderer_base m_compop_renderer_base;
140148
renderer_scanline m_renderer_scanline;
141149
#ifdef AGG_ALIASED_ENABLED
142150
renderer_primitives m_renderer_primitives;
@@ -826,7 +834,9 @@ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorO
826834
}
827835
r->m_rendering_buffer.attach(r->buffer, width, height, width * 4);
828836
r->m_pixel_format.attach(r->m_rendering_buffer);
837+
r->m_compop_pixel_format.attach(r->m_rendering_buffer);
829838
r->m_renderer_base.attach(r->m_pixel_format);
839+
r->m_compop_renderer_base.attach(r->m_compop_pixel_format);
830840
r->m_renderer_scanline.attach(r->m_renderer_base);
831841
r->default_gamma = atof(msGetOutputFormatOption( format, "GAMMA", "0.75" ));
832842
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,
11191129

11201130

11211131
if(patternlength>1) {
1122-
//dash the hatch and render it clipped by the shape
1132+
//dash the color-hatch and render it clipped by the shape
11231133
mapserver::conv_dash<mapserver::path_storage > dash(hatch);
11241134
mapserver::conv_stroke<mapserver::conv_dash<mapserver::path_storage> > stroke(dash);
11251135
for (int i=0; i<patternlength; i+=2) {
@@ -1146,10 +1156,194 @@ int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width,
11461156
return MS_SUCCESS;
11471157
}
11481158

1159+
#ifdef USE_PIXMAN
1160+
static pixman_op_t ms2pixman_compop(CompositingOperation c) {
1161+
switch(c) {
1162+
case MS_COMPOP_CLEAR:
1163+
return PIXMAN_OP_CLEAR;
1164+
case MS_COMPOP_SRC:
1165+
return PIXMAN_OP_SRC;
1166+
case MS_COMPOP_DST:
1167+
return PIXMAN_OP_DST;
1168+
case MS_COMPOP_SRC_OVER:
1169+
return PIXMAN_OP_OVER;
1170+
case MS_COMPOP_DST_OVER:
1171+
return PIXMAN_OP_OVER_REVERSE;
1172+
case MS_COMPOP_SRC_IN:
1173+
return PIXMAN_OP_IN;
1174+
case MS_COMPOP_DST_IN:
1175+
return PIXMAN_OP_IN_REVERSE;
1176+
case MS_COMPOP_SRC_OUT:
1177+
return PIXMAN_OP_OUT;
1178+
case MS_COMPOP_DST_OUT:
1179+
return PIXMAN_OP_OUT_REVERSE;
1180+
case MS_COMPOP_SRC_ATOP:
1181+
return PIXMAN_OP_ATOP;
1182+
case MS_COMPOP_DST_ATOP:
1183+
return PIXMAN_OP_ATOP_REVERSE;
1184+
case MS_COMPOP_XOR:
1185+
return PIXMAN_OP_XOR;
1186+
case MS_COMPOP_PLUS:
1187+
return PIXMAN_OP_ADD;
1188+
case MS_COMPOP_MULTIPLY:
1189+
return PIXMAN_OP_MULTIPLY;
1190+
case MS_COMPOP_SCREEN:
1191+
return PIXMAN_OP_SCREEN;
1192+
case MS_COMPOP_OVERLAY:
1193+
return PIXMAN_OP_OVERLAY;
1194+
case MS_COMPOP_DARKEN:
1195+
return PIXMAN_OP_DARKEN;
1196+
case MS_COMPOP_LIGHTEN:
1197+
return PIXMAN_OP_LIGHTEN;
1198+
case MS_COMPOP_COLOR_DODGE:
1199+
return PIXMAN_OP_COLOR_DODGE;
1200+
case MS_COMPOP_COLOR_BURN:
1201+
return PIXMAN_OP_COLOR_DODGE;
1202+
case MS_COMPOP_HARD_LIGHT:
1203+
return PIXMAN_OP_HARD_LIGHT;
1204+
case MS_COMPOP_SOFT_LIGHT:
1205+
return PIXMAN_OP_SOFT_LIGHT;
1206+
case MS_COMPOP_DIFFERENCE:
1207+
return PIXMAN_OP_DIFFERENCE;
1208+
case MS_COMPOP_EXCLUSION:
1209+
return PIXMAN_OP_EXCLUSION;
1210+
case MS_COMPOP_INVERT:
1211+
case MS_COMPOP_INVERT_RGB:
1212+
case MS_COMPOP_MINUS:
1213+
case MS_COMPOP_CONTRAST:
1214+
default:
1215+
return PIXMAN_OP_OVER;
1216+
}
1217+
}
1218+
#else
1219+
static mapserver::comp_op_e ms2agg_compop(CompositingOperation c) {
1220+
switch(c) {
1221+
case MS_COMPOP_CLEAR:
1222+
return mapserver::comp_op_clear;
1223+
case MS_COMPOP_SRC:
1224+
return mapserver::comp_op_src;
1225+
case MS_COMPOP_DST:
1226+
return mapserver::comp_op_dst;
1227+
case MS_COMPOP_SRC_OVER:
1228+
return mapserver::comp_op_src_over;
1229+
case MS_COMPOP_DST_OVER:
1230+
return mapserver::comp_op_dst_over;
1231+
case MS_COMPOP_SRC_IN:
1232+
return mapserver::comp_op_src_in;
1233+
case MS_COMPOP_DST_IN:
1234+
return mapserver::comp_op_dst_in;
1235+
case MS_COMPOP_SRC_OUT:
1236+
return mapserver::comp_op_src_out;
1237+
case MS_COMPOP_DST_OUT:
1238+
return mapserver::comp_op_dst_out;
1239+
case MS_COMPOP_SRC_ATOP:
1240+
return mapserver::comp_op_src_atop;
1241+
case MS_COMPOP_DST_ATOP:
1242+
return mapserver::comp_op_dst_atop;
1243+
case MS_COMPOP_XOR:
1244+
return mapserver::comp_op_xor;
1245+
case MS_COMPOP_PLUS:
1246+
return mapserver::comp_op_plus;
1247+
case MS_COMPOP_MINUS:
1248+
return mapserver::comp_op_minus;
1249+
case MS_COMPOP_MULTIPLY:
1250+
return mapserver::comp_op_multiply;
1251+
case MS_COMPOP_SCREEN:
1252+
return mapserver::comp_op_screen;
1253+
case MS_COMPOP_OVERLAY:
1254+
return mapserver::comp_op_overlay;
1255+
case MS_COMPOP_DARKEN:
1256+
return mapserver::comp_op_darken;
1257+
case MS_COMPOP_LIGHTEN:
1258+
return mapserver::comp_op_lighten;
1259+
case MS_COMPOP_COLOR_DODGE:
1260+
return mapserver::comp_op_color_dodge;
1261+
case MS_COMPOP_COLOR_BURN:
1262+
return mapserver::comp_op_color_burn;
1263+
case MS_COMPOP_HARD_LIGHT:
1264+
return mapserver::comp_op_hard_light;
1265+
case MS_COMPOP_SOFT_LIGHT:
1266+
return mapserver::comp_op_soft_light;
1267+
case MS_COMPOP_DIFFERENCE:
1268+
return mapserver::comp_op_difference;
1269+
case MS_COMPOP_EXCLUSION:
1270+
return mapserver::comp_op_exclusion;
1271+
case MS_COMPOP_CONTRAST:
1272+
return mapserver::comp_op_contrast;
1273+
case MS_COMPOP_INVERT:
1274+
return mapserver::comp_op_invert;
1275+
case MS_COMPOP_INVERT_RGB:
1276+
return mapserver::comp_op_invert_rgb;
1277+
default:
1278+
return mapserver::comp_op_src_over;
1279+
}
1280+
}
1281+
#endif
1282+
1283+
int aggCompositeRasterBuffer(imageObj *dest, rasterBufferObj *overlay, CompositingOperation comp, int opacity) {
1284+
assert(overlay->type == MS_BUFFER_BYTE_RGBA);
1285+
AGG2Renderer *r = AGG_RENDERER(dest);
1286+
#ifdef USE_PIXMAN
1287+
pixman_image_t *si = pixman_image_create_bits(PIXMAN_a8r8g8b8,overlay->width,overlay->height,
1288+
(uint32_t*)overlay->data.rgba.pixels,overlay->data.rgba.row_step);
1289+
pixman_image_t *bi = pixman_image_create_bits(PIXMAN_a8r8g8b8,dest->width,dest->height,
1290+
(uint32_t*)r->buffer,dest->width*4);
1291+
pixman_image_t *alpha_mask_i=NULL, *alpha_mask_i_ptr;
1292+
pixman_image_set_filter(si,PIXMAN_FILTER_NEAREST, NULL, 0);
1293+
unsigned char *alpha_mask = NULL;
1294+
if(opacity > 0) {
1295+
if(opacity == 100) {
1296+
alpha_mask_i_ptr = NULL;
1297+
} else {
1298+
unsigned char alpha = (unsigned char)(opacity * 2.55);
1299+
if(!alpha_mask_i) {
1300+
alpha_mask = (unsigned char*)msSmallMalloc(dest->width * dest->height);
1301+
alpha_mask_i = pixman_image_create_bits(PIXMAN_a8,dest->width,dest->height,
1302+
(uint32_t*)alpha_mask,dest->width);
1303+
}
1304+
memset(alpha_mask,alpha,dest->width*dest->height);
1305+
alpha_mask_i_ptr = alpha_mask_i;
1306+
}
1307+
pixman_image_composite (ms2pixman_compop(comp), si, alpha_mask_i_ptr, bi,
1308+
0, 0, 0, 0, 0, 0, dest->width,dest->height);
1309+
}
1310+
pixman_image_unref(si);
1311+
pixman_image_unref(bi);
1312+
if(alpha_mask_i) {
1313+
pixman_image_unref(alpha_mask_i);
1314+
msFree(alpha_mask);
1315+
}
1316+
return MS_SUCCESS;
1317+
#else
1318+
rendering_buffer b(overlay->data.rgba.pixels, overlay->width, overlay->height, overlay->data.rgba.row_step);
1319+
pixel_format pf(b);
1320+
mapserver::comp_op_e comp_op = ms2agg_compop(comp);
1321+
if(comp == mapserver::comp_op_src_over) {
1322+
r->m_renderer_base.blend_from(pf,0,0,0,unsigned(opacity * 2.55));
1323+
} else {
1324+
compop_pixel_format pixf(r->m_rendering_buffer);
1325+
compop_renderer_base ren(pixf);
1326+
pixf.comp_op(comp_op);
1327+
ren.blend_from(pf,0,0,0,unsigned(opacity * 2.55));
1328+
}
1329+
return MS_SUCCESS;
1330+
#endif
1331+
}
1332+
1333+
rasterBufferObj* msApplyFilterToRasterBuffer(const rasterBufferObj *rb, CompositingFilter *filter) {
1334+
rasterBufferObj *rbret = (rasterBufferObj*)msSmallCalloc(sizeof(rasterBufferObj),1);
1335+
msCopyRasterBuffer(rbret,rb);
1336+
rendering_buffer b(rbret->data.rgba.pixels, rbret->width, rbret->height, rbret->data.rgba.row_step);
1337+
pixel_format pf(b);
1338+
/* for now, we only support a blurring filter */
1339+
int radius = atoi(filter->filter);
1340+
mapserver::stack_blur_rgba32(pf,radius,radius);
1341+
return rbret;
1342+
}
11491343

11501344
int msPopulateRendererVTableAGG(rendererVTableObj * renderer)
11511345
{
1152-
renderer->supports_transparent_layers = 0;
1346+
renderer->compositeRasterBuffer = &aggCompositeRasterBuffer;
11531347
renderer->supports_pixel_buffer = 1;
11541348
renderer->use_imagecache = 0;
11551349
renderer->supports_clipping = 0;

0 commit comments

Comments
 (0)