diff -Nru mapserver-7.0.7/apache/mod_mapserver.c mapserver-7.6.4/apache/mod_mapserver.c --- mapserver-7.0.7/apache/mod_mapserver.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/apache/mod_mapserver.c 2021-07-12 20:16:21.000000000 +0000 @@ -40,7 +40,7 @@ msIO_apacheError (void *cbData, void *data, int byteCount) { /* error reporting is done through the log file... */ - ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, (char*) data); + ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s", (char*) data); return strlen ((char*) data); } diff -Nru mapserver-7.0.7/ci/travis/after_success.sh mapserver-7.6.4/ci/travis/after_success.sh --- mapserver-7.0.7/ci/travis/after_success.sh 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/ci/travis/after_success.sh 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,12 @@ +#!/bin/sh +set -eu + +if [ "$BUILD_NAME" != "PHP_7.3_WITH_ASAN" ]; then + # Only run coverage when it is safe to do so (not on pull requests), and only on main branch + echo "$TRAVIS_SECURE_ENV_VARS" + echo "$TRAVIS_BRANCH" + sh -c 'if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "main"; then echo "run coverage"; ./run_code_coverage_upload.sh; fi' + ln -s ../../../mapparser.y build/CMakeFiles/mapserver.dir/ + ln -s ../../../maplexer.l build/CMakeFiles/mapserver.dir/ + coveralls --exclude renderers --exclude mapscript --exclude apache --exclude build/mapscript/mapscriptJAVA_wrap.c --exclude build/mapscript/mapscriptPYTHON_wrap.c --exclude shp2img.c --exclude legend.c --exclude scalebar.c --exclude msencrypt.c --exclude sortshp.c --exclude shptreevis.c --exclude shptree.c --exclude testexpr.c --exclude sym2img.c --exclude testcopy.c --exclude shptreetst.c --exclude tile4ms.c --exclude proj --exclude swig-3.0.12 --extension .c --extension .cpp +fi diff -Nru mapserver-7.0.7/ci/travis/before_install.sh mapserver-7.6.4/ci/travis/before_install.sh --- mapserver-7.0.7/ci/travis/before_install.sh 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/ci/travis/before_install.sh 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,38 @@ +#!/bin/sh +set -eu + +# Remove pre-installed things in Travis image +if ls /etc/apt/sources.list.d/pgdg* 2>/dev/null >/dev/null; then sudo mv /etc/apt/sources.list.d/pgdg* /tmp; fi +dpkg -l | grep postgresql || /bin/true +dpkg -l | grep postgis || /bin/true +sudo apt-get remove --purge postgresql* libpq-dev libpq5 || /bin/true + +sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable +sudo apt-get update +sudo apt-get install -y --allow-unauthenticated protobuf-c-compiler libprotobuf-c0-dev bison flex libfribidi-dev cmake librsvg2-dev colordiff libpq-dev libpng-dev libjpeg-dev libgif-dev libgeos-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal-dev libproj-dev libxml2-dev libexempi-dev lcov lftp postgis libharfbuzz-dev gdal-bin ccache curl postgresql-server-dev-10 postgresql-10-postgis-3 postgresql-10-postgis-3-scripts swig g++ +# following are already installed on Travis CI +#sudo apt-get install --allow-unauthenticated php-dev python-dev python3-dev +sudo apt-get install -y --allow-unauthenticated libmono-system-drawing4.0-cil mono-mcs +sudo apt-get install -y --allow-unauthenticated libperl-dev +sudo apt-get install -y --allow-unauthenticated openjdk-8-jdk + +pip install cpp-coveralls pyflakes lxml +sudo pip install -U -r msautotest/requirements.txt + +export CC="ccache gcc" +export CXX="ccache g++" + +sudo sed -i 's/md5/trust/' /etc/postgresql/10/main/pg_hba.conf +sudo sed -i 's/peer/trust/' /etc/postgresql/10/main/pg_hba.conf +sudo service postgresql restart 10 + +cd msautotest +python -m pyflakes . +./create_postgis_test_data.sh + +# py3 +python -m http.server &> /dev/null & + +cd .. +touch maplexer.l +touch mapparser.y diff -Nru mapserver-7.0.7/ci/travis/script.sh mapserver-7.6.4/ci/travis/script.sh --- mapserver-7.0.7/ci/travis/script.sh 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/ci/travis/script.sh 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,39 @@ +#!/bin/sh +set -eu + +#if [ "$BUILD_NAME" = "PHP_7.3_WITH_ASAN" ]; then +# export CC="ccache clang" +# export CXX="ccache clang++" +#else + export CC="ccache gcc" + export CXX="ccache g++" +#fi + +curl http://download.osgeo.org/proj/proj-6.1.1.tar.gz > proj-6.1.1.tar.gz +tar xzf proj-6.1.1.tar.gz +mv proj-6.1.1 proj +(cd proj/data && curl http://download.osgeo.org/proj/proj-datumgrid-1.8.tar.gz > proj-datumgrid-1.8.tar.gz && tar xvzf proj-datumgrid-1.8.tar.gz) +(cd proj; CFLAGS='-O2 -DPROJ_RENAME_SYMBOLS' CXXFLAGS='-O2 -DPROJ_RENAME_SYMBOLS' ./configure --disable-static --prefix=/usr/local && CCACHE_CPP2=yes make -j2 && sudo make -j3 install) +sudo rm -f /usr/include/proj_api.h + +if [ "$BUILD_NAME" = "PHP_7.3_WITH_ASAN" ]; then + # Force use of PROJ 4 API + sudo rm /usr/local/include/proj.h + # -DNDEBUG to avoid issues with cairo cleanup + make cmakebuild MFLAGS="-j2" CMAKE_C_FLAGS="-g -fsanitize=address -DNDEBUG -DPROJ_RENAME_SYMBOLS -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" CMAKE_CXX_FLAGS="-g -fsanitize=address -DNDEBUG -DPROJ_RENAME_SYMBOLS -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" EXTRA_CMAKEFLAGS="-DCMAKE_BUILD_TYPE=None -DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address -DPROJ_INCLUDE_DIR=/usr/local/include -DPROJ_LIBRARY=/usr/local/lib/libproj.so.15" + export AUTOTEST_OPTS="--strict --run_under_asan" + # Only run tests that only involve mapserv/shp2img binaries. mspython, etc would require LD_PREOLOAD'ing the asan shared object + make -j4 asan_compatible_tests +elif [ "$BUILD_NAME" = "PHP_7.4_WITH_PROJ6" ]; then + # Avoid any use of PROJ 4 API + sudo rm -f /usr/include/proj_api.h + make cmakebuild MFLAGS="-j2" CMAKE_C_FLAGS="-O2 -DPROJ_RENAME_SYMBOLS" CMAKE_CXX_FLAGS="-O2 -DPROJ_RENAME_SYMBOLS" EXTRA_CMAKEFLAGS="-DPROJ_INCLUDE_DIR=/usr/local/include -DPROJ_LIBRARY=/usr/local/lib/libproj.so.15" + make mspython-wheel + make -j4 test +else + # Force use of PROJ 4 API + sudo rm /usr/local/include/proj.h + make cmakebuild MFLAGS="-j2" CMAKE_C_FLAGS="-DPROJ_RENAME_SYMBOLS -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" CMAKE_CXX_FLAGS="-DPROJ_RENAME_SYMBOLS -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" EXTRA_CMAKEFLAGS="-DPROJ_INCLUDE_DIR=/usr/local/include -DPROJ_LIBRARY=/usr/local/lib/libproj.so.15" + make mspython-wheel + make -j4 test +fi diff -Nru mapserver-7.0.7/classobject.c mapserver-7.6.4/classobject.c --- mapserver-7.0.7/classobject.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/classobject.c 2021-07-12 20:16:21.000000000 +0000 @@ -31,12 +31,6 @@ #include "mapserver.h" -#ifdef USE_GDAL -# include "gdal.h" -# include "cpl_conv.h" -#endif - - /* ** Add a label to a classObj (order doesn't matter for labels like it does with styles) diff -Nru mapserver-7.0.7/cmake/FindOracle.cmake mapserver-7.6.4/cmake/FindOracle.cmake --- mapserver-7.0.7/cmake/FindOracle.cmake 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/cmake/FindOracle.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -37,7 +37,7 @@ ${ORACLE_HOME}/OCI/include) # Oracle XE on Windows set(ORACLE_OCI_NAMES clntsh libclntsh oci) - set(ORACLE_NNZ_NAMES nnz10 libnnz10 nnz11 libnnz11 nnz12 libnnz12 ociw32) + set(ORACLE_NNZ_NAMES nnz10 libnnz10 nnz11 libnnz11 nnz12 libnnz12 nnz18 libnnz18 ociw32 nnz19 libnnz19) set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11 oraocci12) set(ORACLE_LIB_DIR diff -Nru mapserver-7.0.7/cmake/FindPHP5.cmake mapserver-7.6.4/cmake/FindPHP5.cmake --- mapserver-7.0.7/cmake/FindPHP5.cmake 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/cmake/FindPHP5.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -# - Find PHP5 -# This module finds if PHP5 is installed and determines where the include files -# and libraries are. It also determines what the name of the library is. This -# code sets the following variables: -# -# PHP5_INCLUDE_PATH = path to where php.h can be found -# PHP5_EXECUTABLE = full path to the php4 binary -# -# file is derived from FindPHP4.cmake -# - -SET(PHP5_FOUND "NO") - -SET(PHP5_POSSIBLE_INCLUDE_PATHS - /usr/include/php5 - /usr/local/include/php5 - /usr/include/php - /usr/local/include/php - /usr/local/apache/php - ${PHP5_INCLUDES} - ) - -SET(PHP5_POSSIBLE_LIB_PATHS - /usr/lib -if(WIN32) - ${PHP5_INCLUDES}/Release_TS -endif(WIN32) - ) - -find_library(PHP5_LIBRARY - NAMES php5ts.lib - PATHS /sw /opt/local ${PHP5_INCLUDES}/Release_TS -) - -FIND_PATH(PHP5_FOUND_INCLUDE_PATH main/php.h - ${PHP5_POSSIBLE_INCLUDE_PATHS}) - -IF(PHP5_FOUND_INCLUDE_PATH) - SET(php5_paths "${PHP5_POSSIBLE_INCLUDE_PATHS}") - FOREACH(php5_path Zend main TSRM) - SET(php5_paths ${php5_paths} "${PHP5_FOUND_INCLUDE_PATH}/${php5_path}") - ENDFOREACH(php5_path Zend main TSRM) - SET(PHP5_INCLUDE_PATH "${php5_paths}" INTERNAL "PHP5 include paths") -ENDIF(PHP5_FOUND_INCLUDE_PATH) - -FIND_PROGRAM(PHP5_EXECUTABLE - NAMES php5 php - PATHS - /usr/local/bin - ) - -MARK_AS_ADVANCED( - PHP5_EXECUTABLE - PHP5_FOUND_INCLUDE_PATH - ) - -IF( NOT PHP5_CONFIG_EXECUTABLE ) -FIND_PROGRAM(PHP5_CONFIG_EXECUTABLE - NAMES php5-config php-config - ) -ENDIF( NOT PHP5_CONFIG_EXECUTABLE ) - -IF(PHP5_CONFIG_EXECUTABLE) - EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --version - OUTPUT_VARIABLE PHP5_VERSION) - STRING(REPLACE "\n" "" PHP5_VERSION "${PHP5_VERSION}") - - EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --extension-dir - OUTPUT_VARIABLE PHP5_EXTENSION_DIR) - STRING(REPLACE "\n" "" PHP5_EXTENSION_DIR "${PHP5_EXTENSION_DIR}") - - EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --includes - OUTPUT_VARIABLE PHP5_INCLUDES) - STRING(REPLACE "-I" "" PHP5_INCLUDES "${PHP5_INCLUDES}") - STRING(REPLACE " " ";" PHP5_INCLUDES "${PHP5_INCLUDES}") - STRING(REPLACE "\n" "" PHP5_INCLUDES "${PHP5_INCLUDES}") - LIST(GET PHP5_INCLUDES 0 PHP5_INCLUDE_DIR) - - set(PHP5_MAIN_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/main) - set(PHP5_TSRM_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/TSRM) - set(PHP5_ZEND_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/Zend) - set(PHP5_REGEX_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/regex) - set(PHP5_EXT_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext) - set(PHP5_DATE_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext/date/lib) - set(PHP5_STANDARD_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext/standard) - - MESSAGE(STATUS ${PHP5_MAIN_INCLUDE_DIR}) - - IF(NOT PHP5_INCLUDE_PATH) - set(PHP5_INCLUDE_PATH ${PHP5_INCLUDES}) - ENDIF(NOT PHP5_INCLUDE_PATH) - - IF(PHP5_VERSION LESS 5) - MESSAGE(FATAL_ERROR "PHP version is not 5 or later") - ENDIF(PHP5_VERSION LESS 5) - - IF(PHP5_EXECUTABLE AND PHP5_INCLUDES) - set(PHP5_FOUND "yes") - MESSAGE(STATUS "Found PHP5-Version ${PHP5_VERSION} (using ${PHP5_CONFIG_EXECUTABLE})") - ENDIF(PHP5_EXECUTABLE AND PHP5_INCLUDES) - - FIND_PROGRAM(PHPUNIT_EXECUTABLE - NAMES phpunit phpunit2 - PATHS - /usr/local/bin - ) - - IF(PHPUNIT_EXECUTABLE) - MESSAGE(STATUS "Found phpunit: ${PHPUNIT_EXECUTABLE}") - ENDIF(PHPUNIT_EXECUTABLE) - -ENDIF(PHP5_CONFIG_EXECUTABLE) diff -Nru mapserver-7.0.7/cmake/FindPHP.cmake mapserver-7.6.4/cmake/FindPHP.cmake --- mapserver-7.0.7/cmake/FindPHP.cmake 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/cmake/FindPHP.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,117 @@ +# - Find PHP +# This module finds if PHP is installed and determines where the include files +# and libraries are. It also determines what the name of the library is. This +# code sets the following variables: +# +# PHP_INCLUDE_PATH = path to where php.h can be found +# PHP_EXECUTABLE = full path to the php binary +# + +SET(PHP_FOUND "NO") + +SET(PHP_POSSIBLE_INCLUDE_PATHS + /usr/include/php + /usr/local/include/php + /usr/include/php + /usr/local/include/php + /usr/local/apache/php + ${PHP_INCLUDES} +) + +find_library(PHP_LIBRARY NAMES php5ts php5 php7ts php7 PATHS /sw /opt/local) + +if(WIN32) + string(SUBSTRING $ENV{VSCMD_VER} 0 2 VSCMD_VER) + SET(PHP_INCLUDE_PATH "C:/php-sdk/phpmaster/vc${VSCMD_VER}/$ENV{VSCMD_ARG_TGT_ARCH}/php-src") + SET(PHP_POSSIBLE_INCLUDE_PATHS ${PHP_INCLUDE_PATH}) + if(CMAKE_CL_64) + SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/$ENV{PLATFORM}") + endif(CMAKE_CL_64) + if(WITH_THREAD_SAFETY) + SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/Release_TS") + SET(PHP_LIBRARY_NAMES php5ts php7ts) + else(WITH_THREAD_SAFETY) + SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/Release") + SET(PHP_LIBRARY_NAMES php5 php7) + endif(WITH_THREAD_SAFETY) + find_library(PHP_LIBRARY NAMES ${PHP_LIBRARY_NAMES} PATHS ${PHP_INCLUDE_PATH}) +endif(WIN32) + + +FIND_PATH(PHP_FOUND_INCLUDE_PATH main/php.h ${PHP_POSSIBLE_INCLUDE_PATHS}) + +IF(PHP_FOUND_INCLUDE_PATH) + SET(php_paths "${PHP_POSSIBLE_INCLUDE_PATHS}") + FOREACH(php_path Zend main TSRM) + SET(php_paths ${php_paths} "${PHP_FOUND_INCLUDE_PATH}/${php_path}") + ENDFOREACH(php_path Zend main TSRM) + SET(PHP_INCLUDE_PATH "${php_paths}" INTERNAL "PHP include paths") +ENDIF(PHP_FOUND_INCLUDE_PATH) + +FIND_PROGRAM(PHP_EXECUTABLE + NAMES php + PATHS + /usr/local/bin + ) + +MARK_AS_ADVANCED( + PHP_EXECUTABLE + PHP_FOUND_INCLUDE_PATH + ) + +IF( NOT PHP_CONFIG_EXECUTABLE ) +FIND_PROGRAM(PHP_CONFIG_EXECUTABLE + NAMES php-config + ) +ENDIF( NOT PHP_CONFIG_EXECUTABLE ) + +IF(PHP_CONFIG_EXECUTABLE) + EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --version + OUTPUT_VARIABLE PHP_VERSION) + STRING(REPLACE "\n" "" PHP_VERSION "${PHP_VERSION}") + + EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --extension-dir + OUTPUT_VARIABLE PHP_EXTENSION_DIR) + STRING(REPLACE "\n" "" PHP_EXTENSION_DIR "${PHP_EXTENSION_DIR}") + + EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --includes + OUTPUT_VARIABLE PHP_INCLUDES) + STRING(REPLACE "-I" "" PHP_INCLUDES "${PHP_INCLUDES}") + STRING(REPLACE " " ";" PHP_INCLUDES "${PHP_INCLUDES}") + STRING(REPLACE "\n" "" PHP_INCLUDES "${PHP_INCLUDES}") + LIST(GET PHP_INCLUDES 0 PHP_INCLUDE_DIR) + + set(PHP_MAIN_INCLUDE_DIR ${PHP_INCLUDE_DIR}/main) + set(PHP_TSRM_INCLUDE_DIR ${PHP_INCLUDE_DIR}/TSRM) + set(PHP_ZEND_INCLUDE_DIR ${PHP_INCLUDE_DIR}/Zend) + set(PHP_REGEX_INCLUDE_DIR ${PHP_INCLUDE_DIR}/regex) + set(PHP_EXT_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext) + set(PHP_DATE_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext/date/lib) + set(PHP_STANDARD_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext/standard) + + MESSAGE(STATUS ${PHP_MAIN_INCLUDE_DIR}) + + IF(NOT PHP_INCLUDE_PATH) + set(PHP_INCLUDE_PATH ${PHP_INCLUDES}) + ENDIF(NOT PHP_INCLUDE_PATH) + + IF(PHP_VERSION LESS 5) + MESSAGE(FATAL_ERROR "PHP version is not 5 or later") + ENDIF(PHP_VERSION LESS 5) + + IF(PHP_EXECUTABLE AND PHP_INCLUDES) + set(PHP_FOUND "yes") + MESSAGE(STATUS "Found PHP-Version ${PHP_VERSION} (using ${PHP_CONFIG_EXECUTABLE})") + ENDIF(PHP_EXECUTABLE AND PHP_INCLUDES) + + FIND_PROGRAM(PHPUNIT_EXECUTABLE + NAMES phpunit phpunit2 + PATHS + /usr/local/bin + ) + + IF(PHPUNIT_EXECUTABLE) + MESSAGE(STATUS "Found phpunit: ${PHPUNIT_EXECUTABLE}") + ENDIF(PHPUNIT_EXECUTABLE) + +ENDIF(PHP_CONFIG_EXECUTABLE) diff -Nru mapserver-7.0.7/cmake/FindProj.cmake mapserver-7.6.4/cmake/FindProj.cmake --- mapserver-7.0.7/cmake/FindProj.cmake 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/cmake/FindProj.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -1,17 +1,40 @@ -# Find Proj -# -# If it's found it sets PROJ_FOUND to TRUE -# and following variables are set: -# PROJ_INCLUDE_DIR -# PROJ_LIBRARY - - -FIND_PATH(PROJ_INCLUDE_DIR proj_api.h) - -FIND_LIBRARY(PROJ_LIBRARY NAMES proj proj_i) - -set(PROJ_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) -set(PROJ_LIBRARIES ${PROJ_LIBRARY}) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(PROJ DEFAULT_MSG PROJ_LIBRARY PROJ_INCLUDE_DIR) -mark_as_advanced(PROJ_LIBRARY PROJ_INCLUDE_DIR) +# Find Proj +# +# If it's found it sets PROJ_FOUND to TRUE +# and following variables are set: +# PROJ_INCLUDE_DIR +# PROJ_LIBRARY + + +FIND_PATH(PROJ_INCLUDE_DIR NAMES proj.h proj_api.h) + +FIND_LIBRARY(PROJ_LIBRARY NAMES proj proj_i) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PROJ DEFAULT_MSG PROJ_LIBRARY PROJ_INCLUDE_DIR) +mark_as_advanced(PROJ_LIBRARY PROJ_INCLUDE_DIR) + + +IF (PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + SET(PROJ_FOUND TRUE) +ENDIF (PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + +IF (PROJ_FOUND) + IF (EXISTS ${PROJ_INCLUDE_DIR}/proj.h) + FILE(READ ${PROJ_INCLUDE_DIR}/proj.h proj_version) + STRING(REGEX REPLACE "^.*PROJ_VERSION_MAJOR +([0-9]+).*$" "\\1" PROJ_VERSION_MAJOR "${proj_version}") + STRING(REGEX REPLACE "^.*PROJ_VERSION_MINOR +([0-9]+).*$" "\\1" PROJ_VERSION_MINOR "${proj_version}") + STRING(REGEX REPLACE "^.*PROJ_VERSION_PATCH +([0-9]+).*$" "\\1" PROJ_VERSION_PATCH "${proj_version}") + + MESSAGE(STATUS "Found Proj ${PROJ_VERSION_MAJOR}.${PROJ_VERSION_MINOR}") + + IF ((PROJ_VERSION_MAJOR EQUAL 6) AND (PROJ_VERSION_MINOR EQUAL 3) AND (PROJ_VERSION_PATCH EQUAL 0)) + MESSAGE (FATAL_ERROR "MapServer known to crash with PROJ 6.3.0. Use 6.3.1 or higher.") + ENDIF ((PROJ_VERSION_MAJOR EQUAL 6) AND (PROJ_VERSION_MINOR EQUAL 3) AND (PROJ_VERSION_PATCH EQUAL 0)) + + ADD_DEFINITIONS(-DPROJ_VERSION_MAJOR=${PROJ_VERSION_MAJOR}) + ELSE() + MESSAGE(STATUS "Found Proj 4.x") + ADD_DEFINITIONS(-DPROJ_VERSION_MAJOR=4) + ENDIF() +ENDIF (PROJ_FOUND) diff -Nru mapserver-7.0.7/cmake/FindProtobufC.cmake mapserver-7.6.4/cmake/FindProtobufC.cmake --- mapserver-7.0.7/cmake/FindProtobufC.cmake 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/cmake/FindProtobufC.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,111 @@ +# - Find protobuf-c +# Find protobuf c implementation libraries, includes and the protoc-c compiler +# FindProtobufC was loosely based on FindProtobuf that is shipped with cmake +# +# Module defines: +# PROTOBUFC_FOUND - library, includes and compiler where found +# PROTOBUFC_INCLUDE_DIRS - include directories +# PROTOBUFC_LIBRARIES - protobuf-c libraries +# PROTOBUFC_EXECUTEABLE - protobuf-c compiler +# +# Environment variables: +# PROTOBUFC_ROOTDIR - optional - rootdir of protobuf-c installation +# +# Cache entries: +# PROTOBUFC_LIBRARY - detected protobuf-c library +# PROTOBUF_INCLUDE_DIR - detected protobuf-c include dir(s) +# PROTOBUF_COMPILER - detected protobuf-c compiler +# +#### +# +# ==================================================================== +# Example: +# +# find_package(ProtobufC REQUIRED) +# include_directories(${PROTOBUFC_INCLUDE_DIRS}) +# include_directories(${CMAKE_CURRENT_BINARY_DIR}) +# PROTOBUFC_GENERATE_C(PROTO_SOURCES PROTO_HEADERS protobuf.proto) +# add_executable(bar bar.c ${PROTO_SRCn} ${PROTO_HDRS}) +# target_link_libraries(bar ${PROTOBUF_LIBRARIES}) +# +# NOTE: You may need to link against pthreads, depending +# on the platform. +# +# NOTE: The PROTOBUF_GENERATE_CPP macro & add_executable() or add_library() +# calls only work properly within the same directory. +# +# ==================================================================== + +#============================================================================= +# Copyright 2013 Thinstuff Technologies GmbH +# Copyright 2013 Bernhard Miklautz +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +set(PROTBUFC_SOURCE_EXTENSION "pb-c.c") +set(PROTBUFC_HEADER_EXTENSION "pb-c.h") +function(PROTOBUFC_GENERATE_C SOURCES HEADERS) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUFC_GENERATE_C() called without any proto files") + return() + endif(NOT ARGN) + + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + get_filename_component(FIL_PATH ${ABS_FIL} PATH) + + list(APPEND ${SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_SOURCE_EXTENSION}") + list(APPEND ${HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_HEADER_EXTENSION}") + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_SOURCE_EXTENSION}" + "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_HEADER_EXTENSION}" + COMMAND ${PROTOBUFC_COMPILER} + ARGS --c_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} -I ${FIL_PATH} ${ABS_FIL} + DEPENDS ${ABS_FIL} + COMMENT "Running protobuf-c compiler on ${FIL}" + VERBATIM ) + endforeach() + set_source_files_properties(${${SOURCES}} ${${HEADERS}} PROPERTIES GENERATED TRUE) + set(${SOURCES} ${${SOURCES}} PARENT_SCOPE) + set(${HEADERS} ${${HEADERS}} PARENT_SCOPE) +endfunction() + +find_library(PROTOBUFC_LIBRARY + NAMES "protobuf-c" + PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR + PATH_SUFFIXES "lib") +mark_as_advanced(PROTOBUFC_LIBRARY) + +find_path(PROTOBUFC_INCLUDE_DIR + NAMES "google/protobuf-c/protobuf-c.h" + PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR + PATH_SUFFIXES "include") +mark_as_advanced(PROTOBUFC_INCLUDE_DIR) + +find_program(PROTOBUFC_COMPILER + NAMES "protoc-c" + PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR + PATH_SUFFIXES "bin") +mark_as_advanced(PROTOBUFC_COMPILER) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ProtobufC DEFAULT_MSG PROTOBUFC_LIBRARY PROTOBUFC_COMPILER PROTOBUFC_INCLUDE_DIR ) + +if (PROTOBUFC_FOUND) + set(PROTOBUFC_LIBRARIES ${PROTOBUFC_LIBRARY}) + set(PROTOBUFC_INCLUDE_DIRS ${PROTOBUFC_INCLUDE_DIR}) + set(PROTOBUFC_EXECUTEABLE ${PROTOBUFC_COMPILER}) +endif(PROTOBUFC_FOUND) diff -Nru mapserver-7.0.7/cmake/FindPythonModule.cmake mapserver-7.6.4/cmake/FindPythonModule.cmake --- mapserver-7.0.7/cmake/FindPythonModule.cmake 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/cmake/FindPythonModule.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,24 @@ +# Find if a Python module is installed +# Found at http://www.cmake.org/pipermail/cmake/2011-January/041666.html +# To use do: find_python_module(PyQt4 REQUIRED) +function(find_python_module module) + string(TOUPPER ${module} module_upper) + if(NOT PY_${module_upper}) + if(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") + set(${module}_FIND_REQUIRED TRUE) + endif() + # A module's location is usually a directory, but for binary modules + # it's a .so file. + execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" + RESULT_VARIABLE _${module}_status + OUTPUT_VARIABLE _${module}_location + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT _${module}_status) + set(PY_${module_upper} ${_${module}_location} CACHE STRING + "Location of Python module ${module}") + endif(NOT _${module}_status) + endif(NOT PY_${module_upper}) + find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) +endfunction(find_python_module) diff -Nru mapserver-7.0.7/CMakeLists.txt mapserver-7.6.4/CMakeLists.txt --- mapserver-7.0.7/CMakeLists.txt 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/CMakeLists.txt 2021-07-12 20:16:21.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 3.0) project (MapServer) @@ -16,10 +16,28 @@ set (MapServer_VERSION_MAJOR 7) -set (MapServer_VERSION_MINOR 0) -set (MapServer_VERSION_REVISION 7) +set (MapServer_VERSION_MINOR 6) +set (MapServer_VERSION_REVISION 4) set (MapServer_VERSION_SUFFIX "") +# Set C++ version +# Make CMAKE_CXX_STANDARD available as cache option overridable by user +set(CMAKE_CXX_STANDARD 11 + CACHE STRING "C++ standard version to use (default is 11)") +message(STATUS "Requiring C++${CMAKE_CXX_STANDARD}") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +message(STATUS "Requiring C++${CMAKE_CXX_STANDARD} - done") + +# Set C99 version +# Make CMAKE_C_STANDARD available as cache option overridable by user +set(CMAKE_C_STANDARD 99 + CACHE STRING "C standard version to use (default is 99)") +message(STATUS "Requiring C${CMAKE_C_STANDARD}") +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) +message(STATUS "Requiring C${CMAKE_C_STANDARD} - done") + set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR}) set(TARGET_VERSION_MINOR ${MapServer_VERSION_MINOR}) @@ -33,6 +51,10 @@ MATH(EXPR MapServer_VERSION_NUM "${MapServer_VERSION_MAJOR}*10000+${MapServer_VERSION_MINOR}*100+${MapServer_VERSION_REVISION}") SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) + +# Add custom function to check Python modules are installed +include(FindPythonModule) + if (APPLE) set(CMAKE_FIND_FRAMEWORK "LAST") endif (APPLE) @@ -92,7 +114,6 @@ check_function_exists("strrstr" HAVE_STRRSTR) check_function_exists("strcasecmp" HAVE_STRCASECMP) check_function_exists("strcasestr" HAVE_STRCASESTR) -check_function_exists("strdup" HAVE_STRDUP) check_function_exists("strlcat" HAVE_STRLCAT) check_function_exists("strlcpy" HAVE_STRLCPY) check_function_exists("strlen" HAVE_STRLEN) @@ -116,7 +137,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) #options suported by the cmake builder -option(WITH_PROJ "Choose if reprojection support should be built in" ON) +option(WITH_PROTOBUFC "Choose if protocol buffers support should be built in (required for vector tiles)" ON) option(WITH_KML "Enable native KML output support (requires libxml2 support)" OFF) option(WITH_SOS "Enable SOS Server support (requires PROJ and libxml2 support)" OFF) option(WITH_WMS "Enable WMS Server support (requires proj support)" ON) @@ -130,8 +151,6 @@ option(WITH_FCGI "Choose if FastCGI support should be built in" ON) option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON) option(WITH_POSTGIS "Choose if Postgis input support should be built in" ON) -option(WITH_GDAL "Choose if GDAL input raster support should be built in" ON) -option(WITH_OGR "Choose if OGR/GDAL input vector support should be built in" ON) option(WITH_CLIENT_WMS "Enable Client WMS Layer support (requires CURL and GDAL support)" OFF) option(WITH_CLIENT_WFS "Enable Client WMS Layer support (requires CURL and OGR support)" OFF) option(WITH_CURL "Enable Curl HTTP support (required for wms/wfs client, and remote SLD)" OFF) @@ -142,11 +161,12 @@ option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) option(WITH_PYTHON "Enable Python mapscript support" OFF) option(WITH_PHP "Enable PHP mapscript support" OFF) +option(WITH_PHPNG "Enable PHPNG (SWIG) mapscript support" OFF) option(WITH_PERL "Enable Perl mapscript support" OFF) option(WITH_RUBY "Enable Ruby mapscript support" OFF) option(WITH_JAVA "Enable Java mapscript support" OFF) option(WITH_CSHARP "Enable C# mapscript support" OFF) -option(WITH_POINT_Z_M "include Z and M coordinates in point structure (advanced, not recommended)" OFF) +option(WITH_POINT_Z_M "include Z and M coordinates in point structure" ON) option(WITH_ORACLESPATIAL "include oracle spatial database input support" OFF) option(WITH_ORACLE_PLUGIN "include oracle spatial database input support as plugin" OFF) option(WITH_MSSQL2008 "include mssql 2008 database input support as plugin" OFF) @@ -165,9 +185,9 @@ # PERLV_ld_DETECT? # Add compiler flags for warnings -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wdeclaration-after-statement") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=format-security") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=format-security") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) @@ -241,6 +261,8 @@ set(REGEX_MALLOC 1) set(USE_GENERIC_MS_NINT 1) set(HAVE_STRING_H 0) + # Suppress warnings for regex.c + set_source_files_properties(${REGEX_SOURCES} PROPERTIES COMPILE_FLAGS /w) else(WIN32) set(REGEX_SOURCES "") endif(WIN32) @@ -254,15 +276,16 @@ mapcluster.c mapio.c mappostgis.c maptemplate.c mapcontext.c mapjoin.c mappostgresql.c mapthread.c mapcopy.c maplabel.c mapprimitive.c maptile.c mapcpl.c maplayer.c mapproject.c maptime.c mapcrypto.c maplegend.c hittest.c -mapprojhack.c maptree.c mapdebug.c maplexer.c mapquantization.c mapunion.c +maptree.c mapdebug.c maplexer.c mapquantization.c mapunion.c mapdraw.c maplibxml2.c mapquery.c maputil.c strptime.c mapdrawgdal.c mapraster.c mapuvraster.c mapdummyrenderer.c mapobject.c maprasterquery.c mapwcs.c maperror.c mapogcfilter.c mapregex.c mapwcs11.c mapfile.c -mapogcfiltercommon.c maprendering.c mapwcs20.c mapogcsld.c +mapogcfiltercommon.cpp maprendering.c mapwcs20.c mapogcsld.c mapmetadata.c mapresample.c mapwfs.c mapgdal.c mapogcsos.c mapscale.c mapwfs11.c mapwfs20.c -mapgeomtransform.c mapogroutput.c mapwfslayer.c mapagg.cpp mapkml.cpp +mapgeomtransform.c mapogroutput.cpp mapwfslayer.c mapagg.cpp mapkml.cpp mapgeomutil.cpp mapkmlrenderer.cpp fontcache.c textlayout.c maputfgrid.cpp -mapogr.cpp mapcontour.c mapsmoothing.c mapv8.cpp ${REGEX_SOURCES} kerneldensity.c) +mapogr.cpp mapcontour.c mapsmoothing.c mapv8.cpp ${REGEX_SOURCES} kerneldensity.c +mapcompositingfilter.c mapmvt.c) set(mapserver_HEADERS cgiutil.h dejavu-sans-condensed.h dxfcolor.h fontcache.h hittest.h mapagg.h @@ -273,8 +296,39 @@ mapserver-api.h mapserver.h mapserv.h mapshape.h mapsymbol.h maptemplate.h mapthread.h maptile.h maptime.h maptree.h maputfgrid.h mapwcs.h uthash.h) +if(WIN32) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/version.rc + @ONLY) + set(mapserver_SOURCES ${mapserver_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +endif(WIN32) + +if(WITH_PROTOBUFC) + find_package(ProtobufC) + if(NOT PROTOBUFC_FOUND) + report_optional_not_found(PROTOBUFC) + else(NOT PROTOBUFC_FOUND) + list(APPEND ALL_INCLUDE_DIRS ${PROTOBUFC_INCLUDE_DIR}) + + FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/renderers/mvt) + # Create custom command for protoc-c + ADD_CUSTOM_COMMAND( + COMMAND ${PROTOBUFC_COMPILER} + ARGS --c_out=${PROJECT_BINARY_DIR}/renderers/mvt --proto_path=${PROJECT_SOURCE_DIR}/renderers/mvt ${PROJECT_SOURCE_DIR}/renderers/mvt/vector_tile.proto + OUTPUT ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.h + ) + + SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.h ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c GENERATED) + set (vectortile_SOURCES ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c) + + set (USE_PBF 1) + endif(NOT PROTOBUFC_FOUND) +endif (WITH_PROTOBUFC) + + if(BUILD_DYNAMIC) - add_library(mapserver SHARED ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) + add_library(mapserver SHARED ${vectortile_SOURCES} ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) set_target_properties( mapserver PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 2 @@ -282,7 +336,7 @@ endif(BUILD_DYNAMIC) if(BUILD_STATIC) - add_library(mapserver_static STATIC ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) + add_library(mapserver_static STATIC ${vectortile_SOURCES} ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) set_target_properties( mapserver_static PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 2 @@ -351,17 +405,20 @@ list(APPEND ALL_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIR}) -if(WITH_PROJ) - find_package(Proj) - if(NOT PROJ_FOUND) - report_optional_not_found(PROJ) - else(NOT PROJ_FOUND) - include_directories(${PROJ_INCLUDE_DIR}) - ms_link_libraries( ${PROJ_LIBRARY}) - list(APPEND ALL_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) - set (USE_PROJ 1) - endif(NOT PROJ_FOUND) -endif (WITH_PROJ) +find_package(Proj) +if(NOT PROJ_FOUND) + report_mandatory_not_found(PROJ) +endif(NOT PROJ_FOUND) + +include_directories(${PROJ_INCLUDE_DIR}) +ms_link_libraries( ${PROJ_LIBRARY}) +list(APPEND ALL_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) + +if(USE_PBF) + include_directories(${PROJECT_BINARY_DIR}/renderers/mvt) + include_directories(${PROTOBUFC_INCLUDE_DIR}) + ms_link_libraries( ${PROTOBUFC_LIBRARY}) +endif() if(WITH_PIXMAN) find_package(Pixman) @@ -376,11 +433,7 @@ endif (WITH_PIXMAN) if(WITH_WMS) - if(USE_PROJ) - set(USE_WMS_SVR 1) - else(USE_PROJ) - report_dependency_error(WMS PROJ) - endif(USE_PROJ) + set(USE_WMS_SVR 1) endif(WITH_WMS) if(WITH_FRIBIDI) @@ -493,7 +546,6 @@ if(WITH_MSSQL2008) find_package(ODBC) if(ODBC_FOUND) - include_directories(${ODBC_INCLUDE_DIR}) add_library(msplugin_mssql2008 MODULE mapmssql2008.c) target_link_libraries(msplugin_mssql2008 ${ODBC_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_mssql2008 PROPERTIES COMPILE_FLAGS "-DUSE_MSSQL2008_PLUGIN -DUSE_MSSQL2008") @@ -548,17 +600,14 @@ endif(POSTGRESQL_FOUND) endif (WITH_POSTGIS) -if(WITH_GDAL) - find_package(GDAL) - if(GDAL_FOUND) - include_directories(${GDAL_INCLUDE_DIR}) - ms_link_libraries( ${GDAL_LIBRARY}) - list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) - set (USE_GDAL 1) - else(GDAL_FOUND) - report_optional_not_found(GDAL) - endif(GDAL_FOUND) -endif (WITH_GDAL) +find_package(GDAL) +if(NOT GDAL_FOUND) + report_mandatory_not_found(GDAL) +endif(NOT GDAL_FOUND) + +include_directories(${GDAL_INCLUDE_DIR}) +ms_link_libraries( ${GDAL_LIBRARY}) +list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) if(WITH_SVGCAIRO) if(WITH_RSVG) @@ -593,25 +642,6 @@ endif(RSVG_FOUND AND GOBJECT_FOUND) endif (WITH_RSVG) -if(WITH_OGR) - if(GDAL_FOUND) - set (USE_OGR 1) - else(GDAL_FOUND) - find_package(GDAL) - if(GDAL_FOUND) - include_directories(${GDAL_INCLUDE_DIR}) - ms_link_libraries( ${GDAL_LIBRARY}) - list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) - set (USE_OGR 1) - else(GDAL_FOUND) - message(SEND_ERROR "GDAL library could not be found and is needed for OGR support. - HINTS: - - disable OGR support by adding -DWITH_OGR=0 - - add the GDAL install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\"") - endif(GDAL_FOUND) - endif(GDAL_FOUND) -endif(WITH_OGR) - if(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) set(WITH_CURL ON) endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) @@ -640,56 +670,19 @@ endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(WITH_CLIENT_WMS) - if(USE_GDAL AND USE_PROJ) - set(USE_WMS_LYR 1) - else(USE_GDAL AND USE_PROJ) - if(NOT USE_GDAL) - report_dependency_error(CLIENT_WMS GDAL) - endif(NOT USE_GDAL) - if( NOT USE_PROJ) - report_dependency_error(CLIENT_WMS PROJ) - endif(NOT USE_PROJ) - endif(USE_GDAL AND USE_PROJ) + set(USE_WMS_LYR 1) endif(WITH_CLIENT_WMS) if(WITH_CLIENT_WFS) - if(USE_OGR AND USE_PROJ) - set(USE_WFS_LYR 1) - else(USE_OGR AND USE_PROJ) - if(NOT USE_OGR) - report_dependency_error(CLIENT_WFS OGR) - endif(NOT USE_OGR) - if( NOT USE_PROJ) - report_dependency_error(CLIENT_WFS PROJ) - endif(NOT USE_PROJ) - endif(USE_OGR AND USE_PROJ) + set(USE_WFS_LYR 1) endif(WITH_CLIENT_WFS) if(WITH_WFS) - if(USE_PROJ AND USE_OGR) - set(USE_WFS_SVR 1) - #TODO: set WFS_USE_LIBXML2 ? - else(USE_PROJ AND USE_OGR) - if( NOT USE_OGR) - report_dependency_error(WFS OGR) - endif( NOT USE_OGR) - if( NOT USE_PROJ) - report_dependency_error(WFS PROJ) - endif( NOT USE_PROJ) - endif(USE_PROJ AND USE_OGR) + set(USE_WFS_SVR 1) endif(WITH_WFS) if(WITH_WCS) - if(USE_PROJ AND USE_GDAL) - set(USE_WCS_SVR 1) - else(USE_PROJ AND USE_GDAL) - if(NOT USE_GDAL) - report_dependency_error(WCS GDAL) - endif(NOT USE_GDAL) - if(NOT USE_PROJ) - report_dependency_error(WCS PROJ) - endif(NOT USE_PROJ) - endif(USE_PROJ AND USE_GDAL) + set(USE_WCS_SVR 1) endif(WITH_WCS) if(WITH_LIBXML2) @@ -715,20 +708,11 @@ endif( USE_WFS_SVR AND NOT USE_LIBXML2 ) if(WITH_SOS) - if(NOT USE_OGR) - report_dependency_error(WITH_SOS OGR) - endif(NOT USE_OGR) - - if(USE_PROJ AND USE_LIBXML2) + if(USE_LIBXML2) set(USE_SOS_SVR 1) - else(USE_PROJ AND USE_LIBXML2) - if(NOT USE_LIBXML2) - report_dependency_error(SOS LIBXML2) - endif(NOT USE_LIBXML2) - if(NOT USE_PROJ) - report_dependency_error(SOS PROJ) - endif(NOT USE_PROJ) - endif(USE_PROJ AND USE_LIBXML2) + else(USE_LIBXML2) + report_dependency_error(SOS LIBXML2) + endif(USE_LIBXML2) endif(WITH_SOS) if(WITH_POINT_Z_M) @@ -826,6 +810,11 @@ set(USE_PHP_MAPSCRIPT 1) endif(WITH_PHP) +if(WITH_PHPNG) + add_subdirectory("mapscript/phpng") + set(USE_PHPNG_MAPSCRIPT 1) +endif(WITH_PHPNG) + if(WITH_APACHE_MODULE) add_subdirectory("apache") set(USE_APACHE_MODULE 1) @@ -857,7 +846,11 @@ endif(UNIX) if (WIN32) -ms_link_libraries( ${MS_EXTERNAL_LIBS} ws2_32.lib) + ms_link_libraries( ${MS_EXTERNAL_LIBS} ws2_32.lib) + if (MSVC) + #4701 : Potentially uninitialized local variable 'name' used (https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4701) + set_target_properties(mapserver PROPERTIES COMPILE_FLAGS "/EHsc /wd4267 /wd4244 /wd4018 /w14701") + endif(MSVC) endif (WIN32) configure_file ( @@ -893,12 +886,12 @@ message(STATUS "* Summary of configured options for this build") message(STATUS " * Mandatory components") +message(STATUS " * GDAL: ${GDAL_LIBRARY}") +message(STATUS " * PROJ: ${PROJ_LIBRARY}") message(STATUS " * png: ${PNG_LIBRARY}") message(STATUS " * jpeg: ${JPEG_LIBRARY}") message(STATUS " * freetype: ${FREETYPE_LIBRARY}") message(STATUS " * Optional components") -status_optional_component("GDAL" "${USE_GDAL}" "${GDAL_LIBRARY}") -status_optional_component("OGR" "${USE_OGR}" "${GDAL_LIBRARY}") status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}") status_optional_component("MYSQL" "${USE_MYSQL}" "${MYSQL_LIBRARY}") status_optional_component("FRIBIDI" "${USE_FRIBIDI}" "${FRIBIDI_LIBRARY}") @@ -908,12 +901,12 @@ 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}") status_optional_component("FastCGI" "${USE_FASTCGI}" "${FCGI_LIBRARY}") +status_optional_component("PROTOBUFC" "${USE_PBF}" "${PROTOBUFC_LIBRARY}") if(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) if(USE_ORACLESPATIAL) status_optional_component("Oracle Spatial" "${USE_ORACLESPATIAL}" "${ORACLE_LIBRARY}") @@ -943,6 +936,7 @@ message(STATUS " * Mapscripts") status_optional_feature("Python" "${USE_PYTHON_MAPSCRIPT}") status_optional_feature("PHP" "${USE_PHP_MAPSCRIPT}") +status_optional_feature("PHPNG" "${USE_PHPNG_MAPSCRIPT}") status_optional_feature("PERL" "${USE_PERL_MAPSCRIPT}") status_optional_feature("RUBY" "${USE_RUBY_MAPSCRIPT}") status_optional_feature("JAVA" "${USE_JAVA_MAPSCRIPT}") @@ -951,6 +945,7 @@ status_optional_feature("Apache Module (Experimental)" "${USE_APACHE_MODULE}") message(STATUS "") +message(STATUS "PROJECT_BINARY_DIR is set to ${PROJECT_BINARY_DIR}") message(STATUS "Will install files to ${CMAKE_INSTALL_PREFIX}") message(STATUS "Will install libraries to ${INSTALL_LIB_DIR}") diff -Nru mapserver-7.0.7/CONTRIBUTING.md mapserver-7.6.4/CONTRIBUTING.md --- mapserver-7.0.7/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/CONTRIBUTING.md 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,37 @@ +# How to contribute to MapServer + +Contributions to the MapServer project are most welcome, and can take many forms such as detailed bug reports, documentation, +tests, features, and patches. Note that all contributions are managed by the MapServer [Project Steering Committee](https://mapserver.org/psc.html). + +## Bugs and Help + +GitHub issues should only be created to log bugs. For general help and support the MapServer [mailing lists](https://mapserver.org/community/lists.html) +should be used. If you are unsure if you have discovered a bug, or may need help with configuring MapServer please +post to the [mapserver-users list](https://lists.osgeo.org/mailman/listinfo/mapserver-users). There is also +a [MapServer FAQ](https://mapserver.org/faq.html) which may have a solution to your problem. + +If you have discovered a bug, please refer to the [Bug Submission page](https://mapserver.org/development/bugs.html) for +guidelines on creating an issue on GitHub. Please also search the existing issues to see if the bug has already been reported, and +add any further details to the existing issue. + +For professional support please see the [MapServer Service Providers page](https://mapserver.org/community/service_providers.html). + +## Development + +A separate [mapserver-dev mailing list](https://lists.osgeo.org/mailman/listinfo/mapserver-dev) is available for developers +working on the MapServer code. Send a short message there to introduce yourself +to the community, and mention what you are interested in working on. + +Details on using GitHub can be found on the [MapServer GitHub page](https://mapserver.org/development/git.html). + +Request for Comments (RFCs), where upcoming major changes to the source +code are proposed, and a description of the various software tests & release +plans, can be found on the [MapServer Development page](https://mapserver.org/development/). + +Additional developer notes can be found in the [MapServer wiki](https://github.com/mapserver/mapserver/wiki#developer-notes), including +coding style and guidelines, memory management, and working with Git. + +## Documentation + +The MapServer documentation is stored in a [separate repository](https://github.com/MapServer/MapServer-documentation). Please submit any documentation +issues or changes there. See the [Documentation Development Guide](https://mapserver.org/development/documentation.html) for further details. diff -Nru mapserver-7.0.7/debian/cgi-mapserver.install mapserver-7.6.4/debian/cgi-mapserver.install --- mapserver-7.0.7/debian/cgi-mapserver.install 2017-01-16 21:41:00.000000000 +0000 +++ mapserver-7.6.4/debian/cgi-mapserver.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/cgi-bin/mapserv diff -Nru mapserver-7.0.7/debian/cgi-mapserver.links mapserver-7.6.4/debian/cgi-mapserver.links --- mapserver-7.0.7/debian/cgi-mapserver.links 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/cgi-mapserver.links 2019-03-30 09:59:05.000000000 +0000 @@ -0,0 +1 @@ +usr/bin/mapserv usr/lib/cgi-bin/mapserv diff -Nru mapserver-7.0.7/debian/cgi-mapserver.lintian-overrides mapserver-7.6.4/debian/cgi-mapserver.lintian-overrides --- mapserver-7.0.7/debian/cgi-mapserver.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/cgi-mapserver.lintian-overrides 2020-07-03 05:19:35.000000000 +0000 @@ -0,0 +1,3 @@ +# Not a problem +breakout-link usr/lib/cgi-bin/mapserv -> usr/bin/mapserv + diff -Nru mapserver-7.0.7/debian/changelog mapserver-7.6.4/debian/changelog --- mapserver-7.0.7/debian/changelog 2018-03-01 09:35:17.000000000 +0000 +++ mapserver-7.6.4/debian/changelog 2021-01-22 14:00:00.000000000 +0000 @@ -1,14 +1,326 @@ -mapserver (7.0.7-1build2) bionic; urgency=high +mapserver (7.6.4-0~bionic0) bionic; urgency=medium - * No change rebuild against ruby-defaults without ruby2.3 support. + * New upstream release. + + -- Angelos Tzotsos Fri, 22 Jan 2021 16:00:00 +0200 + +mapserver (7.6.2-1~bionic1) bionic; urgency=medium + + * patch 6216 added: PROJ >= 6 reprojection: fix use of freed memory when input and output projections are the same. + + -- Angelos Tzotsos Fri, 22 Jan 2021 16:00:00 +0200 + +mapserver (7.6.2-1~bionic0) bionic; urgency=medium + + * No change rebuild for bionic. + + -- Angelos Tzotsos Fri, 22 Jan 2021 16:00:00 +0200 + +mapserver (7.6.2-1) unstable; urgency=medium + + * Update symbols for other architectures. + * Move from experimental to unstable. + + -- Bas Couwenberg Wed, 09 Dec 2020 06:01:02 +0100 + +mapserver (7.6.2-1~exp1) experimental; urgency=medium + + * New upstream release. + * Update symbols for other architectures. + * Bump watch file version to 4. + * Update lintian overrides. + * Bump Standards-Version to 4.5.1, no changes. + * Require at least cmake 3.0. + * Update copyright file. + * Update upstream metadata. + * Update Homepage URL to use HTTPS. + * Update symbols for amd64. + + -- Bas Couwenberg Tue, 08 Dec 2020 05:29:11 +0100 + +mapserver (7.6.1-1) unstable; urgency=medium + + * Update symbols for other architectures. + * Move from experimental to unstable. + + -- Bas Couwenberg Sat, 01 Aug 2020 08:05:35 +0200 + +mapserver (7.6.1-1~exp1) experimental; urgency=medium + + * New upstream release. + * Drop phpng-mapscript.patch, included upstream. + * Update symbols for amd64. + * Add lintian overrides for file-references-package-build-path. + + -- Bas Couwenberg Fri, 31 Jul 2020 19:35:49 +0200 + +mapserver (7.6.0-2) unstable; urgency=medium + + * Add upstream patch to install mapscript.php. + (LP: #1884854) + * Include mapscript.php in php-mapscript-ng. + * Add lintian overrides for breakout-link. + + -- Bas Couwenberg Sat, 27 Jun 2020 20:32:54 +0200 + +mapserver (7.6.0-1) unstable; urgency=medium + + * New upstream release. + * Update 7.6.0~rc4 symbols for other architectures. + * Strip pre-releases from symbols version. + * Move from experimental to unstable. + + -- Bas Couwenberg Fri, 08 May 2020 17:38:17 +0200 + +mapserver (7.6.0~rc4-1~exp1) experimental; urgency=medium + + * New upstream release candidate. + * Drop override for mailing-list-obsolete-in-debian-infrastructure. + * Update symbols for other architectures. + + -- Bas Couwenberg Tue, 05 May 2020 05:46:51 +0200 + +mapserver (7.6.0~rc3-1~exp1) experimental; urgency=medium + + * New upstream release candidate. + * Update symbols for amd64. + * Add override for mailing-list-obsolete-in-debian-infrastructure. + + -- Bas Couwenberg Sat, 25 Apr 2020 06:45:11 +0200 + +mapserver (7.6.0~rc2-1~exp1) experimental; urgency=medium + + * New upstream release candidate. + + -- Bas Couwenberg Sat, 11 Apr 2020 06:47:59 +0200 + +mapserver (7.6.0~rc1-1~exp1) experimental; urgency=medium + + * New upstream release candidate. + + -- Bas Couwenberg Mon, 06 Apr 2020 05:56:37 +0200 + +mapserver (7.6.0~beta2-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Drop -D_GNU_SOURCE, fixed upstream. + + -- Bas Couwenberg Sun, 29 Mar 2020 08:46:12 +0200 + +mapserver (7.6.0~beta1-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Drop obsolete CMake options. + * Update copyright years for copyright holders. + * Drop swig-4.0.1.patch, included upstream. + * Add -D_GNU_SOURCE to CPPFLAGS. + * Update symbols for amd64. + + -- Bas Couwenberg Mon, 23 Mar 2020 06:51:15 +0100 + +mapserver (7.4.4-1) unstable; urgency=high + + * New upstream release. + * Drop mapscript-buffer-overflow.patch, included upstream. + + -- Bas Couwenberg Fri, 20 Mar 2020 21:15:45 +0100 + +mapserver (7.4.3-3) unstable; urgency=high + + * Bump debhelper compat to 10, changes: + - Drop --parallel option, enabled by default + * Add upstream patch to fix PHPMapScript error handling vulnerabilities. + + -- Bas Couwenberg Fri, 20 Mar 2020 20:40:37 +0100 + +mapserver (7.4.3-2) unstable; urgency=medium + + * Bump Standards-Version to 4.5.0, no changes. + * Add upstream patch to fix FTBFS with SWIG 4.0.1. + (closes: #951886) + + -- Bas Couwenberg Sat, 22 Feb 2020 19:25:03 +0100 + +mapserver (7.4.3-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version to 4.4.1, no changes. + * Drop Provides: ${python3:Provides}. + * Change python3-all{,-dev} build dependency to python3{,-dev}, + only the default interpreter is used. + * Drop Name field from upstream metadata. + * Drop unused overrides for file-references-package-build-path. + * Update symbols for amd64. + * Rename TODO.Debian to TODO. + + -- Bas Couwenberg Tue, 17 Dec 2019 05:34:32 +0100 + +mapserver (7.4.2-1) unstable; urgency=medium - -- Dimitri John Ledkov Thu, 01 Mar 2018 09:35:17 +0000 + * New upstream release. + * Update 7.4.1 symbols for other architectures. + * Update 7.4.2 symbols for amd64. + + -- Bas Couwenberg Sat, 14 Sep 2019 07:55:23 +0200 + +mapserver (7.4.1-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version to 4.4.0, no changes. + + -- Bas Couwenberg Sat, 13 Jul 2019 06:39:37 +0200 + +mapserver (7.4.0-1) unstable; urgency=medium + + * Update symbols for other architectures. + * Update gbp.conf to use --source-only-changes by default. + * Move from experimental to unstable. + + -- Bas Couwenberg Sun, 07 Jul 2019 08:41:08 +0200 + +mapserver (7.4.0-1~exp1) experimental; urgency=medium + + * New upstream release. + * Update 7.4.0~rc2 symbols for other architectures. + * Update 7.4.0 symbols for amd64. + + -- Bas Couwenberg Tue, 14 May 2019 17:28:54 +0200 + +mapserver (7.4.0~rc2-1~exp1) experimental; urgency=medium + + * New upstream release candidate. + * Update symbols for other architectures. + + -- Bas Couwenberg Fri, 10 May 2019 16:54:50 +0200 + +mapserver (7.4.0~rc1-1~exp1) experimental; urgency=medium -mapserver (7.0.7-1build1) bionic; urgency=medium + * New upstream release candidate. + * Update 7.4.0~beta2 symbols for other architectures. + * Update 7.4.0~rc1 symbols for amd64. - * No-change rebuild for ruby2.5 update. + -- Bas Couwenberg Thu, 02 May 2019 06:27:49 +0200 - -- Matthias Klose Thu, 01 Feb 2018 19:13:52 +0000 +mapserver (7.4.0~beta2-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Update symbols for other architectures. + * Drop patches applied upstream. Refresh remaining patches. + + -- Bas Couwenberg Thu, 18 Apr 2019 06:30:22 +0200 + +mapserver (7.4.0~beta1-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Remove package name from lintian overrides. + * Re-enable PHP MapScript, support for PHP 7 available now. + * Add python-setuptools to build dependencies. + * Switch Python MapScript to Python 3. + * Drop Ruby MapScript, causes FTBFS. + * Update symbols for amd64. + * Add patch to fix spelling errors. + * Use ttf-bitstream-vera instead of embedded copy. + * Add patch for shebang in Python MapScript example scripts. + * Set INSTALL_LIB_DIR to Multi-Arch path. + * Move all CMake options to dh_auto_configure override. + * Also build PHPNG MapScript (based on SWIG). + * Drop unused shlibs:Depends from cgi-mapserver package. + + -- Bas Couwenberg Sat, 30 Mar 2019 09:59:55 +0100 + +mapserver (7.2.2-1) unstable; urgency=medium + + * Update symbols for other architectures. + * Move from experimental to unstable. + + -- Bas Couwenberg Wed, 20 Feb 2019 05:43:10 +0100 + +mapserver (7.2.2-1~exp1) experimental; urgency=medium + + * New upstream release. + * Add Build-Depends-Package field to symbols file. + * Bump Standards-Version to 4.3.0, no changes. + * Refresh patches. + * Update copyright years for Open Source Geospatial Foundation. + * Update symbols for amd64. + * Add lintian overrides for file-references-package-build-path. + + -- Bas Couwenberg Tue, 19 Feb 2019 18:07:57 +0100 + +mapserver (7.2.1-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version to 4.2.1, no changes. + * Drop patches applied upstream. Refresh remaining patches. + * Fix docs install for README rename. + + -- Bas Couwenberg Tue, 02 Oct 2018 07:11:40 +0200 + +mapserver (7.2.0-5) unstable; urgency=medium + + * Bump Standards-Version to 4.2.0, no changes. + * Add patch to fix FTBFS with CMake 3.12.x. + (closes: #906605) + + -- Bas Couwenberg Sun, 19 Aug 2018 09:45:57 +0200 + +mapserver (7.2.0-4) unstable; urgency=medium + + * Drop autopkgtest to test installability. + * Add lintian override for testsuite-autopkgtest-missing. + + -- Bas Couwenberg Tue, 31 Jul 2018 21:45:41 +0200 + +mapserver (7.2.0-3) unstable; urgency=medium + + * Add upstream patch to update HISTORY.TXT for 7.2.0 release. + * Update symbols for mipsel. + + -- Bas Couwenberg Tue, 24 Jul 2018 20:02:20 +0200 + +mapserver (7.2.0-2) unstable; urgency=medium + + * Add patch to remove -beta2 version suffix. + * Update symbols for other architectures. + + -- Bas Couwenberg Tue, 24 Jul 2018 14:11:34 +0200 + +mapserver (7.2.0-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version to 4.1.5, no changes. + * Update symbols for amd64. + * Strip pre-releases from symbols version. + * Move from experimental to unstable. + + -- Bas Couwenberg Tue, 24 Jul 2018 08:08:43 +0200 + +mapserver (7.2.0~beta2-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Update symbols for other architectures. + + -- Bas Couwenberg Wed, 13 Jun 2018 18:15:40 +0200 + +mapserver (7.2.0~beta1-1~exp1) experimental; urgency=medium + + * New upstream beta release. + * Update copyright-format URL to use HTTPS. + * Bump Standards-Version to 4.1.4, no changes. + * Fix deprecated source override location. + * Update watch file to use HTTPS. + * Update Vcs-* URLs for Salsa. + * Strip trailing whitespace from control & rules files. + * Update copyright file, changes: + - Update copyright years for existing copyright holders + - Update license for Bison files + - Drop license & copyright for pygdioctx, removed upstream + * Add protobuf build dependencies for MVT support. + * Drop obsolete dbg package. + * Replace /usr/lib/cgi-bin/mapserv with symlink to /usr/bin/mapserv. + * Update symbols for amd64. + + -- Bas Couwenberg Wed, 09 May 2018 22:21:12 +0200 mapserver (7.0.7-1) unstable; urgency=medium @@ -509,7 +821,7 @@ -- Francesco Paolo Lovergine Fri, 23 Dec 2011 14:02:06 +0100 mapserver (6.0.1-1) unstable; urgency=low - + [ Alan Boudreault ] * New upstream release. @@ -558,7 +870,7 @@ * Fix Validation of symbol index values (CVE-2010-1678) [http://trac.osgeo.org/mapserver/ticket/3641] - + -- Alan Boudreault Thu, 06 Jan 2011 11:18:29 -0500 mapserver (5.6.5-1.1) unstable; urgency=low @@ -624,7 +936,7 @@ * New upstream release, with a few important bug fixes. * Modified ruby mapscript package to use ruby 1.9.1 instead of 1.9.0. (closes: #565831) - + [ Francesco Paolo Lovergine ] * Removed Fabio Tranchitella from Uploaders. diff -Nru mapserver-7.0.7/debian/compat mapserver-7.6.4/debian/compat --- mapserver-7.0.7/debian/compat 2017-01-28 15:41:11.000000000 +0000 +++ mapserver-7.6.4/debian/compat 2020-03-27 16:59:55.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru mapserver-7.0.7/debian/control mapserver-7.6.4/debian/control --- mapserver-7.0.7/debian/control 2018-03-01 09:35:17.000000000 +0000 +++ mapserver-7.6.4/debian/control 2020-12-08 04:28:27.000000000 +0000 @@ -1,16 +1,15 @@ Source: mapserver -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian GIS Project +Maintainer: Debian GIS Project Uploaders: Francesco Paolo Lovergine , Alan Boudreault , Bas Couwenberg Section: devel Priority: optional -Build-Depends: debhelper (>= 9), -# dh-php, +Build-Depends: debhelper (>= 10~), + dh-php, dh-python, dpkg-dev (>= 1.16.1.1), - cmake (>= 2.8.12.1-1.2), + cmake (>= 3.0), chrpath, default-jdk, ant, @@ -26,30 +25,30 @@ libjpeg-dev, libperl-dev, libpng-dev, + libprotobuf-c-dev, libpq-dev, libproj-dev, librsvg2-dev, libxml2-dev, libxslt1-dev, zlib1g-dev (>= 1.1.4), -# php-dev, + php-dev, pkg-config, pkg-kde-tools, - python-all (>= 2.6.6-3~), - python-all-dev (>= 2.6.6-3~), - ruby, - ruby-all-dev, - gem2deb, + protobuf-c-compiler, + python3, + python3-dev, + python3-setuptools, swig, docbook2x, docbook-xsl, docbook-xml, xsltproc Build-Conflicts: libcurl3-openssl-dev -Standards-Version: 4.1.1 -Vcs-Browser: https://anonscm.debian.org/cgit/pkg-grass/mapserver.git -Vcs-Git: https://anonscm.debian.org/git/pkg-grass/mapserver.git -Homepage: http://www.mapserver.org +Standards-Version: 4.5.1 +Vcs-Browser: https://salsa.debian.org/debian-gis-team/mapserver +Vcs-Git: https://salsa.debian.org/debian-gis-team/mapserver.git +Homepage: https://mapserver.org XS-Ruby-Versions: all Package: libmapserver2 @@ -61,9 +60,9 @@ mapserver-bin, mapserver-doc, libmapscript-perl, -# php-mapscript, - python-mapscript, - ruby-mapscript + php-mapscript, + php-mapscript-ng, + python3-mapscript Pre-Depends: ${misc:Pre-Depends} Description: Shared library for MapServer This package contains the shared library. @@ -73,21 +72,6 @@ functionality in MapScript is provided by the suggested mapscript library packages. -Package: libmapserver-dbg -Architecture: any -Section: debug -Depends: libmapserver2 (= ${binary:Version}), - ${misc:Depends} -Breaks: libmapserver1-dbg (<< 7.0.0~) -Replaces: libmapserver1-dbg (<< 7.0.0~) -Description: Debugging symbols for libmapserver - MapServer is a CGI-based framework for Internet map services which - supports Open Geospatial Consortium (OGC) standards. Scripting - functionality in MapScript is provided by the suggested mapscript - library packages. - . - This package contains the debugging symbols for libmapserver. - Package: libmapserver-dev Architecture: any Section: libdevel @@ -97,9 +81,9 @@ mapserver-bin, mapserver-doc, libmapscript-perl, -# php-mapscript, - python-mapscript, - ruby-mapscript + php-mapscript, + php-mapscript-ng, + python3-mapscript Breaks: libmapserver-6.2.1-dev (<< 6.4.0-1~), libmapserver1-dev (<< 7.0.0~) Replaces: libmapserver-6.2.1-dev (<< 6.4.0-1~), @@ -115,14 +99,13 @@ Package: cgi-mapserver Architecture: any Section: web -Depends: ${shlibs:Depends}, +Depends: mapserver-bin, ${misc:Depends} -Suggests: mapserver-bin, - mapserver-doc, +Suggests: mapserver-doc, libmapscript-perl, -# php-mapscript, - python-mapscript, - ruby-mapscript + php-mapscript, + php-mapscript-ng, + python3-mapscript Description: CGI executable for MapServer This package contains the mapserv CGI program. It provides the MapServer template language, and can be used to implement Web Map @@ -142,9 +125,9 @@ mapserver-doc, shapelib, libmapscript-perl, -# php-mapscript, - python-mapscript, - ruby-mapscript + php-mapscript, + php-mapscript-ng, + python3-mapscript Description: MapServer utilities This package provides command-line utilities for MapServer. . @@ -159,9 +142,9 @@ Depends: ${misc:Depends} Suggests: cgi-mapserver, libmapscript-perl, -# php-mapscript, - python-mapscript, - ruby-mapscript + php-mapscript, + php-mapscript-ng, + python3-mapscript Description: documentation for MapServer This package provides some brief documentation for MapServer. . @@ -170,19 +153,37 @@ functionality in MapScript is provided by the suggested mapscript library packages. -#Package: php-mapscript -#Architecture: any -#Section: php -#Depends: ${php:Depends}, -# ${shlibs:Depends}, -# ${misc:Depends} -#Suggests: mapserver-bin, -# mapserver-doc -#Description: php-cgi module for MapServer -# PHP MapScript provides MapServer functions for PHP scripts. -# . -# MapServer is a CGI-based framework for Internet map services which -# supports Open Geospatial Consortium (OGC) standards. +Package: php-mapscript +Architecture: any +Section: php +Depends: ${php:Depends}, + ${shlibs:Depends}, + ${misc:Depends} +Suggests: mapserver-bin, + mapserver-doc +Description: php-cgi module for MapServer + PHP MapScript provides MapServer functions for PHP scripts. + . + MapServer is a CGI-based framework for Internet map services which + supports Open Geospatial Consortium (OGC) standards. + . + This package provides the traditional MapScript for PHP. + +Package: php-mapscript-ng +Architecture: any +Section: php +Depends: ${php:Depends}, + ${shlibs:Depends}, + ${misc:Depends} +Suggests: mapserver-bin, + mapserver-doc +Description: PHP MapServer module (SWIG) + PHP MapScript provides MapServer functions for PHP scripts. + . + MapServer is a CGI-based framework for Internet map services which + supports Open Geospatial Consortium (OGC) standards. + . + This package provides MapScript for PHP based on SWIG. Package: libmapscript-perl Architecture: any @@ -201,47 +202,21 @@ MapServer is a CGI-based framework for Internet map services which supports Open Geospatial Consortium (OGC) standards. -Package: python-mapscript +Package: python3-mapscript Architecture: any Section: python -Depends: ${python:Depends}, +Depends: ttf-bitstream-vera, + ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends} Suggests: mapserver-bin, mapserver-doc -Provides: ${python:Provides} Description: Python library for MapServer Python MapScript provides MapServer functions for Python scripts. . MapServer is a CGI-based framework for Internet map services which supports Open Geospatial Consortium (OGC) standards. -Package: ruby-mapscript -Architecture: any -Section: ruby -Depends: ruby | ruby-interpreter, - ${shlibs:Depends}, - ${misc:Depends} -Suggests: mapserver-bin, - mapserver-doc -Breaks: libmapscript-ruby (<< 6.4.0-1~), - libmapscript-ruby1.8 (<< 6.4.0-1~), - libmapscript-ruby1.9.1 (<< 6.4.0-1~) -Provides: libmapscript-ruby, - libmapscript-ruby1.8, - libmapscript-ruby1.9.1 -Replaces: libmapscript-ruby (<< 6.4.0-1~), - libmapscript-ruby1.8 (<< 6.4.0-1~), - libmapscript-ruby1.9.1 (<< 6.4.0-1~) -XB-Ruby-Versions: all -Description: MapServer library for Ruby - Ruby MapScript provides MapServer functions for Ruby scripts. - . - This package contains examples and the MapServer functions for Ruby. - . - MapServer is a CGI-based framework for Internet map services which - supports Open Geospatial Consortium (OGC) standards. - Package: libmapscript-java Architecture: any Section: java @@ -254,4 +229,3 @@ . MapServer is a CGI-based framework for Internet map services which supports Open Geospatial Consortium (OGC) standards. - diff -Nru mapserver-7.0.7/debian/copyright mapserver-7.6.4/debian/copyright --- mapserver-7.0.7/debian/copyright 2017-05-09 20:13:10.000000000 +0000 +++ mapserver-7.6.4/debian/copyright 2020-12-08 04:26:09.000000000 +0000 @@ -1,27 +1,28 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: MapServer Upstream-Contact: The MapServer team Source: https://github.com/mapserver/mapserver Files: * -Copyright: 2008-2017, Open Source Geospatial Foundation. - 1996-2014, Regents of the University of Minnesota. - 2011, 2013, Alan Boudreault, MapGears - 2013, Even Rouault - 2010-2011, EOX IT Services GmbH, Austria - 2000-2010, Daniel Morissette, DM Solutions Group Inc. - 2001-2002, 2004, 2007, 2010, Frank Warmerdam - 2008, 2010, Paul Ramsey - 2009-2010, Thomas Bonfort - 2000-2006, 2008, Y. Assefa, DM Solutions Group inc. - 2006-2007, Tom Kralidis - 2007, IS Consulting (www.mapdotnet.com) +Copyright: Joyent, Inc. and other Node contributors + 2002, Refractions Research + 2003, John Novak, Novacell Technologies + 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc 2000-2005, DM Solutions Group 2004-2005, Sean Gillies - 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc - 2003, John Novak, Novacell Technologies - 2002, Refractions Research - Joyent, Inc. and other Node contributors + 2007, IS Consulting (www.mapdotnet.com) + 2000-2006, 2008, Y. Assefa, DM Solutions Group inc. + 2009-2010, Thomas Bonfort + 2008, 2010, Paul Ramsey + 2001-2002, 2004, 2007, 2010, Frank Warmerdam + 2000-2010, Daniel Morissette, DM Solutions Group Inc. + 2010-2011, EOX IT Services GmbH, Austria + 2011, 2013, Alan Boudreault, MapGears + 2006-2007, 2017, Tom Kralidis + 1996-2019, Regents of the University of Minnesota. + 2019, Seth Girvin + 2008-2020, Open Source Geospatial Foundation. + 2013, 2020, Even Rouault License: MIT Files: dejavu-sans-condensed.h @@ -36,24 +37,24 @@ information see http://c.snippets.org/snip_lister.php?fname=bitarray.c. Files: mapquantization.c -Copyright: 1996-2005, Regents of the University of Minnesota - 1989, 1991, Jef Poskanzer +Copyright: 1989, 1991, Jef Poskanzer 1997, 2000, 2002, Greg Roelofs + 1996-2005, Regents of the University of Minnesota License: MIT-mapquantization Comment: Contains code derived from pngquant.c and libpam3.c. Files: maptclutf.c -Copyright: 1996-2007, Regents of the University of Minnesota - 1997-1998, Sun Microsystems, Inc +Copyright: 1997-1998, Sun Microsystems, Inc + 1996-2007, Regents of the University of Minnesota License: MIT-maptclutf Comment: Contains code derived from tclUtf.c. Files: mapstring.c -Copyright: 1996-2005, Regents of the University of Minnesota - 1998, Todd C. Miller - 2000-2004, University of Illinois Board of Trustees - 2000-2005, Mark D. Roth - 1990, 1993, The Regents of the University of California +Copyright: 1990, 1993, The Regents of the University of California + 1998, Todd C. Miller + 2000-2004, University of Illinois Board of Trustees + 1996-2005, Regents of the University of Minnesota + 2000-2005, Mark D. Roth License: MIT-mapstring Comment: Contains string functions from various sources. @@ -63,18 +64,13 @@ Files: mapparser.c mapparser.h -Copyright: 1984, 1989-1990, 2000-2006, Free Software Foundation, Inc. -License: GPL-2+ with Bison exception +Copyright: 1984, 1989-1990, 2000-2011, Free Software Foundation, Inc. +License: GPL-3+ with Bison exception Files: uthash.h Copyright: 2003-2013, Troy D. Hanson License: BSD-1-clause -Files: mapscript/python/pygdioctx/pygdioctx.c - mapscript/python/pygdioctx/pygdioctx.h -Copyright: 1995, Richard Jones, Bureau of Meteorology Australia -License: BSD-3-clause-GDMODULE-LICENSE - Files: opengl/glext.h Copyright: 1991-2004, Silicon Graphics, Inc 2005, NVIDIA Corporation @@ -343,35 +339,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -License: BSD-3-clause-GDMODULE-LICENSE - All rights reserved. - . - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - . - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. Neither the name of the Bureau of Meteorology - Australia nor the names of its contributors may be used to endorse - or promote products derived from this software without specific - prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - License: BSD-1-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -487,11 +454,11 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -License: GPL-2+ with Bison exception +License: GPL-3+ with Bison exception This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the license, or + (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -499,9 +466,7 @@ GNU General Public License for more details. . You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program; if not, see . As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -517,8 +482,8 @@ version 2.2 of Bison. . On Debian systems, the full text of the GNU General Public - License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + License version 3 can be found in the file + `/usr/share/common-licenses/GPL-3'. License: SGI-B-1.1 License Applicability. Except to the extent portions of this file are diff -Nru mapserver-7.0.7/debian/gbp.conf mapserver-7.6.4/debian/gbp.conf --- mapserver-7.0.7/debian/gbp.conf 2017-08-06 16:12:08.000000000 +0000 +++ mapserver-7.6.4/debian/gbp.conf 2020-08-06 03:51:37.000000000 +0000 @@ -14,3 +14,6 @@ # Always use pristine-tar. pristine-tar = True + +[buildpackage] +pbuilder-options = --source-only-changes diff -Nru mapserver-7.0.7/debian/libmapscript-java.lintian-overrides mapserver-7.6.4/debian/libmapscript-java.lintian-overrides --- mapserver-7.0.7/debian/libmapscript-java.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/libmapscript-java.lintian-overrides 2020-08-06 03:34:57.000000000 +0000 @@ -0,0 +1,3 @@ +# Cannot easily be fixed +file-references-package-build-path * + diff -Nru mapserver-7.0.7/debian/libmapscript-perl.lintian-overrides mapserver-7.6.4/debian/libmapscript-perl.lintian-overrides --- mapserver-7.0.7/debian/libmapscript-perl.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/libmapscript-perl.lintian-overrides 2020-08-06 03:34:57.000000000 +0000 @@ -0,0 +1,3 @@ +# Cannot easily be fixed +file-references-package-build-path * + diff -Nru mapserver-7.0.7/debian/libmapserver2.lintian-overrides mapserver-7.6.4/debian/libmapserver2.lintian-overrides --- mapserver-7.0.7/debian/libmapserver2.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/libmapserver2.lintian-overrides 2020-08-06 03:34:57.000000000 +0000 @@ -0,0 +1,3 @@ +# Cannot easily be fixed +file-references-package-build-path * + diff -Nru mapserver-7.0.7/debian/libmapserver2.symbols mapserver-7.6.4/debian/libmapserver2.symbols --- mapserver-7.0.7/debian/libmapserver2.symbols 2017-11-15 20:00:35.000000000 +0000 +++ mapserver-7.6.4/debian/libmapserver2.symbols 2020-12-09 05:00:39.000000000 +0000 @@ -1,7 +1,7 @@ -# SymbolsHelper-Confirmed: 7.0.7 amd64 +# SymbolsHelper-Confirmed: 7.6.2 amd64 arm64 armel armhf i386 powerpc ppc64 ppc64el riscv64 sparc64 libmapserver.so.2 #PACKAGE# #MINVER# +* Build-Depends-Package: libmapserver-dev BuildExpressionTree@Base 6.2.1 - CleanVSIDir@Base 6.2.1 CompareEllipseRegion@Base 6.2.1 CompareRectangleRegion@Base 6.2.1 DefineAxis@Base 6.2.1 @@ -20,28 +20,17 @@ FLTFreeFilterEncodingNode@Base 6.2.1 FLTGetBBOX@Base 6.2.1 FLTGetBinaryComparisonCommonExpression@Base 6.2.1 - FLTGetBinaryComparisonExpresssion@Base 6.2.1 FLTGetBinaryComparisonSQLExpresssion@Base 6.2.1 FLTGetCapabilities@Base 6.2.1 FLTGetCommonExpression@Base 6.2.1 FLTGetDuring@Base 7.0.0 FLTGetExpressionForValuesRanges@Base 6.2.1 - FLTGetFeatureIdCommonExpression@Base 6.2.1 FLTGetGeosOperator@Base 6.2.1 - FLTGetIsBetweenComparisonCommonExpresssion@Base 6.2.1 - FLTGetIsBetweenComparisonExpresssion@Base 6.2.1 FLTGetIsBetweenComparisonSQLExpresssion@Base 6.2.1 - FLTGetIsLikeComparisonCommonExpression@Base 6.2.1 - FLTGetIsLikeComparisonExpression@Base 6.2.1 FLTGetIsLikeComparisonSQLExpression@Base 6.2.1 - FLTGetLogicalComparisonCommonExpression@Base 6.2.1 - FLTGetLogicalComparisonExpresssion@Base 6.2.1 FLTGetLogicalComparisonSQLExpresssion@Base 6.2.1 - FLTGetMapserverExpression@Base 6.2.1 - FLTGetNodeExpression@Base 6.2.1 FLTGetSQLExpression@Base 6.2.1 FLTGetShape@Base 6.2.1 - FLTGetSpatialComparisonCommonExpression@Base 6.2.1 FLTGetTimeExpression@Base 7.0.0 FLTHasSpatialFilter@Base 6.2.1 FLTInsertElementInNode@Base 6.2.1 @@ -62,6 +51,7 @@ FLTIsTemporalFilterType@Base 7.0.0 FLTLayerApplyCondSQLFilterToLayer@Base 6.2.1 FLTLayerApplyPlainFilterToLayer@Base 6.2.1 + FLTLayerSetInvalidRectIfSupported@Base 7.6.0 FLTNumberOfFilterType@Base 6.2.1 FLTParseFilterEncoding@Base 6.2.1 FLTParseGMLBox@Base 6.2.1 @@ -69,6 +59,7 @@ FLTPreParseFilterForAliasAndGroup@Base 7.0.0 FLTProcessPropertyIsNull@Base 7.0.3 FLTSimplify@Base 7.0.0 + FLTSplitFilters@Base 7.2.0 FLTValidFilterNode@Base 6.2.1 FLTValidForBBoxFilter@Base 6.2.1 FLTogrConvertGeometry@Base 6.2.1 @@ -87,6 +78,7 @@ LayerDefaultGetItems@Base 6.2.1 LayerDefaultGetNumFeatures@Base 6.2.1 LayerDefaultGetShape@Base 6.2.1 + LayerDefaultGetShapeCount@Base 7.2.0 LayerDefaultInitItemInfo@Base 6.2.1 LayerDefaultIsOpen@Base 6.2.1 LayerDefaultNextShape@Base 6.2.1 @@ -128,25 +120,27 @@ _Z18encodeForRenderingj@Base 7.0.0 _Z18utfgridCreateImageiiP15outputFormatObjP8colorObj@Base 7.0.0 _Z19agg2RenderLineTiledP8imageObjP8shapeObjS0_@Base 6.2.1 - _Z19utfgridRenderGlyphsP8imageObjP11textPathObjP8colorObjS4_i@Base 7.0.0 - _Z20agg2RenderGlyphsPathP8imageObjP11textPathObjP8colorObjS4_i@Base 7.0.0 - (optional=templinst)_Z20decompose_ft_outlineIN9mapserver9path_baseINS0_20vertex_block_storageIdLj8ELj256EEEEEEbRK11FT_Outline_bRKNS0_12trans_affineERT_@Base 7.0.0 - (optional=templinst)_Z20renderPolygonHatchesIN9mapserver12conv_clipperI15polygon_adaptorNS0_11conv_strokeINS0_9conv_dashINS0_9path_baseINS0_20vertex_block_storageIdLj8ELj256EEEEENS0_12null_markersEEES9_EEEEEiP8imageObjRT_P8colorObj@Base 7.0.0 - (optional=templinst)_Z20renderPolygonHatchesIN9mapserver12conv_clipperI15polygon_adaptorNS0_11conv_strokeINS0_9path_baseINS0_20vertex_block_storageIdLj8ELj256EEEEENS0_12null_markersEEEEEEiP8imageObjRT_P8colorObj@Base 7.0.0 + _Z19utfgridRenderGlyphsP8imageObjP11textPathObjP8colorObjS4_ii@Base 7.6.0 + _Z20agg2RenderGlyphsPathP8imageObjP11textPathObjP8colorObjS4_ii@Base 7.6.0 _Z20utfgridRenderPolygonP8imageObjP8shapeObjP8colorObj@Base 7.0.0 _Z21agg2MergeRasterBufferP8imageObjP15rasterBufferObjdiiiiii@Base 6.2.1 _Z22agg2RenderPixmapSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 6.2.1 _Z22agg2RenderPolygonTiledP8imageObjP8shapeObjS0_@Base 6.2.1 _Z22agg2RenderVectorSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 6.2.1 _Z22aggGetRasterBufferCopyP8imageObjP15rasterBufferObj@Base 6.2.1 + _Z22msOGRRecursiveFileListPKc@Base 7.6.0 _Z23agg2RenderEllipseSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 6.2.1 _Z23msOGREscapePropertyNameP8layerObjPKc@Base 6.2.1 _Z24aggCompositeRasterBufferP8imageObjP15rasterBufferObj20CompositingOperationi@Base 7.0.0 _Z24aggGetRasterBufferHandleP8imageObjP15rasterBufferObj@Base 6.2.1 + _Z24msOGRLayerGetNumFeaturesP8layerObj@Base 7.2.0 _Z25aggInitializeRasterBufferP15rasterBufferObjiii@Base 6.2.1 _Z25utfgridRenderPixmapSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 7.0.0 _Z25utfgridRenderVectorSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 7.0.0 _Z26utfgridRenderEllipseSymbolP8imageObjddP9symbolObjP14symbolStyleObj@Base 7.0.0 + _Z31FLTGetFeatureIdCommonExpressionP11_FilterNodeP8layerObj@Base 7.6.0 + _Z39FLTGetLogicalComparisonCommonExpressionP11_FilterNodeP8layerObj@Base 7.6.0 + _Z39FLTGetSpatialComparisonCommonExpressionP11_FilterNodeP8layerObj@Base 7.6.0 _Z9growTableP11lookupTable@Base 7.0.0 _ZN10ClipperLib10SwapPointsERNS_8IntPointES1_@Base 6.2.1 _ZN10ClipperLib11ClipperBase10AddPolygonERKSt6vectorINS_8IntPointESaIS2_EENS_8PolyTypeE@Base 6.2.1 @@ -192,6 +186,9 @@ _ZN10ClipperLib17E2InsertsBeforeE1ERNS_5TEdgeES1_@Base 6.2.1 _ZN10ClipperLib17FindAppendLinkEndEPNS_6OutRecE@Base 6.2.1 _ZN10ClipperLib17GetOverlapSegmentENS_8IntPointES0_S0_S0_RS0_S1_@Base 6.2.1 + _ZN10ClipperLib17PolyOffsetBuilder7DoMiterEv@Base 7.6.1 + _ZN10ClipperLib17PolyOffsetBuilder7DoRoundEv@Base 7.6.1 + _ZN10ClipperLib17PolyOffsetBuilder8DoSquareEd@Base 7.4.1 _ZN10ClipperLib17PolyOffsetBuilderC1ERKSt6vectorIS1_INS_8IntPointESaIS2_EESaIS4_EERS6_dNS_8JoinTypeEd@Base 6.2.1 _ZN10ClipperLib17PolyOffsetBuilderC2ERKSt6vectorIS1_INS_8IntPointESaIS2_EESaIS4_EERS6_dNS_8JoinTypeEd@Base 6.2.1 _ZN10ClipperLib18GetNextNonDupOutPtEPNS_5OutPtERS1_@Base 6.2.1 @@ -205,8 +202,6 @@ _ZN10ClipperLib4TopXERNS_5TEdgeEx@Base 6.2.1 _ZN10ClipperLib5GetDxENS_8IntPointES0_@Base 6.2.1 _ZN10ClipperLib5SetDxERNS_5TEdgeE@Base 6.2.1 - (arch=i386 m68k mips mipsel powerpc)_ZN10ClipperLib6Int128C1Ex@Base 7.0.6 - (arch=i386 m68k mips mipsel powerpc)_ZN10ClipperLib6Int128C2Ex@Base 7.0.6 _ZN10ClipperLib7Clipper10ClearJoinsEv@Base 6.2.1 _ZN10ClipperLib7Clipper11AddHorzJoinEPNS_5TEdgeEi@Base 6.2.1 _ZN10ClipperLib7Clipper11BuildResultERSt6vectorIS1_INS_8IntPointESaIS2_EESaIS4_EE@Base 6.2.1 @@ -220,8 +215,8 @@ _ZN10ClipperLib7Clipper13BuildResultExERSt6vectorINS_9ExPolygonESaIS2_EE@Base 6.2.1 _ZN10ClipperLib7Clipper13DeleteFromAELEPNS_5TEdgeE@Base 6.2.1 _ZN10ClipperLib7Clipper13DeleteFromSELEPNS_5TEdgeE@Base 6.2.1 - (arch=armel armhf hppa hurd-i386 i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe sparc x32)_ZN10ClipperLib7Clipper13DisposeOutRecEjb@Base 7.0.6 - (arch=alpha amd64 arm64 ia64 kfreebsd-amd64 mips64el ppc64 ppc64el s390 s390x sparc64)_ZN10ClipperLib7Clipper13DisposeOutRecEmb@Base 7.0.1 + (arch=armel armhf hppa hurd-i386 i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe sh4 sparc x32)_ZN10ClipperLib7Clipper13DisposeOutRecEjb@Base 7.2.0 + (arch=alpha amd64 arm64 ia64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390 s390x sparc64)_ZN10ClipperLib7Clipper13DisposeOutRecEmb@Base 7.2.0 _ZN10ClipperLib7Clipper14ClearHorzJoinsEv@Base 6.2.1 _ZN10ClipperLib7Clipper14FixHoleLinkageEPNS_6OutRecE@Base 6.2.1 _ZN10ClipperLib7Clipper14InsertScanbeamEx@Base 6.2.1 @@ -315,8 +310,8 @@ _ZN11KmlRendererD0Ev@Base 6.4.0 _ZN11KmlRendererD1Ev@Base 6.4.0 _ZN11KmlRendererD2Ev@Base 6.4.0 - (arch=!amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64el !s390x !sparc64)_ZN12AGG2RendererD1Ev@Base 7.0.1 - (arch=!amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64el !s390x !sparc64)_ZN12AGG2RendererD2Ev@Base 7.0.1 + _ZN12AGG2RendererD1Ev@Base 7.4.1 + _ZN12AGG2RendererD2Ev@Base 7.4.1 _ZN12line_adaptor6vertexEPdS0_@Base 6.2.1 _ZN12line_adaptorD0Ev@Base 6.2.1 _ZN12line_adaptorD1Ev@Base 6.2.1 @@ -333,8 +328,8 @@ _ZN19polygon_adaptor_utfD0Ev@Base 7.0.0 _ZN19polygon_adaptor_utfD1Ev@Base 7.0.0 _ZN19polygon_adaptor_utfD2Ev@Base 7.0.0 - (optional=templinst|arch=alpha amd64 arm64 hppa ia64 kfreebsd-amd64 mips64el ppc64 ppc64el s390 s390x sparc sparc64 x32)_ZN9mapserver10conv_curveINS_20path_storage_integerIiLj6EEENS_6curve3ENS_6curve4EE6vertexEPdS6_@Base 6.4.0 - (optional=templinst|arch=alpha amd64 arm64 hppa ia64 kfreebsd-amd64 mips64el ppc64 ppc64el s390 s390x sparc sparc64 x32)_ZN9mapserver10conv_curveINS_20path_storage_integerIsLj6EEENS_6curve3ENS_6curve4EE6vertexEPdS6_@Base 6.4.0 + (optional=templinst)_ZN9mapserver10conv_curveINS_20path_storage_integerIiLj6EEENS_6curve3ENS_6curve4EE6vertexEPdS6_@Base 6.4.0 + (optional=templinst)_ZN9mapserver10conv_curveINS_20path_storage_integerIsLj6EEENS_6curve3ENS_6curve4EE6vertexEPdS6_@Base 6.4.0 (optional=templinst|arch=sparc)_ZN9mapserver10conv_curveINS_31serialized_integer_path_adaptorIsLj6EEENS_6curve3ENS_6curve4EED1Ev@Base 6.4.1 (optional=templinst|arch=sparc)_ZN9mapserver10conv_curveINS_31serialized_integer_path_adaptorIsLj6EEENS_6curve3ENS_6curve4EED2Ev@Base 6.4.1 (optional=templinst)_ZN9mapserver10conv_curveINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_6curve3ENS_6curve4EE6vertexEPdS8_@Base 7.0.0 @@ -355,6 +350,7 @@ _ZN9mapserver10mcs11_propE@Base 6.2.1 _ZN9mapserver10mcs12_propE@Base 6.2.1 _ZN9mapserver10mcs13_propE@Base 6.2.1 + (optional=templinst|arch=armel armhf i386 mipsel powerpc sh4)_ZN9mapserver10pod_vectorINS_5rgba8EE8allocateEjj@Base 7.6.1 _ZN9mapserver10vcgen_dash10add_vertexEddj@Base 6.2.1 _ZN9mapserver10vcgen_dash10dash_startEd@Base 6.2.1 _ZN9mapserver10vcgen_dash10remove_allEv@Base 6.2.1 @@ -367,22 +363,19 @@ _ZN9mapserver10vcgen_dashC2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11math_strokeINS_11pod_bvectorINS_10point_baseIdEELj6EEEE10calc_miterERS4_RKNS_11vertex_distES9_S9_ddddNS_11line_join_eEdd@Base 6.2.1 (optional=templinst)_ZN9mapserver11math_strokeINS_11pod_bvectorINS_10point_baseIdEELj6EEEE8calc_arcERS4_dddddd@Base 6.2.1 - (optional=templinst)_ZN9mapserver11math_strokeINS_11pod_bvectorINS_10point_baseIdEELj6EEEE8calc_capERS4_RKNS_11vertex_distES9_d@Base 6.2.1 + (optional=templinst|arch=armel armhf i386 mipsel powerpc sh4)_ZN9mapserver11math_strokeINS_11pod_bvectorINS_10point_baseIdEELj6EEEE8calc_capERS4_RKNS_11vertex_distES9_d@Base 7.6.1 (optional=templinst)_ZN9mapserver11math_strokeINS_11pod_bvectorINS_10point_baseIdEELj6EEEE9calc_joinERS4_RKNS_11vertex_distES9_S9_dd@Base 6.2.1 - (optional=templinst|arch=alpha amd64 arm64 hppa kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64 x32)_ZN9mapserver11pod_bvectorIN10ClipperLib8IntPointELj8EE14allocate_blockEj@Base 6.4.0 + (optional=templinst)_ZN9mapserver11pod_bvectorIN10ClipperLib8IntPointELj8EE14allocate_blockEj@Base 6.4.0 (optional=templinst)_ZN9mapserver11pod_bvectorIN10ClipperLib8IntPointELj8EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorIN10ClipperLib8IntPointELj8EED2Ev@Base 6.2.1 - (optional=templinst|arch=alpha amd64 arm64 hppa kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64 x32)_ZN9mapserver11pod_bvectorINS_10point_baseIdEELj6EE14allocate_blockEj@Base 7.0.0 (optional=templinst)_ZN9mapserver11pod_bvectorINS_10point_baseIdEELj6EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_10point_baseIdEELj6EED2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_11vertex_distELj6EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_11vertex_distELj6EED2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14line_aa_vertexELj6EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14line_aa_vertexELj6EED2Ev@Base 6.2.1 - (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIiLj6EEELj6EE14allocate_blockEj@Base 7.0.0 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIiLj6EEELj6EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIiLj6EEELj6EED2Ev@Base 6.2.1 - (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIsLj6EEELj6EE14allocate_blockEj@Base 7.0.0 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIsLj6EEELj6EED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_14vertex_integerIsLj6EEELj6EED2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver11pod_bvectorINS_19scanline_storage_aaIhE13scanline_dataELj8EED1Ev@Base 7.0.2 @@ -399,14 +392,18 @@ (optional=templinst)_ZN9mapserver11pod_bvectorIhLj12EED1Ev@Base 7.0.2 (optional=templinst)_ZN9mapserver11pod_bvectorIhLj12EED2Ev@Base 7.0.2 (optional=templinst)_ZN9mapserver11qsort_cellsINS_7cell_aaEEEvPPT_j@Base 6.2.1 - (optional=templinst|arch=!amd64 !arm64 !hppa !mips64el !ppc64el !s390x !sparc64)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE11end_contourERSt6vectorISC_IN10ClipperLib8IntPointESaISE_EESaISG_EE@Base 7.0.2 - (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE11next_vertexEPdSC_@Base 6.4.0 + (optional=templinst|arch=i386)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE11add_vertex_ERdSC_@Base 7.6.1 + (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE11end_contourERSt6vectorISC_IN10ClipperLib8IntPointESaISE_EESaISG_EE@Base 7.0.2 + (optional=templinst|arch=armel armhf i386 mipsel powerpc)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE11next_vertexEPdSC_@Base 7.6.1 + (optional=templinst|arch=armel armhf i386 mipsel powerpc)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE3addIPS1_EEvRT_RSt6vectorISG_IN10ClipperLib8IntPointESaISI_EESaISK_EE@Base 7.6.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE6rewindEj@Base 6.2.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEE6vertexEPdSC_@Base 6.4.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEES8_EEED2Ev@Base 6.2.1 - (optional=templinst|arch=!amd64 !arm64 !hppa !mips64el !ppc64el !s390x !sparc64)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE11end_contourERSt6vectorISA_IN10ClipperLib8IntPointESaISC_EESaISE_EE@Base 7.0.2 - (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE11next_vertexEPdSA_@Base 6.4.0 + (optional=templinst|arch=i386)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE11add_vertex_ERdSA_@Base 7.6.1 + (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE11end_contourERSt6vectorISA_IN10ClipperLib8IntPointESaISC_EESaISE_EE@Base 7.0.2 + (optional=templinst|arch=armel armhf i386 mipsel powerpc)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE11next_vertexEPdSA_@Base 7.6.1 + (optional=templinst|arch=armel armhf i386 mipsel powerpc)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE3addIPS1_EEvRT_RSt6vectorISE_IN10ClipperLib8IntPointESaISG_EESaISI_EE@Base 7.6.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE6rewindEj@Base 6.2.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEE6vertexEPdSA_@Base 6.4.1 (optional=templinst)_ZN9mapserver12conv_clipperI15polygon_adaptorNS_11conv_strokeINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEEED1Ev@Base 6.2.1 @@ -436,6 +433,9 @@ _ZN9mapserver12vcgen_strokeC1Ev@Base 6.2.1 _ZN9mapserver12vcgen_strokeC2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEE10blend_fromIS8_EEvRKT_PKNS_9rect_baseIiEEiih@Base 6.2.1 + (optional=templinst)_ZN9mapserver13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEE11blend_hlineEiiiRKS3_h@Base 7.6.1 + (optional=templinst)_ZN9mapserver13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEE17blend_color_hspanEiiiPKS3_PKhh@Base 7.6.1 + (optional=templinst)_ZN9mapserver13renderer_baseINS_24pixfmt_custom_blend_rgbaINS_24comp_op_adaptor_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEEEE10blend_fromINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preIS3_S4_EES7_jEEEEvRKT_PKNS_9rect_baseIiEEiih@Base 7.6.1 _ZN9mapserver13vcgen_contour10add_vertexEddj@Base 6.2.1 _ZN9mapserver13vcgen_contour10remove_allEv@Base 6.2.1 _ZN9mapserver13vcgen_contour6rewindEj@Base 6.2.1 @@ -460,7 +460,7 @@ (optional=templinst)_ZN9mapserver16comp_op_rgba_xorINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 _ZN9mapserver16mcs7x12_mono_lowE@Base 6.2.1 (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_11scanline_p8ENS_26renderer_scanline_aa_solidINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEEEEEEvRT_RT0_RT1_@Base 6.2.1 - (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_11scanline_u8ENS_19scanline_storage_aaIhEEEEvRT_RT0_RT1_@Base 6.2.1 + (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_11scanline_u8ENS_19scanline_storage_aaIhEEEEvRT_RT0_RT1_@Base 7.2.0 (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_11scanline_u8ENS_26renderer_scanline_aa_solidINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEEEEEEvRT_RT0_RT1_@Base 6.2.1 (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_12scanline_binENS_20scanline_storage_binEEEvRT_RT0_RT1_@Base 6.2.1 (optional=templinst)_ZN9mapserver16render_scanlinesINS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_12scanline_binENS_27renderer_scanline_bin_solidINS_13renderer_baseI10pixfmt_utfI8utfpix32NS_13row_ptr_cacheIjEELj1ELj0EEEEEEEEvRT_RT0_RT1_@Base 7.0.0 @@ -474,24 +474,26 @@ (optional=templinst)_ZN9mapserver18comp_op_rgba_minusINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 _ZN9mapserver18comp_op_table_rgbaINS_5rgba8ENS_10order_bgraEE14g_comp_op_funcE@Base 7.0.1 (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenI12line_adaptorNS_10vcgen_dashENS_12null_markersEE6vertexEPdS5_@Base 6.2.1 - (optional=templinst|arch=alpha amd64 arm64 hppa kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64 x32)_ZN9mapserver18conv_adaptor_vcgenI12line_adaptorNS_12vcgen_strokeENS_12null_markersEE6vertexEPdS5_@Base 6.4.0 - (optional=templinst|arch=alpha amd64 arm64 hppa kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64 x32)_ZN9mapserver18conv_adaptor_vcgenI16line_adaptor_utfNS_12vcgen_strokeENS_12null_markersEE6vertexEPdS5_@Base 7.0.0 + (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenI12line_adaptorNS_12vcgen_strokeENS_12null_markersEE6vertexEPdS5_@Base 6.4.0 + (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenI16line_adaptor_utfNS_12vcgen_strokeENS_12null_markersEE6vertexEPdS5_@Base 7.0.0 (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenINS_9conv_dashINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12null_markersEEENS_12vcgen_strokeES6_E6vertexEPdSA_@Base 6.2.1 (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_10vcgen_dashENS_12null_markersEE6vertexEPdS8_@Base 6.2.1 (optional=templinst)_ZN9mapserver18conv_adaptor_vcgenINS_9path_baseINS_20vertex_block_storageIdLj8ELj256EEEEENS_12vcgen_strokeENS_12null_markersEE6vertexEPdS8_@Base 6.2.1 (optional=templinst)_ZN9mapserver18rasterizer_sl_clipINS_12ras_conv_intEE7line_toINS_19rasterizer_cells_aaINS_7cell_aaEEEEEvRT_ii@Base 6.2.1 (optional=templinst)_ZN9mapserver18render_scanline_aaINS_11scanline_p8ENS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_14span_allocatorIS5_EENS_17span_pattern_rgbaINS_19image_accessor_wrapISA_NS_16wrap_mode_repeatESG_EEEEEEvRKT_RT0_RT1_RT2_@Base 6.2.1 + (optional=templinst|arch=armel armhf i386 mipsel powerpc sh4)_ZN9mapserver18render_scanline_aaINS_11scanline_p8ENS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_14span_allocatorIS5_EENS_36span_image_filter_rgba_bilinear_clipISA_NS_24span_interpolator_linearINS_12trans_affineELj8EEEEEEEvRKT_RT0_RT1_RT2_@Base 7.6.1 (optional=templinst)_ZN9mapserver19comp_op_rgba_darkenINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver19comp_op_rgba_dst_inINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver19comp_op_rgba_invertINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver19comp_op_rgba_screenINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver19comp_op_rgba_src_inINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEE10sort_cellsEv@Base 7.0.0 - (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEE12render_hlineEiiiii@Base 6.2.1 + (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEE12render_hlineEiiiii@Base 7.6.1 (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEE14allocate_blockEv@Base 6.4.0 (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEE4lineEiiii@Base 6.2.1 (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver19rasterizer_cells_aaINS_7cell_aaEED2Ev@Base 6.2.1 + (optional=templinst)_ZN9mapserver19scanline_storage_aaIhE6renderINS_11scanline_u8EEEvRKT_@Base 7.4.1 (optional=templinst)_ZN9mapserver19scanline_storage_aaIhED1Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver19scanline_storage_aaIhED2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver20comp_op_rgba_dst_outINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 @@ -501,7 +503,10 @@ (optional=templinst)_ZN9mapserver20decompose_ft_outlineINS_20path_storage_integerIiLj6EEEEEbRK11FT_Outline_bRKNS_12trans_affineERT_@Base 6.2.1 (optional=templinst)_ZN9mapserver20decompose_ft_outlineINS_20path_storage_integerIsLj6EEEEEbRK11FT_Outline_bRKNS_12trans_affineERT_@Base 6.2.1 _ZN9mapserver20mcs11_prop_condensedE@Base 6.2.1 - (optional=templinst)_ZN9mapserver20vertex_block_storageIdLj8ELj256EE12storage_ptrsEPPd@Base 7.0.0 + (optional=templinst|arch=!armel !armhf !i386 !powerpc)_ZN9mapserver20path_storage_integerIiLj6EE6curve3Eiiii@Base 7.6.1 + (optional=templinst)_ZN9mapserver20path_storage_integerIsLj6EE6curve3Essss@Base 7.6.1 + (optional=templinst)_ZN9mapserver20scanline_storage_bin6renderINS_12scanline_binEEEvRKT_@Base 7.6.1 + (optional=templinst)_ZN9mapserver20vertex_block_storageIdLj8ELj256EE14allocate_blockEj@Base 7.6.1 (optional=templinst)_ZN9mapserver20vertex_block_storageIdLj8ELj256EE8free_allEv@Base 6.2.1 (optional=templinst)_ZN9mapserver21comp_op_rgba_contrastINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver21comp_op_rgba_dst_atopINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 @@ -516,8 +521,9 @@ (optional=templinst|arch=sparc)_ZN9mapserver21rasterizer_outline_aaINS_22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS5_EEEEEENS_14line_coord_satEED2Ev@Base 6.4.1 (optional=templinst)_ZN9mapserver22comp_op_rgba_exclusionINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE10add_vertexEddj@Base 6.2.1 - (optional=templinst|arch=armel armhf hurd-i386 i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE8add_pathINS_10conv_curveINS_20path_storage_integerIiLj6EEENS_6curve3ENS_6curve4EEEEEvRT_j@Base 6.2.1 - (optional=templinst|arch=armel armhf hurd-i386 i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE8add_pathINS_10conv_curveINS_20path_storage_integerIsLj6EEENS_6curve3ENS_6curve4EEEEEvRT_j@Base 6.2.1 + (optional=templinst)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE14sweep_scanlineINS_11scanline_p8EEEbRT_@Base 7.6.1 + (optional=templinst)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE14sweep_scanlineINS_11scanline_u8EEEbRT_@Base 7.6.1 + (optional=templinst)_ZN9mapserver22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEE14sweep_scanlineINS_12scanline_binEEEbRT_@Base 7.6.1 (optional=templinst)_ZN9mapserver22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS4_EEEEE13line3_no_clipERKNS_15line_parametersEiiii@Base 6.2.1 (optional=templinst)_ZN9mapserver22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS4_EEEEE5line3ERKNS_15line_parametersEiiii@Base 6.2.1 (optional=templinst)_ZN9mapserver23comp_op_rgba_color_burnINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 @@ -525,7 +531,16 @@ (optional=templinst)_ZN9mapserver23comp_op_rgba_hard_lightINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver23comp_op_rgba_invert_rgbINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 (optional=templinst)_ZN9mapserver23comp_op_rgba_soft_lightINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 + (optional=templinst)_ZN9mapserver23line_interpolator_imageINS_22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS5_EEEEEEE8step_horEv@Base 7.4.1 + (optional=templinst)_ZN9mapserver23line_interpolator_imageINS_22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS5_EEEEEEE8step_verEv@Base 7.6.1 + (optional=templinst)_ZN9mapserver23line_interpolator_imageINS_22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS5_EEEEEEEC1ERSG_RKNS_15line_parametersEiiiiid@Base 7.4.1 + (optional=templinst)_ZN9mapserver23line_interpolator_imageINS_22renderer_outline_imageINS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEENS_18line_image_patternINS_28pattern_filter_bilinear_rgbaIS5_EEEEEEEC2ERSG_RKNS_15line_parametersEiiiiid@Base 7.4.1 + (optional=templinst|arch=amd64 i386)_ZN9mapserver23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjE17blend_color_vspanEiijPKS2_PKhh@Base 7.6.1 (optional=templinst)_ZN9mapserver24comp_op_rgba_color_dodgeINS_5rgba8ENS_10order_bgraEE9blend_pixEPhjjjjj@Base 7.0.0 + (optional=templinst)_ZN9mapserver24render_scanline_aa_solidINS_11scanline_p8ENS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEES5_EEvRKT_RT0_RKT1_@Base 7.6.1 + (optional=templinst)_ZN9mapserver24render_scanline_aa_solidINS_11scanline_u8ENS_13renderer_baseINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEEEES5_EEvRKT_RT0_RKT1_@Base 7.6.1 + (optional=templinst|arch=!amd64 !arm64)_ZN9mapserver24span_interpolator_linearINS_12trans_affineELj8EE5beginEddj@Base 7.6.1 + (optional=templinst)_ZN9mapserver25decompose_ft_bitmap_gray8INS_22rasterizer_scanline_aaINS_18rasterizer_sl_clipINS_12ras_conv_intEEEEENS_11scanline_u8ENS_19scanline_storage_aaIhEEEEvRK10FT_Bitmap_iibRT_RT0_RT1_@Base 7.6.1 _ZN9mapserver25font_engine_freetype_base10resolutionEj@Base 6.2.1 _ZN9mapserver25font_engine_freetype_base11add_kerningEjjPdS1_@Base 6.2.1 _ZN9mapserver25font_engine_freetype_base13prepare_glyphEj@Base 6.2.1 @@ -544,7 +559,7 @@ _ZN9mapserver25font_engine_freetype_baseD1Ev@Base 6.2.1 _ZN9mapserver25font_engine_freetype_baseD2Ev@Base 6.2.1 (optional=templinst)_ZN9mapserver25render_scanline_bin_solidINS_12scanline_binENS_13renderer_baseI10pixfmt_utfI8utfpix32NS_13row_ptr_cacheIjEELj1ELj0EEEES4_EEvRKT_RT0_RKT1_@Base 7.0.0 - (optional=templinst)_ZN9mapserver28pattern_filter_bilinear_rgbaINS_5rgba8EE14pixel_high_resEPKPKS1_PS1_ii@Base 7.0.2 + (optional=templinst)_ZN9mapserver36span_image_filter_rgba_bilinear_clipINS_23pixfmt_alpha_blend_rgbaINS_16blender_rgba_preINS_5rgba8ENS_10order_bgraEEENS_12row_accessorIhEEjEENS_24span_interpolator_linearINS_12trans_affineELj8EEEE8generateEPS3_iij@Base 7.4.1 _ZN9mapserver3arc19approximation_scaleEd@Base 6.2.1 _ZN9mapserver3arc4initEddddddb@Base 6.2.1 _ZN9mapserver3arc6rewindEj@Base 6.2.1 @@ -563,9 +578,6 @@ _ZN9mapserver7gse8x16E@Base 6.2.1 _ZN9mapserver9bisectrixERKNS_15line_parametersES2_PiS3_@Base 6.2.1 (optional=templinst|arch=sparc)_ZN9mapserver9path_baseINS_20vertex_block_storageIdLj8ELj256EEEE11concat_pathINS_14conv_transformINS_10conv_curveINS_31serialized_integer_path_adaptorIsLj6EEENS_6curve3ENS_6curve4EEENS_12trans_affineEEEEEvRT_j@Base 6.4.1 - (optional=templinst)_ZN9mapserver9path_baseINS_20vertex_block_storageIdLj8ELj256EEEE6curve3Edddd@Base 7.0.0 - (optional=templinst)_ZN9mapserver9path_baseINS_20vertex_block_storageIdLj8ELj256EEEE6curve4Edddddd@Base 7.0.0 - (optional=templinst|arch=!amd64)_ZN9mapserver9path_baseINS_20vertex_block_storageIdLj8ELj256EEEE6vertexEPdS4_@Base 7.0.2 _ZN9mapserver9verdana12E@Base 6.2.1 _ZN9mapserver9verdana13E@Base 6.2.1 _ZN9mapserver9verdana14E@Base 6.2.1 @@ -573,8 +585,8 @@ _ZN9mapserver9verdana17E@Base 6.2.1 _ZN9mapserver9verdana18E@Base 6.2.1 _ZNK10ClipperLib16clipperException4whatEv@Base 6.2.1 - (arch=sparc)_ZNK10ClipperLib6Int128dvERKS0_@Base 6.4.1 - (arch=!amd64 !arm64 !hppa !mips64el !ppc64el !s390x !sparc64)_ZNK10ClipperLib6Int128mlERKS0_@Base 7.0.2 + (arch=armel armhf i386 mipsel powerpc sh4 sparc)_ZNK10ClipperLib6Int128dvERKS0_@Base 7.6.1 + _ZNK10ClipperLib6Int128mlERKS0_@Base 7.6.1 _ZNK10ClipperLib7Clipper14IsContributingERKNS_5TEdgeE@Base 6.2.1 _ZNK10ClipperLib7Clipper17IsEvenOddFillTypeERKNS_5TEdgeE@Base 6.2.1 _ZNK10ClipperLib7Clipper20IsEvenOddAltFillTypeERKNS_5TEdgeE@Base 6.2.1 @@ -586,41 +598,46 @@ _ZNK9mapserver12trans_affine8is_equalERKS0_d@Base 6.2.1 _ZNK9mapserver12trans_affine8is_validEd@Base 6.2.1 _ZNK9mapserver12trans_affine8rotationEv@Base 6.2.1 - (arch=armel armhf hurd-i386 i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe)_ZNK9mapserver12trans_affine9transformEPdS1_@Base 7.0.6 + (optional=templinst)_ZNK9mapserver18line_image_patternINS_28pattern_filter_bilinear_rgbaINS_5rgba8EEEE5pixelEPS2_ii@Base 7.6.1 (optional=templinst)_ZNK9mapserver18rasterizer_sl_clipINS_12ras_conv_intEE11line_clip_yINS_19rasterizer_cells_aaINS_7cell_aaEEEEEvRT_iiiijj@Base 6.2.1 + (optional=templinst)_ZNK9mapserver19scanline_storage_aaIhE9serializeEPh@Base 7.6.1 _ZNK9mapserver25font_engine_freetype_base14write_glyph_toEPh@Base 6.2.1 _ZNK9mapserver25font_engine_freetype_base8ascenderEv@Base 6.2.1 _ZNK9mapserver25font_engine_freetype_base9descenderEv@Base 6.2.1 _ZNK9mapserver25font_engine_freetype_base9find_faceEPKc@Base 6.2.1 _ZNK9mapserver25font_engine_freetype_base9num_facesEv@Base 6.2.1 - (optional=templinst|arch=!amd64 !arm64 !hppa !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIN10ClipperLib11DoublePointESaIS1_EE17_M_default_appendEj@Base 7.0.2 - (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE17_M_default_appendEj@Base 7.0.2 - (optional=templinst|arch=amd64 arm64 mips64el ppc64el s390x sparc64)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE17_M_default_appendEm@Base 7.0.2 + (optional=templinst)_ZNSt12_Destroy_auxILb0EE9__destroyIPSt6vectorIN10ClipperLib8IntPointESaIS4_EEEEvT_S8_@Base 7.6.1 + (optional=templinst|arch=!amd64 !arm64 !hppa !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZNSt6vectorIN10ClipperLib11DoublePointESaIS1_EE17_M_default_appendEj@Base 7.0.2 + (optional=templinst|arch=!armel !armhf !i386 !m68k !mipsel !powerpc !sh4)_ZNSt6vectorIN10ClipperLib11DoublePointESaIS1_EE17_M_default_appendEm@Base 7.4.0 + (optional=templinst|arch=!amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE17_M_default_appendEj@Base 7.0.2 + (optional=templinst|arch=amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390x sparc64)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE17_M_default_appendEm@Base 7.0.2 (optional=templinst)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 7.0.7 (optional=templinst|subst)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE7reserveE{size_t}@Base 6.4.0 - (optional=templinst)_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EEaSERKS3_@Base 6.2.1 - (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIN10ClipperLib9ExPolygonESaIS1_EE17_M_default_appendEj@Base 7.0.2 - (optional=templinst|arch=amd64 arm64 mips64el ppc64el s390x sparc64)_ZNSt6vectorIN10ClipperLib9ExPolygonESaIS1_EE17_M_default_appendEm@Base 7.0.2 + (optional=templinst|arch=!amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZNSt6vectorIN10ClipperLib9ExPolygonESaIS1_EE17_M_default_appendEj@Base 7.0.2 + (optional=templinst|arch=amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390x sparc64)_ZNSt6vectorIN10ClipperLib9ExPolygonESaIS1_EE17_M_default_appendEm@Base 7.0.2 (optional=templinst)_ZNSt6vectorIN10ClipperLib9ExPolygonESaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 7.0.7 (optional=templinst)_ZNSt6vectorIP10msExprNodeSaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 7.0.7 (optional=templinst)_ZNSt6vectorIP10msExprNodeSaIS1_EE9push_backERKS1_@Base 7.0.5 - (optional=templinst)_ZNSt6vectorIP10msExprNodeSaIS1_EEaSERKS3_@Base 7.0.5 - (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIPN10ClipperLib11HorzJoinRecESaIS2_EE17_M_default_appendEj@Base 7.0.2 + (optional=templinst|arch=armel armhf i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe sh4)_ZNSt6vectorIPN10ClipperLib11HorzJoinRecESaIS2_EE17_M_default_appendEj@Base 7.2.0 + (optional=templinst|arch=!armel !armhf !i386 !m68k !mipsel !powerpc !sh4)_ZNSt6vectorIPN10ClipperLib11HorzJoinRecESaIS2_EE17_M_default_appendEm@Base 7.4.0 + (optional=templinst)_ZNSt6vectorIPN10ClipperLib11HorzJoinRecESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 7.4.1 (optional=templinst)_ZNSt6vectorIPN10ClipperLib5TEdgeESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 7.0.7 (optional=templinst)_ZNSt6vectorIPN10ClipperLib6OutRecESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 7.0.7 - (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIPN10ClipperLib7JoinRecESaIS2_EE17_M_default_appendEj@Base 7.0.2 - (optional=templinst)_ZNSt6vectorIPN10ClipperLib7JoinRecESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 7.0.7 - (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !s390x !sparc64)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EE17_M_default_appendEj@Base 7.0.2 - (optional=templinst|arch=amd64 arm64 mips64el ppc64el s390x sparc64)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EE17_M_default_appendEm@Base 7.0.2 + (optional=templinst|arch=armel armhf i386 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe sh4)_ZNSt6vectorIPN10ClipperLib7JoinRecESaIS2_EE17_M_default_appendEj@Base 7.2.0 + (optional=templinst|arch=!armel !armhf !i386 !m68k !mipsel !powerpc !sh4)_ZNSt6vectorIPN10ClipperLib7JoinRecESaIS2_EE17_M_default_appendEm@Base 7.4.0 + (optional=templinst)_ZNSt6vectorIPN10ClipperLib7JoinRecESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 7.2.0 + (optional=templinst|arch=!amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EE17_M_default_appendEj@Base 7.0.2 + (optional=templinst|arch=amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390x sparc64)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EE17_M_default_appendEm@Base 7.0.2 (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EE17_M_realloc_insertIJRKS3_EEEvN9__gnu_cxx17__normal_iteratorIPS3_S5_EEDpOT_@Base 7.0.7 + (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EEC1ERKS5_@Base 7.6.1 + (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EEC2ERKS5_@Base 7.6.1 (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EED1Ev@Base 6.2.1 (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EED2Ev@Base 6.2.1 - (optional=templinst)_ZNSt6vectorIS_IN10ClipperLib8IntPointESaIS1_EESaIS3_EEaSERKS5_@Base 6.2.1 - (optional=templinst|arch=!alpha !amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !s390x !sparc64)_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEEiS4_NS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_T0_SG_T1_T2_@Base 6.4.1 - (optional=templinst|arch=alpha amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64)_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEElS4_NS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_T0_SG_T1_T2_@Base 6.4.1 + (optional=templinst|arch=!alpha !amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEEiS4_NS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_T0_SG_T1_T2_@Base 6.4.1 + (optional=templinst|arch=alpha amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390x sparc64)_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEElS4_NS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_T0_SG_T1_T2_@Base 6.4.1 (optional=templinst)_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEENS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_SF_T0_@Base 6.4.1 - (optional=templinst|arch=!alpha !amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !s390x !sparc64)_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEEiNS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_SF_T0_T1_@Base 6.4.1 - (optional=templinst|arch=alpha amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el s390x sparc64)_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEElNS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_SF_T0_T1_@Base 6.4.1 + (optional=templinst|arch=!alpha !amd64 !arm64 !kfreebsd-amd64 !mips64el !ppc64 !ppc64el !riscv64 !s390x !sparc64)_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEEiNS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_SF_T0_T1_@Base 6.4.1 + (optional=templinst|arch=alpha amd64 arm64 kfreebsd-amd64 mips64el ppc64 ppc64el riscv64 s390x sparc64)_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEElNS0_5__ops15_Iter_comp_iterIPFbS4_S4_EEEEvT_SF_T0_T1_@Base 6.4.1 (optional=templinst|arch=sparc)_ZSt4sortIN9__gnu_cxx17__normal_iteratorIPPN10ClipperLib6OutRecESt6vectorIS4_SaIS4_EEEEPFbS4_S4_EEvT_SC_T0_@Base 6.4.1 (optional=templinst)_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_@Base 7.0.5 _ZTI11KmlRenderer@Base 6.4.0 @@ -645,8 +662,10 @@ _ZTVN10ClipperLib11ClipperBaseE@Base 6.2.1 _ZTVN10ClipperLib16clipperExceptionE@Base 6.2.1 _ZTVN10ClipperLib7ClipperE@Base 6.2.1 + (optional=templinst)_ZZNSt8__detail18__to_chars_10_implIjEEvPcjT_E8__digits@Base 7.6.1 _get_param_value@Base 7.0.0 - _msSLDParseSizeParameter@Base 6.2.1 + _msMetadataGetCodeList@Base 7.2.0 + _msMetadataGetContact@Base 7.2.0 _msValidateTime@Base 6.2.1 _ms_script_prefix_am@Base 7.0.0 _ms_script_prefix_ar@Base 7.0.0 @@ -705,6 +724,7 @@ circleLayerDrawShape@Base 6.2.1 cleanupCairo@Base 6.2.1 cleanupDummy@Base 6.2.1 + cleanupResultCache@Base 7.2.0 closeLayerRasterCairo@Base 6.2.1 closeLayerVectorCairo@Base 6.2.1 clusterDestroyData@Base 6.2.1 @@ -741,6 +761,7 @@ freeClass@Base 6.2.1 freeClassHitTests@Base 6.4.0 freeCluster@Base 6.2.1 + freeCompositingFilter@Base 7.2.0 freeFeatureList@Base 6.2.1 freeGrid@Base 7.0.0 freeImageCache@Base 6.2.1 @@ -751,7 +772,7 @@ freeLabelHitTests@Base 6.4.0 freeLabelLeader@Base 7.0.0 freeLayer@Base 6.2.1 - freeLayerCompositers@Base 7.0.2 + freeLayerCompositer@Base 7.2.0 freeLayerHitTests@Base 6.4.0 freeLegend@Base 6.2.1 freeMapHitTests@Base 6.4.0 @@ -838,11 +859,6 @@ intersectTextSymbol@Base 7.0.0 isOn@Base 6.2.1 isScaleInRange@Base 6.2.1 - jpeg_buffer_empty_output_buffer@Base 6.2.1 - jpeg_buffer_term_destination@Base 6.2.1 - jpeg_init_destination@Base 6.2.1 - jpeg_stream_empty_output_buffer@Base 6.2.1 - jpeg_stream_term_destination@Base 6.2.1 lineLayerDrawShape@Base 6.2.1 loadClass@Base 6.2.1 loadCluster@Base 6.2.1 @@ -887,12 +903,17 @@ msAlphaBlendPM@Base 6.2.1 msAppendOutputFormat@Base 6.2.1 msAppendSymbol@Base 6.2.1 + msApplyBlackeningCompositingFilter@Base 7.2.0 + msApplyBlurringCompositingFilter@Base 7.2.0 + msApplyCompositingFilter@Base 7.2.0 msApplyDefaultOutputFormats@Base 6.2.1 msApplyDefaultSubstitutions@Base 6.2.1 - msApplyFilterToRasterBuffer@Base 7.0.0 + msApplyGrayscaleCompositingFilter@Base 7.2.0 msApplyMapConfigOptions@Base 6.2.1 msApplyOutputFormat@Base 6.2.1 msApplySubstitutions@Base 6.2.1 + msApplyTranslationCompositingFilter@Base 7.2.0 + msApplyWhiteningCompositingFilter@Base 7.2.0 msAxisDenormalizePoints@Base 6.2.1 msAxisNormalizePoints@Base 6.2.1 msAxisSwapShape@Base 6.2.1 @@ -930,6 +951,7 @@ msCircleDrawLineSymbol@Base 7.0.0 msCircleDrawShadeSymbol@Base 6.2.1 msClassifyRasterBuffer@Base 6.2.1 + msCleanVSIDir@Base 7.4.3 msCleanup@Base 6.2.1 msCleanupKernelDensityDataset@Base 7.0.0 msClipPolygonRect@Base 6.2.1 @@ -1086,6 +1108,10 @@ msDrawRasterLayer@Base 6.2.1 msDrawRasterLayerGDAL@Base 6.2.1 msDrawRasterLayerLow@Base 6.2.1 + msDrawRasterLayerLowCheckIfMustDraw@Base 7.2.0 + msDrawRasterLayerLowCloseDataset@Base 7.2.0 + msDrawRasterLayerLowOpenDataset@Base 7.2.0 + msDrawRasterLayerLowWithDataset@Base 7.2.0 msDrawRasterLoadProjection@Base 6.4.0 msDrawRasterSetupTileLayer@Base 6.4.0 msDrawReferenceMap@Base 6.2.1 @@ -1102,7 +1128,6 @@ msDrawVectorLayer@Base 6.2.1 msDrawWMSLayer@Base 6.2.1 msDrawWMSLayerLow@Base 6.2.1 - msDumpLayer@Base 6.2.1 msDumpResult@Base 6.2.1 msEmbedLegend@Base 6.2.1 msEmbedScalebar@Base 6.2.1 @@ -1114,6 +1139,7 @@ msEndShapeKml@Base 6.4.0 msEscapeJSonString@Base 7.0.0 msEvalContext@Base 6.2.1 + msEvalDoubleExpression@Base 7.6.0 msEvalExpression@Base 6.2.1 msEvalRegex@Base 6.2.1 msEvalTextExpression@Base 7.0.0 @@ -1146,6 +1172,7 @@ msFreeOutputFormat@Base 6.2.1 msFreeProjTransformer@Base 6.2.1 msFreeProjection@Base 6.2.1 + msFreeProjectionExceptContext@Base 7.6.0 msFreeQuery@Base 6.2.1 msFreeRasterBuffer@Base 6.2.1 msFreeShape@Base 6.2.1 @@ -1154,6 +1181,7 @@ msFreeSymbolSet@Base 6.2.1 msFreeWmsParamsObj@Base 6.2.1 msGDALCleanup@Base 6.2.1 + msGDALDriverSupportsVirtualIOOutput@Base 7.6.2 msGDALInitialize@Base 6.2.1 msGEOSArea@Base 6.2.1 msGEOSBoundary@Base 6.2.1 @@ -1261,6 +1289,8 @@ msGetProjectionString@Base 6.2.1 msGetQueryResultBounds@Base 6.2.1 msGetRasterBufferKml@Base 6.4.0 + msGetShapeRAMSize@Base 7.2.0 + msGetStringListFromHashTable@Base 7.6.0 msGetStringSize@Base 7.0.0 msGetSymbol@Base 6.2.1 msGetSymbolIndex@Base 6.2.1 @@ -1385,6 +1415,7 @@ msIsAxisInverted@Base 6.2.1 msIsAxisInvertedProj@Base 7.0.0 msIsDegenerateShape@Base 6.2.1 + msIsGlyphASpace@Base 7.2.0 msIsLayerQueryable@Base 6.2.1 msIsOuterRing@Base 6.2.1 msIsXMLTagValid@Base 6.2.1 @@ -1420,6 +1451,7 @@ msLayerGetProcessing@Base 6.2.1 msLayerGetProcessingKey@Base 6.2.1 msLayerGetShape@Base 6.2.1 + msLayerGetShapeCount@Base 7.2.0 msLayerInitItemInfo@Base 6.2.1 msLayerIsOpen@Base 6.2.1 msLayerIsVisible@Base 6.2.1 @@ -1444,6 +1476,7 @@ msLegendCalcSize@Base 6.2.1 msLibXml2GenerateList@Base 6.2.1 msLibXml2GetFirstChild@Base 7.0.0 + msLibXml2GetFirstChildElement@Base 7.2.0 msLibXml2GetFirstChildNs@Base 7.0.0 msLibXml2GetXPath@Base 6.2.1 msLibXml2GetXPathTree@Base 6.2.1 @@ -1471,6 +1504,7 @@ msLoadSymbolSet@Base 6.2.1 msLongToString@Base 6.2.1 msLookupHashTable@Base 6.2.1 + msMVTWriteTile@Base 7.2.0 msMapComputeGeotransform@Base 6.2.1 msMapGeorefToPixel@Base 6.2.1 msMapIgnoreMissingData@Base 6.2.1 @@ -1489,6 +1523,11 @@ msMaybeAllocateClassStyle@Base 6.2.1 msMergeRasterBufferKml@Base 6.4.0 msMergeRect@Base 6.2.1 + msMetadataCreateParamsObj@Base 7.2.0 + msMetadataDispatch@Base 7.2.0 + msMetadataFreeParamsObj@Base 7.2.0 + msMetadataParseRequest@Base 7.2.0 + msMetadataSetGetMetadataURL@Base 7.2.0 msMoveClassDown@Base 6.2.1 msMoveClassUp@Base 6.2.1 msMoveLabelStyleDown@Base 6.2.1 @@ -1517,12 +1556,12 @@ msOGRLayerNextShape@Base 6.2.1 msOGRLayerOpen@Base 6.2.1 msOGRLayerWhichShapes@Base 6.2.1 - msOGRRecursiveFileList@Base 6.2.1 msOGRShapeFromWKT@Base 6.2.1 msOGRShapeToWKT@Base 6.2.1 msOGRUpdateStyleFromString@Base 6.2.1 msOGRWriteFromQuery@Base 6.2.1 msOWSBuildURLFilename@Base 6.2.1 + msOWSClearRequestObj@Base 7.6.0 msOWSCommonBoundingBox@Base 6.2.1 msOWSCommonExceptionReport@Base 6.2.1 msOWSCommonNegotiateVersion@Base 6.2.1 @@ -1548,10 +1587,12 @@ msOWSGetProjURN@Base 6.2.1 msOWSGetSchemasLocation@Base 6.2.1 msOWSGetVersionString@Base 6.2.1 + msOWSInitRequestObj@Base 7.6.0 msOWSIpDisabled@Base 6.4.0 msOWSIpInList@Base 6.4.0 msOWSIpInMetadata@Base 6.4.0 msOWSIpParse@Base 6.4.0 + msOWSLanguageNegotiation@Base 7.2.0 msOWSLookupMetadata2@Base 6.2.1 msOWSLookupMetadata@Base 6.2.1 msOWSLookupMetadataWithLanguage@Base 6.2.1 @@ -1607,6 +1648,7 @@ msOracleSpatialLayerWhichShapes@Base 6.2.1 msOutlineRenderingPrepareStyle@Base 7.0.0 msOutlineRenderingRestoreStyle@Base 7.0.0 + msOutputFormatResolveFromImage@Base 7.2.0 msOutputFormatValidate@Base 6.2.1 msOwsIsOutputFormatValid@Base 6.2.1 msPOSTGRESQLJoinClose@Base 6.2.1 @@ -1629,6 +1671,7 @@ msPopulateRendererVTableCairoRaster@Base 6.2.1 msPopulateRendererVTableCairoSVG@Base 6.2.1 msPopulateRendererVTableKML@Base 6.2.1 + msPopulateRendererVTableMVT@Base 7.2.0 msPopulateRendererVTableOGR@Base 6.2.1 msPopulateRendererVTableUTFGrid@Base 7.0.0 msPopulateTextSymbolForLabelAndString@Base 7.0.0 @@ -1652,7 +1695,9 @@ msPostGISLayerFreeItemInfo@Base 6.2.1 msPostGISLayerGetExtent@Base 7.0.0 msPostGISLayerGetItems@Base 6.2.1 + msPostGISLayerGetNumFeatures@Base 7.2.0 msPostGISLayerGetShape@Base 6.2.1 + msPostGISLayerGetShapeCount@Base 7.2.0 msPostGISLayerInitItemInfo@Base 6.2.1 msPostGISLayerInitializeVirtualTable@Base 6.2.1 msPostGISLayerIsOpen@Base 6.2.1 @@ -1673,15 +1718,26 @@ msProcessProjection@Base 6.2.1 msProcessQueryTemplate@Base 6.2.1 msProcessTemplate@Base 6.2.1 + msProjIsGeographicCRS@Base 7.6.0 msProjLibInitFromEnv@Base 7.0.0 msProjTransformer@Base 6.2.1 + msProjectCreateReprojector@Base 7.6.0 + msProjectDestroyReprojector@Base 7.6.0 msProjectHasLonWrap@Base 7.0.7 msProjectLine@Base 6.2.1 + msProjectLineEx@Base 7.6.0 msProjectPoint@Base 6.2.1 + msProjectPointEx@Base 7.6.0 msProjectRect@Base 6.2.1 - msProjectRectGrid@Base 6.2.1 msProjectShape@Base 6.2.1 + msProjectShapeEx@Base 7.6.0 + msProjectTransformPoints@Base 7.6.0 + msProjectionContextGetFromPool@Base 7.6.0 + msProjectionContextPoolCleanup@Base 7.6.0 + msProjectionContextReleaseToPool@Base 7.6.0 + msProjectionInheritContextFrom@Base 7.6.0 msProjectionObj2OGCWKT@Base 6.2.1 + msProjectionSetContext@Base 7.6.0 msProjectionsDiffer@Base 6.2.1 msQuantizeRasterBuffer@Base 6.2.1 msQueryByFeatures@Base 6.2.1 @@ -1740,7 +1796,6 @@ msReplaceSubstring@Base 6.2.1 msResampleGDALToMap@Base 6.2.1 msResetErrorList@Base 6.2.1 - msRestoreOldFilter@Base 6.2.1 msReturnNestedTemplateQuery@Base 6.2.1 msReturnOpenLayersPage@Base 6.2.1 msReturnPage@Base 6.2.1 @@ -1802,6 +1857,7 @@ msSLDParseLineSymbolizer@Base 6.2.1 msSLDParseLogicalExpression@Base 6.2.1 msSLDParseNamedLayer@Base 6.2.1 + msSLDParseOgcExpression@Base 7.6.0 msSLDParsePointSymbolizer@Base 6.2.1 msSLDParsePolygonFill@Base 6.2.1 msSLDParsePolygonSymbolizer@Base 6.2.1 @@ -1862,6 +1918,7 @@ msShapeFromWKT@Base 6.2.1 msShapeGetClass@Base 6.2.1 msShapeGetLabelAnnotation@Base 7.0.0 + msShapeGetNextClass@Base 7.6.0 msShapeToRange@Base 6.2.1 msShapeToWKT@Base 6.2.1 msShapefileClose@Base 6.2.1 @@ -1878,6 +1935,11 @@ msStartNewLayerKml@Base 6.4.0 msStartShapeKml@Base 6.4.0 msStrdup@Base 6.2.1 + msStringBufferAlloc@Base 7.6.0 + msStringBufferAppend@Base 7.6.0 + msStringBufferFree@Base 7.6.0 + msStringBufferGetString@Base 7.6.0 + msStringBufferReleaseStringAndFree@Base 7.6.0 msStringChop@Base 6.2.1 msStringConcatenate@Base 6.2.1 msStringEscape@Base 6.2.1 @@ -1907,9 +1969,7 @@ msTileIndexAbsoluteDir@Base 6.2.1 msTileSetExtent@Base 6.2.1 msTileSetup@Base 6.2.1 - msTiledSHPClose@Base 6.2.1 msTiledSHPCloseVT@Base 6.2.1 - msTiledSHPGetShape@Base 6.2.1 msTiledSHPLayerFreeItemInfo@Base 6.2.1 msTiledSHPLayerGetExtent@Base 6.2.1 msTiledSHPLayerGetItems@Base 6.2.1 @@ -1917,10 +1977,6 @@ msTiledSHPLayerInitializeVirtualTable@Base 6.2.1 msTiledSHPLayerIsOpen@Base 6.2.1 msTiledSHPLayerSupportsCommonFilters@Base 6.2.1 - msTiledSHPNextShape@Base 6.2.1 - msTiledSHPOpenFile@Base 6.2.1 - msTiledSHPTryOpen@Base 6.2.1 - msTiledSHPWhichShapes@Base 6.2.1 msTimeCleanup@Base 6.2.1 msTimeCompare@Base 6.2.1 msTimeGetResolution@Base 6.2.1 @@ -1944,6 +2000,7 @@ msTryBuildPath3@Base 6.2.1 msTryBuildPath@Base 6.2.1 msUTF8ToUniChar@Base 6.2.1 + msUVRASTERGetSearchRect@Base 7.6.0 msUVRASTERLayerClose@Base 6.2.1 msUVRASTERLayerFreeItemInfo@Base 6.2.1 msUVRASTERLayerGetExtent@Base 6.2.1 @@ -1954,6 +2011,7 @@ msUVRASTERLayerNextShape@Base 6.2.1 msUVRASTERLayerOpen@Base 6.2.1 msUVRASTERLayerSetTimeFilter@Base 6.2.1 + msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes@Base 7.2.0 msUVRASTERLayerWhichShapes@Base 6.2.1 msUnionLayerClose@Base 6.2.1 msUnionLayerCopyVirtualTable@Base 6.2.1 @@ -1984,6 +2042,8 @@ msValidateParameter@Base 6.2.1 msValidateTimeValue@Base 6.2.1 msValueToRange@Base 6.2.1 + msWCSApplyDatasetMetadataAsCreationOptions@Base 7.2.0 + msWCSApplyLayerCreationOptions@Base 7.2.0 msWCSCreateParamsObj20@Base 6.2.1 msWCSDescribeCoverage11@Base 6.2.1 msWCSDescribeCoverage20@Base 6.2.1 @@ -1991,6 +2051,7 @@ msWCSException11@Base 6.2.1 msWCSException20@Base 6.2.1 msWCSException@Base 6.2.1 + msWCSFreeCoverageMetadata@Base 7.2.0 msWCSFreeParams@Base 6.2.1 msWCSFreeParamsObj20@Base 6.2.1 msWCSGetCapabilities11@Base 6.2.1 @@ -2037,6 +2098,7 @@ msWFSUpdateRequestInfo@Base 6.2.1 msWMSApplyDimension@Base 6.2.1 msWMSApplyDimensionLayer@Base 6.2.1 + msWMSApplyFilter@Base 7.2.0 msWMSApplyTime@Base 6.2.1 msWMSDescribeLayer@Base 6.2.1 msWMSDispatch@Base 6.2.1 @@ -2062,7 +2124,6 @@ msWMSPrintScaleHint@Base 6.2.1 msWMSSetTimePattern@Base 6.2.1 msWMSValidateDimensionValue@Base 6.2.1 - msWrapText@Base 6.2.1 msWriteClassToString@Base 6.4.0 msWriteClusterToString@Base 6.4.0 msWriteError@Base 6.2.1 @@ -2088,7 +2149,6 @@ ms_regerror@Base 6.2.1 ms_regexec@Base 6.2.1 ms_regfree@Base 6.2.1 - ms_timeFormats@Base 6.2.1 ms_time_inited@Base 6.2.1 msyy_create_buffer@Base 6.2.1 msyy_delete_buffer@Base 6.2.1 @@ -2138,17 +2198,13 @@ msyystring_size_tmp@Base 6.2.1 msyytext@Base 6.2.1 msyywrap@Base 6.2.1 + mvtWriteShape@Base 7.2.0 offsetAndTest@Base 6.2.1 - ogrEnabled@Base 6.2.1 path@Base 6.2.1 pieLayerProcessDynamicDiameter@Base 6.2.1 plustospace@Base 6.2.1 - png_flush_data@Base 6.2.1 - png_write_data_to_buffer@Base 6.2.1 - png_write_data_to_stream@Base 6.2.1 pointArrayFree@Base 6.2.1 pointArrayNew@Base 6.2.1 - pointLayerDrawShape@Base 6.2.1 polygonLayerDrawShape@Base 6.2.1 populateRendererVTableCairoVector@Base 6.2.1 postgresTimeStampForTimeString@Base 6.2.1 @@ -2208,7 +2264,6 @@ setCoordinate@Base 6.2.1 setExtent@Base 6.2.1 setExtentFromShapes@Base 6.2.1 - sortLayerByMetadata@Base 6.2.1 sortLayerByOrder@Base 6.2.1 startLayerDummy@Base 6.2.1 startLayerRasterCairo@Base 6.2.1 @@ -2219,6 +2274,21 @@ strrstr@Base 6.2.1 unescape_url@Base 6.2.1 unicode_is_latin1@Base 7.0.0 + use_global_ft_cache@Base 7.2.0 + vector_tile__tile__descriptor@Base 7.2.0 + vector_tile__tile__feature__descriptor@Base 7.2.0 + vector_tile__tile__feature__init@Base 7.2.0 + vector_tile__tile__free_unpacked@Base 7.2.0 + vector_tile__tile__geom_type__descriptor@Base 7.2.0 + vector_tile__tile__get_packed_size@Base 7.2.0 + vector_tile__tile__init@Base 7.2.0 + vector_tile__tile__layer__descriptor@Base 7.2.0 + vector_tile__tile__layer__init@Base 7.2.0 + vector_tile__tile__pack@Base 7.2.0 + vector_tile__tile__pack_to_buffer@Base 7.2.0 + vector_tile__tile__unpack@Base 7.2.0 + vector_tile__tile__value__descriptor@Base 7.2.0 + vector_tile__tile__value__init@Base 7.2.0 (c++)"virtual thunk to ClipperLib::Clipper::Clear()@Base" 6.2.1 (c++)"virtual thunk to ClipperLib::Clipper::Reset()@Base" 6.2.1 (c++)"virtual thunk to ClipperLib::Clipper::~Clipper()@Base" 6.2.1 diff -Nru mapserver-7.0.7/debian/mapscript-ng.ini mapserver-7.6.4/debian/mapscript-ng.ini --- mapserver-7.0.7/debian/mapscript-ng.ini 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/mapscript-ng.ini 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1 @@ +extension=php_mapscriptng.so diff -Nru mapserver-7.0.7/debian/mapserver-bin.lintian-overrides mapserver-7.6.4/debian/mapserver-bin.lintian-overrides --- mapserver-7.0.7/debian/mapserver-bin.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/mapserver-bin.lintian-overrides 2020-08-06 03:34:57.000000000 +0000 @@ -0,0 +1,3 @@ +# Cannot easily be fixed +file-references-package-build-path * + diff -Nru mapserver-7.0.7/debian/mapserver-doc.docs mapserver-7.6.4/debian/mapserver-doc.docs --- mapserver-7.0.7/debian/mapserver-doc.docs 2017-05-09 20:13:10.000000000 +0000 +++ mapserver-7.6.4/debian/mapserver-doc.docs 2019-03-30 09:59:05.000000000 +0000 @@ -1,4 +1,4 @@ -README +README.rst fonts symbols MIGRATION_GUIDE.txt diff -Nru mapserver-7.0.7/debian/patches/hardening.patch mapserver-7.6.4/debian/patches/hardening.patch --- mapserver-7.0.7/debian/patches/hardening.patch 2017-03-15 16:06:33.000000000 +0000 +++ mapserver-7.6.4/debian/patches/hardening.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -Description: Add support for hardening build flags. -Author: Bas Couwenberg -Last-Update: 2013-09-02 -Forwarded: not-needed - ---- a/mapscript/ruby/CMakeLists.txt -+++ b/mapscript/ruby/CMakeLists.txt -@@ -7,6 +7,23 @@ include_directories(${PROJECT_SOURCE_DIR - include_directories(${PROJECT_SOURCE_DIR}/mapscript/ruby) - SWIG_ADD_MODULE(rubymapscript ruby ../mapscript.i) - -+# Ruby mapscript fails to build with -Werror=format-security -+ -+if(${CMAKE_C_FLAGS} MATCHES "-Werror=format-security") -+ string(REPLACE "-Werror=format-security" "" TMP "${CMAKE_C_FLAGS}") -+ set(CMAKE_C_FLAGS "${TMP}") -+endif(${CMAKE_C_FLAGS} MATCHES "-Werror=format-security") -+ -+if(${CMAKE_CXX_FLAGS} MATCHES "-Werror=format-security") -+ string(REPLACE "-Werror=format-security" "" TMP "${CMAKE_CXX_FLAGS}") -+ set(CMAKE_CXX_FLAGS "${TMP}") -+endif(${CMAKE_CXX_FLAGS} MATCHES "-Werror=format-security") -+ -+if(${CMAKE_CPP_FLAGS} MATCHES "-Werror=format-security") -+ string(REPLACE "-Werror=format-security" "" TMP "${CMAKE_CPP_FLAGS}") -+ set(CMAKE_CPP_FLAGS "${TMP}") -+endif(${CMAKE_CPP_FLAGS} MATCHES "-Werror=format-security") -+ - SWIG_LINK_LIBRARIES(rubymapscript ${RUBY_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) - - set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES PREFIX "") diff -Nru mapserver-7.0.7/debian/patches/interpreter-path.path mapserver-7.6.4/debian/patches/interpreter-path.path --- mapserver-7.0.7/debian/patches/interpreter-path.path 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/patches/interpreter-path.path 2020-12-08 04:49:56.000000000 +0000 @@ -0,0 +1,36 @@ +Description: Fix example-unusual-interpreter lintian issue. +Author: Bas Couwenberg +Forwarded: not-needed + +--- a/mapscript/python/examples/project_csv.py ++++ b/mapscript/python/examples/project_csv.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/python3 + + """ + Simple example to read a csv file and reproject point x/y data +--- a/mapscript/python/examples/shpdump.py ++++ b/mapscript/python/examples/shpdump.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/python3 + + """ + Dump the contents of the passed in Shapefile +--- a/mapscript/python/examples/shpinfo.py ++++ b/mapscript/python/examples/shpinfo.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/python3 + + """ + Extracts basic descriptive information from a Shapefile +--- a/mapscript/python/examples/wxs.py ++++ b/mapscript/python/examples/wxs.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/python3 + + """ + Output WMS GetCapabilities response for a Mapfile diff -Nru mapserver-7.0.7/debian/patches/java-hardening.patch mapserver-7.6.4/debian/patches/java-hardening.patch --- mapserver-7.0.7/debian/patches/java-hardening.patch 2017-03-15 16:06:33.000000000 +0000 +++ mapserver-7.6.4/debian/patches/java-hardening.patch 2020-08-06 03:34:57.000000000 +0000 @@ -6,9 +6,9 @@ --- a/mapscript/java/CMakeLists.txt +++ b/mapscript/java/CMakeLists.txt -@@ -15,6 +15,23 @@ SET (CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_ - SET(CMAKE_SWIG_FLAGS -package edu.umn.gis.mapscript) - SWIG_ADD_MODULE(javamapscript java ../mapscript.i) +@@ -26,6 +26,23 @@ else () + swig_add_module(javamapscript java ../mapscript.i) + endif () +# Java mapscript fails to build with -Werror=format-security + @@ -27,14 +27,13 @@ + set(CMAKE_CPP_FLAGS "${TMP}") +endif(${CMAKE_CPP_FLAGS} MATCHES "-Werror=format-security") + - SWIG_LINK_LIBRARIES(javamapscript ${MAPSERVER_LIBMAPSERVER}) + swig_link_libraries(javamapscript ${MAPSERVER_LIBMAPSERVER}) - ADD_CUSTOM_COMMAND(TARGET javamapscript -@@ -26,5 +43,5 @@ ADD_CUSTOM_COMMAND(TARGET javamapscript + add_custom_command(TARGET javamapscript +@@ -37,4 +54,5 @@ add_custom_command(TARGET javamapscript ) - get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_javamapscript_REAL_NAME} LOCATION) --install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${CMAKE_INSTALL_LIBDIR}) -- -+install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION lib/jni) + set(mapscript_files $) +-install(FILES ${mapscript_files} DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++install(FILES ${mapscript_files} DESTINATION lib/jni) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.jar DESTINATION share/java) diff -Nru mapserver-7.0.7/debian/patches/perl-mapscript-install.patch mapserver-7.6.4/debian/patches/perl-mapscript-install.patch --- mapserver-7.0.7/debian/patches/perl-mapscript-install.patch 2017-03-15 16:06:33.000000000 +0000 +++ mapserver-7.6.4/debian/patches/perl-mapscript-install.patch 2019-07-07 06:53:23.000000000 +0000 @@ -5,21 +5,23 @@ --- a/mapscript/perl/CMakeLists.txt +++ b/mapscript/perl/CMakeLists.txt -@@ -2,7 +2,7 @@ FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) - FIND_PACKAGE(Perl REQUIRED) - FIND_PACKAGE(PerlLibs REQUIRED) +@@ -2,7 +2,7 @@ find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) + find_package(Perl REQUIRED) + find_package(PerlLibs REQUIRED) -set(CUSTOM_PERL_SITE_ARCH_DIR ${PERL_SITEARCH} CACHE DIR "Custom installation directory for perl binary extension") +set(CUSTOM_PERL_VENDOR_ARCH_DIR ${PERL_VENDORARCH} CACHE DIR "Custom installation directory for perl binary extension") - INCLUDE_DIRECTORIES(${PERL_INCLUDE_PATH}) + include_directories(${PERL_INCLUDE_PATH}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) -@@ -20,6 +20,6 @@ endif(APPLE) +@@ -23,8 +23,8 @@ if(APPLE) + set_target_properties(perlmapscript PROPERTIES SUFFIX ".bundle") + endif(APPLE) - get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_perlmapscript_REAL_NAME} LOCATION) - set(mapscript_files ${LOC_MAPSCRIPT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/mapscript.pm) --install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}/auto/mapscript) --install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.pm DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}) -+install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${CUSTOM_PERL_VENDOR_ARCH_DIR}/auto/mapscript) -+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.pm DESTINATION ${CUSTOM_PERL_VENDOR_ARCH_DIR}) +-install(FILES $ DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}/auto/mapscript) +-install(FILES $/mapscript.pm DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}) ++install(FILES $ DESTINATION ${CUSTOM_PERL_VENDOR_ARCH_DIR}/auto/mapscript) ++install(FILES $/mapscript.pm DESTINATION ${CUSTOM_PERL_VENDOR_ARCH_DIR}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/examples DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff -Nru mapserver-7.0.7/debian/patches/ruby-mapscript-install.patch mapserver-7.6.4/debian/patches/ruby-mapscript-install.patch --- mapserver-7.0.7/debian/patches/ruby-mapscript-install.patch 2017-03-15 16:06:33.000000000 +0000 +++ mapserver-7.6.4/debian/patches/ruby-mapscript-install.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Description: Install Ruby mapscript to vendorarchdir instead of archdir. -Author: Bas Couwenberg -Last-Update: 2013-09-11 -Forwarded: not-needed - ---- a/mapscript/ruby/CMakeLists.txt -+++ b/mapscript/ruby/CMakeLists.txt -@@ -33,5 +33,5 @@ if(APPLE) - endif(APPLE) - - get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_rubymapscript_REAL_NAME} LOCATION) --execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts RbConfig::CONFIG['sitearchdir']" OUTPUT_VARIABLE RUBY_SITEARCHDIR OUTPUT_STRIP_TRAILING_WHITESPACE) --install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${RUBY_SITEARCHDIR}) -+execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts RbConfig::CONFIG['vendorarchdir']" OUTPUT_VARIABLE RUBY_VENDORARCHDIR OUTPUT_STRIP_TRAILING_WHITESPACE) -+install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${RUBY_VENDORARCHDIR}) diff -Nru mapserver-7.0.7/debian/patches/series mapserver-7.6.4/debian/patches/series --- mapserver-7.0.7/debian/patches/series 2017-06-18 11:09:09.000000000 +0000 +++ mapserver-7.6.4/debian/patches/series 2021-01-22 14:00:00.000000000 +0000 @@ -1,4 +1,3 @@ -hardening.patch perl-mapscript-install.patch -ruby-mapscript-install.patch java-hardening.patch +interpreter-path.path diff -Nru mapserver-7.0.7/debian/php-mapscript.install mapserver-7.6.4/debian/php-mapscript.install --- mapserver-7.0.7/debian/php-mapscript.install 2017-05-09 20:13:10.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript.install 2019-07-07 06:53:23.000000000 +0000 @@ -1,2 +1 @@ -usr/lib/php/ -etc/php/*/mods-available/ +usr/lib/php/*/php_mapscript.* diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.install mapserver-7.6.4/debian/php-mapscript-ng.install --- mapserver-7.0.7/debian/php-mapscript-ng.install 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.install 2020-07-03 05:19:35.000000000 +0000 @@ -0,0 +1,2 @@ +usr/lib/php/*/php_mapscriptng.* +usr/lib/php/*/mapscript.php diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.lintian-overrides mapserver-7.6.4/debian/php-mapscript-ng.lintian-overrides --- mapserver-7.0.7/debian/php-mapscript-ng.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.lintian-overrides 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1,4 @@ +# Build uses -D_FORTIFY_SOURCE=2, but hardening-check reports: +# Fortify Source functions: no, only unprotected functions found! +hardening-no-fortify-functions * + diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.php mapserver-7.6.4/debian/php-mapscript-ng.php --- mapserver-7.0.7/debian/php-mapscript-ng.php 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.php 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1 @@ +mod debian/mapscript-ng.ini diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.postinst mapserver-7.6.4/debian/php-mapscript-ng.postinst --- mapserver-7.0.7/debian/php-mapscript-ng.postinst 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.postinst 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e + +# Source debconf library. +. /usr/share/debconf/confmodule + +#DEBHELPER# + +exit 0 diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.postrm mapserver-7.6.4/debian/php-mapscript-ng.postrm --- mapserver-7.0.7/debian/php-mapscript-ng.postrm 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.postrm 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +#DEBHELPER# + +exit 0 diff -Nru mapserver-7.0.7/debian/php-mapscript-ng.prerm mapserver-7.6.4/debian/php-mapscript-ng.prerm --- mapserver-7.0.7/debian/php-mapscript-ng.prerm 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/php-mapscript-ng.prerm 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +#DEBHELPER# + +exit 0 diff -Nru mapserver-7.0.7/debian/python3-mapscript.examples mapserver-7.6.4/debian/python3-mapscript.examples --- mapserver-7.0.7/debian/python3-mapscript.examples 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/python3-mapscript.examples 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1 @@ +mapscript/python/examples/* diff -Nru mapserver-7.0.7/debian/python3-mapscript.install mapserver-7.6.4/debian/python3-mapscript.install --- mapserver-7.0.7/debian/python3-mapscript.install 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/python3-mapscript.install 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/python*/ diff -Nru mapserver-7.0.7/debian/python3-mapscript.links mapserver-7.6.4/debian/python3-mapscript.links --- mapserver-7.0.7/debian/python3-mapscript.links 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/python3-mapscript.links 2019-07-07 06:53:23.000000000 +0000 @@ -0,0 +1,2 @@ +usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf usr/lib/python3/dist-packages/mapscript/tests/data/vera/Vera.ttf +usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf usr/lib/python3/dist-packages/mapscript/tests/data/vera/VeraBd.ttf diff -Nru mapserver-7.0.7/debian/python3-mapscript.lintian-overrides mapserver-7.6.4/debian/python3-mapscript.lintian-overrides --- mapserver-7.0.7/debian/python3-mapscript.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/python3-mapscript.lintian-overrides 2020-12-08 04:49:56.000000000 +0000 @@ -0,0 +1,8 @@ +# Not a problem +breakout-link usr/lib/python3/dist-packages/mapscript/tests/data/vera/Vera.ttf -> usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf +breakout-link usr/lib/python3/dist-packages/mapscript/tests/data/vera/VeraBd.ttf -> usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf +package-contains-documentation-outside-usr-share-doc * + +# Cannot easily be fixed +file-references-package-build-path * + diff -Nru mapserver-7.0.7/debian/python-mapscript.examples mapserver-7.6.4/debian/python-mapscript.examples --- mapserver-7.0.7/debian/python-mapscript.examples 2017-01-16 21:41:00.000000000 +0000 +++ mapserver-7.6.4/debian/python-mapscript.examples 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -mapscript/python/examples/* diff -Nru mapserver-7.0.7/debian/python-mapscript.install mapserver-7.6.4/debian/python-mapscript.install --- mapserver-7.0.7/debian/python-mapscript.install 2017-01-28 15:41:11.000000000 +0000 +++ mapserver-7.6.4/debian/python-mapscript.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/python*/ diff -Nru mapserver-7.0.7/debian/ruby-mapscript.docs mapserver-7.6.4/debian/ruby-mapscript.docs --- mapserver-7.0.7/debian/ruby-mapscript.docs 2017-01-28 15:41:11.000000000 +0000 +++ mapserver-7.6.4/debian/ruby-mapscript.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -mapscript/ruby/README diff -Nru mapserver-7.0.7/debian/ruby-mapscript.examples mapserver-7.6.4/debian/ruby-mapscript.examples --- mapserver-7.0.7/debian/ruby-mapscript.examples 2017-01-28 15:41:11.000000000 +0000 +++ mapserver-7.6.4/debian/ruby-mapscript.examples 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -mapscript/ruby/examples/* diff -Nru mapserver-7.0.7/debian/ruby-mapscript.install mapserver-7.6.4/debian/ruby-mapscript.install --- mapserver-7.0.7/debian/ruby-mapscript.install 2017-03-15 16:06:34.000000000 +0000 +++ mapserver-7.6.4/debian/ruby-mapscript.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/*/ruby/vendor_ruby/*/mapscript.so diff -Nru mapserver-7.0.7/debian/rules mapserver-7.6.4/debian/rules --- mapserver-7.0.7/debian/rules 2017-11-15 20:00:35.000000000 +0000 +++ mapserver-7.6.4/debian/rules 2020-05-14 04:25:38.000000000 +0000 @@ -22,56 +22,13 @@ CFLAGS += $(CPPFLAGS) CFLAGS += $(LDFLAGS) -RUBYVERSIONS := $(shell dh_ruby --print-supported) -#PHPAPI := $(shell php-config --phpapi) - MANPAGES := $(wildcard debian/man/*.*.xml) MS_VERSION := $(shell echo $(DEB_VERSION_UPSTREAM) | sed -e 's/\+.*//') BUILD_DATE := $(shell LC_ALL=C date -u "+%d %B %Y" -d "@$(SOURCE_DATE_EPOCH)") -CMAKE_OPTS := \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_EXE_LINKER_FLAGS="$(LDFLAGS)" \ - -DCMAKE_MODULE_LINKER_FLAGS="$(LDFLAGS)" \ - -DCMAKE_SHARED_LINKER_FLAGS="$(LDFLAGS)" \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_VERBOSE_MAKEFILE=1 \ - -DWITH_PROJ=1 \ - -DWITH_KML=1 \ - -DWITH_SOS=1 \ - -DWITH_WMS=1 \ - -DWITH_FRIBIDI=1 \ - -DWITH_HARFBUZZ=1 \ - -DWITH_ICONV=1 \ - -DWITH_CAIRO=1 \ - -DWITH_SVGCAIRO=0 \ - -DWITH_RSVG=1 \ - -DWITH_MYSQL=0 \ - -DWITH_FCGI=1 \ - -DWITH_GEOS=1 \ - -DWITH_POSTGIS=1 \ - -DWITH_GDAL=1 \ - -DWITH_OGR=1 \ - -DWITH_CURL=1 \ - -DWITH_CLIENT_WMS=1 \ - -DWITH_CLIENT_WFS=1 \ - -DWITH_WFS=1 \ - -DWITH_WCS=1 \ - -DWITH_LIBXML2=1 \ - -DWITH_THREAD_SAFETY=1 \ - -DWITH_GIF=1 \ - -DWITH_ORACLESPATIAL=0 \ - -DWITH_ORACLE_PLUGIN=0 \ - -DWITH_MSSQL2008=0 \ - -DWITH_EXEMPI=0 \ - -DWITH_XMLMAPFILE=0 \ - -DWITH_V8=0 \ - -DWITH_PIXMAN=0 - %: - dh $@ --with python2,pkgkde_symbolshelper \ - --parallel \ + dh $@ --with php,python3,pkgkde_symbolshelper \ --buildsystem cmake override_dh_auto_clean: @@ -82,26 +39,48 @@ -$(RM) -rf build-ruby*/ debian/tmp-ruby*/ override_dh_auto_configure: - dh_auto_configure -- $(CMAKE_OPTS) \ - -DWITH_PYTHON=1 \ - -DWITH_PHP=0 \ - -DWITH_PERL=1 \ - -DWITH_RUBY=0 \ - -DWITH_JAVA=1 \ - -DWITH_CSHARP=0 - - for RUBY in $(RUBYVERSIONS); do \ - dh_auto_configure --builddirectory=build-$$RUBY -- $(CMAKE_OPTS) \ - -DWITH_PYTHON=0 \ - -DWITH_PHP=0 \ - -DWITH_PERL=0 \ - -DWITH_RUBY=1 \ - -DWITH_JAVA=0 \ - -DWITH_CSHARP=0 \ - -DRUBY_EXECUTABLE=/usr/bin/$$RUBY \ - ; \ - done - + dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_EXE_LINKER_FLAGS="$(LDFLAGS)" \ + -DCMAKE_MODULE_LINKER_FLAGS="$(LDFLAGS)" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(LDFLAGS)" \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DINSTALL_LIB_DIR="/usr/lib/$(DEB_HOST_MULTIARCH)" \ + -DWITH_KML=1 \ + -DWITH_SOS=1 \ + -DWITH_WMS=1 \ + -DWITH_FRIBIDI=1 \ + -DWITH_HARFBUZZ=1 \ + -DWITH_ICONV=1 \ + -DWITH_CAIRO=1 \ + -DWITH_SVGCAIRO=0 \ + -DWITH_RSVG=1 \ + -DWITH_MYSQL=0 \ + -DWITH_FCGI=1 \ + -DWITH_GEOS=1 \ + -DWITH_POSTGIS=1 \ + -DWITH_CURL=1 \ + -DWITH_CLIENT_WMS=1 \ + -DWITH_CLIENT_WFS=1 \ + -DWITH_WFS=1 \ + -DWITH_WCS=1 \ + -DWITH_LIBXML2=1 \ + -DWITH_THREAD_SAFETY=1 \ + -DWITH_GIF=1 \ + -DWITH_ORACLESPATIAL=0 \ + -DWITH_ORACLE_PLUGIN=0 \ + -DWITH_MSSQL2008=0 \ + -DWITH_EXEMPI=0 \ + -DWITH_XMLMAPFILE=0 \ + -DWITH_V8=0 \ + -DWITH_PIXMAN=0 \ + -DWITH_PYTHON=1 \ + -DWITH_PHP=1 \ + -DWITH_PHPNG=1 \ + -DWITH_PERL=1 \ + -DWITH_RUBY=0 \ + -DWITH_JAVA=1 \ + -DWITH_CSHARP=0 override_dh_auto_build: # Create man pages from DocBook XML @@ -112,63 +91,39 @@ dh_auto_build - for RUBY in $(RUBYVERSIONS); do \ - dh_auto_build --builddirectory=build-$$RUBY ; \ - done - override_dh_auto_test: # msautotest submodule is not used override_dh_auto_install: dh_auto_install - for RUBY in $(RUBYVERSIONS); do \ - dh_auto_install --builddirectory=build-$$RUBY --destdir=debian/tmp-$$RUBY ; \ - mkdir -p debian/tmp/`$$RUBY -r rbconfig -e "print RbConfig::CONFIG['vendorarchdir']"` ; \ - mv -v debian/tmp-$$RUBY`$$RUBY -r rbconfig -e "print RbConfig::CONFIG['vendorarchdir']"`/mapscript.so \ - debian/tmp`$$RUBY -r rbconfig -e "print RbConfig::CONFIG['vendorarchdir']"`/ ; \ - done - - -mkdir -p $(CURDIR)/debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/ - -mv -v $(CURDIR)/debian/tmp/usr/lib/libmapserver*.so* $(CURDIR)/debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/ - -sed -i "s/lib\/libmapserver/lib\/$(DEB_HOST_MULTIARCH)\/libmapserver/g" $(CURDIR)/debian/tmp/usr/share/*/cmake/*.cmake - # removing embedded rpath in binaries -find $(CURDIR)/debian/tmp/usr/bin -type f -exec chrpath --delete {} \; # removing embedded rpath in libraries -find $(CURDIR)/debian/tmp/usr/lib -name "*.so*" -type f -exec chrpath --delete {} \; - # CGI mapserver - -mkdir -p debian/tmp/usr/lib/cgi-bin - install -m755 debian/tmp/usr/bin/mapserv debian/tmp/usr/lib/cgi-bin/mapserv - - # TODO: Use dh_php for substvars & mapscript.ini installation - # PHP mapscript - #echo 'misc:Depends=phpapi-'$(PHPAPI) >> debian/php-mapscript.substvars - - #-mkdir -p debian/tmp/etc/php/7.0/mods-available/ - #install -m644 debian/mapscript.ini debian/tmp/etc/php/7.0/mods-available/ - override_dh_installchangelogs: dh_installchangelogs HISTORY.TXT override_dh_installexamples: dh_installexamples - #-chmod a-x $(CURDIR)/debian/php-mapscript/usr/share/doc/php-mapscript/examples/*.phtml + -chmod a-x $(CURDIR)/debian/php-mapscript/usr/share/doc/php-mapscript/examples/*.phtml override_dh_install: dh_install --autodest --list-missing + $(RM) $(CURDIR)/debian/*/usr/lib/python*/*-packages/mapscript/tests/data/vera/* + override_dh_compress: dh_compress -X.xml -X.xsd -X.xsl override_dh_makeshlibs: dh_makeshlibs -Xphp_mapscript -- -c0 -v$(MS_VERSION) -override_dh_python2: - dh_python2 -ppython-mapscript +override_dh_python3: + dh_python3 -ppython3-mapscript override_dh_perl: dh_perl -plibmapscript-perl @@ -177,5 +132,4 @@ dh_java -plibmapscript-java override_dh_strip: - dh_strip --dbg-package=libmapserver-dbg - + dh_strip --dbgsym-migration='libmapserver-dbg (<< 7.2.0~)' diff -Nru mapserver-7.0.7/debian/source.lintian-overrides mapserver-7.6.4/debian/source.lintian-overrides --- mapserver-7.0.7/debian/source.lintian-overrides 2017-11-15 20:00:35.000000000 +0000 +++ mapserver-7.6.4/debian/source.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -# download.osgeo.org is not available via HTTPS -mapserver source: debian-watch-uses-insecure-uri * - -# Only a single Python version is supported during the build -mapserver source: python-foo-but-no-python3-foo python-mapscript - diff -Nru mapserver-7.0.7/debian/tests/control mapserver-7.6.4/debian/tests/control --- mapserver-7.0.7/debian/tests/control 2017-06-21 19:00:55.000000000 +0000 +++ mapserver-7.6.4/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -# Test installability -Depends: @ -Test-Command: /bin/true diff -Nru mapserver-7.0.7/debian/TODO mapserver-7.6.4/debian/TODO --- mapserver-7.0.7/debian/TODO 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/TODO 2020-03-23 04:46:44.000000000 +0000 @@ -0,0 +1,4 @@ +Debian mapserver TODO list +-------------------------- + +- Include some more bindings when someone requests them. diff -Nru mapserver-7.0.7/debian/TODO.Debian mapserver-7.6.4/debian/TODO.Debian --- mapserver-7.0.7/debian/TODO.Debian 2017-01-28 15:41:11.000000000 +0000 +++ mapserver-7.6.4/debian/TODO.Debian 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -Debian mapserver TODO list --------------------------- - -- Include some more bindings when someone requests them. diff -Nru mapserver-7.0.7/debian/upstream/metadata mapserver-7.6.4/debian/upstream/metadata --- mapserver-7.0.7/debian/upstream/metadata 2017-03-15 16:06:34.000000000 +0000 +++ mapserver-7.6.4/debian/upstream/metadata 2020-12-08 04:27:59.000000000 +0000 @@ -1,8 +1,6 @@ --- Bug-Database: https://github.com/mapserver/mapserver/issues Bug-Submit: https://github.com/mapserver/mapserver/issues/new -Contact: The MapServer team -FAQ: http://mapserver.org/faq.html -Name: MapServer +FAQ: https://mapserver.org/faq.html Repository: https://github.com/mapserver/mapserver.git Repository-Browse: https://github.com/mapserver/mapserver diff -Nru mapserver-7.0.7/debian/watch mapserver-7.6.4/debian/watch --- mapserver-7.0.7/debian/watch 2017-05-09 20:13:10.000000000 +0000 +++ mapserver-7.6.4/debian/watch 2020-11-06 18:31:45.000000000 +0000 @@ -1,6 +1,6 @@ -version=3 +version=4 opts=\ dversionmangle=s/\+(debian|dfsg|ds|deb)\d*$//,\ uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/;s/RC/rc/;s/-/./g \ -http://download.osgeo.org/mapserver/ \ +https://download.osgeo.org/mapserver/ \ (?:.*/)?(?:rel|v|mapserver)[\-\_]?(\d\S+)\.(?:tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -Nru mapserver-7.0.7/fontcache.c mapserver-7.6.4/fontcache.c --- mapserver-7.0.7/fontcache.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/fontcache.c 2021-07-12 20:16:21.000000000 +0000 @@ -46,6 +46,7 @@ ft_cache cache; }; ft_thread_cache *ft_caches; +int use_global_ft_cache; #else ft_cache global_ft_cache; #endif @@ -96,15 +97,19 @@ UT_HASH_DEL(c->bitmap_glyph_cache, cur_bitmap); free(cur_bitmap); } + memset(c,0,sizeof(ft_cache)); } ft_cache* msGetFontCache() { #ifndef USE_THREAD return &global_ft_cache; #else - void* nThreadId = msGetThreadId(); + void* nThreadId = 0; ft_thread_cache *prev = NULL, *cur = ft_caches; + if (!use_global_ft_cache) + nThreadId = msGetThreadId(); + if( cur != NULL && cur->thread_id == nThreadId ) return &cur->cache; @@ -155,6 +160,12 @@ ft_cache *c = msGetFontCache(); msInitFontCache(c); #else + char* use_global_cache = getenv("MS_USE_GLOBAL_FT_CACHE"); + if (use_global_cache) + use_global_ft_cache = atoi(use_global_cache); + else + use_global_ft_cache = 0; + ft_caches = NULL; #endif } @@ -183,6 +194,10 @@ if(face->face->charmap && face->face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { unicode |= 0xf000; /* why? */ } +#ifdef USE_THREAD + if (use_global_ft_cache) + msAcquireLock(TLOCK_TTF); +#endif UT_HASH_FIND_INT(face->index_cache,&unicode,ic); if(!ic) { ic = msSmallMalloc(sizeof(index_element)); @@ -190,6 +205,10 @@ ic->unicode = unicode; UT_HASH_ADD_INT(face->index_cache,unicode,ic); } +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return ic->codepoint; } @@ -202,15 +221,23 @@ if(!key) { key = MS_DEFAULT_FONT_KEY; } +#ifdef USE_THREAD + if (use_global_ft_cache) + msAcquireLock(TLOCK_TTF); +#endif UT_HASH_FIND_STR(cache->face_cache,key,fc); if(!fc) { - char *fontfile = NULL; + const char *fontfile = NULL; fc = msSmallCalloc(1,sizeof(face_element)); if(fontset && strcmp(key,MS_DEFAULT_FONT_KEY)) { fontfile = msLookupHashTable(&(fontset->fonts),key); if(!fontfile) { msSetError(MS_MISCERR, "Could not find font with key \"%s\" in fontset", "msGetFontFace()", key); free(fc); +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return NULL; } error = FT_New_Face(cache->library,fontfile,0, &(fc->face)); @@ -220,6 +247,10 @@ if(error) { msSetError(MS_MISCERR, "Freetype was unable to load font file \"%s\" for key \"%s\"", "msGetFontFace()", fontfile, key); free(fc); +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return NULL; } if(!fc->face->charmap) { @@ -231,7 +262,10 @@ fc->font = msStrdup(key); UT_HASH_ADD_KEYPTR(hh,cache->face_cache,fc->font, strlen(key), fc); } - +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return fc; } @@ -241,6 +275,10 @@ memset(&key,0,sizeof(glyph_element_key)); key.codepoint = codepoint; key.size = size; +#ifdef USE_THREAD + if (use_global_ft_cache) + msAcquireLock(TLOCK_TTF); +#endif UT_HASH_FIND(hh,face->glyph_cache,&key,sizeof(glyph_element_key),gc); if(!gc) { FT_Error error; @@ -249,9 +287,19 @@ FT_Set_Pixel_Sizes(face->face,0,MS_NINT(size * 96/72.0)); } error = FT_Load_Glyph(face->face,key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) { + msDebug("Unable to load glyph %u for font \"%s\". Using ? as fallback.\n", key.codepoint, face->font); + // If we can't find a glyph then try to fallback to a question mark. + unsigned int fallbackCodepoint = msGetGlyphIndex(face, 0x3F); + error = FT_Load_Glyph(face->face,fallbackCodepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + } if(error) { - msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",key.codepoint, face->font); + msSetError(MS_MISCERR, "unable to load glyph %u for font \"%s\"", "msGetGlyphByIndex()",key.codepoint, face->font); free(gc); +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return NULL; } gc->metrics.minx = face->face->glyph->metrics.horiBearingX / 64.0; @@ -262,6 +310,10 @@ gc->key = key; UT_HASH_ADD(hh,face->glyph_cache,key,sizeof(glyph_element_key), gc); } +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return gc; } @@ -271,6 +323,10 @@ ft_cache *cache = msGetFontCache(); memset(&key,0,sizeof(outline_element_key)); key.glyph = glyph; +#ifdef USE_THREAD + if (use_global_ft_cache) + msAcquireLock(TLOCK_TTF); +#endif UT_HASH_FIND(hh,face->outline_cache,&key, sizeof(outline_element_key),oc); if(!oc) { FT_Matrix matrix; @@ -284,9 +340,19 @@ matrix.xy = matrix.yx = 0x00000L; pen.x = pen.y = 0; FT_Set_Transform(face->face, &matrix, &pen); - error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) { + msDebug("Unable to load glyph %u for font \"%s\". Using ? as fallback.\n", glyph->key.codepoint, face->font); + // If we can't find a glyph then try to fallback to a question mark. + unsigned int fallbackCodepoint = msGetGlyphIndex(face, 0x3F); + error = FT_Load_Glyph(face->face,fallbackCodepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + } if(error) { - msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",glyph->key.codepoint, face->font); + msSetError(MS_MISCERR, "unable to load glyph %u for font \"%s\"", "msGetGlyphOutline()",glyph->key.codepoint, face->font); +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return NULL; } error = FT_Outline_New(cache->library, face->face->glyph->outline.n_points, @@ -295,5 +361,17 @@ oc->key = key; UT_HASH_ADD(hh,face->outline_cache,key,sizeof(outline_element_key), oc); } +#ifdef USE_THREAD + if (use_global_ft_cache) + msReleaseLock(TLOCK_TTF); +#endif return oc; } + +int msIsGlyphASpace(glyphObj *glyph) { + /* space or tab, for now */ + unsigned int space,tab; + space = msGetGlyphIndex(glyph->face,0x20); + tab = msGetGlyphIndex(glyph->face,0x9); + return glyph->glyph->key.codepoint == space || glyph->glyph->key.codepoint == tab; +} diff -Nru mapserver-7.0.7/fontcache.h mapserver-7.6.4/fontcache.h --- mapserver-7.0.7/fontcache.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/fontcache.h 2021-07-12 20:16:21.000000000 +0000 @@ -80,6 +80,7 @@ glyph_element* msGetBitmapGlyph(rendererVTableObj *renderer, unsigned int size, unsigned int unicode); unsigned int msGetGlyphIndex(face_element *face, unsigned int unicode); glyph_element* msGetGlyphByIndex(face_element *face, unsigned int size, unsigned int codepoint); +int msIsGlyphASpace(glyphObj *glyph); #ifdef __cplusplus } diff -Nru mapserver-7.0.7/.github/workflows/check-crlf.yml mapserver-7.6.4/.github/workflows/check-crlf.yml --- mapserver-7.0.7/.github/workflows/check-crlf.yml 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/.github/workflows/check-crlf.yml 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,20 @@ +# check for Windows CRLF in files +# homepage: https://github.com/marketplace/actions/check-crlf + +name: Check CRLF + +on: [push, pull_request] + +jobs: + Check-CRLF: + name: verify that only LF linefeeds are used + runs-on: ubuntu-18.04 + + steps: + - name: Checkout repository contents + uses: actions/checkout@v1 + + - name: Use action to check for CRLF endings + uses: erclu/check-crlf@v1.1.2 + with: # ignore directories containing *.pdf and *.tab + exclude: msautotest/misc/data/ /msautotest/renderers/expected/ \ No newline at end of file diff -Nru mapserver-7.0.7/HISTORY.TXT mapserver-7.6.4/HISTORY.TXT --- mapserver-7.0.7/HISTORY.TXT 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/HISTORY.TXT 2021-07-12 20:16:21.000000000 +0000 @@ -10,7 +10,191 @@ For a complete change history, please see the Git log comments. For more details about recent point releases, please see the online changelog at: -http://mapserver.org/development/changelog/ +https://mapserver.org/development/changelog/ + +7.6.4 release (2021-07-12) +-------------------------- + +- improved performance of GPKG and SpatiaLite queries (#6361) + +- WFS: fix paging with GPKG/Spatialite datasources and non-point geometries (#6325) + +- PostGIS: use ST_Intersects instead of && for bounding box (#6348) + +see detailed changelog for other fixes + +7.6.3 release (2021-04-30) +------------------------- + +- fix security flaw for processing the MAP parameter (#6313) + +- fix code defects through Coverity Scan warnings (#6307) + +- add support for PROJ 8 (#6249) + +see detailed changelog for other fixes + +7.6.2 release (2020-12-07) +------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.6.1 release (2020-07-31) +------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.6.0 release (2020-05-08) +-------------------------- + +- for essential WMS client layers set EXCEPTIONS to XML by default (#6066) + +7.6.0-rc4 release (2020-05-04) +------------------------------ + +- Fix case insensitive 'using unique' for PostGIS connections (#6062) + +- Add handling essential WMS layers (#6061) + +7.6.0-rc3 release (2020-04-24) +------------------------------ + +- Handle special characters in paths on Windows (#5995) + +- Add attribute binding for label ALIGN, OFFSET, POSITION (#6052) + +7.6.0-rc2 release (2020-04-10) +------------------------------ + +- Fix memory corruption in msGEOSGetCentroid (#6041) + +7.6.0-rc1 release (2020-04-05) +------------------------------ + +- Fix alpha value for hex colors (#6023) + +7.6.0-beta2 release (2020-03-28) +-------------------------------- + +- fixed build with PHPNG + gnu_source (#6015) + +- fixed rendermode with geomtransform (#6021) + +7.6.0-beta1 release (2020-03-22) +-------------------------------- + +- Full support for PROJ6 API (#5888) + +- Enable PointZM data support (X,Y,Z,M coordinates) by default + +- SLD support enhancements (RFC 124) except PR#5832 + +- CONNECTIONOPTIONS support in mapfile LAYER (RFC 125) + +- Enforce C99 and C++11 build requirements (RFC 128) + +7.4.4 release (2020-3-20) +------------------------- + +- Security release, see ticket #6014 for more information. + +7.4.3 release (2019-12-16) +-------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.2 release (2019-9-13) +------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.1 release (2019-7-12) +------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.0 release (2019-5-14) +------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.0-rc2 release (2019-5-10) +---------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.0-rc1 release (2019-5-1) +---------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.4.0-beta2 release (2019-4-17) +------------------------------- + +- Addresses XSS issue with [layers] template tag (fix available in 6.4, 7.0 and 7.2 branches as well) + +- Added Perl/Mapscript to Travis CI + +- No other major changes, see detailed changelog for bug fixes + +7.4.0-beta1 release (2019-3-29) +------------------------------- + +- Python MapScript binding is available as installable Wheels with a full test suite and examples + +- C# MapScript binding is now compatible with .NET Core + +- PHP 7 MapScript binding support - both PHP/MapScript and Swig/MapScript + +- Added workaround to allow compiling against Proj 6 (#5766) + +7.2.2 release (2019-2-19) +-------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.2.1 release (2018-10-1) +-------------------------- + +- No major changes, see detailed changelog for bug fixes + +7.2.0 release (2018-07-23) +-------------------------- + +- Fixed issue with ring handling with polygons in MVT support (#5626) + +- No other major changes, see detailed changelog for bug fixes + +7.2.0-beta2 release (2018-6-13) + +- Update beta1 release notes to remove reference to PHP7 support + +- No other major changes, see detailed changelog for bug fixes + +7.2.0-beta1 release (2018-5-9) +-------------------- + +- Support for Enhanced Layer Metadata Management (RFC82) + +- Calculate MINDISTANCE from label bounds instead of label center (#5369) + +- Reposition follow labels on maxoverlapangle colisions (RFC112) + +- Implement chainable compositing filters (RFC113) + +- Faster retrieval of shape count (RFC114) + +- WMS layer groups are now requestable + +- Support C-style multi-line content types (#5362) + +- Python 3.x support (#5561) + +- Support Vendor-Specific OGC FILTER parameter in WMS requests (RFC118) + +- Mapbox Vector Tile (MVT) Support (RFC119) + +- INSPIRE download service support for WCS 2.0 (RFC120) 7.0.0 release (2015/07/24) -------------------------- @@ -1630,7 +1814,7 @@ - Fixed a scalebar rounding problem causing to draw zero scalebar width (#2890) -- SLD: if it conatins a Filer Encoding tag, try to always set the +- SLD: if it contains a Filter Encoding tag, try to always set the layer's FILTER element (#2889) - Add support for rendering INLINE layers with layer attributes (items) (#2870) diff -Nru mapserver-7.0.7/hittest.c mapserver-7.6.4/hittest.c --- mapserver-7.0.7/hittest.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/hittest.c 2021-07-12 20:16:21.000000000 +0000 @@ -172,10 +172,8 @@ /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; -#ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ -#endif } else { searchrect.minx = searchrect.miny = 0; diff -Nru mapserver-7.0.7/INSTALL.CMAKE mapserver-7.6.4/INSTALL.CMAKE --- mapserver-7.0.7/INSTALL.CMAKE 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/INSTALL.CMAKE 2021-07-12 20:16:21.000000000 +0000 @@ -12,9 +12,8 @@ Install CMake ------------- -MapServer requires at least CMake version 2.6.0, although the build process with -such an old version has not been thouroughly tested. 2.8.0 and above are -recommended. +MapServer now requires at least CMake version 3.0, although the CMake process was +first implemented in MapServer 6.4 with CMake 2.6.0. Distro Packaged Version ....................... @@ -147,7 +146,7 @@ - option(WITH_THREAD_SAFETY "Choose if a thread-safe version of libmapserver should be built (only recommended for some mapscripts)" OFF) - option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) - option(WITH_PYTHON "Enable Python mapscript support" OFF) - - option(WITH_PHP "Enable Python mapscript support" OFF) + - option(WITH_PHP "Enable PHP mapscript support" OFF) - option(WITH_PERL "Enable Perl mapscript support" OFF) - option(WITH_RUBY "Enable Ruby mapscript support" OFF) - option(WITH_JAVA "Enable Java mapscript support" OFF) diff -Nru mapserver-7.0.7/kerneldensity.c mapserver-7.6.4/kerneldensity.c --- mapserver-7.0.7/kerneldensity.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/kerneldensity.c 2021-07-12 20:16:21.000000000 +0000 @@ -28,7 +28,6 @@ #include "mapserver.h" #include -#ifdef USE_GDAL #include "gdal.h" #include "cpl_string.h" @@ -84,7 +83,7 @@ int status,layer_idx, i,j, nclasses=0, have_sample=0; rectObj searchrect; shapeObj shape; - layerObj *layer; + layerObj *layer = NULL; float *values = NULL; int radius = 10, im_width = image->width, im_height = image->height; int expand_searchrect=1; @@ -180,11 +179,9 @@ searchrect.maxy = map->height-1; } -#ifdef USE_PROJ layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); if(layer->project) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ -#endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); /* nothing to do */ @@ -199,11 +196,23 @@ double weight = 1.0; if(!values) /* defer allocation until we effectively have a feature */ values = (float*) msSmallCalloc(im_width * im_height, sizeof(float)); -#ifdef USE_PROJ + if(layer->project) - msProjectShape(&layer->projection, &map->projection, &shape); -#endif - + { + if( layer->reprojectorLayerToMap == NULL ) + { + layer->reprojectorLayerToMap = msProjectCreateReprojector( + &layer->projection, &map->projection); + if( layer->reprojectorLayerToMap == NULL ) + { + msFreeShape(&shape); + msLayerClose(layer); + return MS_FAILURE; + } + } + msProjectShapeEx(layer->reprojectorLayerToMap, &shape); + } + /* the weight for the sample is set to 1.0 by default. If the * layer has some classes defined, we will read the weight from * the class->style->size (which can be binded to an attribute) @@ -332,15 +341,6 @@ } return status; } -#else - - -int msComputeKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void **hDSvoid, void **cleanup_ptr) { - msSetError(MS_MISCERR,"msComputeKernelDensityDataset()", "KernelDensity layers require GDAL support, however GDAL support is not compiled in this build"); - return MS_FAILURE; -} - -#endif int msCleanupKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void *cleanup_ptr) { free(cleanup_ptr); diff -Nru mapserver-7.0.7/layerobject.c mapserver-7.6.4/layerobject.c --- mapserver-7.0.7/layerobject.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/layerobject.c 2021-07-12 20:16:21.000000000 +0000 @@ -31,12 +31,6 @@ #include "mapserver.h" -#ifdef USE_GDAL -# include "gdal.h" -# include "cpl_conv.h" -#endif - - /* =========================================================================== msInsertClass diff -Nru mapserver-7.0.7/Makefile mapserver-7.6.4/Makefile --- mapserver-7.0.7/Makefile 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/Makefile 2021-07-12 20:16:21.000000000 +0000 @@ -1,15 +1,17 @@ -AUTOTEST_OPTS=-strict -q +AUTOTEST_OPTS?=--strict_mode PHP_MAPSCRIPT=build/mapscript/php/php_mapscript.so PYTHON_MAPSCRIPT_PATH=build/mapscript/python JAVA_MAPSCRIPT_PATH=build/mapscript/java +CSHARP_MAPSCRIPT_PATH=build/mapscript/csharp +PERL_MAPSCRIPT_PATH=build/mapscript/perl BUILDPATH=../../build FLEX=flex YACC=yacc -CMAKEFLAGS=-DCMAKE_C_FLAGS="--coverage" -DCMAKE_CXX_FLAGS="--coverage" \ +CMAKEFLAGS=-DCMAKE_C_FLAGS="--coverage ${CMAKE_C_FLAGS}" -DCMAKE_CXX_FLAGS="--coverage ${CMAKE_CXX_FLAGS}" \ -DCMAKE_SHARED_LINKER_FLAGS="-lgcov" -DWITH_CLIENT_WMS=1 \ - -DWITH_CLIENT_WFS=1 -DWITH_KML=1 -DWITH_SOS=1 -DWITH_PHP=1 \ + -DWITH_CLIENT_WFS=1 -DWITH_KML=1 -DWITH_SOS=1 -DWITH_CSHARP=1 -DWITH_PHP=1 -DWITH_PERL=1 \ -DWITH_PYTHON=1 -DWITH_JAVA=1 -DWITH_THREAD_SAFETY=1 -DWITH_FRIBIDI=1 -DWITH_FCGI=0 -DWITH_EXEMPI=1 \ - -DCMAKE_BUILD_TYPE=Release -DWITH_RSVG=1 -DWITH_CURL=1 -DWITH_HARFBUZZ=1 -DWITH_POINT_Z_M=1 + -DCMAKE_BUILD_TYPE=Release -DWITH_RSVG=1 -DWITH_CURL=1 -DWITH_HARFBUZZ=1 -DWITH_POINT_Z_M=1 -DWITH_MSSQL2008=ON ${EXTRA_CMAKEFLAGS} all: cmakebuild cmakebuild: lexer parser @@ -20,34 +22,59 @@ $(error "This Makefile is used to run the \"test\" target") wxs-testcase: - cd msautotest/wxs && chmod 777 tmp && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) + cd msautotest/wxs && chmod 777 tmp && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) renderers-testcase: - cd msautotest/renderers && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) + cd msautotest/renderers && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) misc-testcase: - cd msautotest/misc && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) + cd msautotest/misc && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) gdal-testcase: - cd msautotest/gdal && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) + cd msautotest/gdal && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) query-testcase: - cd msautotest/query && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) + cd msautotest/query && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) + +sld-testcase: + cd msautotest/sld && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && (./run_test.py $(AUTOTEST_OPTS) || /bin/true) mspython-testcase: test -f "$(PYTHON_MAPSCRIPT_PATH)/_mapscript.so" && (export PYTHONPATH="../../$(PYTHON_MAPSCRIPT_PATH)" && cd msautotest/mspython && python run_all_tests.py) +mspython-wheel: + cd build && cmake --build . --target pythonmapscript-wheel + php-testcase: test -f "$(PHP_MAPSCRIPT)" && (export PHP_MAPSCRIPT_SO="../../$(PHP_MAPSCRIPT)" && cd msautotest/php && ./run_test.sh) java-testcase: test -d "$(JAVA_MAPSCRIPT_PATH)" && (export JAVA_MAPSCRIPT_SO="../../$(JAVA_MAPSCRIPT_PATH)" && cd mapscript/java && ./run_test.sh) +csharp-testcase: + test -d "$(CSHARP_MAPSCRIPT_PATH)" && (export CSHARP_MAPSCRIPT_SO="../../$(CSHARP_MAPSCRIPT_PATH)" && cd mapscript/csharp && ./run_test.sh) + +perl-testcase: + cd "$(PERL_MAPSCRIPT_PATH)" \ + && PERL5LIB=`pwd` \ + && prove tests \ + && perl examples/RFC24.pl ../../../tests/test.map \ + && perl examples/shp_in_shp.pl --infile1 ../../../tests/line.shp --infile1_shpid 0 --infile2 ../../../tests/polygon.shp --infile2_shpid 0 \ + && perl examples/dump.pl --file ../../../tests/line.shp \ + && perl examples/thin.pl --input ../../../tests/polygon --output examples/junk --tolerance=5 + + + test: cmakebuild - @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase mspython-testcase + @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase sld-testcase mspython-testcase @./print-test-results.sh @$(MAKE) $(MFLAGS) php-testcase + @$(MAKE) $(MFLAGS) csharp-testcase + @$(MAKE) $(MFLAGS) perl-testcase +asan_compatible_tests: cmakebuild + @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase sld-testcase + @./print-test-results.sh lexer: maplexer.c parser: mapparser.c diff -Nru mapserver-7.0.7/Makefile.vc mapserver-7.6.4/Makefile.vc --- mapserver-7.0.7/Makefile.vc 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/Makefile.vc 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -# -# makefile.vc - Main MapServer makefile for MSVC++ -# -# This VC++ makefile will build MAPSERVER.LIB, MAPSERV.EXE, and the other -# MapServer command-line programs. -# -# To use the makefile: -# - Open a DOS prompt window -# - Run the VCVARS32.BAT script to initialize the VC++ environment variables -# - Start the build with: nmake /f makefile.vc -# -# $Id$ -# -MAPSERVER_ROOT = . - -!INCLUDE nmake.opt - -BASE_CFLAGS = $(OPTFLAGS) - -CFLAGS=$(BASE_CFLAGS) $(MS_CFLAGS) -CC= cl -LINK= link - -# -# Main MapServer library. -# -MS_DLL = libmap.dll - -MS_OBJS = mapbits.obj maphash.obj mapshape.obj mapxbase.obj \ - mapparser.obj maplexer.obj maptree.obj \ - mapsearch.obj mapstring.obj mapsymbol.obj mapfile.obj \ - maplegend.obj maputil.obj mapscale.obj mapquery.obj \ - maplabel.obj maperror.obj mapprimitive.obj mapproject.obj\ - mapraster.obj cgiutil.obj mapsde.obj mapogr.obj maptime.obj \ - maptemplate.obj mappostgis.obj maplayer.obj mapresample.obj \ - mapwms.obj mapwmslayer.obj mapgml.obj maporaclespatial.obj \ - mapprojhack.obj mapdraw.obj mapgd.obj mapoutput.obj \ - mapgdal.obj mapwfs.obj mapwfs11.obj mapwfslayer.obj mapows.obj maphttp.obj \ - mapcontext.obj mapdrawgdal.obj mapjoin.obj mapgraticule.obj \ - mapimagemap.obj mapcopy.obj maprasterquery.obj \ - mapogcfilter.obj mapogcsld.obj mapthread.obj mapobject.obj \ - classobject.obj layerobject.obj mapwcs.obj mapwcs11.obj mapwcs20.obj \ - mapgeos.obj strptime.obj mapogroutput.obj \ - mapcpl.obj mapio.obj mappool.obj mapregex.obj mappluginlayer.obj \ - mapogcsos.obj mappostgresql.obj mapcrypto.obj mapowscommon.obj \ - maplibxml2.obj mapdebug.obj mapchart.obj mapagg.obj maptclutf.obj \ - maprendering.obj mapimageio.obj mapcairo.obj \ - mapoglrenderer.obj mapoglcontext.obj mapogl.obj \ - maptile.obj $(EPPL_OBJ) $(REGEX_OBJ) mapgeomtransform.obj mapunion.obj \ - mapkmlrenderer.obj mapkml.obj mapdummyrenderer.obj mapgeomutil.obj mapquantization.obj \ - mapogcfiltercommon.obj mapcluster.obj mapuvraster.obj mapcontour.obj mapsmoothing.obj mapservutil.obj hittest.obj $(AGG_OBJ) - -MS_HDRS = mapserver.h mapfile.h - -MS_EXE = mapserv.exe \ - shp2img.exe legend.exe \ - shptree.exe scalebar.exe sortshp.exe tile4ms.exe \ - shptreevis.exe msencrypt.exe - -# -# -# -default: all - -all: $(MS_LIB) $(MS_EXE) mapscriptvars - -$(MS_OBJS): $(MS_HDRS) - -$(MS_DLL) $(MS_LIB_DLL): $(MS_LIB) - link /dll $(LDEBUG) \ - $(MS_OBJS) $(EXTERNAL_LIBS) \ - /out:$(MS_DLL) /implib:$(MS_LIB_DLL) - if exist $(MS_DLL).manifest mt -manifest $(MS_DLL).manifest -outputresource:$(MS_DLL);2 - -$(MS_LIB): $(MS_OBJS) - if exist $(GDAL_DIR)\gdal.pdb copy $(GDAL_DIR)\gdal.pdb . - lib /out:$(MS_LIB) $(MS_OBJS) - -!IFDEF DLLBUILD -$(MS_EXE): $(MS_DLL) $(MS_LIB_DLL) -!ELSE -$(MS_EXE): $(MS_LIB) -!ENDIF - -gd:: - cd gd-1.2 - nmake /f makefile.nt OPTFLAGS="$(OPTFLAGS)" - cd .. - -.c.obj: - $(CC) $(CFLAGS) /c $*.c /Fo$*.obj - -.cpp.obj: - $(CC) $(CFLAGS) /c $*.cpp /Fo$*.obj - -.c.exe: - $(CC) $(CFLAGS) /c $*.c /Fo$*.obj -!IFDEF DLLBUILD - $(LINK) $(LDEBUG) $(LDFLAGS) $*.obj $(LIBS_DLL) -!ELSE - $(LINK) $(LDEBUG) $(LDFLAGS) $*.obj $(LIBS) -!ENDIF - if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 - -clean: - del *.obj - del $(REGEX_OBJ) - del $(AGG_OBJ) - del *.lib - del *.dll - del $(MS_EXE) - del *.pdb - del *.exp - del *.ilk - del *.manifest - del renderers\agg\*.obj -!IFDEF DOT_NET - cd mapscript\csharp - nmake /f makefile.vc clean - cd ..\.. -!ENDIF -!IFDEF JAVA_HOME - cd mapscript\java - nmake /f makefile.vc clean - cd ..\.. -!ENDIF -!IFDEF PHP_HOME - cd mapscript\php - nmake /f makefile.vc clean - cd ..\.. -!ENDIF -!IFDEF PYTHON_HOME - cd mapscript\python - -del mapscript_wrap.c - -rmdir /s /q build - cd ..\.. -!ENDIF - - -mapscriptvars: makefile.vc nmake.opt - -del mapscriptvars - echo $(MS_CURRENT) > mapscriptvars -!IFDEF WIN64 - echo $(MS_DEFS) -DWIN32 -D_WIN32 -DUSE_GENERIC_MS_NINT >> mapscriptvars -!ELSE - echo $(MS_DEFS) -DWIN32 -D_WIN32 >> mapscriptvars -!ENDIF - echo $(INCLUDES) >> mapscriptvars - echo $(LIBS_DLL) >> mapscriptvars - echo $(LIBS) >> mapscriptvars - findstr MS_VERSION mapserver-version.h | findstr define >> mapscriptvars - -#install: $(MS_DLL) $(MS_EXE) python csharp java php -install: $(MS_DLL) $(MS_EXE) - -mkdir $(BINDIR) - xcopy /y /r /d /f $(MS_DLL) $(BINDIR) - copy *.exe $(BINDIR) -!IFDEF PYTHON_HOME - -mkdir $(BINDIR)\mapscript\python - xcopy /y /r /d /f .\mapscript\python\dist\*.zip $(BINDIR)\mapscript\python -!ENDIF -!IFDEF DOT_NET - -mkdir $(BINDIR)\mapscript\csharp - xcopy /y /r /d /f .\mapscript\csharp\*.dll $(BINDIR)\mapscript\csharp - xcopy /y /r /d /f .\mapscript\csharp\*.exe $(BINDIR)\mapscript\csharp - xcopy /y /r /d /f .\mapscript\csharp\*.manifest $(BINDIR)\mapscript\csharp - xcopy /y /r /d /f .\mapscript\csharp\*.config $(BINDIR)\mapscript\csharp -!ENDIF -!IFDEF JAVA_HOME - -mkdir $(BINDIR)\mapscript\java - xcopy /y /r /d /f .\mapscript\java\*.dll $(BINDIR)\mapscript\java - xcopy /y /r /d /f .\mapscript\java\*.jar $(BINDIR)\mapscript\java -!ENDIF -!IFDEF PHP_HOME - -mkdir $(BINDIR)\mapscript\php - xcopy /y /r /d /f .\mapscript\php\*.dll $(BINDIR)\mapscript\php -!ENDIF - -!IFDEF PYTHON_HOME -python: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) - cd mapscript\python - $(SWIG) -python -shadow -o mapscript_wrap.c ../mapscript.i - $(PYTHON_HOME)\PCBuild\python.exe setup.py bdist - cd ..\.. -!ELSE -python: -!ENDIF - -!IFDEF DOT_NET -csharp: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) - cd mapscript\csharp - nmake /f makefile.vc - cd ..\.. -!ELSE -csharp: -!ENDIF - -!IFDEF JAVA_HOME -java: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) - cd mapscript\java - nmake /f makefile.vc - cd ..\.. -!ELSE -java: -!ENDIF - -!IFDEF PHP_HOME -php: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) - cd mapscript\php - nmake /f makefile.vc - cd ..\.. -!ELSE -php: -!ENDIF - -!IF DEFINED(SDE_OPT) || DEFINED(ORACLE) || DEFINED(MSSQL2008) - -!IFDEF ORACLE -ORACLE_LIB=$(ORACLE_DIR)/lib/msvc/oci.lib -!ENDIF - -!IFDEF SDE_OPT -!IF $(SDE_VERSION) >= 92 -SDE_LIB = $(SDE_DIR)\lib\pe.lib \ - $(SDE_DIR)\lib\sde.lib \ - $(SDE_DIR)\lib\sg.lib -!ELSE -SDE_LIB = $(SDE_DIR)\lib\pe$(SDE_VERSION).lib \ - $(SDE_DIR)\lib\sde$(SDE_VERSION).lib \ - $(SDE_DIR)\lib\sg$(SDE_VERSION).lib -!ENDIF -!ENDIF -!ENDIF - -plugins: - -del mapsde.obj - -del maporaclespatial.obj - -del mapmssql2008.obj - -!IFDEF SDE_OPT - $(CC) $(CFLAGS) -DUSE_SDE /c mapsde.c /Fomapsde.obj - link /dll $(LDEBUG) /out:msplugin_sde_$(SDE_VERSION).dll mapsde.obj mapthread.obj mapserver_i.lib $(SDE_LIB) - if exist msplugin_sde_$(SDE_VERSION).dll.manifest mt -manifest msplugin_sde_$(SDE_VERSION).dll.manifest -outputresource:msplugin_sde_$(SDE_VERSION).dll;2 - -del mapsde.obj -!ENDIF -!IFDEF ORACLE - $(CC) $(CFLAGS) -DUSE_ORACLESPATIAL /c maporaclespatial.c /Fomaporaclespatial.obj - link /dll $(LDEBUG) /out:msplugin_oracle.dll maporaclespatial.obj $(ORACLE_LIB) mapserver_i.lib - if exist msplugin_oracle.dll.manifest mt -manifest msplugin_oracle.dll.manifest -outputresource:msplugin_oracle.dll;2 - -del maporaclespatial.obj -!ENDIF -!IFDEF MSSQL2008 - $(CC) $(CFLAGS) $(ODBC_INC) -DUSE_MSSQL2008 -DUSE_MSSQL2008_PLUGIN /c mapmssql2008.c /Fomapmssql2008.obj - link /dll $(LDEBUG) /out:msplugin_mssql2008.dll mapmssql2008.obj $(ODBC_LIBS) mapserver_i.lib - if exist msplugin_mssql2008.dll.manifest mt -manifest msplugin_mssql2008.dll.manifest -outputresource:msplugin_mssql2008.dll;2 - -del mapmssql2008.obj -!ENDIF diff -Nru mapserver-7.0.7/mapagg.cpp mapserver-7.6.4/mapagg.cpp --- mapserver-7.0.7/mapagg.cpp 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapagg.cpp 2021-07-12 20:16:21.000000000 +0000 @@ -560,7 +560,7 @@ return MS_SUCCESS; } -int agg2RenderGlyphsPath(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { +int agg2RenderGlyphsPath(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow, int isMarker) { mapserver::path_storage glyphs; mapserver::trans_affine trans; AGG2Renderer *r = AGG_RENDERER(img); @@ -1333,15 +1333,10 @@ #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); +void msApplyBlurringCompositingFilter(rasterBufferObj *rb, unsigned int radius) { + rendering_buffer b(rb->data.rgba.pixels, rb->width, rb->height, rb->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) diff -Nru mapserver-7.0.7/mapaxisorder.h mapserver-7.6.4/mapaxisorder.h --- mapserver-7.0.7/mapaxisorder.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapaxisorder.h 2021-07-12 20:16:21.000000000 +0000 @@ -524,8 +524,8 @@ 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -724,7 +724,7 @@ 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, @@ -740,7 +740,7 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -762,14 +762,14 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, - 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, - 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -779,11 +779,11 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -805,10 +805,10 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -825,12 +825,12 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -868,13 +868,13 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -901,8 +901,8 @@ 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -921,12 +921,15 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -955,9 +958,13 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -987,6 +994,10 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1000,13 +1011,24 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1020,10 +1042,12 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1041,6 +1065,10 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1052,11 +1080,20 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1067,6 +1104,8 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1083,6 +1122,7 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1099,16 +1139,38 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -1117,69 +1179,7 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -2773,7 +2773,7 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -3473,7 +3473,7 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -3945,12 +3945,11 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, + 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, @@ -3970,7 +3969,8 @@ 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, - 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, + 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, + 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, diff -Nru mapserver-7.0.7/mapcairo.c mapserver-7.6.4/mapcairo.c --- mapserver-7.0.7/mapcairo.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapcairo.c 2021-07-12 20:16:21.000000000 +0000 @@ -34,6 +34,7 @@ #if defined(_WIN32) && !defined(__CYGWIN__) #include #include +#include #else #include #include @@ -54,10 +55,8 @@ #endif #endif -#ifdef USE_GDAL #include #include -#endif #include "fontcache.h" @@ -408,7 +407,7 @@ return MS_SUCCESS; } -int renderGlyphs2Cairo(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { +int renderGlyphs2Cairo(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow, int isMarker) { cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); cairoFaceCache *cairo_face = NULL; @@ -536,9 +535,6 @@ static void msTransformToGeospatialPDF(imageObj *img, mapObj *map, cairo_renderer *r) { - /* We need a GDAL 1.10 PDF driver at runtime, but as far as the C API is concerned, GDAL 1.9 is */ - /* largely sufficient. */ -#if defined(USE_GDAL) && defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900 GDALDatasetH hDS = NULL; const char* pszGEO_ENCODING = NULL; GDALDriverH hPDFDriver = NULL; @@ -645,7 +641,6 @@ VSIUnlink(pszTmpFilename); msFree(pszTmpFilename); -#endif } int saveImageCairo(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) @@ -1017,6 +1012,7 @@ struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; + int status; if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; @@ -1084,10 +1080,9 @@ pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; - if(MS_SUCCESS != MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle)) - return MS_FAILURE; + status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); - return MS_SUCCESS; + return status; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); diff -Nru mapserver-7.0.7/mapchart.c mapserver-7.6.4/mapchart.c --- mapserver-7.0.7/mapchart.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapchart.c 2021-07-12 20:16:21.000000000 +0000 @@ -249,10 +249,20 @@ int c; status = msLayerNextShape(layer, shape); if(status == MS_SUCCESS) { -#ifdef USE_PROJ + if(layer->project) - msProjectShape(&layer->projection, &map->projection, shape); -#endif + { + if( layer->reprojectorLayerToMap == NULL ) + { + layer->reprojectorLayerToMap = msProjectCreateReprojector( + &layer->projection, &map->projection); + if( layer->reprojectorLayerToMap == NULL ) + { + return MS_FAILURE; + } + } + msProjectShapeEx(layer->reprojectorLayerToMap, shape); + } if(msBindLayerToShape(layer, shape, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS) != MS_SUCCESS) return MS_FAILURE; /* error message is set in msBindLayerToShape() */ @@ -340,7 +350,7 @@ int status=MS_SUCCESS; const char *chartRangeProcessingKey=NULL; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); - double diameter, mindiameter=-1, maxdiameter, minvalue, maxvalue, exponent=0; + double diameter=0, mindiameter=-1, maxdiameter=0, minvalue=0, maxvalue=0, exponent=0; double *values; styleObj **styles; pointObj center; @@ -361,9 +371,9 @@ return MS_FAILURE; } } -#ifdef USE_PROJ + layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); -#endif + /* step through the target shapes */ msInitShape(&shape); @@ -497,7 +507,7 @@ double *values; styleObj **styles; pointObj center; - double barMaxVal,barMinVal; + double barMaxVal = 0.0,barMinVal = 0.0; int numvalues = layer->numclasses; int numvalues_for_shape; if(chartSizeProcessingKey==NULL) { @@ -620,10 +630,8 @@ searchrect.maxy = map->height-1; } -#ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ -#endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ diff -Nru mapserver-7.0.7/mapcluster.c mapserver-7.6.4/mapcluster.c --- mapserver-7.0.7/mapcluster.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapcluster.c 2021-07-12 20:16:21.000000000 +0000 @@ -64,6 +64,10 @@ #define SPLITRATIO 0.55 #define TREE_MAX_DEPTH 10 +/* cluster algorithm */ +#define MSCLUSTER_ALGORITHM_FULL 0 +#define MSCLUSTER_ALGORITHM_SIMPLE 1 + /* cluster data */ struct cluster_info { double x; /* x position of the current point */ @@ -135,6 +139,8 @@ clusterCompareRegionFunc fnCompare; /* diagnostics */ int depth; + /* processing algorithm */ + int algorithm; }; @@ -438,6 +444,50 @@ } } +/* traverse the quadtree to find the neighbouring clusters and update data on the cluster*/ +static void findRelatedShapes2(msClusterLayerInfo* layerinfo, + clusterTreeNode *node, clusterInfo* current) +{ + int i; + clusterInfo* s; + + /* -------------------------------------------------------------------- */ + /* Does this node overlap the area of interest at all? If not, */ + /* return without adding to the list at all. */ + /* -------------------------------------------------------------------- */ + if(!msRectOverlap(&node->rect, ¤t->bounds)) + return; + + /* Modify the feature count of the related shapes */ + s = node->shapes; + while (s) { + if (layerinfo->fnCompare(s, current)) { + if (layerinfo->rank > 0) { + double r = (current->x - s->x) * (current->x - s->x) + (current->y - s->y) * (current->y - s->y); + if (r < layerinfo->rank) { + layerinfo->current = s; + layerinfo->rank = r; + } + } + else { + /* no rank was specified, return immediately */ + layerinfo->current = s; + return; + } + } + s = s->next; + } + + if (node->subnode[0] == NULL) + return; + + /* Recurse to subnodes if they exist */ + for (i = 0; i < 4; i++) { + if (node->subnode[i]) + findRelatedShapes2(layerinfo, node->subnode[i], current); + } +} + /* traverse the quadtree to find the neighbouring shapes and update some data on the related shapes (when removing a feature) */ static void findRelatedShapesRemove(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) @@ -773,6 +823,72 @@ && !node->subnode[2] && !node->subnode[3]); } +/* collecting the cluster shapes, returns true if this subnode must be removed */ +static int collectClusterShapes2(layerObj* layer, msClusterLayerInfo* layerinfo, clusterTreeNode *node) +{ + int i; + clusterInfo* current = NULL; + clusterInfo* s; + + while (node->shapes) { + s = node->shapes; + /* removing from the list */ + node->shapes = s->next; + + InitShapeAttributes(layer, s); + + if (s->filter) { + s->next = layerinfo->finalized; + layerinfo->finalized = s; + ++layerinfo->numFinalized; + } else { + /* this shape is filtered */ + s->next = layerinfo->filtered; + layerinfo->filtered = s; + ++layerinfo->numFiltered; + } + + /* update the parameters of the related shapes if any */ + if (s->siblings) { + current = s->siblings; + while(current) { + UpdateShapeAttributes(layer, s, current); + + /* setting the average position to the cluster position */ + current->avgx = s->x; + current->avgy = s->y; + + if (current->next == NULL) { + if (layerinfo->get_all_shapes == MS_TRUE) { + /* insert the siblings into the finalization list */ + current->next = layerinfo->finalized; + layerinfo->finalized = s->siblings; + s->siblings = NULL; + } + break; + } + + current = current->next; + } + } + } + + /* Recurse to subnodes if they exist */ + for (i = 0; i < 4; i++) { + if (node->subnode[i] && collectClusterShapes2(layer, layerinfo, node->subnode[i])) { + /* placing this empty node to the finalization queue */ + node->subnode[i]->subnode[0] = layerinfo->finalizedNodes; + layerinfo->finalizedNodes = node->subnode[i]; + node->subnode[i] = NULL; + ++layerinfo->numFinalizedNodes; + } + } + + /* returns true is this subnode must be removed */ + return (!node->shapes && !node->subnode[0] && !node->subnode[1] + && !node->subnode[2] && !node->subnode[3]); +} + int selectClusterShape(layerObj* layer, long shapeindex) { int i; @@ -881,9 +997,11 @@ int status; clusterInfo* current; int depth; + char *pszProcessing; #ifdef USE_CLUSTER_EXTERNAL int layerIndex; #endif + reprojectionObj* reprojector = NULL; msClusterLayerInfo* layerinfo = layer->layerinfo; @@ -904,17 +1022,24 @@ layerinfo->current = layerinfo->finalized; /* restart */ + /* check whether the simplified algorithm was selected */ + pszProcessing = msLayerGetProcessingKey(layer, "CLUSTER_ALGORITHM"); + if(pszProcessing && !strncasecmp(pszProcessing,"SIMPLE",6)) + layerinfo->algorithm = MSCLUSTER_ALGORITHM_SIMPLE; + else + layerinfo->algorithm = MSCLUSTER_ALGORITHM_FULL; + /* check whether all shapes should be returned from a query */ if(msLayerGetProcessingKey(layer, "CLUSTER_GET_ALL_SHAPES") != NULL) layerinfo->get_all_shapes = MS_TRUE; else layerinfo->get_all_shapes = MS_FALSE; - /* check whether the location of the shapes should be preserved (no averaging) */ + /* check whether the location of the shapes should be preserved */ if(msLayerGetProcessingKey(layer, "CLUSTER_KEEP_LOCATIONS") != NULL) layerinfo->keep_locations = MS_TRUE; else - layerinfo->keep_locations = MS_FALSE; + layerinfo->keep_locations = MS_FALSE; /* check whether the maxdistance and the buffer parameters are specified in map units (scale independent clustering) */ @@ -946,10 +1071,8 @@ layerinfo->searchRect = searchrect; /* reproject the rectangle to layer coordinates */ -#ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ -#endif /* determine the compare method */ layerinfo->fnCompare = CompareRectangleRegion; @@ -1009,11 +1132,18 @@ if ((current = clusterInfoCreate(layerinfo)) == NULL) return MS_FAILURE; +#if defined(USE_CLUSTER_EXTERNAL) + if(srcLayer->transform == MS_TRUE && srcLayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srcLayer->projection), &(layer->projection))) + { + reprojector = msProjectCreateReprojector(&srcLayer->projection, &layer->projection); + } +#endif + while((status = msLayerNextShape(srcLayer, ¤t->shape)) == MS_SUCCESS) { -#if defined(USE_PROJ) && defined(USE_CLUSTER_EXTERNAL) +#if defined(USE_CLUSTER_EXTERNAL) /* transform the shape to the projection of this layer */ - if(srcLayer->transform == MS_TRUE && srcLayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srcLayer->projection), &(layer->projection))) - msProjectShape(&srcLayer->projection, &layer->projection, ¤t->shape); + if( reprojector ) + msProjectShapeEx(reprojector, ¤t->shape); #endif /* set up positions and variance */ current->avgx = current->x = current->shape.bounds.minx; @@ -1042,138 +1172,193 @@ if (layer->cluster.group.string) current->group = msClusterGetGroupText(&layer->cluster.group, ¤t->shape); - /*start a query for the related shapes */ - findRelatedShapes(layerinfo, layerinfo->root, current); - - /* add this shape to the tree */ - if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { - clusterInfoDestroyList(layerinfo, current); - return MS_FAILURE; + if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_FULL) { + /*start a query for the related shapes */ + findRelatedShapes(layerinfo, layerinfo->root, current); + + /* add this shape to the tree */ + if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { + clusterInfoDestroyList(layerinfo, current); + msProjectDestroyReprojector(reprojector); + return MS_FAILURE; + } + } + else if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_SIMPLE) { + /* find a related cluster and try to assign */ + layerinfo->rank = 0; + layerinfo->current = NULL; + findRelatedShapes2(layerinfo, layerinfo->root, current); + if (layerinfo->current) { + /* store these points until all clusters are created */ + current->next = layerinfo->finalizedSiblings; + layerinfo->finalizedSiblings = current; + } + else { + /* if not found add this shape as a new cluster */ + if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { + clusterInfoDestroyList(layerinfo, current); + msProjectDestroyReprojector(reprojector); + return MS_FAILURE; + } + } } if ((current = clusterInfoCreate(layerinfo)) == NULL) { clusterInfoDestroyList(layerinfo, current); + msProjectDestroyReprojector(reprojector); return MS_FAILURE; } } + msProjectDestroyReprojector(reprojector); + clusterInfoDestroyList(layerinfo, current); - while (layerinfo->root) { + if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_FULL) { + while (layerinfo->root) { #ifdef TESTCOUNT - int n; - double avgx, avgy; + int n; + double avgx, avgy; #endif - /* pick up the best cluster from the tree and do the finalization */ - /* the initial rank must be big enough */ - layerinfo->rank = (searchrect.maxx - searchrect.minx) * (searchrect.maxx - searchrect.minx) + - (searchrect.maxy - searchrect.miny) * (searchrect.maxy - searchrect.miny) + 1; - - layerinfo->current = NULL; - findBestCluster(layer, layerinfo, layerinfo->root); - - if (layerinfo->current == NULL) { - if (layer->debug >= MS_DEBUGLEVEL_VVV) - msDebug("Clustering terminated.\n"); - break; /* completed */ - } - - /* Update the feature count of the shape */ - InitShapeAttributes(layer, layerinfo->current); + /* pick up the best cluster from the tree and do the finalization */ + /* the initial rank must be big enough */ + layerinfo->rank = (searchrect.maxx - searchrect.minx) * (searchrect.maxx - searchrect.minx) + + (searchrect.maxy - searchrect.miny) * (searchrect.maxy - searchrect.miny) + 1; + + layerinfo->current = NULL; + findBestCluster(layer, layerinfo, layerinfo->root); + + if (layerinfo->current == NULL) { + if (layer->debug >= MS_DEBUGLEVEL_VVV) + msDebug("Clustering terminated.\n"); + break; /* completed */ + } - /* collecting the shapes of the cluster */ - collectClusterShapes(layerinfo, layerinfo->root, layerinfo->current); + /* Update the feature count of the shape */ + InitShapeAttributes(layer, layerinfo->current); + + /* collecting the shapes of the cluster */ + collectClusterShapes(layerinfo, layerinfo->root, layerinfo->current); - if (layer->debug >= MS_DEBUGLEVEL_VVV) { - msDebug("processing cluster %p: rank=%lf fcount=%d ncoll=%d nfin=%d nfins=%d nflt=%d bounds={%lf %lf %lf %lf}\n", layerinfo->current, layerinfo->rank, layerinfo->current->numsiblings + 1, + if (layer->debug >= MS_DEBUGLEVEL_VVV) { + msDebug("processing cluster %p: rank=%lf fcount=%d ncoll=%d nfin=%d nfins=%d nflt=%d bounds={%lf %lf %lf %lf}\n", layerinfo->current, layerinfo->rank, layerinfo->current->numsiblings + 1, layerinfo->current->numcollected, layerinfo->numFinalized, layerinfo->numFinalizedSiblings, layerinfo->numFiltered, layerinfo->current->bounds.minx, layerinfo->current->bounds.miny, layerinfo->current->bounds.maxx, layerinfo->current->bounds.maxy); - if (layerinfo->current->node) { - char pszBuffer[TREE_MAX_DEPTH + 1]; - clusterTreeNode* node = layerinfo->current->node; - int position = node->position; - int i = 1; - while (position > 0 && i <= TREE_MAX_DEPTH) { - pszBuffer[TREE_MAX_DEPTH - i] = '0' + (position % 4); - position = position >> 2; - ++i; - } - pszBuffer[TREE_MAX_DEPTH] = 0; - - msDebug(" ->node %p: count=%d index=%d pos=%s subn={%p %p %p %p} rect={%lf %lf %lf %lf}\n", - node, node->numshapes, node->index, pszBuffer + TREE_MAX_DEPTH - i + 1, - node->subnode[0], node->subnode[1], node->subnode[2], node->subnode[3], + if (layerinfo->current->node) { + char pszBuffer[TREE_MAX_DEPTH + 1]; + clusterTreeNode* node = layerinfo->current->node; + int position = node->position; + int i = 1; + while (position > 0 && i <= TREE_MAX_DEPTH) { + pszBuffer[TREE_MAX_DEPTH - i] = '0' + (position % 4); + position = position >> 2; + ++i; + } + pszBuffer[TREE_MAX_DEPTH] = 0; + + msDebug(" ->node %p: count=%d index=%d pos=%s subn={%p %p %p %p} rect={%lf %lf %lf %lf}\n", + node, node->numshapes, node->index, pszBuffer + TREE_MAX_DEPTH - i + 1, + node->subnode[0], node->subnode[1], node->subnode[2], node->subnode[3], node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); + } } - } #ifdef TESTCOUNT - avgx = layerinfo->current->x; - avgy = layerinfo->current->y; - n = 0; + avgx = layerinfo->current->x; + avgy = layerinfo->current->y; + n = 0; #endif - if (layerinfo->current->numsiblings > 0) { - /* update the parameters due to the shape removal */ - findRelatedShapesRemove(layerinfo, layerinfo->root, layerinfo->current); - - if (layerinfo->current->filter == 0) { - /* filtered shapes has no siblings */ - layerinfo->current->numsiblings = 0; - layerinfo->current->avgx = layerinfo->current->x; - layerinfo->current->avgy = layerinfo->current->y; - } + if (layerinfo->current->numsiblings > 0) { + /* update the parameters due to the shape removal */ + findRelatedShapesRemove(layerinfo, layerinfo->root, layerinfo->current); + + if (layerinfo->current->filter == 0) { + /* filtered shapes has no siblings */ + layerinfo->current->numsiblings = 0; + layerinfo->current->avgx = layerinfo->current->x; + layerinfo->current->avgy = layerinfo->current->y; + } - /* update the parameters of the related shapes if any */ - if (layerinfo->finalizedSiblings) { - current = layerinfo->finalizedSiblings; - while(current) { - /* update the parameters due to the shape removal */ - findRelatedShapesRemove(layerinfo, layerinfo->root, current); - UpdateShapeAttributes(layer, layerinfo->current, current); + /* update the parameters of the related shapes if any */ + if (layerinfo->finalizedSiblings) { + current = layerinfo->finalizedSiblings; + while(current) { + /* update the parameters due to the shape removal */ + findRelatedShapesRemove(layerinfo, layerinfo->root, current); + UpdateShapeAttributes(layer, layerinfo->current, current); #ifdef TESTCOUNT - avgx += current->x; - avgy += current->y; - ++n; + avgx += current->x; + avgy += current->y; + ++n; #endif - /* setting the average position to the same value */ - current->avgx = layerinfo->current->avgx; - current->avgy = layerinfo->current->avgy; - - if (current->next == NULL) { - if (layerinfo->get_all_shapes == MS_TRUE) { - /* insert the siblings into the finalization list */ - current->next = layerinfo->finalized; - layerinfo->finalized = layerinfo->finalizedSiblings; - } else { + /* setting the average position to the same value */ + current->avgx = layerinfo->current->avgx; + current->avgy = layerinfo->current->avgy; + + if (current->next == NULL) { + if (layerinfo->get_all_shapes == MS_TRUE) { + /* insert the siblings into the finalization list */ + current->next = layerinfo->finalized; + layerinfo->finalized = layerinfo->finalizedSiblings; + } else { /* preserve the clustered siblings for later use */ - layerinfo->current->siblings = layerinfo->finalizedSiblings; + layerinfo->current->siblings = layerinfo->finalizedSiblings; + } + break; } - break; + + current = current->next; } - current = current->next; + layerinfo->finalizedSiblings = NULL; } - - layerinfo->finalizedSiblings = NULL; } - } #ifdef TESTCOUNT - avgx /= (n + 1); - avgy /= (n + 1); + avgx /= (n + 1); + avgy /= (n + 1); - if (layerinfo->current->numsiblings != n) - layerinfo->current->numsiblings = n; + if (layerinfo->current->numsiblings != n) + layerinfo->current->numsiblings = n; - if (fabs(layerinfo->current->avgx - avgx) / avgx > 0.000000001 || - fabs(layerinfo->current->avgy - avgy) / avgy > 0.000000001) { - layerinfo->current->avgx = avgx; - layerinfo->current->avgy = avgy; - } + if (fabs(layerinfo->current->avgx - avgx) / avgx > 0.000000001 || + fabs(layerinfo->current->avgy - avgy) / avgy > 0.000000001) { + layerinfo->current->avgx = avgx; + layerinfo->current->avgy = avgy; + } #endif + } + } + else if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_SIMPLE) { + /* assingn stired points to clusters */ + while (layerinfo->finalizedSiblings) { + current = layerinfo->finalizedSiblings; + layerinfo->rank = maxDistanceX * maxDistanceX + maxDistanceY * maxDistanceY; + layerinfo->current = NULL; + findRelatedShapes2(layerinfo, layerinfo->root, current); + if (layerinfo->current) { + clusterInfo* s = layerinfo->current; + /* found a matching cluster */ + ++s->numsiblings; + /* assign to cluster */ + layerinfo->finalizedSiblings = current->next; + current->next = s->siblings; + s->siblings = current; + } + else { + /* this appears to be a bug */ + layerinfo->finalizedSiblings = current->next; + current->next = layerinfo->filtered; + layerinfo->filtered = current; + ++layerinfo->numFiltered; + } + } + + /* collecting the shapes of the cluster */ + collectClusterShapes2(layer, layerinfo, layerinfo->root); } /* set the pointer to the first shape */ @@ -1560,6 +1745,7 @@ vtable->LayerWhichShapes = msClusterLayerWhichShapes; vtable->LayerNextShape = msClusterLayerNextShape; vtable->LayerGetShape = msClusterLayerGetShape; + /* layer->vtable->LayerGetShapeCount, use default */ vtable->LayerClose = msClusterLayerClose; diff -Nru mapserver-7.0.7/mapcompositingfilter.c mapserver-7.6.4/mapcompositingfilter.c --- mapserver-7.0.7/mapcompositingfilter.c 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/mapcompositingfilter.c 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * Project: MapServer + * Purpose: RFC 113 Layer compositing + * Author: Thomas Bonfort and the MapServer team. + * + ****************************************************************************** + * Copyright (c) 1996-2015 Regents of the University of Minnesota. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of this Software or works derived from this Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ +#include "mapserver.h" +#include +#define pixmove(rb,srcx,srcy,dstx,dsty) \ + memcpy(rb->data.rgba.pixels+dsty*rb->data.rgba.row_step+dstx*4,\ + rb->data.rgba.pixels+srcy*rb->data.rgba.row_step+srcx*4,\ + 4) +#define pixerase(rb,x,y) memset(rb->data.rgba.pixels+y*rb->data.rgba.row_step+x*4,0,4) + +void msApplyTranslationCompositingFilter(rasterBufferObj *rb, int xtrans, int ytrans) { + int src_sx,src_sy,dst_sx,dst_sy,x,y,dst_x,dst_y; + if(abs(xtrans)>=rb->width || abs(ytrans)>=rb->height) { + for(y = 0; yheight; y++) + for(x = 0; xwidth; x++) + pixerase(rb,x,y); + } + if(xtrans == 0 && ytrans == 0) + return; + if(xtrans>=0) { + if(ytrans>=0) { + src_sx = rb->width - xtrans - 1; + src_sy = rb->height - ytrans - 1; + dst_sx = rb->width - 1; + dst_sy = rb->height -1; + for(y = src_sy,dst_y= dst_sy;y>=0;y--,dst_y--) { + for(x = src_sx,dst_x= dst_sx;x>=0;x--,dst_x--) { + pixmove(rb,x,y,dst_x,dst_y); + } + } + for(y=0;ywidth;x++) + pixerase(rb,x,y); + for(y=ytrans;yheight;y++) + for(x=0;xwidth - xtrans - 1; + src_sy = - ytrans; + dst_sx = rb->width - 1; + dst_sy = 0; + for(y = src_sy,dst_y= dst_sy;yheight;y++,dst_y++) { + for(x = src_sx,dst_x= dst_sx;x>=0;x--,dst_x--) { + pixmove(rb,x,y,dst_x,dst_y); + } + } + for(y=0;yheight+ytrans;y++) + for(x=0;xheight+ytrans;yheight;y++) + for(x=0;xwidth;x++) + pixerase(rb,x,y); + } + } else { + if(ytrans>=0) { + src_sx = - xtrans; + src_sy = rb->height - ytrans - 1; + dst_sx = 0; + dst_sy = rb->height -1; + for(y = src_sy,dst_y= dst_sy;y>=0;y--,dst_y--) { + for(x = src_sx,dst_x= dst_sx;xwidth;x++,dst_x++) { + pixmove(rb,x,y,dst_x,dst_y); + } + } + for(y=0;ywidth;x++) + pixerase(rb,x,y); + for(y=ytrans;yheight;y++) + for(x=rb->width+xtrans;xwidth;x++) + pixerase(rb,x,y); + } else { + src_sx = - xtrans; + src_sy = - ytrans; + dst_sx = 0; + dst_sy = 0; + for(y = src_sy,dst_y= dst_sy;yheight;y++,dst_y++) { + for(x = src_sx,dst_x= dst_sx;xwidth;x++,dst_x++) { + pixmove(rb,x,y,dst_x,dst_y); + } + } + for(y=0;yheight+ytrans;y++) + for(x=rb->width+xtrans;xwidth;x++) + pixerase(rb,x,y); + for(y=rb->height+ytrans;yheight;y++) + for(x=0;xwidth;x++) + pixerase(rb,x,y); + } + } +} + +void msApplyBlackeningCompositingFilter(rasterBufferObj *rb) { + int row,col; + unsigned char *r,*g,*b; + for(row=0;rowheight;row++) { + r = rb->data.rgba.r + row*rb->data.rgba.row_step; + g = rb->data.rgba.g + row*rb->data.rgba.row_step; + b = rb->data.rgba.b + row*rb->data.rgba.row_step; + for(col=0;colwidth;col++) { + *r = *g = *b = 0; + r+=4;g+=4;b+=4; + } + } +} + +void msApplyWhiteningCompositingFilter(rasterBufferObj *rb) { + int row,col; + unsigned char *r,*g,*b,*a; + for(row=0;rowheight;row++) { + r = rb->data.rgba.r + row*rb->data.rgba.row_step; + g = rb->data.rgba.g + row*rb->data.rgba.row_step; + b = rb->data.rgba.b + row*rb->data.rgba.row_step; + a = rb->data.rgba.a + row*rb->data.rgba.row_step; + for(col=0;colwidth;col++) { + *r = *g = *b = *a; + r+=4;g+=4;b+=4;a+=4; + } + } +} + +void msApplyGrayscaleCompositingFilter(rasterBufferObj *rb) { + int row,col; + unsigned char *r,*g,*b; + for(row=0;rowheight;row++) { + r = rb->data.rgba.r + row*rb->data.rgba.row_step; + g = rb->data.rgba.g + row*rb->data.rgba.row_step; + b = rb->data.rgba.b + row*rb->data.rgba.row_step; + for(col=0;colwidth;col++) { + unsigned int mix = (unsigned int)*r + (unsigned int)*g + (unsigned int)*b; + mix /=3; + *r = *g = *b = (unsigned char)mix; + r+=4;g+=4;b+=4; + } + } +} + +int msApplyCompositingFilter(mapObj *map, rasterBufferObj *rb, CompositingFilter *filter) { + int rstatus; + regex_t regex; + regmatch_t pmatch[3]; + + /* test for blurring filter */ + regcomp(®ex, "blur\\(([0-9]+)\\)", REG_EXTENDED); + rstatus = regexec(®ex, filter->filter, 2, pmatch, 0); + regfree(®ex); + if(!rstatus) { + char *rad = malloc(pmatch[1].rm_eo - pmatch[1].rm_so + 1); + unsigned int irad; + strncpy(rad,filter->filter+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so); + rad[pmatch[1].rm_eo - pmatch[1].rm_so]=0; + //msDebug("got blur filter with radius %s\n",rad); + irad = atoi(rad); + free(rad); + irad = MS_NINT(irad*map->resolution/map->defresolution); + msApplyBlurringCompositingFilter(rb,irad); + return MS_SUCCESS; + } + + /* test for translation filter */ + regcomp(®ex, "translate\\((-?[0-9]+),(-?[0-9]+)\\)", REG_EXTENDED); + rstatus = regexec(®ex, filter->filter, 3, pmatch, 0); + regfree(®ex); + if(!rstatus) { + char *num; + int xtrans,ytrans; + num = malloc(pmatch[1].rm_eo - pmatch[1].rm_so + 1); + strncpy(num,filter->filter+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so); + num[pmatch[1].rm_eo - pmatch[1].rm_so]=0; + xtrans = atoi(num); + free(num); + num = malloc(pmatch[2].rm_eo - pmatch[2].rm_so + 1); + strncpy(num,filter->filter+pmatch[2].rm_so,pmatch[2].rm_eo-pmatch[2].rm_so); + num[pmatch[2].rm_eo - pmatch[2].rm_so]=0; + ytrans = atoi(num); + free(num); + //msDebug("got translation filter of radius %d,%d\n",xtrans,ytrans); + xtrans = MS_NINT(xtrans*map->resolution/map->defresolution); + ytrans = MS_NINT(ytrans*map->resolution/map->defresolution); + msApplyTranslationCompositingFilter(rb,xtrans,ytrans); + return MS_SUCCESS; + } + + /* test for grayscale filter */ + if(!strncmp(filter->filter,"grayscale()",strlen("grayscale()"))) { + msApplyGrayscaleCompositingFilter(rb); + return MS_SUCCESS; + } + if(!strncmp(filter->filter,"blacken()",strlen("blacken()"))) { + msApplyBlackeningCompositingFilter(rb); + return MS_SUCCESS; + } + if(!strncmp(filter->filter,"whiten()",strlen("whiten()"))) { + msApplyWhiteningCompositingFilter(rb); + return MS_SUCCESS; + } + + msSetError(MS_MISCERR,"unknown compositing filter (%s)", "msApplyCompositingFilter()", filter->filter); + return MS_FAILURE; +} diff -Nru mapserver-7.0.7/mapcontext.c mapserver-7.6.4/mapcontext.c --- mapserver-7.0.7/mapcontext.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapcontext.c 2021-07-12 20:16:21.000000000 +0000 @@ -29,8 +29,10 @@ #include "mapserver.h" #include "mapows.h" +#include "cpl_vsi.h" -#if defined(USE_WMS_LYR) && defined(USE_OGR) + +#if defined(USE_WMS_LYR) /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */ #include "cpl_minixml.h" @@ -47,12 +49,12 @@ char * msGetMapContextFileText(char *filename) { char *pszBuffer; - FILE *stream; + VSILFILE *stream; int nLength; /* open file */ if(filename != NULL && strlen(filename) > 0) { - stream = fopen(filename, "rb"); + stream = VSIFOpenL(filename, "rb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; @@ -62,32 +64,32 @@ return NULL; } - fseek( stream, 0, SEEK_END ); - nLength = ftell( stream ); - fseek( stream, 0, SEEK_SET ); + VSIFSeekL( stream, 0, SEEK_END ); + nLength = (int) VSIFTellL( stream ); + VSIFSeekL( stream, 0, SEEK_SET ); pszBuffer = (char *) malloc(nLength+1); if( pszBuffer == NULL ) { msSetError(MS_MEMERR, "(%s)", "msGetMapContextFileText()", filename); - fclose( stream ); + VSIFCloseL( stream ); return NULL; } - if(fread( pszBuffer, nLength, 1, stream ) == 0 && !feof(stream)) { + if(VSIFReadL( pszBuffer, nLength, 1, stream ) == 0) { free( pszBuffer ); - fclose( stream ); + VSIFCloseL( stream ); msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } pszBuffer[nLength] = '\0'; - fclose( stream ); + VSIFCloseL( stream ); return pszBuffer; } -#if defined(USE_WMS_LYR) && defined(USE_OGR) +#if defined(USE_WMS_LYR) /* **msGetMapContextXMLHashValue() @@ -264,7 +266,8 @@ char *pszXMLName, char *pszMetadataName, char *pszHashDelimiter) { - char *pszHash, *pszXMLValue, *pszMetadata; + const char *pszHash, *pszXMLValue; + char *pszMetadata; if(psRoot == NULL || psRoot->psChild == NULL || metadata == NULL || pszMetadataName == NULL || pszXMLName == NULL) @@ -350,7 +353,9 @@ */ int msLoadMapContextLayerFormat(CPLXMLNode *psFormat, layerObj *layer) { - char *pszValue, *pszValue1, *pszHash; + const char *pszValue; + char *pszValue1; + const char* pszHash; if(psFormat->psChild != NULL && strcasecmp(psFormat->pszValue, "Format") == 0 ) { @@ -442,7 +447,9 @@ int nStyle) { char *pszValue, *pszValue1, *pszValue2; - char *pszHash, *pszStyle=NULL, *pszStyleName; + const char *pszHash; + char* pszStyle=NULL; + char *pszStyleName; CPLXMLNode *psStyleSLDBody; pszStyleName =(char*)CPLGetXMLValue(psStyle,"Name",NULL); @@ -576,7 +583,8 @@ int msLoadMapContextLayerDimension(CPLXMLNode *psDimension, layerObj *layer) { - char *pszValue, *pszHash; + char *pszValue; + const char *pszHash; char *pszDimension=NULL, *pszDimensionName=NULL; pszDimensionName =(char*)CPLGetXMLValue(psDimension,"name",NULL); @@ -803,9 +811,9 @@ int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion, char *filename, int unique_layer_names) { - char *pszProj=NULL; char *pszValue; - char *pszHash, *pszName=NULL; + const char *pszHash; + char *pszName=NULL; CPLXMLNode *psFormatList, *psFormat, *psStyleList, *psStyle, *psExtension; CPLXMLNode *psDimensionList, *psDimension; int nStyle; @@ -828,7 +836,7 @@ /* Status */ pszValue = (char*)CPLGetXMLValue(psLayer, "hidden", "1"); if((pszValue != NULL) && (atoi(pszValue) == 0 && - !strcasecmp(pszValue, "true") == 0)) + strcasecmp(pszValue, "true") != 0)) layer->status = MS_ON; else layer->status = MS_OFF; @@ -961,7 +969,7 @@ pszHash = msLookupHashTable(&(layer->metadata), "wms_srs"); if(((pszHash == NULL) || (strcasecmp(pszHash, "") == 0)) && map->projection.numargs != 0) { - pszProj = map->projection.args[map->projection.numargs-1]; + char* pszProj = map->projection.args[map->projection.numargs-1]; if(pszProj != NULL) { if(strncasecmp(pszProj, "AUTO:", 5) == 0) { @@ -978,6 +986,7 @@ pszProj); } } + msFree(pszProj); } } @@ -1059,7 +1068,7 @@ int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names) { -#if defined(USE_WMS_LYR) && defined(USE_OGR) +#if defined(USE_WMS_LYR) char *pszTmpFile = NULL; int status = 0; @@ -1099,7 +1108,7 @@ */ int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names) { -#if defined(USE_WMS_LYR) && defined(USE_OGR) +#if defined(USE_WMS_LYR) char *pszWholeText, *pszValue; CPLXMLNode *psRoot, *psMapContext, *psLayer, *psLayerList, *psChild; char szPath[MS_MAXPATHLEN]; @@ -1267,8 +1276,8 @@ */ int msSaveMapContext(mapObj *map, char *filename) { -#if defined(USE_WMS_LYR) && defined(USE_OGR) - FILE *stream; +#if defined(USE_WMS_LYR) + VSILFILE *stream; char szPath[MS_MAXPATHLEN]; int nStatus; @@ -1301,10 +1310,11 @@ int msWriteMapContext(mapObj *map, FILE *stream) { -#if defined(USE_WMS_LYR) && defined(USE_OGR) - const char * version, *value; - char * tabspace=NULL, *pszValue, *pszChar,*pszSLD=NULL,*pszURL,*pszSLD2=NULL; - char *pszStyle, *pszCurrent, *pszStyleItem, *pszSLDBody; +#if defined(USE_WMS_LYR) + const char * version; + char *pszEPSG; + char * tabspace=NULL, *pszChar,*pszSLD=NULL,*pszURL,*pszSLD2=NULL; + char *pszStyle, *pszStyleItem, *pszSLDBody; char *pszEncodedVal; int i, nValue, nVersion=OWS_VERSION_NOTSET; /* Dimension element */ @@ -1407,18 +1417,19 @@ if(tabspace) free(tabspace); tabspace = msStrdup(" "); - value = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_TRUE); + msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_TRUE, &pszEPSG); msIO_fprintf( stream, "%s\n", tabspace ); - if(!value || (strcasecmp(value, "(null)") == 0)) + if(!pszEPSG || (strcasecmp(pszEPSG, "(null)") == 0)) msIO_fprintf(stream, "\n"); - pszEncodedVal = msEncodeHTMLEntities(value); + pszEncodedVal = msEncodeHTMLEntities(pszEPSG); msIO_fprintf( stream, "%s\n", tabspace, pszEncodedVal, map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy ); msFree(pszEncodedVal); + msFree(pszEPSG); /* Title, name */ if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { @@ -1441,7 +1452,7 @@ char **papszKeywords; int nKeywords, iKey; - pszValue = msLookupHashTable(&(map->web.metadata), + const char* pszValue = msLookupHashTable(&(map->web.metadata), "wms_keywordlist"); papszKeywords = msStringSplit(pszValue, ',', &nKeywords); if(nKeywords > 0 && papszKeywords) { @@ -1509,6 +1520,9 @@ /* Loop on all layer */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->status != MS_DELETE && GET_LAYER(map, i)->connectiontype == MS_WMS) { + const char* pszValue; + char* pszValueMod; + const char* pszCurrent; if(GET_LAYER(map, i)->status == MS_OFF) nValue = 1; else @@ -1547,21 +1561,21 @@ /* Get base url of the online resource to be the default value */ if(GET_LAYER(map, i)->connection) - pszValue = msStrdup( GET_LAYER(map, i)->connection ); + pszValueMod = msStrdup( GET_LAYER(map, i)->connection ); else - pszValue = msStrdup( "" ); - pszChar = strchr(pszValue, '?'); + pszValueMod = msStrdup( "" ); + pszChar = strchr(pszValueMod, '?'); if( pszChar ) - pszValue[pszChar - pszValue] = '\0'; + pszValueMod[pszChar - pszValueMod] = '\0'; if(msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata), NULL, "wms_onlineresource", OWS_WARN, " \n", - pszValue) == OWS_WARN) + pszValueMod) == OWS_WARN) msIO_fprintf(stream, "\n"); msIO_fprintf(stream, " \n"); - if(pszValue) - free(pszValue); + if(pszValueMod) + free(pszValueMod); /* */ /* Layer information */ @@ -1625,14 +1639,15 @@ GET_LAYER(map, i)->maxscaledenom); /* Layer SRS */ - pszValue = (char*)msOWSGetEPSGProj(&(GET_LAYER(map, i)->projection), + msOWSGetEPSGProj(&(GET_LAYER(map, i)->projection), &(GET_LAYER(map, i)->metadata), - "MO", MS_FALSE); - if(pszValue && (strcasecmp(pszValue, "(null)") != 0)) { - pszEncodedVal = msEncodeHTMLEntities(pszValue); + "MO", MS_FALSE, &pszEPSG); + if(pszEPSG && (strcasecmp(pszEPSG, "(null)") != 0)) { + pszEncodedVal = msEncodeHTMLEntities(pszEPSG); msIO_fprintf(stream, " %s\n", pszEncodedVal); msFree(pszEncodedVal); } + msFree(pszEPSG); /* Format */ if(msLookupHashTable(&(GET_LAYER(map, i)->metadata),"wms_formatlist")==NULL && @@ -1642,17 +1657,17 @@ pszURL = msStrdup( GET_LAYER(map, i)->connection ); else pszURL = msStrdup( "" ); - pszValue = pszURL; - pszValue = strstr( pszValue, "FORMAT=" ); - if( pszValue ) { - pszValue += 7; - pszChar = strchr(pszValue, '&'); + pszValueMod = pszURL; + pszValueMod = strstr( pszValueMod, "FORMAT=" ); + if( pszValueMod ) { + pszValueMod += 7; + pszChar = strchr(pszValueMod, '&'); if( pszChar ) - pszValue[pszChar - pszValue] = '\0'; - if(strcasecmp(pszValue, "") != 0) { - pszEncodedVal = msEncodeHTMLEntities(pszValue); + pszValueMod[pszChar - pszValueMod] = '\0'; + if(strcasecmp(pszValueMod, "") != 0) { + pszEncodedVal = msEncodeHTMLEntities(pszValueMod); msIO_fprintf( stream, " \n"); - msIO_fprintf(stream," %s\n",pszValue); + msIO_fprintf(stream," %s\n",pszValueMod); msIO_fprintf( stream, " \n"); msFree(pszEncodedVal); } @@ -1695,21 +1710,23 @@ /* First check the stylelist */ pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata), "wms_stylelist"); - if(pszValue == NULL || strlen(msStringTrimLeft(pszValue)) < 1) { + while( pszValue && *pszValue == ' ' ) + pszValue ++; + if(pszValue == NULL || strlen(pszValue) < 1) { /* Check if the style is in the connection URL */ pszURL = ""; if(GET_LAYER(map, i)->connection) pszURL = msStrdup( GET_LAYER(map, i)->connection ); else pszURL = msStrdup( "" ); - pszValue = pszURL; + pszValueMod = pszURL; /* Grab the STYLES in the URL */ - pszValue = strstr( pszValue, "STYLES=" ); - if( pszValue ) { - pszValue += 7; - pszChar = strchr(pszValue, '&'); + pszValueMod = strstr( pszValueMod, "STYLES=" ); + if( pszValueMod ) { + pszValueMod += 7; + pszChar = strchr(pszValueMod, '&'); if( pszChar ) - pszValue[pszChar - pszValue] = '\0'; + pszValueMod[pszChar - pszValueMod] = '\0'; /* Check the SLD string from the URL */ if(GET_LAYER(map, i)->connection) @@ -1737,14 +1754,14 @@ pszSLDBody[pszChar - pszSLDBody] = '\0'; pszSLDBody += 9; } - if( (pszValue && (strcasecmp(pszValue, "") != 0)) || + if( (pszValueMod && (strcasecmp(pszValueMod, "") != 0)) || (pszSLD && (strcasecmp(pszSLD, "") != 0)) || (pszSLDBody && (strcasecmp(pszSLDBody, "") != 0))) { /* Write Name and Title */ msIO_fprintf( stream, " \n"); msIO_fprintf( stream, " \n"); msFree(pszEncodedName); @@ -3482,7 +3759,7 @@ GET_LAYER(map, j)->group && strcmp(lp->group, GET_LAYER(map, j)->group) == 0 && msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers)) { - msDumpLayer(map, (GET_LAYER(map, j)), nVersion, script_url_encoded, " ", validated_language, MS_FALSE); + msDumpLayer(map, (GET_LAYER(map, j)), nVersion, script_url_encoded, " ", validated_language, MS_FALSE, MS_FALSE); pabLayerProcessed[j] = 1; } } @@ -3610,6 +3887,7 @@ imageObj *img; int i = 0; int sldrequested = MS_FALSE, sldspatialfilter = MS_FALSE; + int drawquerymap = MS_FALSE; const char *http_max_age; /* __TODO__ msDrawMap() will try to adjust the extent of the map */ @@ -3638,6 +3916,15 @@ } } } + /* If FILTER is passed then we'll render layers as querymap */ + for (i=0; i 0)) { + drawquerymap = MS_TRUE; + map->querymap.status = MS_ON; + map->querymap.style = MS_SELECTED; + break; + } + } /* turn off layer if WMS GetMap is not enabled */ for (i=0; inumlayers; i++) @@ -3678,8 +3965,18 @@ msDrawLayer(map, GET_LAYER(map, i), img); } - } else - img = msDrawMap(map, MS_FALSE); + } else { + + /* intercept requests for Mapbox vector tiles */ + if(!strcmp(MS_IMAGE_MIME_TYPE(map->outputformat), "application/x-protobuf")) { + int status=0; + if((status = msMVTWriteTile(map, MS_TRUE)) != MS_SUCCESS) return MS_FAILURE; + return MS_SUCCESS; + } + + img = msDrawMap(map, drawquerymap); + } + if (img == NULL) return msWMSException(map, nVersion, NULL, wms_exception_format); @@ -3694,6 +3991,7 @@ if(!strcmp(MS_IMAGE_MIME_TYPE(map->outputformat), "application/json")) { msIO_setHeader("Content-Type","application/json; charset=utf-8"); } else { + msOutputFormatResolveFromImage( map, img ); msIO_setHeader("Content-Type", "%s", MS_IMAGE_MIME_TYPE(map->outputformat)); } msIO_sendHeaders(); @@ -3854,6 +4152,7 @@ if(strcasecmp(names[i], "QUERY_LAYERS") == 0) { char **layers; int numlayers, j, k; + const char* rootlayer_name; query_layer = 1; /* flag set if QUERY_LAYERS is the request */ @@ -3863,27 +4162,48 @@ return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } - - for(j=0; jnumlayers; j++) { /* Force all layers OFF by default */ GET_LAYER(map, j)->status = MS_OFF; + } + + /* Special case for root layer */ + rootlayer_name = msOWSLookupMetadata(&(map->web.metadata), "MO", "rootlayer_name"); + if( !rootlayer_name ) + rootlayer_name = map->name; + if( rootlayer_name && msStringInArray(rootlayer_name, layers, numlayers) ) { + for(j=0; jnumlayers; j++) { + layerObj* layer = GET_LAYER(map, j); + if( msIsLayerQueryable(layer) && + msIntegerInArray(layer->index, ows_request->enabled_layers, ows_request->numlayers) ) { + if (layer->connectiontype == MS_WMS) { + wms_layer = MS_TRUE; + wms_connection = layer->connection; + } + + numlayers_found++; + layer->status = MS_ON; + } + } + } + + for(j=0; jnumlayers; j++) { + layerObj* layer = GET_LAYER(map, j); + if( !msIsLayerQueryable(layer) ) + continue; for(k=0; kname && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || - (map->name && strcasecmp(map->name, layers[k]) == 0) || - (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0) || + if (((layer->name && strcasecmp(layer->name, layers[k]) == 0) || + (layer->group && strcasecmp(layer->group, layers[k]) == 0) || ((numNestedGroups[j] >0) && msStringInArray(layers[k], nestedGroups[j], numNestedGroups[j]))) && - (msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { - if (GET_LAYER(map, j)->connectiontype == MS_WMS) { + (msIntegerInArray(layer->index, ows_request->enabled_layers, ows_request->numlayers)) ) { + + if (layer->connectiontype == MS_WMS) { wms_layer = MS_TRUE; - wms_connection = GET_LAYER(map, j)->connection; + wms_connection = layer->connection; } - /* Don't turn on layers that are not queryable but have sublayers. */ - if ((msIsLayerQueryable(GET_LAYER(map, j))) || isUsedInNestedGroup[j] == 0) { - numlayers_found++; - GET_LAYER(map, j)->status = MS_ON; - } + numlayers_found++; + layer->status = MS_ON; } } } @@ -3953,10 +4273,7 @@ /* If a layer of type WMS was found... all layers have to be of that type and with the same connection */ for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->status == MS_ON) { - if (!msIsLayerQueryable(GET_LAYER(map, i))) { - msSetError(MS_WMSERR, "Requested layer(s) are not queryable.", "msWMSFeatureInfo()"); - return msWMSException(map, nVersion, "LayerNotQueryable", wms_exception_format); - } else if (wms_layer == MS_TRUE) { + if (wms_layer == MS_TRUE) { if ( (GET_LAYER(map, i)->connectiontype != MS_WMS) || (strcasecmp(wms_connection, GET_LAYER(map, i)->connection) != 0) ) { msSetError(MS_WMSERR, "Requested WMS layer(s) are not queryable: type or connection differ", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "LayerNotQueryable", wms_exception_format); @@ -4365,7 +4682,7 @@ pszFormat = values[i]; else if (strcasecmp(names[i], "SCALE") == 0) psScale = values[i]; -#ifdef USE_OGR + /* -------------------------------------------------------------------- */ /* SLD support : */ /* - check if the SLD parameter is there. it is supposed to */ @@ -4383,7 +4700,7 @@ psRule = values[i]; else if (strcasecmp(names[i], "STYLE") == 0) pszStyle = values[i]; -#endif + /* -------------------------------------------------------------------- */ /* SLD support: */ /* - because the request parameter "sld_version" is required in */ diff -Nru mapserver-7.0.7/mapwmslayer.c mapserver-7.6.4/mapwmslayer.c --- mapserver-7.0.7/mapwmslayer.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapwmslayer.c 2021-07-12 20:16:21.000000000 +0000 @@ -40,11 +40,7 @@ #include #endif -#ifdef USE_GDAL -# include "cpl_vsi.h" -#endif - -void CleanVSIDir( const char *pszDir ); +#include "cpl_vsi.h" /********************************************************************** * msInitWmsParamsObj() @@ -86,7 +82,7 @@ #ifdef USE_WMS_LYR static int msSetWMSParamString(wmsParamsObj *psWMSParams, const char *name, const char * value, - int urlencode) + int urlencode, int nVersion) { if (urlencode) { char *pszTmp; @@ -96,8 +92,8 @@ * says should not be encoded, when they occur in certain * parameters. * - * TODO: WMS 1.3 removes SRS and FORMAT from the set of - * exceptional cases. + * Note: WMS 1.3 removes SRS and FORMAT from the set of + * exceptional cases, but renames SRS as CRS in any case. */ if( strcmp(name,"LAYERS") == 0 || strcmp(name,"STYLES") == 0 || @@ -105,7 +101,7 @@ pszTmp = msEncodeUrlExcept(value,','); } else if ( strcmp(name,"SRS") == 0 ) { pszTmp = msEncodeUrlExcept(value,':'); - } else if ( strcmp(name,"FORMAT") == 0 ) { + } else if ( nVersion < OWS_1_3_0 && strcmp(name,"FORMAT") == 0 ) { pszTmp = msEncodeUrlExcept(value,'/'); } else { pszTmp = msEncodeUrl(value); @@ -218,7 +214,7 @@ * by the caller. **********************************************************************/ static int msBuildWMSLayerURLBase(mapObj *map, layerObj *lp, - wmsParamsObj *psWMSParams) + wmsParamsObj *psWMSParams, int nRequestType) { const char *pszOnlineResource, *pszVersion, *pszName, *pszFormat; const char *pszFormatList, *pszStyle, /* *pszStyleList,*/ *pszTime; @@ -226,6 +222,7 @@ const char *pszSLD=NULL, *pszStyleSLDBody=NULL, *pszVersionKeyword=NULL; const char *pszSLDBody=NULL, *pszSLDURL = NULL; char *pszSLDGenerated = NULL; + int nVersion=OWS_VERSION_NOTSET; /* If lp->connection is not set then use wms_onlineresource metadata */ pszOnlineResource = lp->connection; @@ -262,9 +259,13 @@ else pszVersionKeyword = "VERSION"; - msSetWMSParamString(psWMSParams, pszVersionKeyword, pszVersion, MS_FALSE); - msSetWMSParamString(psWMSParams, "SERVICE", "WMS", MS_FALSE); - msSetWMSParamString(psWMSParams, "LAYERS", pszName, MS_TRUE); + nVersion = msOWSParseVersionString(pszVersion); + /* WMS 1.0.8 is really just 1.1.0 */ + if (nVersion == OWS_1_0_8) nVersion = OWS_1_1_0; + + msSetWMSParamString(psWMSParams, pszVersionKeyword, pszVersion, MS_FALSE, nVersion); + msSetWMSParamString(psWMSParams, "SERVICE", "WMS", MS_FALSE, nVersion); + msSetWMSParamString(psWMSParams, "LAYERS", pszName, MS_TRUE, nVersion); if (pszFormat==NULL && pszFormatList==NULL) { msSetError(MS_WMSCONNERR, @@ -277,7 +278,7 @@ } if (pszFormat != NULL) { - msSetWMSParamString(psWMSParams, "FORMAT", pszFormat, MS_TRUE); + msSetWMSParamString(psWMSParams, "FORMAT", pszFormat, MS_TRUE, nVersion); } else { /* Look for the first format in list that matches */ char **papszTok; @@ -300,7 +301,7 @@ } if (pszFormat) { - msSetWMSParamString(psWMSParams, "FORMAT", pszFormat, MS_TRUE); + msSetWMSParamString(psWMSParams, "FORMAT", pszFormat, MS_TRUE, nVersion); msFreeCharArray(papszTok, n); } else { msSetError(MS_WMSCONNERR, @@ -334,25 +335,28 @@ } } - /* set STYLES no matter what, even if it's empty (i.e. "STYLES=") - * styles is a required param of WMS + /* set STYLE parameter no matter what, even if it's empty (i.e. "STYLES=") + * GetLegendGraphic doesn't support multiple styles and is named STYLE */ - - msSetWMSParamString(psWMSParams, "STYLES", pszStyle, MS_TRUE); + if (nRequestType == WMS_GETLEGENDGRAPHIC) { + msSetWMSParamString(psWMSParams, "STYLE", pszStyle, MS_TRUE, nVersion); + } else { + msSetWMSParamString(psWMSParams, "STYLES", pszStyle, MS_TRUE, nVersion); + } if (pszSLD != NULL) { /* Only SLD is set */ - msSetWMSParamString(psWMSParams, "SLD", pszSLD, MS_TRUE); + msSetWMSParamString(psWMSParams, "SLD", pszSLD, MS_TRUE, nVersion); } else if (pszStyleSLDBody != NULL) { /* SLDBODY are set */ - msSetWMSParamString(psWMSParams, "SLD_BODY", pszStyleSLDBody, MS_TRUE); + msSetWMSParamString(psWMSParams, "SLD_BODY", pszStyleSLDBody, MS_TRUE, nVersion); } if (msIsLayerQueryable(lp)) { - msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszName, MS_TRUE); + msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszName, MS_TRUE, nVersion); } if (pszTime && strlen(pszTime) > 0) { - msSetWMSParamString(psWMSParams, "TIME", pszTime, MS_TRUE); + msSetWMSParamString(psWMSParams, "TIME", pszTime, MS_TRUE, nVersion); } /* if the metadata wms_sld_body is set to AUTO, we generate @@ -369,27 +373,27 @@ if (pszSLDGenerated) { msSetWMSParamString(psWMSParams, "SLD_BODY", - pszSLDGenerated, MS_TRUE); + pszSLDGenerated, MS_TRUE, nVersion); free(pszSLDGenerated); } } else { - msSetWMSParamString(psWMSParams, "SLD_BODY", pszSLDBody, MS_TRUE); + msSetWMSParamString(psWMSParams, "SLD_BODY", pszSLDBody, MS_TRUE, nVersion); } } if (pszSLDURL) { - msSetWMSParamString(psWMSParams, "SLD", pszSLDURL, MS_TRUE); + msSetWMSParamString(psWMSParams, "SLD", pszSLDURL, MS_TRUE, nVersion); } if (pszBgColor) { - msSetWMSParamString(psWMSParams, "BGCOLOR", pszBgColor, MS_TRUE); + msSetWMSParamString(psWMSParams, "BGCOLOR", pszBgColor, MS_TRUE, nVersion); } if (pszTransparent) { - msSetWMSParamString(psWMSParams, "TRANSPARENT", pszTransparent, MS_TRUE); + msSetWMSParamString(psWMSParams, "TRANSPARENT", pszTransparent, MS_TRUE, nVersion); } else { - msSetWMSParamString(psWMSParams, "TRANSPARENT", "TRUE", MS_TRUE); + msSetWMSParamString(psWMSParams, "TRANSPARENT", "TRUE", MS_TRUE, nVersion); } return MS_SUCCESS; @@ -416,11 +420,16 @@ { #ifdef USE_WMS_LYR char *pszEPSG = NULL; - const char *pszVersion, *pszTmp, *pszRequestParam, *pszExceptionsParam, - *pszLayer=NULL, *pszQueryLayers=NULL; + const char *pszVersion, *pszRequestParam, *pszExceptionsParam, + *pszSrsParamName="SRS", *pszLayer=NULL, *pszQueryLayers=NULL, + *pszUseStrictAxisOrder; rectObj bbox; int bbox_width = map->width, bbox_height = map->height; int nVersion=OWS_VERSION_NOTSET; + int bUseStrictAxisOrder = MS_FALSE; /* this is the assumption up to 1.1.0 */ + int bFlipAxisOrder = MS_FALSE; + const char *pszTmp; + int bIsEssential = MS_FALSE; if (lp->connectiontype != MS_WMS) { msSetError(MS_WMSCONNERR, "Call supported only for CONNECTIONTYPE WMS", @@ -437,7 +446,7 @@ (pszVersion = strstr(lp->connection, "WMTVER=")) == NULL && (pszVersion = strstr(lp->connection, "wmtver=")) == NULL ) ) { /* CONNECTION missing or seems incomplete... try to build from metadata */ - if (msBuildWMSLayerURLBase(map, lp, psWMSParams) != MS_SUCCESS) + if (msBuildWMSLayerURLBase(map, lp, psWMSParams, nRequestType) != MS_SUCCESS) return MS_FAILURE; /* An error already produced. */ /* If we received MS_SUCCESS then version must have been set */ @@ -472,9 +481,14 @@ case OWS_1_1_1: /* All is good, this is a supported version. */ break; + case OWS_1_3_0: + /* 1.3.0 introduces a few changes... */ + pszSrsParamName = "CRS"; + bUseStrictAxisOrder = MS_TRUE; /* this is the assumption for 1.3.0 */ + break; default: /* Not a supported version */ - msSetError(MS_WMSCONNERR, "MapServer supports only WMS 1.0.0 to 1.1.1 (please verify the VERSION parameter in the connection string).", "msBuildWMSLayerURL()"); + msSetError(MS_WMSCONNERR, "MapServer supports only WMS 1.0.0 to 1.3.0 (please verify the VERSION parameter in the connection string).", "msBuildWMSLayerURL()"); return MS_FAILURE; } @@ -515,12 +529,12 @@ * - If map SRS is valid for this layer then use it * - Otherwise request layer in its default SRS and we'll reproject later * ------------------------------------------------------------------ */ - if ((pszEPSG = (char*)msOWSGetEPSGProj(&(map->projection), - NULL, NULL, MS_TRUE)) != NULL && - (pszEPSG = msStrdup(pszEPSG)) != NULL && + msOWSGetEPSGProj(&(map->projection),NULL, NULL, MS_TRUE, &pszEPSG); + if ( pszEPSG && (strncasecmp(pszEPSG, "EPSG:", 5) == 0 || strncasecmp(pszEPSG, "AUTO:", 5) == 0) ) { - const char *pszLyrEPSG, *pszFound; + const char *pszFound; + char *pszLyrEPSG; int nLen; char *pszPtr = NULL; @@ -533,8 +547,7 @@ nLen = strlen(pszEPSG); - pszLyrEPSG = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), - "MO", MS_FALSE); + msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE, &pszLyrEPSG); if (pszLyrEPSG == NULL || (pszFound = strstr(pszLyrEPSG, pszEPSG)) == NULL || @@ -543,19 +556,18 @@ free(pszEPSG); pszEPSG = NULL; } + msFree(pszLyrEPSG); if (pszEPSG && pszPtr) *pszPtr = ','; /* Restore full AUTO:... definition */ } - if (pszEPSG == NULL && - ((pszEPSG = (char*)msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), - "MO", MS_TRUE)) == NULL || - (pszEPSG = msStrdup(pszEPSG)) == NULL || - (strncasecmp(pszEPSG, "EPSG:", 5) != 0 && - strncasecmp(pszEPSG, "AUTO:", 5) != 0 ) ) ) { - msSetError(MS_WMSCONNERR, "Layer must have an EPSG or AUTO projection code (in its PROJECTION object or wms_srs metadata)", "msBuildWMSLayerURL()"); - if (pszEPSG) free(pszEPSG); - return MS_FAILURE; + if (pszEPSG == NULL) { + msOWSGetEPSGProj(&(lp->projection), &(lp->metadata),"MO", MS_TRUE, &pszEPSG); + if( pszEPSG == NULL || (strncasecmp(pszEPSG, "EPSG:", 5) != 0 && strncasecmp(pszEPSG, "AUTO:", 5) != 0) ) { + msSetError(MS_WMSCONNERR, "Layer must have an EPSG or AUTO projection code (in its PROJECTION object or wms_srs metadata)", "msBuildWMSLayerURL()"); + msFree(pszEPSG); + return MS_FAILURE; + } } /* ------------------------------------------------------------------ @@ -580,32 +592,59 @@ pszEPSG=pszNewEPSG; } + /* + * Work out whether we'll be wanting to flip the axis order for the request + */ + pszUseStrictAxisOrder = msOWSLookupMetadata(&(lp->metadata), "MO", "strict_axis_order"); + if (pszUseStrictAxisOrder != NULL) { + if (strncasecmp(pszUseStrictAxisOrder, "1", 1) == 0 || + strncasecmp(pszUseStrictAxisOrder, "true", 4) == 0) { + bUseStrictAxisOrder = MS_TRUE; + } else if (strncasecmp(pszUseStrictAxisOrder, "0", 1) == 0 || + strncasecmp(pszUseStrictAxisOrder, "false", 5) == 0) { + bUseStrictAxisOrder = MS_FALSE; + } + } + if (bUseStrictAxisOrder == MS_TRUE && pszEPSG && + strncasecmp(pszEPSG, "EPSG:", 5) == 0 && + msIsAxisInverted(atoi(pszEPSG + 5))) { + bFlipAxisOrder = MS_TRUE; + } + /* ------------------------------------------------------------------ * Set layer SRS. * ------------------------------------------------------------------ */ /* No need to set lp->proj if it's already set to the right EPSG code */ - if ((pszTmp = msOWSGetEPSGProj(&(lp->projection), NULL, "MO", MS_TRUE)) == NULL || - strcasecmp(pszEPSG, pszTmp) != 0) { - const char *ows_srs; - - /* no need to set lp->proj if it is already set and there is only - one item in the _srs metadata for this layer - we will assume - the projection block matches the _srs metadata (the search for ' ' - in ows_srs is a test to see if there are multiple EPSG: codes) */ - if( lp->projection.numargs == 0 - || (ows_srs = msOWSGetEPSGProj(NULL,&(lp->metadata), "MO", MS_FALSE)) == NULL - || (strchr(ows_srs,' ') != NULL) ) { - if (strncasecmp(pszEPSG, "EPSG:", 5) == 0) { - char szProj[20]; - snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5); - - if (msLoadProjectionString(&(lp->projection), szProj) != 0) - return MS_FAILURE; - } else { - if (msLoadProjectionString(&(lp->projection), pszEPSG) != 0) - return MS_FAILURE; + { + char* pszEPSGCodeFromLayer = NULL; + msOWSGetEPSGProj(&(lp->projection), NULL, "MO", MS_TRUE, &pszEPSGCodeFromLayer); + if (pszEPSGCodeFromLayer == NULL || strcasecmp(pszEPSG, pszEPSGCodeFromLayer) != 0) { + char *ows_srs = NULL; + msOWSGetEPSGProj(NULL, &(lp->metadata), "MO", MS_FALSE, &ows_srs); + /* no need to set lp->proj if it is already set and there is only + one item in the _srs metadata for this layer - we will assume + the projection block matches the _srs metadata (the search for ' ' + in ows_srs is a test to see if there are multiple EPSG: codes) */ + if( lp->projection.numargs == 0 || ows_srs == NULL || (strchr(ows_srs,' ') != NULL) ) { + if (strncasecmp(pszEPSG, "EPSG:", 5) == 0) { + char szProj[20]; + snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5); + if (msLoadProjectionString(&(lp->projection), szProj) != 0) { + msFree(pszEPSGCodeFromLayer); + msFree(ows_srs); + return MS_FAILURE; + } + } else { + if (msLoadProjectionString(&(lp->projection), pszEPSG) != 0) { + msFree(pszEPSGCodeFromLayer); + msFree(ows_srs); + return MS_FAILURE; + } + } } + msFree(ows_srs); } + msFree(pszEPSGCodeFromLayer); } /* ------------------------------------------------------------------ @@ -676,11 +715,10 @@ /* consider restricting the BBOX to match the limits. */ /* -------------------------------------------------------------------- */ if( bbox_width != 0 ) { - const char *ows_srs; + char *ows_srs; rectObj layer_rect; - ows_srs = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), - "MO", MS_FALSE); + msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE, &ows_srs); if( ows_srs && strchr(ows_srs,' ') == NULL && msOWSGetLayerExtent( map, lp, "MO", &layer_rect) == MS_SUCCESS ) { @@ -702,8 +740,8 @@ msRectIntersect( &bbox, &layer_rect ); - bbox_width = ceil((bbox.maxx - bbox.minx) / cellsize); - bbox_height = ceil((bbox.maxy - bbox.miny) / cellsize); + bbox_width = round((bbox.maxx - bbox.minx) / cellsize); + bbox_height = round((bbox.maxy - bbox.miny) / cellsize); /* Force going through the resampler if we're going to receive a clipped BBOX (#4931) */ if(msLayerGetProcessingKey(lp, "RESAMPLE") == NULL) { @@ -711,6 +749,7 @@ } } } + msFree(ows_srs); } /* -------------------------------------------------------------------- */ @@ -729,12 +768,12 @@ * Build the request URL. * At this point we set only the following parameters for GetMap: * REQUEST - * SRS + * SRS (or CRS) * BBOX * * And for GetFeatureInfo: - * X - * Y + * X (I for 1.3.0) + * Y (J for 1.3.0) * INFO_FORMAT * FEATURE_COUNT (only if nFeatureCount > 0) * @@ -748,6 +787,20 @@ * QUERY_LAYERS (for queryable layers only) * ------------------------------------------------------------------ */ + /* ------------------------------------------------------------------ + * Sometimes a requested layer is essential for the map, so if the + * request fails or an error is delivered, the map has not to be drawn + * ------------------------------------------------------------------ */ + if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), + "MO", "essential")) != NULL) { + if( strcasecmp(pszTmp,"true") == 0 + || strcasecmp(pszTmp,"on") == 0 + || strcasecmp(pszTmp,"yes") == 0 ) + bIsEssential = MS_TRUE; + else + bIsEssential = atoi(pszTmp); + } + if (nRequestType == WMS_GETFEATUREINFO) { char szBuf[100] = ""; @@ -756,30 +809,43 @@ else pszRequestParam = "feature_info"; - if (nVersion >= OWS_1_1_0) + if (nVersion >= OWS_1_3_0) + pszExceptionsParam = "XML"; + else if (nVersion >= OWS_1_1_0) /* 1.1.0 to 1.1.0 */ pszExceptionsParam = "application/vnd.ogc.se_xml"; else if (nVersion > OWS_1_0_0) /* 1.0.1 to 1.0.7 */ pszExceptionsParam = "SE_XML"; else pszExceptionsParam = "WMS_XML"; - msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); + msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE, nVersion); msSetWMSParamInt( psWMSParams, "WIDTH", bbox_width); msSetWMSParamInt( psWMSParams, "HEIGHT", bbox_height); - msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); - snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", - bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); - msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE); + msSetWMSParamString(psWMSParams, pszSrsParamName, pszEPSG, MS_FALSE, nVersion); + + if (bFlipAxisOrder == MS_TRUE) { + snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", + bbox.miny, bbox.minx, bbox.maxy, bbox.maxx); + } else { + snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", + bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); + } + msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE, nVersion); - msSetWMSParamInt( psWMSParams, "X", nClickX); - msSetWMSParamInt( psWMSParams, "Y", nClickY); + if (nVersion >= OWS_1_3_0) { + msSetWMSParamInt( psWMSParams, "I", nClickX); + msSetWMSParamInt( psWMSParams, "J", nClickY); + } else { + msSetWMSParamInt( psWMSParams, "X", nClickX); + msSetWMSParamInt( psWMSParams, "Y", nClickY); + } - msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE); - msSetWMSParamString(psWMSParams, "INFO_FORMAT", pszInfoFormat, MS_TRUE); + msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE, nVersion); + msSetWMSParamString(psWMSParams, "INFO_FORMAT", pszInfoFormat, MS_TRUE, nVersion); if (pszQueryLayers) { /* not set in CONNECTION string */ - msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszQueryLayers, MS_FALSE); + msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszQueryLayers, MS_FALSE, nVersion); } /* If FEATURE_COUNT <= 0 then don't pass this parameter */ @@ -796,25 +862,29 @@ msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &scaledenom); snprintf(szBuf, 20, "%g",scaledenom); - msSetWMSParamString(psWMSParams, "SCALE", szBuf, MS_FALSE); + msSetWMSParamString(psWMSParams, "SCALE", szBuf, MS_FALSE, nVersion); } pszRequestParam = "GetLegendGraphic"; pszExceptionsParam = msOWSLookupMetadata(&(lp->metadata), "MO", "exceptions_format"); if (pszExceptionsParam == NULL) { - if (nVersion >= OWS_1_1_0) + if (nVersion >= OWS_1_1_0 && nVersion < OWS_1_3_0) pszExceptionsParam = "application/vnd.ogc.se_inimage"; else pszExceptionsParam = "INIMAGE"; } if (pszLayer) { /* not set in CONNECTION string */ - msSetWMSParamString(psWMSParams, "LAYER", pszLayer, MS_FALSE); + msSetWMSParamString(psWMSParams, "LAYER", pszLayer, MS_FALSE, nVersion); } - msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); - msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); + msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE, nVersion); + msSetWMSParamString(psWMSParams, pszSrsParamName, pszEPSG, MS_FALSE, nVersion); + + if (nVersion >= OWS_1_3_0) { + msSetWMSParamString(psWMSParams, "SLD_VERSION", "1.1.0", MS_FALSE, nVersion); + } } else { /* if (nRequestType == WMS_GETMAP) */ char szBuf[100] = ""; @@ -826,22 +896,35 @@ pszExceptionsParam = msOWSLookupMetadata(&(lp->metadata), "MO", "exceptions_format"); - if (pszExceptionsParam == NULL) { - if (nVersion >= OWS_1_1_0) - pszExceptionsParam = "application/vnd.ogc.se_inimage"; - else - pszExceptionsParam = "INIMAGE"; + + if (!bIsEssential) { + if (pszExceptionsParam == NULL) { + if (nVersion >= OWS_1_1_0 && nVersion < OWS_1_3_0) + pszExceptionsParam = "application/vnd.ogc.se_inimage"; + else + pszExceptionsParam = "INIMAGE"; + } + } else { + /* if layer is essential, do not emit EXCEPTIONS parameter (defaults to XML) */ + pszExceptionsParam = NULL; } - msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); + msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE, nVersion); msSetWMSParamInt( psWMSParams, "WIDTH", bbox_width); msSetWMSParamInt( psWMSParams, "HEIGHT", bbox_height); - msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); + msSetWMSParamString(psWMSParams, pszSrsParamName, pszEPSG, MS_FALSE, nVersion); - snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", - bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); - msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE); - msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE); + if (bFlipAxisOrder == MS_TRUE) { + snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", + bbox.miny, bbox.minx, bbox.maxy, bbox.maxx); + } else { + snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", + bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); + } + msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE, nVersion); + if( pszExceptionsParam ) { + msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE, nVersion); + } } free(pszEPSG); @@ -905,8 +988,8 @@ #ifdef USE_WMS_LYR char *pszURL = NULL, *pszHTTPCookieData = NULL; const char *pszTmp; - rectObj bbox; - int bbox_width, bbox_height; + rectObj bbox = { 0 }; + int bbox_width = 0, bbox_height = 0; int nTimeout, bOkToMerge, bForceSeparateRequest, bCacheToDisk; wmsParamsObj sThisWMSParams; @@ -1123,7 +1206,8 @@ MS_CHECK_ALLOC(pszBuf, nLen, MS_FAILURE); snprintf(pszBuf, nLen, "%s,%s", value1, value2); - msSetWMSParamString(&sThisWMSParams, keys[i], pszBuf,MS_FALSE); + /* TODO should really send the server request version here */ + msSetWMSParamString(&sThisWMSParams, keys[i], pszBuf,MS_FALSE, OWS_VERSION_NOTSET); /* This key existed already, we don't want it counted twice */ sThisWMSParams.numparams--; @@ -1224,6 +1308,22 @@ int currentconnectiontype; int numclasses; char *mem_filename = NULL; + const char *pszTmp; + int bIsEssential = MS_FALSE; + + /* ------------------------------------------------------------------ + * Sometimes a requested layer is essential for the map, so if the + * request fails or an error is delivered, the map has not to be drawn + * ------------------------------------------------------------------ */ + if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), + "MO", "essential")) != NULL) { + if( strcasecmp(pszTmp,"true") == 0 + || strcasecmp(pszTmp,"on") == 0 + || strcasecmp(pszTmp,"yes") == 0 ) + bIsEssential = MS_TRUE; + else + bIsEssential = atoi(pszTmp); + } /* ------------------------------------------------------------------ * Find the request info for this layer in the array, based on nLayerId @@ -1243,8 +1343,9 @@ if ( !MS_HTTP_SUCCESS( pasReqInfo[iReq].nStatus ) ) { /* ==================================================================== Failed downloading layer... we log an error but we still return - SUCCESS here so that the layer is only skipped intead of aborting + SUCCESS here so that the layer is only skipped instead of aborting the whole draw map. + If the layer is essential the map is not to be drawn. ==================================================================== */ msSetError(MS_WMSERR, "WMS GetMap request failed for layer '%s' (Status %d: %s).", @@ -1252,14 +1353,18 @@ (lp->name?lp->name:"(null)"), pasReqInfo[iReq].nStatus, pasReqInfo[iReq].pszErrBuf ); - return MS_SUCCESS; + if (!bIsEssential) + return MS_SUCCESS; + else + return MS_FAILURE; } /* ------------------------------------------------------------------ * Check the Content-Type of the response to see if we got an exception, * if yes then try to parse it and pass the info to msSetError(). * We log an error but we still return SUCCESS here so that the layer - * is only skipped intead of aborting the whole draw map. + * is only skipped instead of aborting the whole draw map. + * If the layer is essential the map is not to be drawn. * ------------------------------------------------------------------ */ if (pasReqInfo[iReq].pszContentType && (strcmp(pasReqInfo[iReq].pszContentType, "text/xml") == 0 || @@ -1304,7 +1409,10 @@ "msDrawWMSLayerLow()", (lp->name?lp->name:"(null)"), szBuf ); - return MS_SUCCESS; + if (!bIsEssential) + return MS_SUCCESS; + else + return MS_FAILURE; } /* ------------------------------------------------------------------ @@ -1312,7 +1420,6 @@ * to attach a "VSI" name to this buffer. * ------------------------------------------------------------------ */ if( pasReqInfo[iReq].pszOutputFile == NULL ) { - CleanVSIDir( "/vsimem/msout" ); mem_filename = msTmpFile(map, NULL, "/vsimem/msout/", "img.tmp" ); VSIFCloseL( @@ -1373,12 +1480,12 @@ if (wldfile && (strlen(wldfile)>=3)) strcpy(wldfile+strlen(wldfile)-3, "wld"); if (wldfile && (fp = VSIFOpenL(wldfile, "wt")) != NULL) { - double dfCellSizeX = MS_CELLSIZE(pasReqInfo[iReq].bbox.minx, - pasReqInfo[iReq].bbox.maxx, - pasReqInfo[iReq].width); - double dfCellSizeY = MS_CELLSIZE(pasReqInfo[iReq].bbox.maxy, - pasReqInfo[iReq].bbox.miny, - pasReqInfo[iReq].height); + double dfCellSizeX = MS_OWS_CELLSIZE(pasReqInfo[iReq].bbox.minx, + pasReqInfo[iReq].bbox.maxx, + pasReqInfo[iReq].width); + double dfCellSizeY = MS_OWS_CELLSIZE(pasReqInfo[iReq].bbox.maxy, + pasReqInfo[iReq].bbox.miny, + pasReqInfo[iReq].height); char world_text[5000]; sprintf( world_text, "%.12f\n0\n0\n%.12f\n%.12f\n%.12f\n", @@ -1394,7 +1501,7 @@ if (msDrawLayer(map, lp, img) != 0) status = MS_FAILURE; - if (!lp->debug) + if (!lp->debug || mem_filename != NULL) VSIUnlink( wldfile ); } else { msSetError(MS_WMSCONNERR, @@ -1406,7 +1513,7 @@ } /* We're done with the remote server's response... delete it. */ - if (!lp->debug) + if (!lp->debug || mem_filename != NULL) VSIUnlink(lp->data); /* restore prveious type */ @@ -1452,15 +1559,16 @@ /* Generate the http request */ for (i=0; inumlayers; i++) { if (GET_LAYER(map,map->layerorder[i])->status == MS_ON) { - if (type == WMS_GETFEATUREINFO && - msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), + if (type == WMS_GETFEATUREINFO ) { + if( msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETFEATUREINFO, MS_WMS, &sLastWMSParams, nClickX, nClickY, nFeatureCount, pszInfoFormat, pasReqInfo, &numReq) == MS_FAILURE) { - msFreeWmsParamsObj(&sLastWMSParams); - msFree(pasReqInfo); - return MS_FAILURE; + msFreeWmsParamsObj(&sLastWMSParams); + msFree(pasReqInfo); + return MS_FAILURE; + } } else if (msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETLEGENDGRAPHIC, MS_WMS, &sLastWMSParams, diff -Nru mapserver-7.0.7/mapxbase.c mapserver-7.6.4/mapxbase.c --- mapserver-7.0.7/mapxbase.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/mapxbase.c 2021-07-12 20:16:21.000000000 +0000 @@ -28,22 +28,13 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#define _FILE_OFFSET_BITS 64 - #include "mapserver.h" #include /* for atof() and atoi() */ #include +#include "cpl_vsi.h" - -/* try to use a large file version of fseek for files up to 4GB (#3514) */ -#if _MSC_VER > 1310 -# define safe_fseek _fseeki64 -#elif defined(fseeko) -# define safe_fseek fseeko -#else -# define safe_fseek fseek -#endif +static inline void IGUR_sizet(size_t ignored) { (void)ignored; } /* Ignore GCC Unused Result */ /************************************************************************/ /* SfRealloc() */ @@ -96,9 +87,9 @@ /* Write the initial 32 byte file header, and all the field */ /* descriptions. */ /* -------------------------------------------------------------------- */ - fseek( psDBF->fp, 0, 0 ); - fwrite( abyHeader, 32, 1, psDBF->fp ); - fwrite( psDBF->pszHeader, 32, psDBF->nFields, psDBF->fp ); + VSIFSeekL( psDBF->fp, 0, 0 ); + VSIFWriteL( abyHeader, 32, 1, psDBF->fp ); + VSIFWriteL( psDBF->pszHeader, 32, psDBF->nFields, psDBF->fp ); /* -------------------------------------------------------------------- */ /* Write out the newline character if there is room for it. */ @@ -107,7 +98,7 @@ char cNewline; cNewline = 0x0d; - fwrite( &cNewline, 1, 1, psDBF->fp ); + VSIFWriteL( &cNewline, 1, 1, psDBF->fp ); } } @@ -127,8 +118,8 @@ nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord + psDBF->nHeaderLength; - safe_fseek( psDBF->fp, nRecordOffset, 0 ); - fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, nRecordOffset, 0 ); + VSIFWriteL( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); } } @@ -172,12 +163,12 @@ /* -------------------------------------------------------------------- */ psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) ); MS_CHECK_ALLOC(psDBF, sizeof(DBFInfo), NULL); - psDBF->fp = fopen( pszDBFFilename, pszAccess ); + psDBF->fp = VSIFOpenL( pszDBFFilename, pszAccess ); if( psDBF->fp == NULL ) { if( strcmp(pszDBFFilename+strlen(pszDBFFilename)-4,".dbf") == 0 ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".DBF"); - psDBF->fp = fopen( pszDBFFilename, pszAccess ); + psDBF->fp = VSIFOpenL( pszDBFFilename, pszAccess ); } } if( psDBF->fp == NULL ) { @@ -199,7 +190,13 @@ /* Read Table Header info */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) msSmallMalloc(500); - fread( pabyBuf, 32, 1, psDBF->fp ); + if( VSIFReadL( pabyBuf, 32, 1, psDBF->fp ) != 1 ) + { + VSIFCloseL( psDBF->fp ); + msFree(psDBF); + msFree(pabyBuf); + return( NULL ); + } psDBF->nRecords = nRecords = pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256; @@ -207,6 +204,13 @@ psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256; psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256; + if (nHeadLen <= 32) { + VSIFCloseL( psDBF->fp ); + msFree(psDBF); + msFree(pabyBuf); + return( NULL ); + } + psDBF->nFields = nFields = (nHeadLen - 32) / 32; psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen); @@ -217,8 +221,15 @@ pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen); psDBF->pszHeader = (char *) pabyBuf; - fseek( psDBF->fp, 32, 0 ); - fread( pabyBuf, nHeadLen, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, 32, 0 ); + if( VSIFReadL( pabyBuf, nHeadLen - 32, 1, psDBF->fp ) != 1 ) + { + msFree(psDBF->pszCurrentRecord); + VSIFCloseL( psDBF->fp ); + msFree(psDBF); + msFree(pabyBuf); + return( NULL ); + } psDBF->panFieldOffset = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->panFieldSize = (int *) msSmallMalloc(sizeof(int) * nFields); @@ -270,8 +281,8 @@ if( psDBF->bUpdated ) { uchar abyFileHeader[32]; - fseek( psDBF->fp, 0, 0 ); - fread( abyFileHeader, 32, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, 0, 0 ); + IGUR_sizet(VSIFReadL( abyFileHeader, 32, 1, psDBF->fp )); abyFileHeader[1] = 95; /* YY */ abyFileHeader[2] = 7; /* MM */ @@ -282,14 +293,14 @@ abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256; abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256; - fseek( psDBF->fp, 0, 0 ); - fwrite( abyFileHeader, 32, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, 0, 0 ); + VSIFWriteL( abyFileHeader, 32, 1, psDBF->fp ); } /* -------------------------------------------------------------------- */ /* Close, and free resources. */ /* -------------------------------------------------------------------- */ - fclose( psDBF->fp ); + VSIFCloseL( psDBF->fp ); if( psDBF->panFieldOffset != NULL ) { free( psDBF->panFieldOffset ); @@ -315,19 +326,22 @@ { DBFHandle psDBF; - FILE *fp; + VSILFILE *fp; /* -------------------------------------------------------------------- */ /* Create the file. */ /* -------------------------------------------------------------------- */ - fp = fopen( pszFilename, "wb" ); + fp = VSIFOpenL( pszFilename, "wb" ); if( fp == NULL ) return( NULL ); - fputc( 0, fp ); - fclose( fp ); + { + char ch = 0; + VSIFWriteL(&ch, 1, 1, fp); + } + VSIFCloseL( fp ); - fp = fopen( pszFilename, "rb+" ); + fp = VSIFOpenL( pszFilename, "rb+" ); if( fp == NULL ) return( NULL ); @@ -338,7 +352,7 @@ if (psDBF == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDBFCreate()", __FILE__, __LINE__, (unsigned int)sizeof(DBFInfo)); - fclose(fp); + VSIFCloseL(fp); return NULL; } @@ -434,10 +448,7 @@ for( i = 0; i < 32; i++ ) pszFInfo[i] = '\0'; - if( strlen(pszFieldName) < 10 ) - strncpy( pszFInfo, pszFieldName, strlen(pszFieldName)); - else - strncpy( pszFInfo, pszFieldName, 10); + strncpy( pszFInfo, pszFieldName, 10); pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1]; @@ -523,8 +534,12 @@ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength; - safe_fseek( psDBF->fp, nRecordOffset, 0 ); - fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, nRecordOffset, 0 ); + if( VSIFReadL( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ) != 1 ) + { + msSetError(MS_DBFERR, "Cannot read record %d.", "msDBFReadAttribute()",hEntity ); + return( NULL ); + } psDBF->nCurrentRecord = hEntity; } @@ -675,9 +690,9 @@ static int msDBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void * pValue ) { unsigned int nRecordOffset; - int i, j; + int i, len; uchar *pabyRec; - char szSField[40], szFormat[12]; + char szSField[40]; /* -------------------------------------------------------------------- */ /* Is this a valid record? */ @@ -710,8 +725,9 @@ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength; - safe_fseek( psDBF->fp, nRecordOffset, 0 ); - fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); + VSIFSeekL( psDBF->fp, nRecordOffset, 0 ); + if( VSIFReadL( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ) != 1 ) + return MS_FALSE; psDBF->nCurrentRecord = hEntity; } @@ -725,28 +741,14 @@ case 'D': case 'N': case 'F': - if( psDBF->panFieldDecimals[iField] == 0 ) { - snprintf( szFormat, sizeof(szFormat), "%%%dd", psDBF->panFieldSize[iField] ); - snprintf(szSField, sizeof(szSField), szFormat, (int) *((double *) pValue) ); - if( (int) strlen(szSField) > psDBF->panFieldSize[iField] ) - szSField[psDBF->panFieldSize[iField]] = '\0'; - strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) ); - } else { - snprintf( szFormat, sizeof(szFormat), "%%%d.%df", psDBF->panFieldSize[iField], psDBF->panFieldDecimals[iField] ); - snprintf(szSField, sizeof(szSField), szFormat, *((double *) pValue) ); - if( (int) strlen(szSField) > psDBF->panFieldSize[iField] ) - szSField[psDBF->panFieldSize[iField]] = '\0'; - strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) ); - } + snprintf(szSField, sizeof(szSField), "%*.*f", psDBF->panFieldSize[iField], psDBF->panFieldDecimals[iField], *(double*) pValue); + len = strlen((char *) szSField); + memcpy(pabyRec+psDBF->panFieldOffset[iField], szSField, MS_MIN(len, psDBF->panFieldSize[iField])); break; default: - if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] ) - j = psDBF->panFieldSize[iField]; - else - j = strlen((char *) pValue); - - strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), (char *) pValue, j ); + len = strlen((char *) pValue); + memcpy(pabyRec+psDBF->panFieldOffset[iField], pValue, MS_MIN(len, psDBF->panFieldSize[iField])); break; } diff -Nru mapserver-7.0.7/MIGRATION_GUIDE.txt mapserver-7.6.4/MIGRATION_GUIDE.txt --- mapserver-7.0.7/MIGRATION_GUIDE.txt 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/MIGRATION_GUIDE.txt 2021-07-12 20:16:21.000000000 +0000 @@ -3,12 +3,13 @@ ***************************************************************************** The current version of the MapServer Migration Guide is available online -at http://www.mapserver.org/MIGRATION_GUIDE.html. +at https://mapserver.org/MIGRATION_GUIDE.html. For developers: -The master copy of the MIGRATION_GUIDE is now located in the root of the -mapserver/docs source tree (https://github.com/mapserver/docs). Developers -are welcome and encouraged to edit/update the guide in the docs tree directly. +The main copy of the MIGRATION_GUIDE is now located in the root of the +/MapServer/MapServer-documentation source tree ( https://github.com/MapServer/MapServer-documentation ). +Developers are welcome and encouraged to edit/update the guide in the documentation +tree directly. diff -Nru mapserver-7.0.7/README mapserver-7.6.4/README --- mapserver-7.0.7/README 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -------- -Summary -------- - - -MapServer is a system for developing web-based GIS applications. -The basic system consists of a CGI program that can be configured to -respond to a variety of spatial requests like making maps, scalebars, -and point, area and feature queries. Virtually all aspects of an -application, from web interface to map appearance can be developed -without any programming. For the more ambitious user, MapServer -applications can be enhanced using Java, JavaScript or many other web -technologies. For more information and complete documentation please -visit: - - http://www.mapserver.org/ - -Bug reports and enhancment submissions can be reported in the MapServer -issue tracker at the following url. If you do make changes and/or enhancements, -please let us know so that they might be incorporated into future releases. - - https://github.com/mapserver/mapserver/issues - - -Join the MapServer user mailing list online at: - - http://www.mapserver.org/community/lists.html - - - ------------ -Credits ------------ - -MapServer was originally written by Stephen Lime. Major funding for development of -MapServer has been provided by NASA through cooperative argreements with -the University of Minnesota, Department of Forest Resources. - -PHP/MapScript developed by DM Solutions Group. - -GDAL/OGR support and significant WMS support provided by DM Solutions Group -which received funding support from Canadian Government's GeoConnections -Program and the Canadian Forest Service. - -Raster support developed by Pete Olson of the State of Minnesota, Land -Management Information Center, and maintained by Frank Warmerdam (DM -Solutions). - -PostGIS spatial database support provided by Dave Blasby of Refractions -Research. - -PDF support developed by Jeff Spielberg and Jamie Wall of Market Insite Group, -Inc. - -OracleSpatial support developed by Rodrigo Cabral of CTTMAR/UNIVALI, Brazil. - -Portions Copyright (c) 1998 State of Minnesota, Land Management Information -Center. - -Portions derived from Shapelib, Copyright 1995-1999 Frank Warmerdam. - -Supporting packages are covered by their own copyrights. - ------------ -License ------------ - -:: - - Copyright (c) 2008-2017 Open Source Geospatial Foundation. - Copyright (c) 1996-2008 Regents of the University of Minnesota. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is furnished - to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies of this Software or works derived from this Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - - diff -Nru mapserver-7.0.7/README.rst mapserver-7.6.4/README.rst --- mapserver-7.0.7/README.rst 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/README.rst 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,101 @@ +MapServer +========= + +| |Build Status| |Appveyor Build Status| |Coveralls Status| + +------- +Summary +------- + +MapServer is a system for developing web-based GIS applications. +The basic system consists of a CGI program that can be configured to +respond to a variety of spatial requests like making maps, scalebars, +and point, area and feature queries. Virtually all aspects of an +application, from web interface to map appearance can be developed +without any programming. For the more ambitious user, MapServer +applications can be enhanced using Python, PHP, Java, JavaScript or +many other web technologies. For more information and complete +documentation please visit: + + https://mapserver.org/ + +Bug reports and enhancement submissions can be reported in the MapServer +issue tracker at the following url. If you do make changes and/or enhancements, +please let us know so that they might be incorporated into future releases. + + https://github.com/MapServer/MapServer/issues + + +Join the MapServer user mailing list online at: + + https://mapserver.org/community/lists.html + + + +Credits +------- + +MapServer was originally written by Stephen Lime. Major funding for development of +MapServer has been provided by NASA through cooperative argreements with +the University of Minnesota, Department of Forest Resources. + +PHP/MapScript developed by DM Solutions Group. + +GDAL/OGR support and significant WMS support provided by DM Solutions Group +which received funding support from Canadian Government's GeoConnections +Program and the Canadian Forest Service. + +Raster support developed by Pete Olson of the State of Minnesota, Land +Management Information Center, and maintained by Frank Warmerdam (DM +Solutions). + +PostGIS spatial database support provided by Dave Blasby of Refractions +Research. + +PDF support developed by Jeff Spielberg and Jamie Wall of Market Insite Group, +Inc. + +OracleSpatial support developed by Rodrigo Cabral of CTTMAR/UNIVALI, Brazil. + +Portions Copyright (c) 1998 State of Minnesota, Land Management Information +Center. + +Portions derived from Shapelib, Copyright 1995-1999 Frank Warmerdam. + +Supporting packages are covered by their own copyrights. + +License +------- + +:: + + Copyright (c) 2008-2021 Open Source Geospatial Foundation. + Copyright (c) 1996-2008 Regents of the University of Minnesota. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies of this Software or works derived from this Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + +.. |Build Status| image:: https://travis-ci.com/MapServer/MapServer.svg?branch=main + :target: https://travis-ci.com/MapServer/MapServer + +.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/vw1n07095a8bg23u?svg=true + :target: https://ci.appveyor.com/project/mapserver/mapserver + +.. |Coveralls Status| image:: https://coveralls.io/repos/github/mapserver/mapserver/badge.svg?branch=master + :target: https://coveralls.io/github/mapserver/mapserver?branch=master diff -Nru mapserver-7.0.7/renderers/agg/include/agg_basics.h mapserver-7.6.4/renderers/agg/include/agg_basics.h --- mapserver-7.0.7/renderers/agg/include/agg_basics.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_basics.h 2021-07-12 20:16:21.000000000 +0000 @@ -211,7 +211,7 @@ { AGG_INLINE static unsigned mul(unsigned a, unsigned b) { - register unsigned q = a * b + (1 << (Shift-1)); + const unsigned q = a * b + (1 << (Shift-1)); return (q + (q >> Shift)) >> Shift; } }; diff -Nru mapserver-7.0.7/renderers/agg/include/agg_conv_clipper.h mapserver-7.6.4/renderers/agg/include/agg_conv_clipper.h --- mapserver-7.0.7/renderers/agg/include/agg_conv_clipper.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_conv_clipper.h 2021-07-12 20:16:21.000000000 +0000 @@ -1,299 +1,299 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 1.1 * -* Date : 4 April 2011 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2011 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -*******************************************************************************/ - -#ifndef AGG_CONV_CLIPPER_INCLUDED -#define AGG_CONV_CLIPPER_INCLUDED - -#if defined(_MSC_VER) && (_MSC_VER >= 1800) -#include -#endif - -#include -#include "agg_basics.h" -#include "agg_array.h" -#include "clipper.hpp" - -namespace mapserver -{ - enum clipper_op_e { clipper_or, - clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a }; - enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative}; - - template class conv_clipper - { - enum status { status_move_to, status_line_to, status_stop }; - typedef VSA source_a_type; - typedef VSB source_b_type; - typedef conv_clipper self_type; - - private: - source_a_type* m_src_a; - source_b_type* m_src_b; - status m_status; - int m_vertex; - int m_contour; - int m_scaling_factor; - clipper_op_e m_operation; - pod_bvector m_vertex_accumulator; - ClipperLib::Polygons m_poly_a; - ClipperLib::Polygons m_poly_b; - ClipperLib::Polygons m_result; - ClipperLib::Clipper m_clipper; - clipper_PolyFillType m_subjFillType; - clipper_PolyFillType m_clipFillType; - - int Round(double val) - { - if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5); - } - - public: - conv_clipper(source_a_type &a, source_b_type &b, - clipper_op_e op = clipper_or, - clipper_PolyFillType subjFillType = clipper_even_odd, - clipper_PolyFillType clipFillType = clipper_even_odd, - int scaling_factor = 2) : - m_src_a(&a), - m_src_b(&b), - m_status(status_move_to), - m_vertex(-1), - m_contour(-1), - m_operation(op), - m_subjFillType(subjFillType), - m_clipFillType(clipFillType) - { - m_scaling_factor = std::max(std::min(scaling_factor, 6),0); - m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); - } - - ~conv_clipper() - { - } - - void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd) - { m_src_a = &source; m_subjFillType = subjFillType; } - void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd) - { m_src_b = &source; m_clipFillType = clipFillType; } - - void operation(clipper_op_e v) { m_operation = v; } - - void rewind(unsigned path_id); - unsigned vertex(double* x, double* y); - - bool next_contour(); - bool next_vertex(double* x, double* y); - void start_extracting(); - void add_vertex_(double &x, double &y); - void end_contour(ClipperLib::Polygons &p); - - template void add(VS &src, ClipperLib::Polygons &p){ - unsigned cmd; - double x; double y; double start_x; double start_y; - bool starting_first_line; - - start_x = 0.0; - start_y = 0.0; - starting_first_line = true; - p.resize(0); - - cmd = src->vertex( &x , &y ); - while(!is_stop(cmd)) - { - if(is_vertex(cmd)) - { - if(is_move_to(cmd)) - { - if(!starting_first_line ) end_contour(p); - start_x = x; - start_y = y; - } - add_vertex_( x, y ); - starting_first_line = false; - } - else if(is_end_poly(cmd)) - { - if(!starting_first_line && is_closed(cmd)) - add_vertex_( start_x, start_y ); - } - cmd = src->vertex( &x, &y ); - } - end_contour(p); - } - }; - - //------------------------------------------------------------------------ - - template - void conv_clipper::start_extracting() - { - m_status = status_move_to; - m_contour = -1; - m_vertex = -1; - } - //------------------------------------------------------------------------------ - - template - void conv_clipper::rewind(unsigned path_id) - { - m_src_a->rewind( path_id ); - m_src_b->rewind( path_id ); - - add( m_src_a , m_poly_a ); - add( m_src_b , m_poly_b ); - m_result.resize(0); - - ClipperLib::PolyFillType pftSubj, pftClip; - switch (m_subjFillType) - { - case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break; - case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break; - case clipper_positive: pftSubj = ClipperLib::pftPositive; break; - default: pftSubj = ClipperLib::pftNegative; - } - switch (m_clipFillType) - { - case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break; - case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break; - case clipper_positive: pftClip = ClipperLib::pftPositive; break; - default: pftClip = ClipperLib::pftNegative; - } - - m_clipper.Clear(); - switch( m_operation ) { - case clipper_or: - { - m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); - m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); - m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip); - break; - } - case clipper_and: - { - m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); - m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); - m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip ); - break; - } - case clipper_xor: - { - m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); - m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); - m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip ); - break; - } - case clipper_a_minus_b: - { - m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); - m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); - m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); - break; - } - case clipper_b_minus_a: - { - m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject ); - m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip ); - m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); - break; - } - } - start_extracting(); - } - //------------------------------------------------------------------------------ - - template - void conv_clipper::end_contour( ClipperLib::Polygons &p) - { - unsigned i, len; - - if( m_vertex_accumulator.size() < 3 ) return; - len = p.size(); - p.resize(len+1); - p[len].resize(m_vertex_accumulator.size()); - for( i = 0 ; i < m_vertex_accumulator.size() ; i++ ) - p[len][i] = m_vertex_accumulator[i]; - m_vertex_accumulator.remove_all(); - } - //------------------------------------------------------------------------------ - - template - void conv_clipper::add_vertex_(double &x, double &y) - { - ClipperLib::IntPoint v; - - v.X = Round(x * m_scaling_factor); - v.Y = Round(y * m_scaling_factor); - m_vertex_accumulator.add( v ); - } - //------------------------------------------------------------------------------ - - template - bool conv_clipper::next_contour() - { - m_contour++; - if(m_contour >= (int)m_result.size()) return false; - m_vertex =-1; - return true; -} -//------------------------------------------------------------------------------ - - template - bool conv_clipper::next_vertex(double *x, double *y) - { - m_vertex++; - if(m_vertex >= (int)m_result[m_contour].size()) return false; - *x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor; - *y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor; - return true; - } - //------------------------------------------------------------------------------ - - template - unsigned conv_clipper::vertex(double *x, double *y) -{ - if( m_status == status_move_to ) - { - if( next_contour() ) - { - if( next_vertex( x, y ) ) - { - m_status =status_line_to; - return path_cmd_move_to; - } - else - { - m_status = status_stop; - return path_cmd_end_poly | path_flags_close; - } - } - else - return path_cmd_stop; - } - else - { - if( next_vertex( x, y ) ) - { - return path_cmd_line_to; - } - else - { - m_status = status_move_to; - return path_cmd_end_poly | path_flags_close; - } - } -} -//------------------------------------------------------------------------------ - - -} //namespace agg -#endif //AGG_CONV_CLIPPER_INCLUDED +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 1.1 * +* Date : 4 April 2011 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2011 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +*******************************************************************************/ + +#ifndef AGG_CONV_CLIPPER_INCLUDED +#define AGG_CONV_CLIPPER_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#include +#endif + +#include +#include "agg_basics.h" +#include "agg_array.h" +#include "clipper.hpp" + +namespace mapserver +{ + enum clipper_op_e { clipper_or, + clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a }; + enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative}; + + template class conv_clipper + { + enum status { status_move_to, status_line_to, status_stop }; + typedef VSA source_a_type; + typedef VSB source_b_type; + typedef conv_clipper self_type; + + private: + source_a_type* m_src_a; + source_b_type* m_src_b; + status m_status; + int m_vertex; + int m_contour; + int m_scaling_factor; + clipper_op_e m_operation; + pod_bvector m_vertex_accumulator; + ClipperLib::Polygons m_poly_a; + ClipperLib::Polygons m_poly_b; + ClipperLib::Polygons m_result; + ClipperLib::Clipper m_clipper; + clipper_PolyFillType m_subjFillType; + clipper_PolyFillType m_clipFillType; + + int Round(double val) + { + if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5); + } + + public: + conv_clipper(source_a_type &a, source_b_type &b, + clipper_op_e op = clipper_or, + clipper_PolyFillType subjFillType = clipper_even_odd, + clipper_PolyFillType clipFillType = clipper_even_odd, + int scaling_factor = 2) : + m_src_a(&a), + m_src_b(&b), + m_status(status_move_to), + m_vertex(-1), + m_contour(-1), + m_operation(op), + m_subjFillType(subjFillType), + m_clipFillType(clipFillType) + { + m_scaling_factor = std::max(std::min(scaling_factor, 6),0); + m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); + } + + ~conv_clipper() + { + } + + void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd) + { m_src_a = &source; m_subjFillType = subjFillType; } + void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd) + { m_src_b = &source; m_clipFillType = clipFillType; } + + void operation(clipper_op_e v) { m_operation = v; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + bool next_contour(); + bool next_vertex(double* x, double* y); + void start_extracting(); + void add_vertex_(double &x, double &y); + void end_contour(ClipperLib::Polygons &p); + + template void add(VS &src, ClipperLib::Polygons &p){ + unsigned cmd; + double x; double y; double start_x; double start_y; + bool starting_first_line; + + start_x = 0.0; + start_y = 0.0; + starting_first_line = true; + p.resize(0); + + cmd = src->vertex( &x , &y ); + while(!is_stop(cmd)) + { + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(!starting_first_line ) end_contour(p); + start_x = x; + start_y = y; + } + add_vertex_( x, y ); + starting_first_line = false; + } + else if(is_end_poly(cmd)) + { + if(!starting_first_line && is_closed(cmd)) + add_vertex_( start_x, start_y ); + } + cmd = src->vertex( &x, &y ); + } + end_contour(p); + } + }; + + //------------------------------------------------------------------------ + + template + void conv_clipper::start_extracting() + { + m_status = status_move_to; + m_contour = -1; + m_vertex = -1; + } + //------------------------------------------------------------------------------ + + template + void conv_clipper::rewind(unsigned path_id) + { + m_src_a->rewind( path_id ); + m_src_b->rewind( path_id ); + + add( m_src_a , m_poly_a ); + add( m_src_b , m_poly_b ); + m_result.resize(0); + + ClipperLib::PolyFillType pftSubj, pftClip; + switch (m_subjFillType) + { + case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break; + case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break; + case clipper_positive: pftSubj = ClipperLib::pftPositive; break; + default: pftSubj = ClipperLib::pftNegative; + } + switch (m_clipFillType) + { + case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break; + case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break; + case clipper_positive: pftClip = ClipperLib::pftPositive; break; + default: pftClip = ClipperLib::pftNegative; + } + + m_clipper.Clear(); + switch( m_operation ) { + case clipper_or: + { + m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); + m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); + m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip); + break; + } + case clipper_and: + { + m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); + m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); + m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip ); + break; + } + case clipper_xor: + { + m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); + m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); + m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip ); + break; + } + case clipper_a_minus_b: + { + m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); + m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); + m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); + break; + } + case clipper_b_minus_a: + { + m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject ); + m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip ); + m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); + break; + } + } + start_extracting(); + } + //------------------------------------------------------------------------------ + + template + void conv_clipper::end_contour( ClipperLib::Polygons &p) + { + unsigned i, len; + + if( m_vertex_accumulator.size() < 3 ) return; + len = p.size(); + p.resize(len+1); + p[len].resize(m_vertex_accumulator.size()); + for( i = 0 ; i < m_vertex_accumulator.size() ; i++ ) + p[len][i] = m_vertex_accumulator[i]; + m_vertex_accumulator.remove_all(); + } + //------------------------------------------------------------------------------ + + template + void conv_clipper::add_vertex_(double &x, double &y) + { + ClipperLib::IntPoint v; + + v.X = Round(x * m_scaling_factor); + v.Y = Round(y * m_scaling_factor); + m_vertex_accumulator.add( v ); + } + //------------------------------------------------------------------------------ + + template + bool conv_clipper::next_contour() + { + m_contour++; + if(m_contour >= (int)m_result.size()) return false; + m_vertex =-1; + return true; +} +//------------------------------------------------------------------------------ + + template + bool conv_clipper::next_vertex(double *x, double *y) + { + m_vertex++; + if(m_vertex >= (int)m_result[m_contour].size()) return false; + *x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor; + *y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor; + return true; + } + //------------------------------------------------------------------------------ + + template + unsigned conv_clipper::vertex(double *x, double *y) +{ + if( m_status == status_move_to ) + { + if( next_contour() ) + { + if( next_vertex( x, y ) ) + { + m_status =status_line_to; + return path_cmd_move_to; + } + else + { + m_status = status_stop; + return path_cmd_end_poly | path_flags_close; + } + } + else + return path_cmd_stop; + } + else + { + if( next_vertex( x, y ) ) + { + return path_cmd_line_to; + } + else + { + m_status = status_move_to; + return path_cmd_end_poly | path_flags_close; + } + } +} +//------------------------------------------------------------------------------ + + +} //namespace agg +#endif //AGG_CONV_CLIPPER_INCLUDED diff -Nru mapserver-7.0.7/renderers/agg/include/agg_conv_curve.h mapserver-7.6.4/renderers/agg/include/agg_conv_curve.h --- mapserver-7.0.7/renderers/agg/include/agg_conv_curve.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_conv_curve.h 2021-07-12 20:16:21.000000000 +0000 @@ -154,10 +154,10 @@ return path_cmd_line_to; } - double ct2_x; - double ct2_y; - double end_x; - double end_y; + double ct2_x = 0; + double ct2_y = 0; + double end_x = 0; + double end_y = 0; unsigned cmd = m_source->vertex(x, y); switch(cmd) diff -Nru mapserver-7.0.7/renderers/agg/include/agg_image_accessors.h mapserver-7.6.4/renderers/agg/include/agg_image_accessors.h --- mapserver-7.0.7/renderers/agg/include/agg_image_accessors.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_image_accessors.h 2021-07-12 20:16:21.000000000 +0000 @@ -174,8 +174,8 @@ private: AGG_INLINE const int8u* pixel() const { - register int x = m_x; - register int y = m_y; + int x = m_x; + int y = m_y; if(x < 0) x = 0; if(y < 0) y = 0; if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; diff -Nru mapserver-7.0.7/renderers/agg/include/agg_path_storage.h mapserver-7.6.4/renderers/agg/include/agg_path_storage.h --- mapserver-7.0.7/renderers/agg/include/agg_path_storage.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_path_storage.h 2021-07-12 20:16:21.000000000 +0000 @@ -720,7 +720,7 @@ template void concat_path(VertexSource& vs, unsigned path_id = 0) { - double x, y; + double x = 0, y = 0; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) diff -Nru mapserver-7.0.7/renderers/agg/include/agg_rendering_buffer.h mapserver-7.6.4/renderers/agg/include/agg_rendering_buffer.h --- mapserver-7.0.7/renderers/agg/include/agg_rendering_buffer.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_rendering_buffer.h 2021-07-12 20:16:21.000000000 +0000 @@ -128,7 +128,7 @@ private: //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer + T* m_buf; // Pointer to rendering buffer T* m_start; // Pointer to first pixel depending on stride unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels @@ -258,7 +258,7 @@ private: //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer + T* m_buf; // Pointer to rendering buffer pod_array m_rows; // Pointers to each row of the buffer unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels diff -Nru mapserver-7.0.7/renderers/agg/include/agg_trans_affine.h mapserver-7.6.4/renderers/agg/include/agg_trans_affine.h --- mapserver-7.0.7/renderers/agg/include/agg_trans_affine.h 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_trans_affine.h 2021-07-12 20:16:21.000000000 +0000 @@ -292,7 +292,7 @@ //------------------------------------------------------------------------ inline void trans_affine::transform(double* x, double* y) const { - register double tmp = *x; + const double tmp = *x; *x = tmp * sx + *y * shx + tx; *y = tmp * shy + *y * sy + ty; } @@ -300,7 +300,7 @@ //------------------------------------------------------------------------ inline void trans_affine::transform_2x2(double* x, double* y) const { - register double tmp = *x; + const double tmp = *x; *x = tmp * sx + *y * shx; *y = tmp * shy + *y * sy; } @@ -308,9 +308,9 @@ //------------------------------------------------------------------------ inline void trans_affine::inverse_transform(double* x, double* y) const { - register double d = determinant_reciprocal(); - register double a = (*x - tx) * d; - register double b = (*y - ty) * d; + const double d = determinant_reciprocal(); + const double a = (*x - tx) * d; + const double b = (*y - ty) * d; *x = a * sy - b * shx; *y = b * sx - a * shy; } diff -Nru mapserver-7.0.7/renderers/agg/include/clipper.hpp mapserver-7.6.4/renderers/agg/include/clipper.hpp --- mapserver-7.0.7/renderers/agg/include/clipper.hpp 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/clipper.hpp 2021-07-12 20:16:21.000000000 +0000 @@ -1,302 +1,302 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.6.3 * -* Date : 11 November 2011 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2011 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -#ifndef clipper_hpp -#define clipper_hpp - -#include -#include -#include -#include -#include - -namespace ClipperLib { - -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -//By far the most widely used winding rules for polygon filling are -//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -//see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; - -typedef signed long long long64; -typedef unsigned long long ulong64; - -struct IntPoint { -public: - long64 X; - long64 Y; - IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; - friend std::ostream& operator <<(std::ostream &s, IntPoint &p); -}; - -typedef std::vector< IntPoint > Polygon; -typedef std::vector< Polygon > Polygons; - -std::ostream& operator <<(std::ostream &s, Polygon &p); -std::ostream& operator <<(std::ostream &s, Polygons &p); - -struct ExPolygon { - Polygon outer; - Polygons holes; -}; -typedef std::vector< ExPolygon > ExPolygons; - -enum JoinType { jtSquare, jtMiter, jtRound }; - -bool Orientation(const Polygon &poly); -double Area(const Polygon &poly); -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype = jtSquare, double MiterLimit = 2); - -void ReversePoints(Polygon& p); -void ReversePoints(Polygons& p); - -//used internally ... -enum EdgeSide { esLeft, esRight }; -enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; - -struct TEdge { - long64 xbot; - long64 ybot; - long64 xcurr; - long64 ycurr; - long64 xtop; - long64 ytop; - double dx; - long64 tmpX; - PolyType polyType; - EdgeSide side; - int windDelta; //1 or -1 depending on winding direction - int windCnt; - int windCnt2; //winding count of the opposite polytype - int outIdx; - TEdge *next; - TEdge *prev; - TEdge *nextInLML; - TEdge *nextInAEL; - TEdge *prevInAEL; - TEdge *nextInSEL; - TEdge *prevInSEL; -}; - -struct IntersectNode { - TEdge *edge1; - TEdge *edge2; - IntPoint pt; - IntersectNode *next; -}; - -struct LocalMinima { - long64 Y; - TEdge *leftBound; - TEdge *rightBound; - LocalMinima *next; -}; - -struct Scanbeam { - long64 Y; - Scanbeam *next; -}; - -struct OutPt; //forward declaration - -struct OutRec { - int idx; - bool isHole; - OutRec *FirstLeft; - OutRec *AppendLink; - OutPt *pts; - OutPt *bottomPt; - TEdge *bottomE1; - TEdge *bottomE2; -}; - -struct OutPt { - int idx; - IntPoint pt; - OutPt *next; - OutPt *prev; -}; - -struct JoinRec { - IntPoint pt1a; - IntPoint pt1b; - int poly1Idx; - IntPoint pt2a; - IntPoint pt2b; - int poly2Idx; -}; - -struct HorzJoinRec { - TEdge *edge; - int savedIdx; -}; - -struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; - -typedef std::vector < OutRec* > PolyOutList; -typedef std::vector < TEdge* > EdgeList; -typedef std::vector < JoinRec* > JoinList; -typedef std::vector < HorzJoinRec* > HorzJoinList; - -//ClipperBase is the ancestor to the Clipper class. It should not be -//instantiated directly. This class simply abstracts the conversion of sets of -//polygon coordinates into edge objects that are stored in a LocalMinima list. -class ClipperBase -{ -public: - ClipperBase(); - virtual ~ClipperBase(); - bool AddPolygon(const Polygon &pg, PolyType polyType); - bool AddPolygons( const Polygons &ppg, PolyType polyType); - virtual void Clear(); - IntRect GetBounds(); -protected: - void DisposeLocalMinimaList(); - TEdge* AddBoundsToLML(TEdge *e); - void PopLocalMinima(); - virtual void Reset(); - void InsertLocalMinima(LocalMinima *newLm); - LocalMinima *m_CurrentLM; - LocalMinima *m_MinimaList; - bool m_UseFullRange; - EdgeList m_edges; -}; - -class Clipper : public virtual ClipperBase -{ -public: - Clipper(); - ~Clipper(); - bool Execute(ClipType clipType, - Polygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - bool Execute(ClipType clipType, - ExPolygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - void Clear(); - bool ReverseSolution() {return m_ReverseOutput;}; - void ReverseSolution(bool value) {m_ReverseOutput = value;}; -protected: - void Reset(); - virtual bool ExecuteInternal(bool fixHoleLinkages); -private: - PolyOutList m_PolyOuts; - JoinList m_Joins; - HorzJoinList m_HorizJoins; - ClipType m_ClipType; - Scanbeam *m_Scanbeam; - TEdge *m_ActiveEdges; - TEdge *m_SortedEdges; - IntersectNode *m_IntersectNodes; - bool m_ExecuteLocked; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - void DisposeScanbeamList(); - void SetWindingCount(TEdge& edge); - bool IsEvenOddFillType(const TEdge& edge) const; - bool IsEvenOddAltFillType(const TEdge& edge) const; - void InsertScanbeam(const long64 Y); - long64 PopScanbeam(); - void InsertLocalMinimaIntoAEL(const long64 botY); - void InsertEdgeIntoAEL(TEdge *edge); - void AddEdgeToSEL(TEdge *edge); - void CopyAELToSEL(); - void DeleteFromSEL(TEdge *e); - void DeleteFromAEL(TEdge *e); - void UpdateEdgeIntoAEL(TEdge *&e); - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - bool IsContributing(const TEdge& edge) const; - bool IsTopHorz(const long64 XPos); - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - void DoMaxima(TEdge *e, long64 topY); - void ProcessHorizontals(); - void ProcessHorizontal(TEdge *horzEdge); - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AppendPolygon(TEdge *e1, TEdge *e2); - void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects); - OutRec* CreateOutRec(); - void AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt); - void DisposeAllPolyPts(); - void DisposeOutRec(PolyOutList::size_type index, bool ignorePts = false); - bool ProcessIntersections(const long64 botY, const long64 topY); - void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); - void BuildIntersectList(const long64 botY, const long64 topY); - void ProcessIntersectList(); - void ProcessEdgesAtTopOfScanbeam(const long64 topY); - void BuildResult(Polygons& polys); - void BuildResultEx(ExPolygons& polys); - void SetHoleState(TEdge *e, OutRec *OutRec); - void DisposeIntersectNodes(); - bool FixupIntersections(); - void FixupOutPolygon(OutRec &outRec); - bool IsHole(TEdge *e); - void FixHoleLinkage(OutRec *outRec); - void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); - void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); - void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); - void ClearJoins(); - void AddHorzJoin(TEdge *e, int idx); - void ClearHorzJoins(); - void JoinCommonEdges(bool fixHoleLinkages); -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class clipperException : public std::exception -{ - public: - clipperException(const char* description): m_descr(description) {} - virtual ~clipperException() throw() {} - virtual const char* what() const throw() {return m_descr.c_str();} - private: - std::string m_descr; -}; -//------------------------------------------------------------------------------ - -} //ClipperLib namespace - -#endif //clipper_hpp - - +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.6.3 * +* Date : 11 November 2011 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2011 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#include +#include +#include +#include +#include + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +typedef signed long long long64; +typedef unsigned long long ulong64; + +struct IntPoint { +public: + long64 X; + long64 Y; + IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; + friend std::ostream& operator <<(std::ostream &s, IntPoint &p); +}; + +typedef std::vector< IntPoint > Polygon; +typedef std::vector< Polygon > Polygons; + +std::ostream& operator <<(std::ostream &s, Polygon &p); +std::ostream& operator <<(std::ostream &s, Polygons &p); + +struct ExPolygon { + Polygon outer; + Polygons holes; +}; +typedef std::vector< ExPolygon > ExPolygons; + +enum JoinType { jtSquare, jtMiter, jtRound }; + +bool Orientation(const Polygon &poly); +double Area(const Polygon &poly); +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype = jtSquare, double MiterLimit = 2); + +void ReversePoints(Polygon& p); +void ReversePoints(Polygons& p); + +//used internally ... +enum EdgeSide { esLeft, esRight }; +enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; + +struct TEdge { + long64 xbot; + long64 ybot; + long64 xcurr; + long64 ycurr; + long64 xtop; + long64 ytop; + double dx; + long64 tmpX; + PolyType polyType; + EdgeSide side; + int windDelta; //1 or -1 depending on winding direction + int windCnt; + int windCnt2; //winding count of the opposite polytype + int outIdx; + TEdge *next; + TEdge *prev; + TEdge *nextInLML; + TEdge *nextInAEL; + TEdge *prevInAEL; + TEdge *nextInSEL; + TEdge *prevInSEL; +}; + +struct IntersectNode { + TEdge *edge1; + TEdge *edge2; + IntPoint pt; + IntersectNode *next; +}; + +struct LocalMinima { + long64 Y; + TEdge *leftBound; + TEdge *rightBound; + LocalMinima *next; +}; + +struct Scanbeam { + long64 Y; + Scanbeam *next; +}; + +struct OutPt; //forward declaration + +struct OutRec { + int idx; + bool isHole; + OutRec *FirstLeft; + OutRec *AppendLink; + OutPt *pts; + OutPt *bottomPt; + TEdge *bottomE1; + TEdge *bottomE2; +}; + +struct OutPt { + int idx; + IntPoint pt; + OutPt *next; + OutPt *prev; +}; + +struct JoinRec { + IntPoint pt1a; + IntPoint pt1b; + int poly1Idx; + IntPoint pt2a; + IntPoint pt2b; + int poly2Idx; +}; + +struct HorzJoinRec { + TEdge *edge; + int savedIdx; +}; + +struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; + +typedef std::vector < OutRec* > PolyOutList; +typedef std::vector < TEdge* > EdgeList; +typedef std::vector < JoinRec* > JoinList; +typedef std::vector < HorzJoinRec* > HorzJoinList; + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase(); + virtual ~ClipperBase(); + bool AddPolygon(const Polygon &pg, PolyType polyType); + bool AddPolygons( const Polygons &ppg, PolyType polyType); + virtual void Clear(); + IntRect GetBounds(); +protected: + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge *e); + void PopLocalMinima(); + virtual void Reset(); + void InsertLocalMinima(LocalMinima *newLm); + LocalMinima *m_CurrentLM; + LocalMinima *m_MinimaList; + bool m_UseFullRange; + EdgeList m_edges; +}; + +class Clipper : public virtual ClipperBase +{ +public: + Clipper(); + ~Clipper(); + bool Execute(ClipType clipType, + Polygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool Execute(ClipType clipType, + ExPolygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + void Clear(); + bool ReverseSolution() {return m_ReverseOutput;}; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; +protected: + void Reset(); + virtual bool ExecuteInternal(bool fixHoleLinkages); +private: + PolyOutList m_PolyOuts; + JoinList m_Joins; + HorzJoinList m_HorizJoins; + ClipType m_ClipType; + Scanbeam *m_Scanbeam; + TEdge *m_ActiveEdges; + TEdge *m_SortedEdges; + IntersectNode *m_IntersectNodes; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + void DisposeScanbeamList(); + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertScanbeam(const long64 Y); + long64 PopScanbeam(); + void InsertLocalMinimaIntoAEL(const long64 botY); + void InsertEdgeIntoAEL(TEdge *edge); + void AddEdgeToSEL(TEdge *edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const long64 XPos); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DoMaxima(TEdge *e, long64 topY); + void ProcessHorizontals(); + void ProcessHorizontal(TEdge *horzEdge); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AppendPolygon(TEdge *e1, TEdge *e2); + void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects); + OutRec* CreateOutRec(); + void AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt); + void DisposeAllPolyPts(); + void DisposeOutRec(PolyOutList::size_type index, bool ignorePts = false); + bool ProcessIntersections(const long64 botY, const long64 topY); + void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); + void BuildIntersectList(const long64 botY, const long64 topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const long64 topY); + void BuildResult(Polygons& polys); + void BuildResultEx(ExPolygons& polys); + void SetHoleState(TEdge *e, OutRec *OutRec); + void DisposeIntersectNodes(); + bool FixupIntersections(); + void FixupOutPolygon(OutRec &outRec); + bool IsHole(TEdge *e); + void FixHoleLinkage(OutRec *outRec); + void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); + void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); + void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); + void ClearJoins(); + void AddHorzJoin(TEdge *e, int idx); + void ClearHorzJoins(); + void JoinCommonEdges(bool fixHoleLinkages); +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff -Nru mapserver-7.0.7/renderers/agg/src/agg_curves.cpp mapserver-7.6.4/renderers/agg/src/agg_curves.cpp --- mapserver-7.0.7/renderers/agg/src/agg_curves.cpp 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/src/agg_curves.cpp 2021-07-12 20:16:21.000000000 +0000 @@ -21,7 +21,6 @@ { //------------------------------------------------------------------------ - const double curve_distance_epsilon = 1e-30; const double curve_collinearity_epsilon = 1e-30; const double curve_angle_tolerance_epsilon = 0.01; enum curve_recursion_limit_e { curve_recursion_limit = 32 }; diff -Nru mapserver-7.0.7/renderers/agg/src/agg_font_freetype.cpp mapserver-7.6.4/renderers/agg/src/agg_font_freetype.cpp --- mapserver-7.0.7/renderers/agg/src/agg_font_freetype.cpp 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/src/agg_font_freetype.cpp 2021-07-12 20:16:21.000000000 +0000 @@ -422,12 +422,12 @@ y += bitmap.rows; pitch = -pitch; } - for(i = 0; i < bitmap.rows; i++) + for(i = 0; i < (unsigned int)bitmap.rows; i++) { sl.reset_spans(); bitset_iterator bits(buf, 0); unsigned int j; - for(j = 0; j < bitmap.width; j++) + for(j = 0; j < (unsigned int)bitmap.width; j++) { if(bits.bit()) sl.add_cell(x + j, cover_full); ++bits; @@ -463,11 +463,11 @@ y += bitmap.rows; pitch = -pitch; } - for(i = 0; i < bitmap.rows; i++) + for(i = 0; i < (unsigned int)bitmap.rows; i++) { sl.reset_spans(); const int8u* p = buf; - for(j = 0; j < bitmap.width; j++) + for(j = 0; j < (unsigned int)bitmap.width; j++) { if(*p) sl.add_cell(x + j, ras.apply_gamma(*p)); ++p; diff -Nru mapserver-7.0.7/renderers/agg/src/clipper.cpp mapserver-7.6.4/renderers/agg/src/clipper.cpp --- mapserver-7.0.7/renderers/agg/src/clipper.cpp 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/src/clipper.cpp 2021-07-12 20:16:21.000000000 +0000 @@ -1,3302 +1,3302 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.6.3 * -* Date : 11 November 2011 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2011 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -/******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ - -#include "../include/clipper.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -static long64 const loRange = 1518500249; //sqrt(2^63 -1)/2 -static long64 const hiRange = 6521908912666391106LL; //sqrt(2^127 -1)/2 -static double const pi = 3.141592653589793238; -enum Direction { dRightToLeft, dLeftToRight }; -enum RangeTest { rtLo, rtHi, rtError }; - -#define HORIZONTAL (-1.0E+40) -#define TOLERANCE (1.0e-20) -#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) -#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) - -inline long64 Abs(long64 val) -{ - if (val < 0) return -val; else return val; -} -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Int128 class (enables safe math on signed 64bit integers) -// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 -// Int128 val2((long64)9223372036854775807); -// Int128 val3 = val1 * val2; -// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) -//------------------------------------------------------------------------------ - -class Int128 -{ - public: - - Int128(long64 _lo = 0) - { - hi = 0; - if (_lo < 0) { - lo = -_lo; - Negate(*this); - } else - lo = _lo; - } - - Int128(const Int128 &val): hi(val.hi), lo(val.lo){} - - long64 operator = (const long64 &val) - { - hi = 0; - lo = Abs(val); - if (val < 0) Negate(*this); - return val; - } - - bool operator == (const Int128 &val) const - {return (hi == val.hi && lo == val.lo);} - - bool operator != (const Int128 &val) const { return !(*this == val);} - - bool operator > (const Int128 &val) const - { - if (hi > val.hi) return true; - else if (hi < val.hi) return false; - else return ulong64(lo) > ulong64(val.lo); - } - - bool operator < (const Int128 &val) const - { - if (hi < val.hi) return true; - else if (hi > val.hi) return false; - else return ulong64(lo) < ulong64(val.lo); - } - - Int128& operator += (const Int128 &rhs) - { - hi += rhs.hi; - lo += rhs.lo; - if (ulong64(lo) < ulong64(rhs.lo)) hi++; - return *this; - } - - Int128 operator + (const Int128 &rhs) const - { - Int128 result(*this); - result+= rhs; - return result; - } - - Int128& operator -= (const Int128 &rhs) - { - Int128 tmp(rhs); - Negate(tmp); - *this += tmp; - return *this; - } - - Int128 operator - (const Int128 &rhs) const - { - Int128 result(*this); - result-= rhs; - return result; - } - - Int128 operator * (const Int128 &rhs) const { - if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) - throw "Int128 operator*: overflow error"; - bool negate = (hi < 0) != (rhs.hi < 0); - - Int128 tmp(*this); - if (tmp.hi < 0) Negate(tmp); - ulong64 int1Hi = ulong64(tmp.lo) >> 32; - ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - tmp = rhs; - if (tmp.hi < 0) Negate(tmp); - ulong64 int2Hi = ulong64(tmp.lo) >> 32; - ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - //nb: see comments in clipper.pas - ulong64 a = int1Hi * int2Hi; - ulong64 b = int1Lo * int2Lo; - ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; - - tmp.hi = long64(a + (c >> 32)); - tmp.lo = long64(c << 32); - tmp.lo += long64(b); - if (ulong64(tmp.lo) < b) tmp.hi++; - if (negate) Negate(tmp); - return tmp; - } - - Int128 operator/ (const Int128 &rhs) const - { - if (rhs.lo == 0 && rhs.hi == 0) - throw "Int128 operator/: divide by zero"; - bool negate = (rhs.hi < 0) != (hi < 0); - Int128 result(*this), denom(rhs); - if (result.hi < 0) Negate(result); - if (denom.hi < 0) Negate(denom); - if (denom > result) return Int128(0); //result is only a fraction of 1 - Negate(denom); - - Int128 p(0); - for (int i = 0; i < 128; ++i) - { - p.hi = p.hi << 1; - if (p.lo < 0) p.hi++; - p.lo = long64(p.lo) << 1; - if (result.hi < 0) p.lo++; - result.hi = result.hi << 1; - if (result.lo < 0) result.hi++; - result.lo = long64(result.lo) << 1; - Int128 p2(p); - p += denom; - if (p.hi < 0) p = p2; - else result.lo++; - } - if (negate) Negate(result); - return result; - } - - double AsDouble() const - { - const double shift64 = 18446744073709551616.0; //2^64 - const double bit64 = 9223372036854775808.0; - if (hi < 0) - { - Int128 tmp(*this); - Negate(tmp); - if (tmp.lo < 0) - return (double)tmp.lo - bit64 - tmp.hi * shift64; - else - return -(double)tmp.lo - tmp.hi * shift64; - } - else if (lo < 0) - return -(double)lo + bit64 + hi * shift64; - else - return (double)lo + (double)hi * shift64; - } - - //for bug testing ... - std::string AsString() const - { - std::string result; - unsigned char r = 0; - Int128 tmp(0), val(*this); - if (hi < 0) Negate(val); - result.resize(50); - std::string::size_type i = result.size() -1; - while (val.hi != 0 || val.lo != 0) - { - Div10(val, tmp, r); - result[i--] = char('0' + r); - val = tmp; - } - if (hi < 0) result[i--] = '-'; - result.erase(0,i+1); - if (result.size() == 0) result = "0"; - return result; - } - -private: - long64 hi; - long64 lo; - - static void Negate(Int128 &val) - { - if (val.lo == 0) - { - if( val.hi == 0) return; - val.lo = ~val.lo; - val.hi = ~val.hi +1; - } - else - { - val.lo = ~val.lo +1; - val.hi = ~val.hi; - } - } - - //debugging only ... - void Div10(const Int128 val, Int128& result, unsigned char & remainder) const - { - remainder = 0; - result = 0; - for (int i = 63; i >= 0; --i) - { - if ((val.hi & ((long64)1 << i)) != 0) - remainder = char((remainder * 2) + 1); else - remainder *= char(2); - if (remainder >= 10) - { - result.hi += ((long64)1 << i); - remainder -= char(10); - } - } - for (int i = 63; i >= 0; --i) - { - if ((val.lo & ((long64)1 << i)) != 0) - remainder = char((remainder * 2) + 1); else - remainder *= char(2); - if (remainder >= 10) - { - result.lo += ((long64)1 << i); - remainder -= char(10); - } - } - } -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -RangeTest TestRange(const Polygon &pts) -{ - RangeTest result = rtLo; - for (Polygon::size_type i = 0; i < pts.size(); ++i) - { - if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) - return rtError; - else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) - result = rtHi; - } - return result; -} -//------------------------------------------------------------------------------ - -bool Orientation(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return false; - bool UseFullInt64Range = false; - - int j = 0, jplus, jminus; - for (int i = 0; i <= highI; ++i) - { - if (Abs(poly[i].X) > hiRange || Abs(poly[i].Y) > hiRange) - throw "Coordinate exceeds range bounds."; - if (Abs(poly[i].X) > loRange || Abs(poly[i].Y) > loRange) - UseFullInt64Range = true; - if (poly[i].Y < poly[j].Y) continue; - if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; - }; - if (j == highI) jplus = 0; - else jplus = j +1; - if (j == 0) jminus = highI; - else jminus = j -1; - - IntPoint vec1, vec2; - //get cross product of vectors of the edges adjacent to highest point ... - vec1.X = poly[j].X - poly[jminus].X; - vec1.Y = poly[j].Y - poly[jminus].Y; - vec2.X = poly[jplus].X - poly[j].X; - vec2.Y = poly[jplus].Y - poly[j].Y; - - if (UseFullInt64Range) - { - Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - - Int128(vec2.X) * Int128(vec1.Y); - return cross > 0; - } - else - { - return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; - } -} -//------------------------------------------------------------------------------ - -bool Orientation(OutRec *outRec, bool UseFullInt64Range) -{ - OutPt *opBottom = outRec->pts, *op = outRec->pts->next; - while (op != outRec->pts) - { - if (op->pt.Y >= opBottom->pt.Y) - { - if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) - opBottom = op; - } - op = op->next; - } - - IntPoint vec1, vec2; - vec1.X = op->pt.X - op->prev->pt.X; - vec1.Y = op->pt.Y - op->prev->pt.Y; - vec2.X = op->next->pt.X - op->pt.X; - vec2.Y = op->next->pt.Y - op->pt.Y; - - if (UseFullInt64Range) - { - Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - Int128(vec2.X) * Int128(vec1.Y); - return cross > 0; - } - else - { - return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; - } -} -//------------------------------------------------------------------------------ - -inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) -{ - return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); -} -//------------------------------------------------------------------------------ - -double Area(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return 0; - bool UseFullInt64Range; - RangeTest rt = TestRange(poly); - switch (rt) { - case rtLo: - UseFullInt64Range = false; - break; - case rtHi: - UseFullInt64Range = true; - break; - default: - throw "Coordinate exceeds range bounds."; - } - - if (UseFullInt64Range) { - Int128 a(0); - a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - - Int128(poly[0].X) * Int128(poly[highI].Y); - for (int i = 0; i < highI; ++i) - a += Int128(poly[i].X) * Int128(poly[i+1].Y) - - Int128(poly[i+1].X) * Int128(poly[i].Y); - return a.AsDouble() / 2; - } - else - { - double a; - a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; - for (int i = 0; i < highI; ++i) - a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; - return a/2; - } -} -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &pt, OutPt *pp) -{ - OutPt *pp2 = pp; - do - { - if (PointsEqual(pp2->pt, pt)) return true; - pp2 = pp2->next; - } - while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) -{ - OutPt *pp2 = pp; - bool result = false; - if (UseFullInt64Range) { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * - Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) - result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - else - { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / - (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - return result; -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) -{ - if (e1.ybot == e1.ytop) return (e2.ybot == e2.ytop); - else if (e1.xbot == e1.xtop) return (e2.xbot == e2.xtop); - else if (UseFullInt64Range) - return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == - Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); - else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == - (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, bool UseFullInt64Range) -{ - if (pt1.Y == pt2.Y) return (pt2.Y == pt3.Y); - else if (pt1.X == pt2.X) return (pt2.X == pt3.X); - else if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == - Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); - else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) -{ - if (pt1.Y == pt2.Y) return (pt3.Y == pt4.Y); - else if (pt1.X == pt2.X) return (pt3.X == pt4.X); - else if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == - Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); - else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); -} -//------------------------------------------------------------------------------ - -double GetDx(const IntPoint pt1, const IntPoint pt2) -{ - if (pt1.Y == pt2.Y) return HORIZONTAL; - else return - (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); -} -//--------------------------------------------------------------------------- - -void SetDx(TEdge &e) -{ - if (e.ybot == e.ytop) e.dx = HORIZONTAL; - else e.dx = - (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); -} -//--------------------------------------------------------------------------- - -void SwapSides(TEdge &edge1, TEdge &edge2) -{ - EdgeSide side = edge1.side; - edge1.side = edge2.side; - edge2.side = side; -} -//------------------------------------------------------------------------------ - -void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) -{ - int outIdx = edge1.outIdx; - edge1.outIdx = edge2.outIdx; - edge2.outIdx = outIdx; -} -//------------------------------------------------------------------------------ - -inline long64 Round(double val) -{ - if ((val < 0)) return static_cast(val - 0.5); - else return static_cast(val + 0.5); -} -//------------------------------------------------------------------------------ - -long64 TopX(TEdge &edge, const long64 currentY) -{ - if( currentY == edge.ytop ) return edge.xtop; - return edge.xbot + Round(edge.dx *(currentY - edge.ybot)); -} -//------------------------------------------------------------------------------ - -long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) -{ - //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y - if (currentY >= pt1.Y) return pt1.X; - else if (currentY == pt2.Y) return pt2.X; - else if (pt1.X == pt2.X) return pt1.X; - else - { - double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); - return Round(pt1.X + (currentY - pt1.Y) *q); - } -} -//------------------------------------------------------------------------------ - -bool IntersectPoint(TEdge &edge1, TEdge &edge2, - IntPoint &ip, bool UseFullInt64Range) -{ - double b1, b2; - if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; - else if (NEAR_ZERO(edge1.dx)) - { - ip.X = edge1.xbot; - if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) - { - ip.Y = edge2.ybot; - } else - { - b2 = edge2.ybot - (edge2.xbot/edge2.dx); - ip.Y = Round(ip.X/edge2.dx + b2); - } - } - else if (NEAR_ZERO(edge2.dx)) - { - ip.X = edge2.xbot; - if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) - { - ip.Y = edge1.ybot; - } else - { - b1 = edge1.ybot - (edge1.xbot/edge1.dx); - ip.Y = Round(ip.X/edge1.dx + b1); - } - } else - { - b1 = edge1.xbot - edge1.ybot * edge1.dx; - b2 = edge2.xbot - edge2.ybot * edge2.dx; - b2 = (b2-b1)/(edge1.dx - edge2.dx); - ip.Y = Round(b2); - ip.X = Round(edge1.dx * b2 + b1); - } - - return - //can be *so close* to the top of one edge that the rounded Y equals one ytop ... - (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y > edge1.ytop && ip.Y > edge2.ytop); -} -//------------------------------------------------------------------------------ - -void ReversePolyPtLinks(OutPt &pp) -{ - OutPt *pp1, *pp2; - pp1 = &pp; - do { - pp2 = pp1->next; - pp1->next = pp1->prev; - pp1->prev = pp2; - pp1 = pp2; - } while( pp1 != &pp ); -} -//------------------------------------------------------------------------------ - -void DisposeOutPts(OutPt*& pp) -{ - if (pp == 0) return; - pp->prev->next = 0; - while( pp ) - { - OutPt *tmpPp = pp; - pp = pp->next; - delete tmpPp ; - } -} -//------------------------------------------------------------------------------ - -void InitEdge(TEdge *e, TEdge *eNext, - TEdge *ePrev, const IntPoint &pt, PolyType polyType) -{ - std::memset( e, 0, sizeof( TEdge )); - - e->next = eNext; - e->prev = ePrev; - e->xcurr = pt.X; - e->ycurr = pt.Y; - if (e->ycurr >= e->next->ycurr) - { - e->xbot = e->xcurr; - e->ybot = e->ycurr; - e->xtop = e->next->xcurr; - e->ytop = e->next->ycurr; - e->windDelta = 1; - } else - { - e->xtop = e->xcurr; - e->ytop = e->ycurr; - e->xbot = e->next->xcurr; - e->ybot = e->next->ycurr; - e->windDelta = -1; - } - SetDx(*e); - e->polyType = polyType; - e->outIdx = -1; -} -//------------------------------------------------------------------------------ - -inline void SwapX(TEdge &e) -{ - //swap horizontal edges' top and bottom x's so they follow the natural - //progression of the bounds - ie so their xbots will align with the - //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - e.xcurr = e.xtop; - e.xtop = e.xbot; - e.xbot = e.xcurr; -} -//------------------------------------------------------------------------------ - -void SwapPoints(IntPoint &pt1, IntPoint &pt2) -{ - IntPoint tmp = pt1; - pt1 = pt2; - pt2 = tmp; -} -//------------------------------------------------------------------------------ - -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) -{ - //precondition: segments are colinear. - if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) - { - if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); - if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); - if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; - return pt1.X < pt2.X; - } else - { - if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; - return pt1.Y > pt2.Y; - } -} -//------------------------------------------------------------------------------ - -OutPt* PolygonBottom(OutPt* pp) -{ - OutPt* p = pp->next; - OutPt* result = pp; - while (p != pp) - { - if (p->pt.Y > result->pt.Y) result = p; - else if (p->pt.Y == result->pt.Y && p->pt.X < result->pt.X) result = p; - p = p->next; - } - return result; -} -//------------------------------------------------------------------------------ - -bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) -{ - //outPt1 & outPt2 => the overlap segment (if the function returns true) - if (!pp) return false; - OutPt* pp2 = pp; - IntPoint pt1a = pt1, pt2a = pt2; - do - { - if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && - SlopesEqual(pt1a, pt2a, pp->pt, true) && - GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) - return true; - pp = pp->next; - } - while (pp != pp2); - return false; -} -//------------------------------------------------------------------------------ - -bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, - const IntPoint pt2, const IntPoint pt3) -{ - if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; - else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); - else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); -} -//------------------------------------------------------------------------------ - -OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) -{ - if (p1 == p2) throw "JoinError"; - OutPt* result = new OutPt; - result->pt = pt; - if (p2 == p1->next) - { - p1->next = result; - p2->prev = result; - result->next = p2; - result->prev = p1; - } else - { - p2->next = result; - p1->prev = result; - result->next = p1; - result->prev = p2; - } - return result; -} - -//------------------------------------------------------------------------------ -// ClipperBase class methods ... -//------------------------------------------------------------------------------ - -ClipperBase::ClipperBase() //constructor -{ - m_MinimaList = 0; - m_CurrentLM = 0; - m_UseFullRange = true; -} -//------------------------------------------------------------------------------ - -ClipperBase::~ClipperBase() //destructor -{ - Clear(); -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) -{ - int len = (int)pg.size(); - if (len < 3) return false; - Polygon p(len); - p[0] = pg[0]; - int j = 0; - - long64 maxVal; - if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; - - for (int i = 0; i < len; ++i) - { - if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) - { - if (m_UseFullRange) - throw "Coordinate exceeds range bounds"; - maxVal = hiRange; - if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) - throw "Coordinate exceeds range bounds"; - m_UseFullRange = true; - } - - if (i == 0 || PointsEqual(p[j], pg[i])) continue; - else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) - { - if (PointsEqual(p[j-1], pg[i])) j--; - } else j++; - p[j] = pg[i]; - } - if (j < 2) return false; - - len = j+1; - for (;;) - { - //nb: test for point equality before testing slopes ... - if (PointsEqual(p[j], p[0])) j--; - else if (PointsEqual(p[0], p[1]) || - SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) - p[0] = p[j--]; - else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; - else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) - { - for (int i = 2; i <= j; ++i) p[i-1] = p[i]; - j--; - } - //exit loop if nothing is changed or there are too few vertices ... - if (j == len-1 || j < 2) break; - len = j +1; - } - if (len < 3) return false; - - //create a new edge array ... - TEdge *edges = new TEdge [len]; - m_edges.push_back(edges); - - //convert vertices to a double-linked-list of edges and initialize ... - edges[0].xcurr = p[0].X; - edges[0].ycurr = p[0].Y; - InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); - for (int i = len-2; i > 0; --i) - InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); - InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); - - //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates - //increase downward so the 'highest' edge will have the smallest ytop) ... - TEdge *e = &edges[0]; - TEdge *eHighest = e; - do - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - if (e->ytop < eHighest->ytop) eHighest = e; - e = e->next; - } - while ( e != &edges[0]); - - //make sure eHighest is positioned so the following loop works safely ... - if (eHighest->windDelta > 0) eHighest = eHighest->next; - if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; - - //finally insert each local minima ... - e = eHighest; - do { - e = AddBoundsToLML(e); - } - while( e != eHighest ); - return true; -} -//------------------------------------------------------------------------------ - -void ClipperBase::InsertLocalMinima(LocalMinima *newLm) -{ - if( ! m_MinimaList ) - { - m_MinimaList = newLm; - } - else if( newLm->Y >= m_MinimaList->Y ) - { - newLm->next = m_MinimaList; - m_MinimaList = newLm; - } else - { - LocalMinima* tmpLm = m_MinimaList; - while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) - tmpLm = tmpLm->next; - newLm->next = tmpLm->next; - tmpLm->next = newLm; - } -} -//------------------------------------------------------------------------------ - -TEdge* ClipperBase::AddBoundsToLML(TEdge *e) -{ - //Starting at the top of one bound we progress to the bottom where there's - //a local minima. We then go to the top of the next bound. These two bounds - //form the left and right (or right and left) bounds of the local minima. - e->nextInLML = 0; - e = e->next; - for (;;) - { - if (NEAR_EQUAL(e->dx, HORIZONTAL)) - { - //nb: proceed through horizontals when approaching from their right, - // but break on horizontal minima if approaching from their left. - // This ensures 'local minima' are always on the left of horizontals. - if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; - if (e->xtop != e->prev->xbot) SwapX(*e); - e->nextInLML = e->prev; - } - else if (e->ycurr == e->prev->ycurr) break; - else e->nextInLML = e->prev; - e = e->next; - } - - //e and e.prev are now at a local minima ... - LocalMinima* newLm = new LocalMinima; - newLm->next = 0; - newLm->Y = e->prev->ybot; - - if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound - { - if (e->xbot != e->prev->xbot) SwapX(*e); - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else if (e->dx < e->prev->dx) - { - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else - { - newLm->leftBound = e; - newLm->rightBound = e->prev; - } - newLm->leftBound->side = esLeft; - newLm->rightBound->side = esRight; - InsertLocalMinima( newLm ); - - for (;;) - { - if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; - e->nextInLML = e->next; - e = e->next; - if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); - } - return e->next; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) -{ - bool result = true; - for (Polygons::size_type i = 0; i < ppg.size(); ++i) - if (AddPolygon(ppg[i], polyType)) result = false; - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Clear() -{ - DisposeLocalMinimaList(); - for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; - m_edges.clear(); - m_UseFullRange = false; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Reset() -{ - m_CurrentLM = m_MinimaList; - if( !m_CurrentLM ) return; //ie nothing to process - - //reset all edges ... - LocalMinima* lm = m_MinimaList; - while( lm ) - { - TEdge* e = lm->leftBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esLeft; - e->outIdx = -1; - e = e->nextInLML; - } - e = lm->rightBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esRight; - e->outIdx = -1; - e = e->nextInLML; - } - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeLocalMinimaList() -{ - while( m_MinimaList ) - { - LocalMinima* tmpLm = m_MinimaList->next; - delete m_MinimaList; - m_MinimaList = tmpLm; - } - m_CurrentLM = 0; -} -//------------------------------------------------------------------------------ - -void ClipperBase::PopLocalMinima() -{ - if( ! m_CurrentLM ) return; - m_CurrentLM = m_CurrentLM->next; -} -//------------------------------------------------------------------------------ - -IntRect ClipperBase::GetBounds() -{ - IntRect result; - LocalMinima* lm = m_MinimaList; - if (!lm) - { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->leftBound->xbot; - result.top = lm->leftBound->ybot; - result.right = lm->leftBound->xbot; - result.bottom = lm->leftBound->ybot; - while (lm) - { - if (lm->leftBound->ybot > result.bottom) - result.bottom = lm->leftBound->ybot; - TEdge* e = lm->leftBound; - for (;;) { - TEdge* bottomE = e; - while (e->nextInLML) - { - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - e = e->nextInLML; - } - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - if (e->xtop < result.left) result.left = e->xtop; - if (e->xtop > result.right) result.right = e->xtop; - if (e->ytop < result.top) result.top = e->ytop; - - if (bottomE == lm->leftBound) e = lm->rightBound; - else break; - } - lm = lm->next; - } - return result; -} - - -//------------------------------------------------------------------------------ -// TClipper methods ... -//------------------------------------------------------------------------------ - -Clipper::Clipper() : ClipperBase() //constructor -{ - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - m_IntersectNodes = 0; - m_ExecuteLocked = false; - m_UseFullRange = false; - m_ReverseOutput = false; -} -//------------------------------------------------------------------------------ - -Clipper::~Clipper() //destructor -{ - Clear(); - DisposeScanbeamList(); -} -//------------------------------------------------------------------------------ - -void Clipper::Clear() -{ - if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor - DisposeAllPolyPts(); - ClipperBase::Clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeScanbeamList() -{ - while ( m_Scanbeam ) { - Scanbeam* sb2 = m_Scanbeam->next; - delete m_Scanbeam; - m_Scanbeam = sb2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::Reset() -{ - ClipperBase::Reset(); - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - LocalMinima* lm = m_MinimaList; - while (lm) - { - InsertScanbeam(lm->Y); - InsertScanbeam(lm->leftBound->ytop); - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, Polygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(false); - if (succeeded) BuildResult(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, ExPolygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(true); - if (succeeded) BuildResultEx(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool PolySort(OutRec *or1, OutRec *or2) -{ - if (or1 == or2) return false; - if (!or1->pts || !or2->pts) - { - if (or1->pts != or2->pts) - { - if (or1->pts) return true; else return false; - } - else return false; - } - int i1, i2; - if (or1->isHole) - i1 = or1->FirstLeft->idx; else - i1 = or1->idx; - if (or2->isHole) - i2 = or2->FirstLeft->idx; else - i2 = or2->idx; - int result = i1 - i2; - if (result == 0 && (or1->isHole != or2->isHole)) - { - if (or1->isHole) return false; - else return true; - } - else return result < 0; -} -//------------------------------------------------------------------------------ - -OutRec* FindAppendLinkEnd(OutRec *outRec) -{ - while (outRec->AppendLink) outRec = outRec->AppendLink; - return outRec; -} -//------------------------------------------------------------------------------ - -void Clipper::FixHoleLinkage(OutRec *outRec) -{ - OutRec *tmp; - if (outRec->bottomPt) - tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; - else - tmp = outRec->FirstLeft; - if (outRec == tmp) throw clipperException("HoleLinkage error"); - - if (tmp) - { - if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); - if (tmp == outRec) tmp = 0; - else if (tmp->isHole) - { - FixHoleLinkage(tmp); - tmp = tmp->FirstLeft; - } - } - outRec->FirstLeft = tmp; - if (!tmp) outRec->isHole = false; - outRec->AppendLink = 0; -} -//------------------------------------------------------------------------------ - -bool Clipper::ExecuteInternal(bool fixHoleLinkages) -{ - bool succeeded; - try { - Reset(); - if (!m_CurrentLM ) return true; - long64 botY = PopScanbeam(); - do { - InsertLocalMinimaIntoAEL(botY); - ClearHorzJoins(); - ProcessHorizontals(); - long64 topY = PopScanbeam(); - succeeded = ProcessIntersections(botY, topY); - if (!succeeded) break; - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - } while( m_Scanbeam ); - } - catch(...) { - succeeded = false; - } - - if (succeeded) - { - //tidy up output polygons and fix orientations where necessary ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->pts) continue; - FixupOutPolygon(*outRec); - if (!outRec->pts) continue; - if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); - if (outRec->isHole == - (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) - ReversePolyPtLinks(*outRec->pts); - } - - JoinCommonEdges(fixHoleLinkages); - if (fixHoleLinkages) - std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); - } - - ClearJoins(); - ClearHorzJoins(); - return succeeded; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertScanbeam(const long64 Y) -{ - if( !m_Scanbeam ) - { - m_Scanbeam = new Scanbeam; - m_Scanbeam->next = 0; - m_Scanbeam->Y = Y; - } - else if( Y > m_Scanbeam->Y ) - { - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = m_Scanbeam; - m_Scanbeam = newSb; - } else - { - Scanbeam* sb2 = m_Scanbeam; - while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; - if( Y == sb2->Y ) return; //ie ignores duplicates - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = sb2->next; - sb2->next = newSb; - } -} -//------------------------------------------------------------------------------ - -long64 Clipper::PopScanbeam() -{ - long64 Y = m_Scanbeam->Y; - Scanbeam* sb2 = m_Scanbeam; - m_Scanbeam = m_Scanbeam->next; - delete sb2; - return Y; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeAllPolyPts(){ - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - DisposeOutRec(i); - m_PolyOuts.clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeOutRec(PolyOutList::size_type index, bool ignorePts) -{ - OutRec *outRec = m_PolyOuts[index]; - if (!ignorePts && outRec->pts) DisposeOutPts(outRec->pts); - delete outRec; - m_PolyOuts[index] = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::SetWindingCount(TEdge &edge) -{ - TEdge *e = edge.prevInAEL; - //find the edge of the same polytype that immediately preceeds 'edge' in AEL - while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; - if ( !e ) - { - edge.windCnt = edge.windDelta; - edge.windCnt2 = 0; - e = m_ActiveEdges; //ie get ready to calc windCnt2 - } else if ( IsEvenOddFillType(edge) ) - { - //EvenOdd filling ... - edge.windCnt = 1; - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } else - { - //nonZero, Positive or Negative filling ... - if ( e->windCnt * e->windDelta < 0 ) - { - if (Abs(e->windCnt) > 1) - { - if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } else - edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; - } else - { - if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) - edge.windCnt = e->windCnt; - else if ( e->windCnt + edge.windDelta == 0 ) - edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } - - //update windCnt2 ... - if ( IsEvenOddAltFillType(edge) ) - { - //EvenOdd filling ... - while ( e != &edge ) - { - edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; - e = e->nextInAEL; - } - } else - { - //nonZero, Positive or Negative filling ... - while ( e != &edge ) - { - edge.windCnt2 += e->windDelta; - e = e->nextInAEL; - } - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_SubjFillType == pftEvenOdd; else - return m_ClipFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_ClipFillType == pftEvenOdd; else - return m_SubjFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsContributing(const TEdge& edge) const -{ - PolyFillType pft, pft2; - if (edge.polyType == ptSubject) - { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else - { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } - - switch(pft) - { - case pftEvenOdd: - case pftNonZero: - if (Abs(edge.windCnt) != 1) return false; - break; - case pftPositive: - if (edge.windCnt != 1) return false; - break; - default: //pftNegative - if (edge.windCnt != -1) return false; - } - - switch(m_ClipType) - { - case ctIntersection: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - case ctUnion: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - case ctDifference: - if (edge.polyType == ptSubject) - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - else - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - default: - return true; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) - { - AddOutPt( e1, e2, pt ); - e2->outIdx = e1->outIdx; - e1->side = esLeft; - e2->side = esRight; - } else - { - AddOutPt( e2, e1, pt ); - e1->outIdx = e2->outIdx; - e1->side = esRight; - e2->side = esLeft; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - AddOutPt( e1, 0, pt ); - if( e1->outIdx == e2->outIdx ) - { - e1->outIdx = -1; - e2->outIdx = -1; - } - else - AppendPolygon( e1, e2 ); -} -//------------------------------------------------------------------------------ - -void Clipper::AddEdgeToSEL(TEdge *edge) -{ - //SEL pointers in PEdge are reused to build a list of horizontal edges. - //However, we don't need to worry about order with horizontal edge processing. - if( !m_SortedEdges ) - { - m_SortedEdges = edge; - edge->prevInSEL = 0; - edge->nextInSEL = 0; - } - else - { - edge->nextInSEL = m_SortedEdges; - edge->prevInSEL = 0; - m_SortedEdges->prevInSEL = edge; - m_SortedEdges = edge; - } -} -//------------------------------------------------------------------------------ - -void Clipper::CopyAELToSEL() -{ - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - if (!m_ActiveEdges) return; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while ( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) -{ - JoinRec* jr = new JoinRec; - if (e1OutIdx >= 0) - jr->poly1Idx = e1OutIdx; else - jr->poly1Idx = e1->outIdx; - jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); - jr->pt1b = IntPoint(e1->xtop, e1->ytop); - if (e2OutIdx >= 0) - jr->poly2Idx = e2OutIdx; else - jr->poly2Idx = e2->outIdx; - jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); - jr->pt2b = IntPoint(e2->xtop, e2->ytop); - m_Joins.push_back(jr); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearJoins() -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - delete m_Joins[i]; - m_Joins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::AddHorzJoin(TEdge *e, int idx) -{ - HorzJoinRec* hj = new HorzJoinRec; - hj->edge = e; - hj->savedIdx = idx; - m_HorizJoins.push_back(hj); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearHorzJoins() -{ - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) - delete m_HorizJoins[i]; - m_HorizJoins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) -{ - while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) - { - TEdge* lb = m_CurrentLM->leftBound; - TEdge* rb = m_CurrentLM->rightBound; - - InsertEdgeIntoAEL( lb ); - InsertScanbeam( lb->ytop ); - InsertEdgeIntoAEL( rb ); - - if (IsEvenOddFillType(*lb)) - { - lb->windDelta = 1; - rb->windDelta = 1; - } - else - { - rb->windDelta = -lb->windDelta; - } - SetWindingCount( *lb ); - rb->windCnt = lb->windCnt; - rb->windCnt2 = lb->windCnt2; - - if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) - { - //nb: only rightbounds can have a horizontal bottom edge - AddEdgeToSEL( rb ); - InsertScanbeam( rb->nextInLML->ytop ); - } - else - InsertScanbeam( rb->ytop ); - - if( IsContributing(*lb) ) - AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); - - //if output polygons share an edge, they'll need joining later ... - if (lb->outIdx >= 0 && lb->prevInAEL && - lb->prevInAEL->outIdx >= 0 && lb->prevInAEL->xcurr == lb->xbot && - SlopesEqual(*lb, *lb->prevInAEL, m_UseFullRange)) - AddJoin(lb, lb->prevInAEL); - - //if any output polygons share an edge, they'll need joining later ... - if (rb->outIdx >= 0) - { - if (NEAR_EQUAL(rb->dx, HORIZONTAL)) - { - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. - HorzJoinRec* hj = m_HorizJoins[i]; - //if horizontals rb and hj.edge overlap, flag for joining later ... - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(rb->xbot, rb->ybot), - IntPoint(rb->xtop, rb->ytop), pt, pt2)) - AddJoin(hj->edge, rb, hj->savedIdx); - } - } - } - - if( lb->nextInAEL != rb ) - { - if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && - SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) - AddJoin(rb, rb->prevInAEL); - - TEdge* e = lb->nextInAEL; - IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); - while( e != rb ) - { - if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); - //nb: For calculating winding counts etc, IntersectEdges() assumes - //that param1 will be to the right of param2 ABOVE the intersection ... - IntersectEdges( rb , e , pt , ipNone); //order important here - e = e->nextInAEL; - } - } - PopLocalMinima(); - } -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromAEL(TEdge *e) -{ - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted - if( AelPrev ) AelPrev->nextInAEL = AelNext; - else m_ActiveEdges = AelNext; - if( AelNext ) AelNext->prevInAEL = AelPrev; - e->nextInAEL = 0; - e->prevInAEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromSEL(TEdge *e) -{ - TEdge* SelPrev = e->prevInSEL; - TEdge* SelNext = e->nextInSEL; - if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted - if( SelPrev ) SelPrev->nextInSEL = SelNext; - else m_SortedEdges = SelNext; - if( SelNext ) SelNext->prevInSEL = SelPrev; - e->nextInSEL = 0; - e->prevInSEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects) -{ - //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before - //e2 in AEL except when e1 is being inserted at the intersection point ... - bool e1stops = !(ipLeft & protects) && !e1->nextInLML && - e1->xtop == pt.X && e1->ytop == pt.Y; - bool e2stops = !(ipRight & protects) && !e2->nextInLML && - e2->xtop == pt.X && e2->ytop == pt.Y; - bool e1Contributing = ( e1->outIdx >= 0 ); - bool e2contributing = ( e2->outIdx >= 0 ); - - //update winding counts... - //assumes that e1 will be to the right of e2 ABOVE the intersection - if ( e1->polyType == e2->polyType ) - { - if ( IsEvenOddFillType( *e1) ) - { - int oldE1WindCnt = e1->windCnt; - e1->windCnt = e2->windCnt; - e2->windCnt = oldE1WindCnt; - } else - { - if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; - else e1->windCnt += e2->windDelta; - if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; - else e2->windCnt -= e1->windDelta; - } - } else - { - if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; - else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; - else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->polyType == ptSubject) - { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else - { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->polyType == ptSubject) - { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else - { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - long64 e1Wc, e2Wc; - switch (e1FillType) - { - case pftPositive: e1Wc = e1->windCnt; break; - case pftNegative: e1Wc = -e1->windCnt; break; - default: e1Wc = Abs(e1->windCnt); - } - switch(e2FillType) - { - case pftPositive: e2Wc = e2->windCnt; break; - case pftNegative: e2Wc = -e2->windCnt; break; - default: e2Wc = Abs(e2->windCnt); - } - - if ( e1Contributing && e2contributing ) - { - if ( e1stops || e2stops || - (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->polyType != e2->polyType && m_ClipType != ctXor) ) - AddLocalMaxPoly(e1, e2, pt); - else - DoBothEdges( e1, e2, pt ); - } - else if ( e1Contributing ) - { - if ((e2Wc == 0 || e2Wc == 1) && - (m_ClipType != ctIntersection || - e2->polyType == ptSubject || (e2->windCnt2 != 0))) - DoEdge1(e1, e2, pt); - } - else if ( e2contributing ) - { - if ((e1Wc == 0 || e1Wc == 1) && - (m_ClipType != ctIntersection || - e1->polyType == ptSubject || (e1->windCnt2 != 0))) - DoEdge2(e1, e2, pt); - } - else if ( (e1Wc == 0 || e1Wc == 1) && - (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) - { - //neither edge is currently contributing ... - - long64 e1Wc2, e2Wc2; - switch (e1FillType2) - { - case pftPositive: e1Wc2 = e1->windCnt2; break; - case pftNegative : e1Wc2 = -e1->windCnt2; break; - default: e1Wc2 = Abs(e1->windCnt2); - } - switch (e2FillType2) - { - case pftPositive: e2Wc2 = e2->windCnt2; break; - case pftNegative: e2Wc2 = -e2->windCnt2; break; - default: e2Wc2 = Abs(e2->windCnt2); - } - - if (e1->polyType != e2->polyType) - AddLocalMinPoly(e1, e2, pt); - else if (e1Wc == 1 && e2Wc == 1) - switch( m_ClipType ) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) - AddLocalMinPoly(e1, e2, pt); - break; - case ctUnion: - if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) - AddLocalMinPoly(e1, e2, pt); - break; - case ctDifference: - if ((e1->polyType == ptClip && e2->polyType == ptClip && - e1Wc2 > 0 && e2Wc2 > 0) || - (e1->polyType == ptSubject && e2->polyType == ptSubject && - e1Wc2 <= 0 && e2Wc2 <= 0)) - AddLocalMinPoly(e1, e2, pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, pt); - } - else - SwapSides( *e1, *e2 ); - } - - if( (e1stops != e2stops) && - ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) - { - SwapSides( *e1, *e2 ); - SwapPolyIndexes( *e1, *e2 ); - } - - //finally, delete any non-contributing maxima edges ... - if( e1stops ) DeleteFromAEL( e1 ); - if( e2stops ) DeleteFromAEL( e2 ); -} -//------------------------------------------------------------------------------ - -void Clipper::SetHoleState(TEdge *e, OutRec *outRec) -{ - bool isHole = false; - TEdge *e2 = e->prevInAEL; - while (e2) - { - if (e2->outIdx >= 0) - { - isHole = !isHole; - if (! outRec->FirstLeft) - outRec->FirstLeft = m_PolyOuts[e2->outIdx]; - } - e2 = e2->prevInAEL; - } - if (isHole) outRec->isHole = true; -} -//------------------------------------------------------------------------------ - -bool GetNextNonDupOutPt(OutPt* pp, OutPt*& next) -{ - next = pp->next; - while (next != pp && PointsEqual(pp->pt, next->pt)) - next = next->next; - return next != pp; -} -//------------------------------------------------------------------------------ - -bool GetPrevNonDupOutPt(OutPt* pp, OutPt*& prev) -{ - prev = pp->prev; - while (prev != pp && PointsEqual(pp->pt, prev->pt)) - prev = prev->prev; - return prev != pp; -} -//------------------------------------------------------------------------------ - -OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) -{ - //work out which polygon fragment has the correct hole state ... - OutPt *outPt1 = outRec1->bottomPt; - OutPt *outPt2 = outRec2->bottomPt; - if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; - else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; - else if (outPt1->pt.X < outPt2->pt.X) return outRec1; - else if (outPt1->pt.X > outPt2->pt.X) return outRec2; - else if (outRec1->bottomE2 == 0) return outRec2; - else if (outRec2->bottomE2 == 0) return outRec1; - else - { - long64 y1 = std::max(outRec1->bottomE1->ybot, outRec1->bottomE2->ybot); - long64 y2 = std::max(outRec2->bottomE1->ybot, outRec2->bottomE2->ybot); - if (y2 == y1 || (y1 > outPt1->pt.Y && y2 > outPt1->pt.Y)) - { - double dx1 = std::max(outRec1->bottomE1->dx, outRec1->bottomE2->dx); - double dx2 = std::max(outRec2->bottomE1->dx, outRec2->bottomE2->dx); - if (dx2 > dx1) return outRec2; else return outRec1; - } - else if (y2 > y1) return outRec2; - else return outRec1; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) -{ - //get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->outIdx]; - OutRec *outRec2 = m_PolyOuts[e2->outIdx]; - OutRec *holeStateRec = GetLowermostRec(outRec1, outRec2); - - //fixup hole status ... - if (holeStateRec == outRec2) - outRec1->isHole = outRec2->isHole; - else - outRec2->isHole = outRec1->isHole; - - OutPt* p1_lft = outRec1->pts; - OutPt* p1_rt = p1_lft->prev; - OutPt* p2_lft = outRec2->pts; - OutPt* p2_rt = p2_lft->prev; - - EdgeSide side; - //join e2 poly onto e1 poly and delete pointers to e2 ... - if( e1->side == esLeft ) - { - if( e2->side == esLeft ) - { - //z y x a b c - ReversePolyPtLinks(*p2_lft); - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - outRec1->pts = p2_rt; - } else - { - //x y z a b c - p2_rt->next = p1_lft; - p1_lft->prev = p2_rt; - p2_lft->prev = p1_rt; - p1_rt->next = p2_lft; - outRec1->pts = p2_lft; - } - side = esLeft; - } else - { - if( e2->side == esRight ) - { - //a b c z y x - ReversePolyPtLinks( *p2_lft ); - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - } else - { - //a b c x y z - p1_rt->next = p2_lft; - p2_lft->prev = p1_rt; - p1_lft->prev = p2_rt; - p2_rt->next = p1_lft; - } - side = esRight; - } - - if (holeStateRec == outRec2) - { - outRec1->bottomPt = outRec2->bottomPt; - outRec1->bottomPt->idx = outRec1->idx; - outRec1->bottomE1 = outRec2->bottomE1; - outRec1->bottomE2 = outRec2->bottomE2; - - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - } - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - int OKIdx = e1->outIdx; - int ObsoleteIdx = e2->outIdx; - - e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly - e2->outIdx = -1; - - TEdge* e = m_ActiveEdges; - while( e ) - { - if( e->outIdx == ObsoleteIdx ) - { - e->outIdx = OKIdx; - e->side = side; - break; - } - e = e->nextInAEL; - } - - for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) - { - if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; - if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; - } - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) - m_HorizJoins[i]->savedIdx = OKIdx; - } - -} -//------------------------------------------------------------------------------ - -OutRec* Clipper::CreateOutRec() -{ - OutRec* result = new OutRec; - result->isHole = false; - result->FirstLeft = 0; - result->AppendLink = 0; - result->pts = 0; - result->bottomPt = 0; - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt) -{ - bool ToFront = (e->side == esLeft); - if( e->outIdx < 0 ) - { - OutRec *outRec = CreateOutRec(); - m_PolyOuts.push_back(outRec); - outRec->idx = (int)m_PolyOuts.size()-1; - e->outIdx = outRec->idx; - OutPt* op = new OutPt; - outRec->pts = op; - outRec->bottomE1 = e; - outRec->bottomE2 = altE; - outRec->bottomPt = op; - op->pt = pt; - op->idx = outRec->idx; - op->next = op; - op->prev = op; - SetHoleState(e, outRec); - } else - { - OutRec *outRec = m_PolyOuts[e->outIdx]; - OutPt* op = outRec->pts; - if ((ToFront && PointsEqual(pt, op->pt)) || - (!ToFront && PointsEqual(pt, op->prev->pt))) return; - OutPt* op2 = new OutPt; - op2->pt = pt; - op2->idx = outRec->idx; - if (op2->pt.Y == outRec->bottomPt->pt.Y && - op2->pt.X < outRec->bottomPt->pt.X) - { - outRec->bottomPt = op2; - outRec->bottomE1 = e; - outRec->bottomE2 = altE; - } - op2->next = op; - op2->prev = op->prev; - op2->prev->next = op2; - op->prev = op2; - if (ToFront) outRec->pts = op2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontals() -{ - TEdge* horzEdge = m_SortedEdges; - while( horzEdge ) - { - DeleteFromSEL( horzEdge ); - ProcessHorizontal( horzEdge ); - horzEdge = m_SortedEdges; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsTopHorz(const long64 XPos) -{ - TEdge* e = m_SortedEdges; - while( e ) - { - if( ( XPos >= std::min(e->xcurr, e->xtop) ) && - ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; - e = e->nextInSEL; - } - return true; -} -//------------------------------------------------------------------------------ - -bool IsMinima(TEdge *e) -{ - return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); -} -//------------------------------------------------------------------------------ - -bool IsMaxima(TEdge *e, const long64 Y) -{ - return e && e->ytop == Y && !e->nextInLML; -} -//------------------------------------------------------------------------------ - -bool IsIntermediate(TEdge *e, const long64 Y) -{ - return e->ytop == Y && e->nextInLML; -} -//------------------------------------------------------------------------------ - -TEdge *GetMaximaPair(TEdge *e) -{ - if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) - return e->prev; else - return e->next; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) -{ - if( !edge1->nextInAEL && !edge1->prevInAEL ) return; - if( !edge2->nextInAEL && !edge2->prevInAEL ) return; - - if( edge1->nextInAEL == edge2 ) - { - TEdge* next = edge2->nextInAEL; - if( next ) next->prevInAEL = edge1; - TEdge* prev = edge1->prevInAEL; - if( prev ) prev->nextInAEL = edge2; - edge2->prevInAEL = prev; - edge2->nextInAEL = edge1; - edge1->prevInAEL = edge2; - edge1->nextInAEL = next; - } - else if( edge2->nextInAEL == edge1 ) - { - TEdge* next = edge1->nextInAEL; - if( next ) next->prevInAEL = edge2; - TEdge* prev = edge2->prevInAEL; - if( prev ) prev->nextInAEL = edge1; - edge1->prevInAEL = prev; - edge1->nextInAEL = edge2; - edge2->prevInAEL = edge1; - edge2->nextInAEL = next; - } - else - { - TEdge* next = edge1->nextInAEL; - TEdge* prev = edge1->prevInAEL; - edge1->nextInAEL = edge2->nextInAEL; - if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; - edge1->prevInAEL = edge2->prevInAEL; - if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; - edge2->nextInAEL = next; - if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; - edge2->prevInAEL = prev; - if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; - } - - if( !edge1->prevInAEL ) m_ActiveEdges = edge1; - else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) -{ - if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; - if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; - - if( edge1->nextInSEL == edge2 ) - { - TEdge* next = edge2->nextInSEL; - if( next ) next->prevInSEL = edge1; - TEdge* prev = edge1->prevInSEL; - if( prev ) prev->nextInSEL = edge2; - edge2->prevInSEL = prev; - edge2->nextInSEL = edge1; - edge1->prevInSEL = edge2; - edge1->nextInSEL = next; - } - else if( edge2->nextInSEL == edge1 ) - { - TEdge* next = edge1->nextInSEL; - if( next ) next->prevInSEL = edge2; - TEdge* prev = edge2->prevInSEL; - if( prev ) prev->nextInSEL = edge1; - edge1->prevInSEL = prev; - edge1->nextInSEL = edge2; - edge2->prevInSEL = edge1; - edge2->nextInSEL = next; - } - else - { - TEdge* next = edge1->nextInSEL; - TEdge* prev = edge1->prevInSEL; - edge1->nextInSEL = edge2->nextInSEL; - if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; - edge1->prevInSEL = edge2->prevInSEL; - if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; - edge2->nextInSEL = next; - if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; - edge2->prevInSEL = prev; - if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; - } - - if( !edge1->prevInSEL ) m_SortedEdges = edge1; - else if( !edge2->prevInSEL ) m_SortedEdges = edge2; -} -//------------------------------------------------------------------------------ - -TEdge* GetNextInAEL(TEdge *e, Direction dir) -{ - if( dir == dLeftToRight ) return e->nextInAEL; - else return e->prevInAEL; -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontal(TEdge *horzEdge) -{ - Direction dir; - long64 horzLeft, horzRight; - - if( horzEdge->xcurr < horzEdge->xtop ) - { - horzLeft = horzEdge->xcurr; - horzRight = horzEdge->xtop; - dir = dLeftToRight; - } else - { - horzLeft = horzEdge->xtop; - horzRight = horzEdge->xcurr; - dir = dRightToLeft; - } - - TEdge* eMaxPair; - if( horzEdge->nextInLML ) eMaxPair = 0; - else eMaxPair = GetMaximaPair(horzEdge); - - TEdge* e = GetNextInAEL( horzEdge , dir ); - while( e ) - { - TEdge* eNext = GetNextInAEL( e, dir ); - - if (eMaxPair || - ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || - ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) - { - //ok, so far it looks like we're still in range of the horizontal edge - if ( e->xcurr == horzEdge->xtop && !eMaxPair ) - { - if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) - { - //if output polygons share an edge, they'll need joining later ... - if (horzEdge->outIdx >= 0 && e->outIdx >= 0) - AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); - break; //we've reached the end of the horizontal line - } - else if (e->dx < horzEdge->nextInLML->dx) - //we really have got to the end of the intermediate horz edge so quit. - //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. - break; - } - - if( e == eMaxPair ) - { - //horzEdge is evidently a maxima horizontal and we've arrived at its end. - if (dir == dLeftToRight) - IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - else - IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - return; - } - else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) - { - //An overlapping horizontal edge. Overlapping horizontal edges are - //processed as if layered with the current horizontal edge (horizEdge) - //being infinitesimally lower that the next (e). Therfore, we - //intersect with e only if e.xcurr is within the bounds of horzEdge ... - if( dir == dLeftToRight ) - IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - else - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - else if( dir == dLeftToRight ) - { - IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - } - else - { - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - SwapPositionsInAEL( horzEdge, e ); - } - else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || - (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; - e = eNext; - } //end while - - if( horzEdge->nextInLML ) - { - if( horzEdge->outIdx >= 0 ) - AddOutPt( horzEdge, 0, IntPoint(horzEdge->xtop, horzEdge->ytop)); - UpdateEdgeIntoAEL( horzEdge ); - } - else - { - if ( horzEdge->outIdx >= 0 ) - IntersectEdges( horzEdge, eMaxPair, - IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - DeleteFromAEL(eMaxPair); - DeleteFromAEL(horzEdge); - } -} -//------------------------------------------------------------------------------ - -void Clipper::UpdateEdgeIntoAEL(TEdge *&e) -{ - if( !e->nextInLML ) throw - clipperException("UpdateEdgeIntoAEL: invalid call"); - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - e->nextInLML->outIdx = e->outIdx; - if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; - else m_ActiveEdges = e->nextInLML; - if( AelNext ) AelNext->prevInAEL = e->nextInLML; - e->nextInLML->side = e->side; - e->nextInLML->windDelta = e->windDelta; - e->nextInLML->windCnt = e->windCnt; - e->nextInLML->windCnt2 = e->windCnt2; - e = e->nextInLML; - e->prevInAEL = AelPrev; - e->nextInAEL = AelNext; - if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); -} -//------------------------------------------------------------------------------ - -bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) -{ - if( !m_ActiveEdges ) return true; - try { - BuildIntersectList(botY, topY); - if ( !m_IntersectNodes) return true; - if ( FixupIntersections() ) ProcessIntersectList(); - else return false; - } - catch(...) { - m_SortedEdges = 0; - DisposeIntersectNodes(); - throw clipperException("ProcessIntersections error"); - } - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeIntersectNodes() -{ - while ( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildIntersectList(const long64 botY, const long64 topY) -{ - if ( !m_ActiveEdges ) return; - - //prepare for sorting ... - TEdge* e = m_ActiveEdges; - e->tmpX = TopX( *e, topY ); - m_SortedEdges = e; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e->tmpX = TopX( *e, topY ); - e = e->nextInAEL; - } - - //bubblesort ... - bool isModified = true; - while( isModified && m_SortedEdges ) - { - isModified = false; - e = m_SortedEdges; - while( e->nextInSEL ) - { - TEdge *eNext = e->nextInSEL; - IntPoint pt; - if(e->tmpX > eNext->tmpX && - IntersectPoint(*e, *eNext, pt, m_UseFullRange)) - { - if (pt.Y > botY) - { - pt.Y = botY; - pt.X = TopX(*e, pt.Y); - } - AddIntersectNode( e, eNext, pt ); - SwapPositionsInSEL(e, eNext); - isModified = true; - } - else - e = eNext; - } - if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; - else break; - } - m_SortedEdges = 0; -} -//------------------------------------------------------------------------------ - -bool Process1Before2(IntersectNode &node1, IntersectNode &node2) -{ - bool result; - if (node1.pt.Y == node2.pt.Y) - { - if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) - { - result = node2.pt.X > node1.pt.X; - if (node2.edge1->dx > 0) return !result; else return result; - } - else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) - { - result = node2.pt.X > node1.pt.X; - if (node2.edge2->dx > 0) return !result; else return result; - } - else return node2.pt.X > node1.pt.X; - } - else return node1.pt.Y > node2.pt.Y; -} -//------------------------------------------------------------------------------ - -void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - IntersectNode* newNode = new IntersectNode; - newNode->edge1 = e1; - newNode->edge2 = e2; - newNode->pt = pt; - newNode->next = 0; - if( !m_IntersectNodes ) m_IntersectNodes = newNode; - else if( Process1Before2(*newNode, *m_IntersectNodes) ) - { - newNode->next = m_IntersectNodes; - m_IntersectNodes = newNode; - } - else - { - IntersectNode* iNode = m_IntersectNodes; - while( iNode->next && Process1Before2(*iNode->next, *newNode) ) - iNode = iNode->next; - newNode->next = iNode->next; - iNode->next = newNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessIntersectList() -{ - while( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - { - IntersectEdges( m_IntersectNodes->edge1 , - m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); - SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); - } - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::DoMaxima(TEdge *e, long64 topY) -{ - TEdge* eMaxPair = GetMaximaPair(e); - long64 X = e->xtop; - TEdge* eNext = e->nextInAEL; - while( eNext != eMaxPair ) - { - if (!eNext) throw clipperException("DoMaxima error"); - IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); - eNext = eNext->nextInAEL; - } - if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) - { - DeleteFromAEL( e ); - DeleteFromAEL( eMaxPair ); - } - else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) - { - IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); - } - else throw clipperException("DoMaxima error"); -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) -{ - TEdge* e = m_ActiveEdges; - while( e ) - { - //1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) - { - //'e' might be removed from AEL, as may any following edges so ... - TEdge* ePrior = e->prevInAEL; - DoMaxima(e, topY); - if( !ePrior ) e = m_ActiveEdges; - else e = ePrior->nextInAEL; - } - else - { - //2. promote horizontal edges, otherwise update xcurr and ycurr ... - if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) - { - if (e->outIdx >= 0) - { - AddOutPt(e, 0, IntPoint(e->xtop, e->ytop)); - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; - HorzJoinRec* hj = m_HorizJoins[i]; - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), - IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) - AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); - } - - AddHorzJoin(e->nextInLML, e->outIdx); - } - UpdateEdgeIntoAEL(e); - AddEdgeToSEL(e); - } else - { - //this just simplifies horizontal processing ... - e->xcurr = TopX( *e, topY ); - e->ycurr = topY; - } - e = e->nextInAEL; - } - } - - //3. Process horizontals at the top of the scanbeam ... - ProcessHorizontals(); - - //4. Promote intermediate vertices ... - e = m_ActiveEdges; - while( e ) - { - if( IsIntermediate( e, topY ) ) - { - if( e->outIdx >= 0 ) AddOutPt(e, 0, IntPoint(e->xtop,e->ytop)); - UpdateEdgeIntoAEL(e); - - //if output polygons share an edge, they'll need joining later ... - if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && - e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->prevInAEL, 0, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->prevInAEL); - } - else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && - e->nextInAEL->ycurr > e->nextInAEL->ytop && - e->nextInAEL->ycurr < e->nextInAEL->ybot && - e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->nextInAEL, 0, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->nextInAEL); - } - } - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolygon(OutRec &outRec) -{ - //FixupOutPolygon() - removes duplicate points and simplifies consecutive - //parallel edges by removing the middle vertex. - OutPt *lastOK = 0; - outRec.pts = outRec.bottomPt; - OutPt *pp = outRec.bottomPt; - - for (;;) - { - if (pp->prev == pp || pp->prev == pp->next ) - { - DisposeOutPts(pp); - outRec.pts = 0; - outRec.bottomPt = 0; - return; - } - //test for duplicate points and for same slope (cross-product) ... - if ( PointsEqual(pp->pt, pp->next->pt) || - SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) - { - lastOK = 0; - OutPt *tmp = pp; - if (pp == outRec.bottomPt) - { - if (tmp->prev->pt.Y > tmp->next->pt.Y) - outRec.bottomPt = tmp->prev; else - outRec.bottomPt = tmp->next; - outRec.pts = outRec.bottomPt; - outRec.bottomPt->idx = outRec.idx; - } - pp->prev->next = pp->next; - pp->next->prev = pp->prev; - pp = pp->prev; - delete tmp; - } - else if (pp == lastOK) break; - else - { - if (!lastOK) lastOK = pp; - pp = pp->next; - } - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult(Polygons &polys) -{ - int k = 0; - polys.resize(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - if (m_PolyOuts[i]->pts) - { - Polygon* pg = &polys[k]; - pg->clear(); - OutPt* p = m_PolyOuts[i]->pts; - do - { - pg->push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - //make sure each polygon has at least 3 vertices ... - if (pg->size() < 3) pg->clear(); else k++; - } - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResultEx(ExPolygons &polys) -{ - PolyOutList::size_type i = 0; - int k = 0; - polys.resize(0); - polys.reserve(m_PolyOuts.size()); - while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) - { - ExPolygon epg; - OutPt* p = m_PolyOuts[i]->pts; - do { - epg.outer.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - i++; - //make sure polygons have at least 3 vertices ... - if (epg.outer.size() < 3) continue; - while (i < m_PolyOuts.size() - && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) - { - Polygon pg; - p = m_PolyOuts[i]->pts; - do { - pg.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - epg.holes.push_back(pg); - i++; - } - polys.push_back(epg); - k++; - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) -{ - TEdge *e1 = int1.edge1; - TEdge *e2 = int1.edge2; - IntPoint p = int1.pt; - - int1.edge1 = int2.edge1; - int1.edge2 = int2.edge2; - int1.pt = int2.pt; - - int2.edge1 = e1; - int2.edge2 = e2; - int2.pt = p; -} -//------------------------------------------------------------------------------ - -bool Clipper::FixupIntersections() -{ - if ( !m_IntersectNodes->next ) return true; - - CopyAELToSEL(); - IntersectNode *int1 = m_IntersectNodes; - IntersectNode *int2 = m_IntersectNodes->next; - while (int2) - { - TEdge *e1 = int1->edge1; - TEdge *e2; - if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; - else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; - else - { - //The current intersection is out of order, so try and swap it with - //a subsequent intersection ... - while (int2) - { - if (int2->edge1->nextInSEL == int2->edge2 || - int2->edge1->prevInSEL == int2->edge2) break; - else int2 = int2->next; - } - if ( !int2 ) return false; //oops!!! - - //found an intersect node that can be swapped ... - SwapIntersectNodes(*int1, *int2); - e1 = int1->edge1; - e2 = int1->edge2; - } - SwapPositionsInSEL(e1, e2); - int1 = int1->next; - int2 = int1->next; - } - - m_SortedEdges = 0; - - //finally, check the last intersection too ... - return (int1->edge1->prevInSEL == int1->edge2 || - int1->edge1->nextInSEL == int1->edge2); -} -//------------------------------------------------------------------------------ - -bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) -{ - if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx; - else return e2.xcurr < e1.xcurr; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertEdgeIntoAEL(TEdge *edge) -{ - edge->prevInAEL = 0; - edge->nextInAEL = 0; - if( !m_ActiveEdges ) - { - m_ActiveEdges = edge; - } - else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) - { - edge->nextInAEL = m_ActiveEdges; - m_ActiveEdges->prevInAEL = edge; - m_ActiveEdges = edge; - } else - { - TEdge* e = m_ActiveEdges; - while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) - e = e->nextInAEL; - edge->nextInAEL = e->nextInAEL; - if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; - edge->prevInAEL = e; - e->nextInAEL = edge; - } -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, edge2, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge2, edge1, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, edge2, pt); - AddOutPt(edge2, edge1, pt); - SwapSides( *edge1 , *edge2 ); - SwapPolyIndexes( *edge1 , *edge2 ); -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) -{ - //when a polygon is split into 2 polygons, make sure any holes the original - //polygon contained link to the correct polygon ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *orec = m_PolyOuts[i]; - if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && - !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) - orec->FirstLeft = outRec2; - } -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) -{ - //if a hole is owned by outRec2 then make it owned by outRec1 ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && - m_PolyOuts[i]->FirstLeft == outRec2) - m_PolyOuts[i]->FirstLeft = outRec1; -} -//---------------------------------------------------------------------- - -void Clipper::JoinCommonEdges(bool fixHoleLinkages) -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - { - JoinRec* j = m_Joins[i]; - OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; - OutPt *pp1a = outRec1->pts; - OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; - OutPt *pp2a = outRec2->pts; - IntPoint pt1 = j->pt2a, pt2 = j->pt2b; - IntPoint pt3 = j->pt1a, pt4 = j->pt1b; - if (!FindSegment(pp1a, pt1, pt2)) continue; - if (j->poly1Idx == j->poly2Idx) - { - //we're searching the same polygon for overlapping segments so - //segment 2 mustn't be the same as segment 1 ... - pp2a = pp1a->next; - if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; - } - else if (!FindSegment(pp2a, pt3, pt4)) continue; - - if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; - - OutPt *p1, *p2, *p3, *p4; - OutPt *prev = pp1a->prev; - //get p1 & p2 polypts - the overlap start & endpoints on poly1 - if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; - else if (PointsEqual(prev->pt, pt1)) p1 = prev; - else p1 = InsertPolyPtBetween(pp1a, prev, pt1); - - if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; - else if (PointsEqual(prev->pt, pt2)) p2 = prev; - else if ((p1 == pp1a) || (p1 == prev)) - p2 = InsertPolyPtBetween(pp1a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) - p2 = InsertPolyPtBetween(pp1a, p1, pt2); else - p2 = InsertPolyPtBetween(p1, prev, pt2); - - //get p3 & p4 polypts - the overlap start & endpoints on poly2 - prev = pp2a->prev; - if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; - else if (PointsEqual(prev->pt, pt1)) p3 = prev; - else p3 = InsertPolyPtBetween(pp2a, prev, pt1); - - if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; - else if (PointsEqual(prev->pt, pt2)) p4 = prev; - else if ((p3 == pp2a) || (p3 == prev)) - p4 = InsertPolyPtBetween(pp2a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) - p4 = InsertPolyPtBetween(pp2a, p3, pt2); else - p4 = InsertPolyPtBetween(p3, prev, pt2); - - //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... - if (p1->next == p2 && p3->prev == p4) - { - p1->next = p3; - p3->prev = p1; - p2->prev = p4; - p4->next = p2; - } - else if (p1->prev == p2 && p3->next == p4) - { - p1->prev = p3; - p3->next = p1; - p2->next = p4; - p4->prev = p2; - } - else - continue; //an orientation is probably wrong - - if (j->poly2Idx == j->poly1Idx) - { - //instead of joining two polygons, we've just created a new one by - //splitting one polygon into two. - outRec1->pts = PolygonBottom(p1); - outRec1->bottomPt = outRec1->pts; - outRec1->bottomPt->idx = outRec1->idx; - outRec2 = CreateOutRec(); - m_PolyOuts.push_back(outRec2); - outRec2->idx = (int)m_PolyOuts.size()-1; - j->poly2Idx = outRec2->idx; - outRec2->pts = PolygonBottom(p2); - outRec2->bottomPt = outRec2->pts; - outRec2->bottomPt->idx = outRec2->idx; - - if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) - { - outRec2->isHole = !outRec1->isHole; - outRec2->FirstLeft = outRec1; - if (outRec2->isHole == Orientation(outRec2, m_UseFullRange)) - ReversePolyPtLinks(*outRec2->pts); - } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) - { - outRec2->isHole = outRec1->isHole; - outRec1->isHole = !outRec2->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; - if (outRec1->isHole == Orientation(outRec1, m_UseFullRange)) - ReversePolyPtLinks(*outRec1->pts); - } else - { - outRec2->isHole = outRec1->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - //make sure any contained holes now link to the correct polygon ... - if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); - } - - //now fixup any subsequent joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) - j2->poly1Idx = j->poly2Idx; - if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) - j2->poly2Idx = j->poly2Idx; - } - - //now cleanup redundant edges too ... - FixupOutPolygon(*outRec1); - FixupOutPolygon(*outRec2); - } else - { - //joined 2 polygons together ... - - //make sure any holes contained by outRec2 now link to outRec1 ... - if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); - - //delete the obsolete pointer ... - int OKIdx = outRec1->idx; - int ObsoleteIdx = outRec2->idx; - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - //holes are practically always joined to outers, not vice versa ... - if (outRec1->isHole && !outRec2->isHole) outRec1->isHole = false; - - //now fixup any subsequent Joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; - if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; - } - - //now cleanup redundant edges too ... - if (outRec1->pts) - FixupOutPolygon(*outRec1); - else - FixupOutPolygon(*outRec2); - } - } -} -//------------------------------------------------------------------------------ - -void ReversePoints(Polygon& p) -{ - std::reverse(p.begin(), p.end()); -} -//------------------------------------------------------------------------------ - -void ReversePoints(Polygons& p) -{ - for (Polygons::size_type i = 0; i < p.size(); ++i) - ReversePoints(p[i]); -} - -//------------------------------------------------------------------------------ -// OffsetPolygon functions ... -//------------------------------------------------------------------------------ - -struct DoublePoint -{ - double X; - double Y; - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} -}; -//------------------------------------------------------------------------------ - -Polygon BuildArc(const IntPoint &pt, - const double a1, const double a2, const double r) -{ - int steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); - Polygon result(steps); - int n = steps - 1; - double da = (a2 - a1) / n; - double a = a1; - for (int i = 0; i <= n; ++i) - { - result[i].X = pt.X + Round(std::cos(a)*r); - result[i].Y = pt.Y + Round(std::sin(a)*r); - a += da; - } - return result; -} -//------------------------------------------------------------------------------ - -DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) -{ - if(pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); - - double dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); - dx *= f; - dy *= f; - return DoublePoint(dy, -dx); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class PolyOffsetBuilder -{ -private: - Polygons m_p; - Polygon* m_curr_poly; - std::vector normals; - double m_delta, m_RMin, m_R; - size_t m_i, m_j, m_k; - static const int buffLength = 128; - JoinType m_jointype; - -public: - -PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - //nb precondition - out_polys != ptsin_polys - if (NEAR_ZERO(delta)) - { - out_polys = in_polys; - return; - } - - this->m_p = in_polys; - this->m_delta = delta; - this->m_jointype = jointype; - if (MiterLimit <= 1) MiterLimit = 1; - m_RMin = 2/(MiterLimit*MiterLimit); - - double deltaSq = delta*delta; - out_polys.clear(); - out_polys.resize(in_polys.size()); - for (m_i = 0; m_i < in_polys.size(); m_i++) - { - m_curr_poly = &out_polys[m_i]; - size_t len = in_polys[m_i].size(); - if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && - m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; - - //when 'shrinking' polygons - to minimize artefacts - //strip those polygons that have an area < pi * delta^2 ... - double a1 = Area(in_polys[m_i]); - if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } - else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area - - if (len == 0 || (len < 3 && delta <= 0)) - continue; - else if (len == 1) - { - Polygon arc; - arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); - out_polys[m_i] = arc; - continue; - } - - //build normals ... - normals.clear(); - normals.resize(len); - normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); - for (m_j = 0; m_j < len -1; ++m_j) - normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); - - m_k = len -1; - for (m_j = 0; m_j < len; ++m_j) - { - switch (jointype) - { - case jtMiter: - { - m_R = 1 + (normals[m_j].X*normals[m_k].X + - normals[m_j].Y*normals[m_k].Y); - if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); - break; - } - case jtSquare: DoSquare(); break; - case jtRound: DoRound(); break; - } - m_k = m_j; - } - } - - //finally, clean up untidy corners using Clipper ... - Clipper clpr; - clpr.AddPolygons(out_polys, ptSubject); - if (delta > 0) - { - if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) - out_polys.clear(); - } - else - { - IntRect r = clpr.GetBounds(); - Polygon outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPolygon(outer, ptSubject); - if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) - { - out_polys.erase(out_polys.begin()); - ReversePoints(out_polys); - - } else - out_polys.clear(); - } -} -//------------------------------------------------------------------------------ - -private: - -void AddPoint(const IntPoint& pt) -{ - Polygon::size_type len = m_curr_poly->size(); - if (len == m_curr_poly->capacity()) - m_curr_poly->reserve(len + buffLength); - m_curr_poly->push_back(pt); -} -//------------------------------------------------------------------------------ - -void DoSquare(double mul = 1.0) -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); - a1 = std::fabs(a2 - a1); - if (a1 > pi) a1 = pi * 2 - a1; - double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); - pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), - (long64)(pt1.Y + normals[m_k].X * dx)); - AddPoint(pt1); - pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), - (long64)(pt2.Y -normals[m_j].X * dx)); - AddPoint(pt2); - } - else - { - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoMiter() -{ - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double q = m_delta / m_R; - AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + - (normals[m_k].X + normals[m_j].X) * q), - (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); - } - else - { - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoRound() -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). - if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) - { - if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); - if (m_delta > 0 && a2 < a1) a2 += pi *2; - else if (m_delta < 0 && a2 > a1) a2 -= pi *2; - Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); - for (Polygon::size_type m = 0; m < arc.size(); m++) - AddPoint(arc[m]); - } - } - else - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); -} -//-------------------------------------------------------------------------- - -}; //end PolyOffsetBuilder - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - if (&out_polys == &in_polys) - { - Polygons poly2(in_polys); - PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); - } - else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, IntPoint& p) -{ - s << p.X << ' ' << p.Y << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygon &p) -{ - for (Polygon::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygons &p) -{ - for (Polygons::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -} //ClipperLib namespace +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.6.3 * +* Date : 11 November 2011 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2011 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "../include/clipper.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +static long64 const loRange = 1518500249; //sqrt(2^63 -1)/2 +static long64 const hiRange = 6521908912666391106LL; //sqrt(2^127 -1)/2 +static double const pi = 3.141592653589793238; +enum Direction { dRightToLeft, dLeftToRight }; +enum RangeTest { rtLo, rtHi, rtError }; + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) +#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) + +inline long64 Abs(long64 val) +{ + if (val < 0) return -val; else return val; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Int128 class (enables safe math on signed 64bit integers) +// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 +// Int128 val2((long64)9223372036854775807); +// Int128 val3 = val1 * val2; +// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) +//------------------------------------------------------------------------------ + +class Int128 +{ + public: + + Int128(long64 _lo = 0) + { + hi = 0; + if (_lo < 0) { + lo = -_lo; + Negate(*this); + } else + lo = _lo; + } + + Int128(const Int128 &val): hi(val.hi), lo(val.lo){} + + long64 operator = (const long64 &val) + { + hi = 0; + lo = Abs(val); + if (val < 0) Negate(*this); + return val; + } + + bool operator == (const Int128 &val) const + {return (hi == val.hi && lo == val.lo);} + + bool operator != (const Int128 &val) const { return !(*this == val);} + + bool operator > (const Int128 &val) const + { + if (hi > val.hi) return true; + else if (hi < val.hi) return false; + else return ulong64(lo) > ulong64(val.lo); + } + + bool operator < (const Int128 &val) const + { + if (hi < val.hi) return true; + else if (hi > val.hi) return false; + else return ulong64(lo) < ulong64(val.lo); + } + + Int128& operator += (const Int128 &rhs) + { + hi += rhs.hi; + lo += rhs.lo; + if (ulong64(lo) < ulong64(rhs.lo)) hi++; + return *this; + } + + Int128 operator + (const Int128 &rhs) const + { + Int128 result(*this); + result+= rhs; + return result; + } + + Int128& operator -= (const Int128 &rhs) + { + Int128 tmp(rhs); + Negate(tmp); + *this += tmp; + return *this; + } + + Int128 operator - (const Int128 &rhs) const + { + Int128 result(*this); + result-= rhs; + return result; + } + + Int128 operator * (const Int128 &rhs) const { + if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) + throw "Int128 operator*: overflow error"; + bool negate = (hi < 0) != (rhs.hi < 0); + + Int128 tmp(*this); + if (tmp.hi < 0) Negate(tmp); + ulong64 int1Hi = ulong64(tmp.lo) >> 32; + ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + tmp = rhs; + if (tmp.hi < 0) Negate(tmp); + ulong64 int2Hi = ulong64(tmp.lo) >> 32; + ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + //nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + tmp.hi = long64(a + (c >> 32)); + tmp.lo = long64(c << 32); + tmp.lo += long64(b); + if (ulong64(tmp.lo) < b) tmp.hi++; + if (negate) Negate(tmp); + return tmp; + } + + Int128 operator/ (const Int128 &rhs) const + { + if (rhs.lo == 0 && rhs.hi == 0) + throw "Int128 operator/: divide by zero"; + bool negate = (rhs.hi < 0) != (hi < 0); + Int128 result(*this), denom(rhs); + if (result.hi < 0) Negate(result); + if (denom.hi < 0) Negate(denom); + if (denom > result) return Int128(0); //result is only a fraction of 1 + Negate(denom); + + Int128 p(0); + for (int i = 0; i < 128; ++i) + { + p.hi = p.hi << 1; + if (p.lo < 0) p.hi++; + p.lo = long64(p.lo) << 1; + if (result.hi < 0) p.lo++; + result.hi = result.hi << 1; + if (result.lo < 0) result.hi++; + result.lo = long64(result.lo) << 1; + Int128 p2(p); + p += denom; + if (p.hi < 0) p = p2; + else result.lo++; + } + if (negate) Negate(result); + return result; + } + + double AsDouble() const + { + const double shift64 = 18446744073709551616.0; //2^64 + const double bit64 = 9223372036854775808.0; + if (hi < 0) + { + Int128 tmp(*this); + Negate(tmp); + if (tmp.lo < 0) + return (double)tmp.lo - bit64 - tmp.hi * shift64; + else + return -(double)tmp.lo - tmp.hi * shift64; + } + else if (lo < 0) + return -(double)lo + bit64 + hi * shift64; + else + return (double)lo + (double)hi * shift64; + } + + //for bug testing ... + std::string AsString() const + { + std::string result; + unsigned char r = 0; + Int128 tmp(0), val(*this); + if (hi < 0) Negate(val); + result.resize(50); + std::string::size_type i = result.size() -1; + while (val.hi != 0 || val.lo != 0) + { + Div10(val, tmp, r); + result[i--] = char('0' + r); + val = tmp; + } + if (hi < 0) result[i--] = '-'; + result.erase(0,i+1); + if (result.size() == 0) result = "0"; + return result; + } + +private: + long64 hi; + long64 lo; + + static void Negate(Int128 &val) + { + if (val.lo == 0) + { + if( val.hi == 0) return; + val.lo = ~val.lo; + val.hi = ~val.hi +1; + } + else + { + val.lo = ~val.lo +1; + val.hi = ~val.hi; + } + } + + //debugging only ... + void Div10(const Int128 val, Int128& result, unsigned char & remainder) const + { + remainder = 0; + result = 0; + for (int i = 63; i >= 0; --i) + { + if ((val.hi & ((long64)1 << i)) != 0) + remainder = char((remainder * 2) + 1); else + remainder *= char(2); + if (remainder >= 10) + { + result.hi += ((long64)1 << i); + remainder -= char(10); + } + } + for (int i = 63; i >= 0; --i) + { + if ((val.lo & ((long64)1 << i)) != 0) + remainder = char((remainder * 2) + 1); else + remainder *= char(2); + if (remainder >= 10) + { + result.lo += ((long64)1 << i); + remainder -= char(10); + } + } + } +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +RangeTest TestRange(const Polygon &pts) +{ + RangeTest result = rtLo; + for (Polygon::size_type i = 0; i < pts.size(); ++i) + { + if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) + return rtError; + else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) + result = rtHi; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Orientation(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return false; + bool UseFullInt64Range = false; + + int j = 0, jplus, jminus; + for (int i = 0; i <= highI; ++i) + { + if (Abs(poly[i].X) > hiRange || Abs(poly[i].Y) > hiRange) + throw "Coordinate exceeds range bounds."; + if (Abs(poly[i].X) > loRange || Abs(poly[i].Y) > loRange) + UseFullInt64Range = true; + if (poly[i].Y < poly[j].Y) continue; + if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; + }; + if (j == highI) jplus = 0; + else jplus = j +1; + if (j == 0) jminus = highI; + else jminus = j -1; + + IntPoint vec1, vec2; + //get cross product of vectors of the edges adjacent to highest point ... + vec1.X = poly[j].X - poly[jminus].X; + vec1.Y = poly[j].Y - poly[jminus].Y; + vec2.X = poly[jplus].X - poly[j].X; + vec2.Y = poly[jplus].Y - poly[j].Y; + + if (UseFullInt64Range) + { + Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - + Int128(vec2.X) * Int128(vec1.Y); + return cross > 0; + } + else + { + return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; + } +} +//------------------------------------------------------------------------------ + +bool Orientation(OutRec *outRec, bool UseFullInt64Range) +{ + OutPt *opBottom = outRec->pts, *op = outRec->pts->next; + while (op != outRec->pts) + { + if (op->pt.Y >= opBottom->pt.Y) + { + if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) + opBottom = op; + } + op = op->next; + } + + IntPoint vec1, vec2; + vec1.X = op->pt.X - op->prev->pt.X; + vec1.Y = op->pt.Y - op->prev->pt.Y; + vec2.X = op->next->pt.X - op->pt.X; + vec2.Y = op->next->pt.Y - op->pt.Y; + + if (UseFullInt64Range) + { + Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - Int128(vec2.X) * Int128(vec1.Y); + return cross > 0; + } + else + { + return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; + } +} +//------------------------------------------------------------------------------ + +inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) +{ + return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); +} +//------------------------------------------------------------------------------ + +double Area(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return 0; + bool UseFullInt64Range; + RangeTest rt = TestRange(poly); + switch (rt) { + case rtLo: + UseFullInt64Range = false; + break; + case rtHi: + UseFullInt64Range = true; + break; + default: + throw "Coordinate exceeds range bounds."; + } + + if (UseFullInt64Range) { + Int128 a(0); + a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - + Int128(poly[0].X) * Int128(poly[highI].Y); + for (int i = 0; i < highI; ++i) + a += Int128(poly[i].X) * Int128(poly[i+1].Y) - + Int128(poly[i+1].X) * Int128(poly[i].Y); + return a.AsDouble() / 2; + } + else + { + double a; + a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; + for (int i = 0; i < highI; ++i) + a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; + return a/2; + } +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (PointsEqual(pp2->pt, pt)) return true; + pp2 = pp2->next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) +{ + OutPt *pp2 = pp; + bool result = false; + if (UseFullInt64Range) { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * + Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) + result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + else + { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / + (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + return result; +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) +{ + if (e1.ybot == e1.ytop) return (e2.ybot == e2.ytop); + else if (e1.xbot == e1.xtop) return (e2.xbot == e2.xtop); + else if (UseFullInt64Range) + return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == + Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); + else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == + (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, bool UseFullInt64Range) +{ + if (pt1.Y == pt2.Y) return (pt2.Y == pt3.Y); + else if (pt1.X == pt2.X) return (pt2.X == pt3.X); + else if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == + Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); + else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +{ + if (pt1.Y == pt2.Y) return (pt3.Y == pt4.Y); + else if (pt1.X == pt2.X) return (pt3.X == pt4.X); + else if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == + Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); + else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); +} +//------------------------------------------------------------------------------ + +double GetDx(const IntPoint pt1, const IntPoint pt2) +{ + if (pt1.Y == pt2.Y) return HORIZONTAL; + else return + (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +void SetDx(TEdge &e) +{ + if (e.ybot == e.ytop) e.dx = HORIZONTAL; + else e.dx = + (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); +} +//--------------------------------------------------------------------------- + +void SwapSides(TEdge &edge1, TEdge &edge2) +{ + EdgeSide side = edge1.side; + edge1.side = edge2.side; + edge2.side = side; +} +//------------------------------------------------------------------------------ + +void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) +{ + int outIdx = edge1.outIdx; + edge1.outIdx = edge2.outIdx; + edge2.outIdx = outIdx; +} +//------------------------------------------------------------------------------ + +inline long64 Round(double val) +{ + if ((val < 0)) return static_cast(val - 0.5); + else return static_cast(val + 0.5); +} +//------------------------------------------------------------------------------ + +long64 TopX(TEdge &edge, const long64 currentY) +{ + if( currentY == edge.ytop ) return edge.xtop; + return edge.xbot + Round(edge.dx *(currentY - edge.ybot)); +} +//------------------------------------------------------------------------------ + +long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) +{ + //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y + if (currentY >= pt1.Y) return pt1.X; + else if (currentY == pt2.Y) return pt2.X; + else if (pt1.X == pt2.X) return pt1.X; + else + { + double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); + return Round(pt1.X + (currentY - pt1.Y) *q); + } +} +//------------------------------------------------------------------------------ + +bool IntersectPoint(TEdge &edge1, TEdge &edge2, + IntPoint &ip, bool UseFullInt64Range) +{ + double b1, b2; + if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; + else if (NEAR_ZERO(edge1.dx)) + { + ip.X = edge1.xbot; + if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) + { + ip.Y = edge2.ybot; + } else + { + b2 = edge2.ybot - (edge2.xbot/edge2.dx); + ip.Y = Round(ip.X/edge2.dx + b2); + } + } + else if (NEAR_ZERO(edge2.dx)) + { + ip.X = edge2.xbot; + if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) + { + ip.Y = edge1.ybot; + } else + { + b1 = edge1.ybot - (edge1.xbot/edge1.dx); + ip.Y = Round(ip.X/edge1.dx + b1); + } + } else + { + b1 = edge1.xbot - edge1.ybot * edge1.dx; + b2 = edge2.xbot - edge2.ybot * edge2.dx; + b2 = (b2-b1)/(edge1.dx - edge2.dx); + ip.Y = Round(b2); + ip.X = Round(edge1.dx * b2 + b1); + } + + return + //can be *so close* to the top of one edge that the rounded Y equals one ytop ... + (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y > edge1.ytop && ip.Y > edge2.ytop); +} +//------------------------------------------------------------------------------ + +void ReversePolyPtLinks(OutPt &pp) +{ + OutPt *pp1, *pp2; + pp1 = &pp; + do { + pp2 = pp1->next; + pp1->next = pp1->prev; + pp1->prev = pp2; + pp1 = pp2; + } while( pp1 != &pp ); +} +//------------------------------------------------------------------------------ + +void DisposeOutPts(OutPt*& pp) +{ + if (pp == 0) return; + pp->prev->next = 0; + while( pp ) + { + OutPt *tmpPp = pp; + pp = pp->next; + delete tmpPp ; + } +} +//------------------------------------------------------------------------------ + +void InitEdge(TEdge *e, TEdge *eNext, + TEdge *ePrev, const IntPoint &pt, PolyType polyType) +{ + std::memset( e, 0, sizeof( TEdge )); + + e->next = eNext; + e->prev = ePrev; + e->xcurr = pt.X; + e->ycurr = pt.Y; + if (e->ycurr >= e->next->ycurr) + { + e->xbot = e->xcurr; + e->ybot = e->ycurr; + e->xtop = e->next->xcurr; + e->ytop = e->next->ycurr; + e->windDelta = 1; + } else + { + e->xtop = e->xcurr; + e->ytop = e->ycurr; + e->xbot = e->next->xcurr; + e->ybot = e->next->ycurr; + e->windDelta = -1; + } + SetDx(*e); + e->polyType = polyType; + e->outIdx = -1; +} +//------------------------------------------------------------------------------ + +inline void SwapX(TEdge &e) +{ + //swap horizontal edges' top and bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + e.xcurr = e.xtop; + e.xtop = e.xbot; + e.xbot = e.xcurr; +} +//------------------------------------------------------------------------------ + +void SwapPoints(IntPoint &pt1, IntPoint &pt2) +{ + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are colinear. + if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) + { + if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); + if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +OutPt* PolygonBottom(OutPt* pp) +{ + OutPt* p = pp->next; + OutPt* result = pp; + while (p != pp) + { + if (p->pt.Y > result->pt.Y) result = p; + else if (p->pt.Y == result->pt.Y && p->pt.X < result->pt.X) result = p; + p = p->next; + } + return result; +} +//------------------------------------------------------------------------------ + +bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) +{ + //outPt1 & outPt2 => the overlap segment (if the function returns true) + if (!pp) return false; + OutPt* pp2 = pp; + IntPoint pt1a = pt1, pt2a = pt2; + do + { + if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && + SlopesEqual(pt1a, pt2a, pp->pt, true) && + GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) + return true; + pp = pp->next; + } + while (pp != pp2); + return false; +} +//------------------------------------------------------------------------------ + +bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, + const IntPoint pt2, const IntPoint pt3) +{ + if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; + else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); + else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); +} +//------------------------------------------------------------------------------ + +OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) +{ + if (p1 == p2) throw "JoinError"; + OutPt* result = new OutPt; + result->pt = pt; + if (p2 == p1->next) + { + p1->next = result; + p2->prev = result; + result->next = p2; + result->prev = p1; + } else + { + p2->next = result; + p1->prev = result; + result->next = p1; + result->prev = p2; + } + return result; +} + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +ClipperBase::ClipperBase() //constructor +{ + m_MinimaList = 0; + m_CurrentLM = 0; + m_UseFullRange = true; +} +//------------------------------------------------------------------------------ + +ClipperBase::~ClipperBase() //destructor +{ + Clear(); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) +{ + int len = (int)pg.size(); + if (len < 3) return false; + Polygon p(len); + p[0] = pg[0]; + int j = 0; + + long64 maxVal; + if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; + + for (int i = 0; i < len; ++i) + { + if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) + { + if (m_UseFullRange) + throw "Coordinate exceeds range bounds"; + maxVal = hiRange; + if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) + throw "Coordinate exceeds range bounds"; + m_UseFullRange = true; + } + + if (i == 0 || PointsEqual(p[j], pg[i])) continue; + else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) + { + if (PointsEqual(p[j-1], pg[i])) j--; + } else j++; + p[j] = pg[i]; + } + if (j < 2) return false; + + len = j+1; + for (;;) + { + //nb: test for point equality before testing slopes ... + if (PointsEqual(p[j], p[0])) j--; + else if (PointsEqual(p[0], p[1]) || + SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) + p[0] = p[j--]; + else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; + else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) + { + for (int i = 2; i <= j; ++i) p[i-1] = p[i]; + j--; + } + //exit loop if nothing is changed or there are too few vertices ... + if (j == len-1 || j < 2) break; + len = j +1; + } + if (len < 3) return false; + + //create a new edge array ... + TEdge *edges = new TEdge [len]; + m_edges.push_back(edges); + + //convert vertices to a double-linked-list of edges and initialize ... + edges[0].xcurr = p[0].X; + edges[0].ycurr = p[0].Y; + InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); + for (int i = len-2; i > 0; --i) + InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); + InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); + + //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates + //increase downward so the 'highest' edge will have the smallest ytop) ... + TEdge *e = &edges[0]; + TEdge *eHighest = e; + do + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + if (e->ytop < eHighest->ytop) eHighest = e; + e = e->next; + } + while ( e != &edges[0]); + + //make sure eHighest is positioned so the following loop works safely ... + if (eHighest->windDelta > 0) eHighest = eHighest->next; + if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; + + //finally insert each local minima ... + e = eHighest; + do { + e = AddBoundsToLML(e); + } + while( e != eHighest ); + return true; +} +//------------------------------------------------------------------------------ + +void ClipperBase::InsertLocalMinima(LocalMinima *newLm) +{ + if( ! m_MinimaList ) + { + m_MinimaList = newLm; + } + else if( newLm->Y >= m_MinimaList->Y ) + { + newLm->next = m_MinimaList; + m_MinimaList = newLm; + } else + { + LocalMinima* tmpLm = m_MinimaList; + while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) + tmpLm = tmpLm->next; + newLm->next = tmpLm->next; + tmpLm->next = newLm; + } +} +//------------------------------------------------------------------------------ + +TEdge* ClipperBase::AddBoundsToLML(TEdge *e) +{ + //Starting at the top of one bound we progress to the bottom where there's + //a local minima. We then go to the top of the next bound. These two bounds + //form the left and right (or right and left) bounds of the local minima. + e->nextInLML = 0; + e = e->next; + for (;;) + { + if (NEAR_EQUAL(e->dx, HORIZONTAL)) + { + //nb: proceed through horizontals when approaching from their right, + // but break on horizontal minima if approaching from their left. + // This ensures 'local minima' are always on the left of horizontals. + if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; + if (e->xtop != e->prev->xbot) SwapX(*e); + e->nextInLML = e->prev; + } + else if (e->ycurr == e->prev->ycurr) break; + else e->nextInLML = e->prev; + e = e->next; + } + + //e and e.prev are now at a local minima ... + LocalMinima* newLm = new LocalMinima; + newLm->next = 0; + newLm->Y = e->prev->ybot; + + if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound + { + if (e->xbot != e->prev->xbot) SwapX(*e); + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else if (e->dx < e->prev->dx) + { + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else + { + newLm->leftBound = e; + newLm->rightBound = e->prev; + } + newLm->leftBound->side = esLeft; + newLm->rightBound->side = esRight; + InsertLocalMinima( newLm ); + + for (;;) + { + if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; + e->nextInLML = e->next; + e = e->next; + if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); + } + return e->next; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) +{ + bool result = true; + for (Polygons::size_type i = 0; i < ppg.size(); ++i) + if (AddPolygon(ppg[i], polyType)) result = false; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; + m_edges.clear(); + m_UseFullRange = false; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Reset() +{ + m_CurrentLM = m_MinimaList; + if( !m_CurrentLM ) return; //ie nothing to process + + //reset all edges ... + LocalMinima* lm = m_MinimaList; + while( lm ) + { + TEdge* e = lm->leftBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esLeft; + e->outIdx = -1; + e = e->nextInLML; + } + e = lm->rightBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esRight; + e->outIdx = -1; + e = e->nextInLML; + } + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeLocalMinimaList() +{ + while( m_MinimaList ) + { + LocalMinima* tmpLm = m_MinimaList->next; + delete m_MinimaList; + m_MinimaList = tmpLm; + } + m_CurrentLM = 0; +} +//------------------------------------------------------------------------------ + +void ClipperBase::PopLocalMinima() +{ + if( ! m_CurrentLM ) return; + m_CurrentLM = m_CurrentLM->next; +} +//------------------------------------------------------------------------------ + +IntRect ClipperBase::GetBounds() +{ + IntRect result; + LocalMinima* lm = m_MinimaList; + if (!lm) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->leftBound->xbot; + result.top = lm->leftBound->ybot; + result.right = lm->leftBound->xbot; + result.bottom = lm->leftBound->ybot; + while (lm) + { + if (lm->leftBound->ybot > result.bottom) + result.bottom = lm->leftBound->ybot; + TEdge* e = lm->leftBound; + for (;;) { + TEdge* bottomE = e; + while (e->nextInLML) + { + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + e = e->nextInLML; + } + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + if (e->xtop < result.left) result.left = e->xtop; + if (e->xtop > result.right) result.right = e->xtop; + if (e->ytop < result.top) result.top = e->ytop; + + if (bottomE == lm->leftBound) e = lm->rightBound; + else break; + } + lm = lm->next; + } + return result; +} + + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper() : ClipperBase() //constructor +{ + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + m_IntersectNodes = 0; + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = false; +} +//------------------------------------------------------------------------------ + +Clipper::~Clipper() //destructor +{ + Clear(); + DisposeScanbeamList(); +} +//------------------------------------------------------------------------------ + +void Clipper::Clear() +{ + if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor + DisposeAllPolyPts(); + ClipperBase::Clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeScanbeamList() +{ + while ( m_Scanbeam ) { + Scanbeam* sb2 = m_Scanbeam->next; + delete m_Scanbeam; + m_Scanbeam = sb2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::Reset() +{ + ClipperBase::Reset(); + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + LocalMinima* lm = m_MinimaList; + while (lm) + { + InsertScanbeam(lm->Y); + InsertScanbeam(lm->leftBound->ytop); + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Polygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(false); + if (succeeded) BuildResult(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, ExPolygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(true); + if (succeeded) BuildResultEx(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool PolySort(OutRec *or1, OutRec *or2) +{ + if (or1 == or2) return false; + if (!or1->pts || !or2->pts) + { + if (or1->pts != or2->pts) + { + if (or1->pts) return true; else return false; + } + else return false; + } + int i1, i2; + if (or1->isHole) + i1 = or1->FirstLeft->idx; else + i1 = or1->idx; + if (or2->isHole) + i2 = or2->FirstLeft->idx; else + i2 = or2->idx; + int result = i1 - i2; + if (result == 0 && (or1->isHole != or2->isHole)) + { + if (or1->isHole) return false; + else return true; + } + else return result < 0; +} +//------------------------------------------------------------------------------ + +OutRec* FindAppendLinkEnd(OutRec *outRec) +{ + while (outRec->AppendLink) outRec = outRec->AppendLink; + return outRec; +} +//------------------------------------------------------------------------------ + +void Clipper::FixHoleLinkage(OutRec *outRec) +{ + OutRec *tmp; + if (outRec->bottomPt) + tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; + else + tmp = outRec->FirstLeft; + if (outRec == tmp) throw clipperException("HoleLinkage error"); + + if (tmp) + { + if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); + if (tmp == outRec) tmp = 0; + else if (tmp->isHole) + { + FixHoleLinkage(tmp); + tmp = tmp->FirstLeft; + } + } + outRec->FirstLeft = tmp; + if (!tmp) outRec->isHole = false; + outRec->AppendLink = 0; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal(bool fixHoleLinkages) +{ + bool succeeded; + try { + Reset(); + if (!m_CurrentLM ) return true; + long64 botY = PopScanbeam(); + do { + InsertLocalMinimaIntoAEL(botY); + ClearHorzJoins(); + ProcessHorizontals(); + long64 topY = PopScanbeam(); + succeeded = ProcessIntersections(botY, topY); + if (!succeeded) break; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while( m_Scanbeam ); + } + catch(...) { + succeeded = false; + } + + if (succeeded) + { + //tidy up output polygons and fix orientations where necessary ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->pts) continue; + FixupOutPolygon(*outRec); + if (!outRec->pts) continue; + if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); + if (outRec->isHole == + (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) + ReversePolyPtLinks(*outRec->pts); + } + + JoinCommonEdges(fixHoleLinkages); + if (fixHoleLinkages) + std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); + } + + ClearJoins(); + ClearHorzJoins(); + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertScanbeam(const long64 Y) +{ + if( !m_Scanbeam ) + { + m_Scanbeam = new Scanbeam; + m_Scanbeam->next = 0; + m_Scanbeam->Y = Y; + } + else if( Y > m_Scanbeam->Y ) + { + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = m_Scanbeam; + m_Scanbeam = newSb; + } else + { + Scanbeam* sb2 = m_Scanbeam; + while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; + if( Y == sb2->Y ) return; //ie ignores duplicates + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = sb2->next; + sb2->next = newSb; + } +} +//------------------------------------------------------------------------------ + +long64 Clipper::PopScanbeam() +{ + long64 Y = m_Scanbeam->Y; + Scanbeam* sb2 = m_Scanbeam; + m_Scanbeam = m_Scanbeam->next; + delete sb2; + return Y; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeAllPolyPts(){ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + DisposeOutRec(i); + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeOutRec(PolyOutList::size_type index, bool ignorePts) +{ + OutRec *outRec = m_PolyOuts[index]; + if (!ignorePts && outRec->pts) DisposeOutPts(outRec->pts); + delete outRec; + m_PolyOuts[index] = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) +{ + TEdge *e = edge.prevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; + if ( !e ) + { + edge.windCnt = edge.windDelta; + edge.windCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc windCnt2 + } else if ( IsEvenOddFillType(edge) ) + { + //EvenOdd filling ... + edge.windCnt = 1; + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } else + { + //nonZero, Positive or Negative filling ... + if ( e->windCnt * e->windDelta < 0 ) + { + if (Abs(e->windCnt) > 1) + { + if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } else + edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; + } else + { + if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) + edge.windCnt = e->windCnt; + else if ( e->windCnt + edge.windDelta == 0 ) + edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } + + //update windCnt2 ... + if ( IsEvenOddAltFillType(edge) ) + { + //EvenOdd filling ... + while ( e != &edge ) + { + edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; + e = e->nextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.windCnt2 += e->windDelta; + e = e->nextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_SubjFillType == pftEvenOdd; else + return m_ClipFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_ClipFillType == pftEvenOdd; else + return m_SubjFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.polyType == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + case pftNonZero: + if (Abs(edge.windCnt) != 1) return false; + break; + case pftPositive: + if (edge.windCnt != 1) return false; + break; + default: //pftNegative + if (edge.windCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + case ctDifference: + if (edge.polyType == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + default: + return true; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) + { + AddOutPt( e1, e2, pt ); + e2->outIdx = e1->outIdx; + e1->side = esLeft; + e2->side = esRight; + } else + { + AddOutPt( e2, e1, pt ); + e1->outIdx = e2->outIdx; + e1->side = esRight; + e2->side = esLeft; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + AddOutPt( e1, 0, pt ); + if( e1->outIdx == e2->outIdx ) + { + e1->outIdx = -1; + e2->outIdx = -1; + } + else + AppendPolygon( e1, e2 ); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->prevInSEL = 0; + edge->nextInSEL = 0; + } + else + { + edge->nextInSEL = m_SortedEdges; + edge->prevInSEL = 0; + m_SortedEdges->prevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + if (!m_ActiveEdges) return; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while ( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) +{ + JoinRec* jr = new JoinRec; + if (e1OutIdx >= 0) + jr->poly1Idx = e1OutIdx; else + jr->poly1Idx = e1->outIdx; + jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); + jr->pt1b = IntPoint(e1->xtop, e1->ytop); + if (e2OutIdx >= 0) + jr->poly2Idx = e2OutIdx; else + jr->poly2Idx = e2->outIdx; + jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); + jr->pt2b = IntPoint(e2->xtop, e2->ytop); + m_Joins.push_back(jr); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearJoins() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + delete m_Joins[i]; + m_Joins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::AddHorzJoin(TEdge *e, int idx) +{ + HorzJoinRec* hj = new HorzJoinRec; + hj->edge = e; + hj->savedIdx = idx; + m_HorizJoins.push_back(hj); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearHorzJoins() +{ + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) + delete m_HorizJoins[i]; + m_HorizJoins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) +{ + while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) + { + TEdge* lb = m_CurrentLM->leftBound; + TEdge* rb = m_CurrentLM->rightBound; + + InsertEdgeIntoAEL( lb ); + InsertScanbeam( lb->ytop ); + InsertEdgeIntoAEL( rb ); + + if (IsEvenOddFillType(*lb)) + { + lb->windDelta = 1; + rb->windDelta = 1; + } + else + { + rb->windDelta = -lb->windDelta; + } + SetWindingCount( *lb ); + rb->windCnt = lb->windCnt; + rb->windCnt2 = lb->windCnt2; + + if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) + { + //nb: only rightbounds can have a horizontal bottom edge + AddEdgeToSEL( rb ); + InsertScanbeam( rb->nextInLML->ytop ); + } + else + InsertScanbeam( rb->ytop ); + + if( IsContributing(*lb) ) + AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); + + //if output polygons share an edge, they'll need joining later ... + if (lb->outIdx >= 0 && lb->prevInAEL && + lb->prevInAEL->outIdx >= 0 && lb->prevInAEL->xcurr == lb->xbot && + SlopesEqual(*lb, *lb->prevInAEL, m_UseFullRange)) + AddJoin(lb, lb->prevInAEL); + + //if any output polygons share an edge, they'll need joining later ... + if (rb->outIdx >= 0) + { + if (NEAR_EQUAL(rb->dx, HORIZONTAL)) + { + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. + HorzJoinRec* hj = m_HorizJoins[i]; + //if horizontals rb and hj.edge overlap, flag for joining later ... + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(rb->xbot, rb->ybot), + IntPoint(rb->xtop, rb->ytop), pt, pt2)) + AddJoin(hj->edge, rb, hj->savedIdx); + } + } + } + + if( lb->nextInAEL != rb ) + { + if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && + SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) + AddJoin(rb, rb->prevInAEL); + + TEdge* e = lb->nextInAEL; + IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); + while( e != rb ) + { + if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the right of param2 ABOVE the intersection ... + IntersectEdges( rb , e , pt , ipNone); //order important here + e = e->nextInAEL; + } + } + PopLocalMinima(); + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted + if( AelPrev ) AelPrev->nextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if( AelNext ) AelNext->prevInAEL = AelPrev; + e->nextInAEL = 0; + e->prevInAEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->prevInSEL; + TEdge* SelNext = e->nextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->nextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->prevInSEL = SelPrev; + e->nextInSEL = 0; + e->prevInSEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects) +{ + //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before + //e2 in AEL except when e1 is being inserted at the intersection point ... + bool e1stops = !(ipLeft & protects) && !e1->nextInLML && + e1->xtop == pt.X && e1->ytop == pt.Y; + bool e2stops = !(ipRight & protects) && !e2->nextInLML && + e2->xtop == pt.X && e2->ytop == pt.Y; + bool e1Contributing = ( e1->outIdx >= 0 ); + bool e2contributing = ( e2->outIdx >= 0 ); + + //update winding counts... + //assumes that e1 will be to the right of e2 ABOVE the intersection + if ( e1->polyType == e2->polyType ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->windCnt; + e1->windCnt = e2->windCnt; + e2->windCnt = oldE1WindCnt; + } else + { + if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; + else e1->windCnt += e2->windDelta; + if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; + else e2->windCnt -= e1->windDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; + else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; + else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->polyType == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->polyType == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + long64 e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->windCnt; break; + case pftNegative: e1Wc = -e1->windCnt; break; + default: e1Wc = Abs(e1->windCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->windCnt; break; + case pftNegative: e2Wc = -e2->windCnt; break; + default: e2Wc = Abs(e2->windCnt); + } + + if ( e1Contributing && e2contributing ) + { + if ( e1stops || e2stops || + (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->polyType != e2->polyType && m_ClipType != ctXor) ) + AddLocalMaxPoly(e1, e2, pt); + else + DoBothEdges( e1, e2, pt ); + } + else if ( e1Contributing ) + { + if ((e2Wc == 0 || e2Wc == 1) && + (m_ClipType != ctIntersection || + e2->polyType == ptSubject || (e2->windCnt2 != 0))) + DoEdge1(e1, e2, pt); + } + else if ( e2contributing ) + { + if ((e1Wc == 0 || e1Wc == 1) && + (m_ClipType != ctIntersection || + e1->polyType == ptSubject || (e1->windCnt2 != 0))) + DoEdge2(e1, e2, pt); + } + else if ( (e1Wc == 0 || e1Wc == 1) && + (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) + { + //neither edge is currently contributing ... + + long64 e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->windCnt2; break; + case pftNegative : e1Wc2 = -e1->windCnt2; break; + default: e1Wc2 = Abs(e1->windCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->windCnt2; break; + case pftNegative: e2Wc2 = -e2->windCnt2; break; + default: e2Wc2 = Abs(e2->windCnt2); + } + + if (e1->polyType != e2->polyType) + AddLocalMinPoly(e1, e2, pt); + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, pt); + break; + case ctDifference: + if ((e1->polyType == ptClip && e2->polyType == ptClip && + e1Wc2 > 0 && e2Wc2 > 0) || + (e1->polyType == ptSubject && e2->polyType == ptSubject && + e1Wc2 <= 0 && e2Wc2 <= 0)) + AddLocalMinPoly(e1, e2, pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, pt); + } + else + SwapSides( *e1, *e2 ); + } + + if( (e1stops != e2stops) && + ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) + { + SwapSides( *e1, *e2 ); + SwapPolyIndexes( *e1, *e2 ); + } + + //finally, delete any non-contributing maxima edges ... + if( e1stops ) DeleteFromAEL( e1 ); + if( e2stops ) DeleteFromAEL( e2 ); +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outRec) +{ + bool isHole = false; + TEdge *e2 = e->prevInAEL; + while (e2) + { + if (e2->outIdx >= 0) + { + isHole = !isHole; + if (! outRec->FirstLeft) + outRec->FirstLeft = m_PolyOuts[e2->outIdx]; + } + e2 = e2->prevInAEL; + } + if (isHole) outRec->isHole = true; +} +//------------------------------------------------------------------------------ + +bool GetNextNonDupOutPt(OutPt* pp, OutPt*& next) +{ + next = pp->next; + while (next != pp && PointsEqual(pp->pt, next->pt)) + next = next->next; + return next != pp; +} +//------------------------------------------------------------------------------ + +bool GetPrevNonDupOutPt(OutPt* pp, OutPt*& prev) +{ + prev = pp->prev; + while (prev != pp && PointsEqual(pp->pt, prev->pt)) + prev = prev->prev; + return prev != pp; +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + OutPt *outPt1 = outRec1->bottomPt; + OutPt *outPt2 = outRec2->bottomPt; + if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; + else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; + else if (outPt1->pt.X < outPt2->pt.X) return outRec1; + else if (outPt1->pt.X > outPt2->pt.X) return outRec2; + else if (outRec1->bottomE2 == 0) return outRec2; + else if (outRec2->bottomE2 == 0) return outRec1; + else + { + long64 y1 = std::max(outRec1->bottomE1->ybot, outRec1->bottomE2->ybot); + long64 y2 = std::max(outRec2->bottomE1->ybot, outRec2->bottomE2->ybot); + if (y2 == y1 || (y1 > outPt1->pt.Y && y2 > outPt1->pt.Y)) + { + double dx1 = std::max(outRec1->bottomE1->dx, outRec1->bottomE2->dx); + double dx2 = std::max(outRec2->bottomE1->dx, outRec2->bottomE2->dx); + if (dx2 > dx1) return outRec2; else return outRec1; + } + else if (y2 > y1) return outRec2; + else return outRec1; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->outIdx]; + OutRec *outRec2 = m_PolyOuts[e2->outIdx]; + OutRec *holeStateRec = GetLowermostRec(outRec1, outRec2); + + //fixup hole status ... + if (holeStateRec == outRec2) + outRec1->isHole = outRec2->isHole; + else + outRec2->isHole = outRec1->isHole; + + OutPt* p1_lft = outRec1->pts; + OutPt* p1_rt = p1_lft->prev; + OutPt* p2_lft = outRec2->pts; + OutPt* p2_rt = p2_lft->prev; + + EdgeSide side; + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->side == esLeft ) + { + if( e2->side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(*p2_lft); + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + outRec1->pts = p2_rt; + } else + { + //x y z a b c + p2_rt->next = p1_lft; + p1_lft->prev = p2_rt; + p2_lft->prev = p1_rt; + p1_rt->next = p2_lft; + outRec1->pts = p2_lft; + } + side = esLeft; + } else + { + if( e2->side == esRight ) + { + //a b c z y x + ReversePolyPtLinks( *p2_lft ); + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + } else + { + //a b c x y z + p1_rt->next = p2_lft; + p2_lft->prev = p1_rt; + p1_lft->prev = p2_rt; + p2_rt->next = p1_lft; + } + side = esRight; + } + + if (holeStateRec == outRec2) + { + outRec1->bottomPt = outRec2->bottomPt; + outRec1->bottomPt->idx = outRec1->idx; + outRec1->bottomE1 = outRec2->bottomE1; + outRec1->bottomE2 = outRec2->bottomE2; + + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + } + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + int OKIdx = e1->outIdx; + int ObsoleteIdx = e2->outIdx; + + e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly + e2->outIdx = -1; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->outIdx == ObsoleteIdx ) + { + e->outIdx = OKIdx; + e->side = side; + break; + } + e = e->nextInAEL; + } + + for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) + { + if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; + if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; + } + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) + m_HorizJoins[i]->savedIdx = OKIdx; + } + +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::CreateOutRec() +{ + OutRec* result = new OutRec; + result->isHole = false; + result->FirstLeft = 0; + result->AppendLink = 0; + result->pts = 0; + result->bottomPt = 0; + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt) +{ + bool ToFront = (e->side == esLeft); + if( e->outIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + m_PolyOuts.push_back(outRec); + outRec->idx = (int)m_PolyOuts.size()-1; + e->outIdx = outRec->idx; + OutPt* op = new OutPt; + outRec->pts = op; + outRec->bottomE1 = e; + outRec->bottomE2 = altE; + outRec->bottomPt = op; + op->pt = pt; + op->idx = outRec->idx; + op->next = op; + op->prev = op; + SetHoleState(e, outRec); + } else + { + OutRec *outRec = m_PolyOuts[e->outIdx]; + OutPt* op = outRec->pts; + if ((ToFront && PointsEqual(pt, op->pt)) || + (!ToFront && PointsEqual(pt, op->prev->pt))) return; + OutPt* op2 = new OutPt; + op2->pt = pt; + op2->idx = outRec->idx; + if (op2->pt.Y == outRec->bottomPt->pt.Y && + op2->pt.X < outRec->bottomPt->pt.X) + { + outRec->bottomPt = op2; + outRec->bottomE1 = e; + outRec->bottomE2 = altE; + } + op2->next = op; + op2->prev = op->prev; + op2->prev->next = op2; + op->prev = op2; + if (ToFront) outRec->pts = op2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals() +{ + TEdge* horzEdge = m_SortedEdges; + while( horzEdge ) + { + DeleteFromSEL( horzEdge ); + ProcessHorizontal( horzEdge ); + horzEdge = m_SortedEdges; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsTopHorz(const long64 XPos) +{ + TEdge* e = m_SortedEdges; + while( e ) + { + if( ( XPos >= std::min(e->xcurr, e->xtop) ) && + ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; + e = e->nextInSEL; + } + return true; +} +//------------------------------------------------------------------------------ + +bool IsMinima(TEdge *e) +{ + return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); +} +//------------------------------------------------------------------------------ + +bool IsMaxima(TEdge *e, const long64 Y) +{ + return e && e->ytop == Y && !e->nextInLML; +} +//------------------------------------------------------------------------------ + +bool IsIntermediate(TEdge *e, const long64 Y) +{ + return e->ytop == Y && e->nextInLML; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPair(TEdge *e) +{ + if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) + return e->prev; else + return e->next; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) +{ + if( !edge1->nextInAEL && !edge1->prevInAEL ) return; + if( !edge2->nextInAEL && !edge2->prevInAEL ) return; + + if( edge1->nextInAEL == edge2 ) + { + TEdge* next = edge2->nextInAEL; + if( next ) next->prevInAEL = edge1; + TEdge* prev = edge1->prevInAEL; + if( prev ) prev->nextInAEL = edge2; + edge2->prevInAEL = prev; + edge2->nextInAEL = edge1; + edge1->prevInAEL = edge2; + edge1->nextInAEL = next; + } + else if( edge2->nextInAEL == edge1 ) + { + TEdge* next = edge1->nextInAEL; + if( next ) next->prevInAEL = edge2; + TEdge* prev = edge2->prevInAEL; + if( prev ) prev->nextInAEL = edge1; + edge1->prevInAEL = prev; + edge1->nextInAEL = edge2; + edge2->prevInAEL = edge1; + edge2->nextInAEL = next; + } + else + { + TEdge* next = edge1->nextInAEL; + TEdge* prev = edge1->prevInAEL; + edge1->nextInAEL = edge2->nextInAEL; + if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; + edge1->prevInAEL = edge2->prevInAEL; + if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; + edge2->nextInAEL = next; + if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; + edge2->prevInAEL = prev; + if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; + } + + if( !edge1->prevInAEL ) m_ActiveEdges = edge1; + else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) +{ + if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; + if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; + + if( edge1->nextInSEL == edge2 ) + { + TEdge* next = edge2->nextInSEL; + if( next ) next->prevInSEL = edge1; + TEdge* prev = edge1->prevInSEL; + if( prev ) prev->nextInSEL = edge2; + edge2->prevInSEL = prev; + edge2->nextInSEL = edge1; + edge1->prevInSEL = edge2; + edge1->nextInSEL = next; + } + else if( edge2->nextInSEL == edge1 ) + { + TEdge* next = edge1->nextInSEL; + if( next ) next->prevInSEL = edge2; + TEdge* prev = edge2->prevInSEL; + if( prev ) prev->nextInSEL = edge1; + edge1->prevInSEL = prev; + edge1->nextInSEL = edge2; + edge2->prevInSEL = edge1; + edge2->nextInSEL = next; + } + else + { + TEdge* next = edge1->nextInSEL; + TEdge* prev = edge1->prevInSEL; + edge1->nextInSEL = edge2->nextInSEL; + if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; + edge1->prevInSEL = edge2->prevInSEL; + if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; + edge2->nextInSEL = next; + if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; + edge2->prevInSEL = prev; + if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; + } + + if( !edge1->prevInSEL ) m_SortedEdges = edge1; + else if( !edge2->prevInSEL ) m_SortedEdges = edge2; +} +//------------------------------------------------------------------------------ + +TEdge* GetNextInAEL(TEdge *e, Direction dir) +{ + if( dir == dLeftToRight ) return e->nextInAEL; + else return e->prevInAEL; +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontal(TEdge *horzEdge) +{ + Direction dir; + long64 horzLeft, horzRight; + + if( horzEdge->xcurr < horzEdge->xtop ) + { + horzLeft = horzEdge->xcurr; + horzRight = horzEdge->xtop; + dir = dLeftToRight; + } else + { + horzLeft = horzEdge->xtop; + horzRight = horzEdge->xcurr; + dir = dRightToLeft; + } + + TEdge* eMaxPair; + if( horzEdge->nextInLML ) eMaxPair = 0; + else eMaxPair = GetMaximaPair(horzEdge); + + TEdge* e = GetNextInAEL( horzEdge , dir ); + while( e ) + { + TEdge* eNext = GetNextInAEL( e, dir ); + + if (eMaxPair || + ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || + ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) + { + //ok, so far it looks like we're still in range of the horizontal edge + if ( e->xcurr == horzEdge->xtop && !eMaxPair ) + { + if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) + { + //if output polygons share an edge, they'll need joining later ... + if (horzEdge->outIdx >= 0 && e->outIdx >= 0) + AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); + break; //we've reached the end of the horizontal line + } + else if (e->dx < horzEdge->nextInLML->dx) + //we really have got to the end of the intermediate horz edge so quit. + //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. + break; + } + + if( e == eMaxPair ) + { + //horzEdge is evidently a maxima horizontal and we've arrived at its end. + if (dir == dLeftToRight) + IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + else + IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + return; + } + else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) + { + //An overlapping horizontal edge. Overlapping horizontal edges are + //processed as if layered with the current horizontal edge (horizEdge) + //being infinitesimally lower that the next (e). Therfore, we + //intersect with e only if e.xcurr is within the bounds of horzEdge ... + if( dir == dLeftToRight ) + IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + else + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + else if( dir == dLeftToRight ) + { + IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + } + else + { + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + SwapPositionsInAEL( horzEdge, e ); + } + else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || + (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; + e = eNext; + } //end while + + if( horzEdge->nextInLML ) + { + if( horzEdge->outIdx >= 0 ) + AddOutPt( horzEdge, 0, IntPoint(horzEdge->xtop, horzEdge->ytop)); + UpdateEdgeIntoAEL( horzEdge ); + } + else + { + if ( horzEdge->outIdx >= 0 ) + IntersectEdges( horzEdge, eMaxPair, + IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + DeleteFromAEL(eMaxPair); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +{ + if( !e->nextInLML ) throw + clipperException("UpdateEdgeIntoAEL: invalid call"); + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + e->nextInLML->outIdx = e->outIdx; + if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; + else m_ActiveEdges = e->nextInLML; + if( AelNext ) AelNext->prevInAEL = e->nextInLML; + e->nextInLML->side = e->side; + e->nextInLML->windDelta = e->windDelta; + e->nextInLML->windCnt = e->windCnt; + e->nextInLML->windCnt2 = e->windCnt2; + e = e->nextInLML; + e->prevInAEL = AelPrev; + e->nextInAEL = AelNext; + if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) +{ + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(botY, topY); + if ( !m_IntersectNodes) return true; + if ( FixupIntersections() ) ProcessIntersectList(); + else return false; + } + catch(...) { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeIntersectNodes() +{ + while ( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const long64 botY, const long64 topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + e->tmpX = TopX( *e, topY ); + m_SortedEdges = e; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e->tmpX = TopX( *e, topY ); + e = e->nextInAEL; + } + + //bubblesort ... + bool isModified = true; + while( isModified && m_SortedEdges ) + { + isModified = false; + e = m_SortedEdges; + while( e->nextInSEL ) + { + TEdge *eNext = e->nextInSEL; + IntPoint pt; + if(e->tmpX > eNext->tmpX && + IntersectPoint(*e, *eNext, pt, m_UseFullRange)) + { + if (pt.Y > botY) + { + pt.Y = botY; + pt.X = TopX(*e, pt.Y); + } + AddIntersectNode( e, eNext, pt ); + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; + else break; + } + m_SortedEdges = 0; +} +//------------------------------------------------------------------------------ + +bool Process1Before2(IntersectNode &node1, IntersectNode &node2) +{ + bool result; + if (node1.pt.Y == node2.pt.Y) + { + if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) + { + result = node2.pt.X > node1.pt.X; + if (node2.edge1->dx > 0) return !result; else return result; + } + else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) + { + result = node2.pt.X > node1.pt.X; + if (node2.edge2->dx > 0) return !result; else return result; + } + else return node2.pt.X > node1.pt.X; + } + else return node1.pt.Y > node2.pt.Y; +} +//------------------------------------------------------------------------------ + +void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + IntersectNode* newNode = new IntersectNode; + newNode->edge1 = e1; + newNode->edge2 = e2; + newNode->pt = pt; + newNode->next = 0; + if( !m_IntersectNodes ) m_IntersectNodes = newNode; + else if( Process1Before2(*newNode, *m_IntersectNodes) ) + { + newNode->next = m_IntersectNodes; + m_IntersectNodes = newNode; + } + else + { + IntersectNode* iNode = m_IntersectNodes; + while( iNode->next && Process1Before2(*iNode->next, *newNode) ) + iNode = iNode->next; + newNode->next = iNode->next; + iNode->next = newNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessIntersectList() +{ + while( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + { + IntersectEdges( m_IntersectNodes->edge1 , + m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); + SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); + } + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e, long64 topY) +{ + TEdge* eMaxPair = GetMaximaPair(e); + long64 X = e->xtop; + TEdge* eNext = e->nextInAEL; + while( eNext != eMaxPair ) + { + if (!eNext) throw clipperException("DoMaxima error"); + IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); + eNext = eNext->nextInAEL; + } + if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) + { + DeleteFromAEL( e ); + DeleteFromAEL( eMaxPair ); + } + else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) + { + IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); + } + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) +{ + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) + { + //'e' might be removed from AEL, as may any following edges so ... + TEdge* ePrior = e->prevInAEL; + DoMaxima(e, topY); + if( !ePrior ) e = m_ActiveEdges; + else e = ePrior->nextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update xcurr and ycurr ... + if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) + { + if (e->outIdx >= 0) + { + AddOutPt(e, 0, IntPoint(e->xtop, e->ytop)); + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; + HorzJoinRec* hj = m_HorizJoins[i]; + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), + IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) + AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); + } + + AddHorzJoin(e->nextInLML, e->outIdx); + } + UpdateEdgeIntoAEL(e); + AddEdgeToSEL(e); + } else + { + //this just simplifies horizontal processing ... + e->xcurr = TopX( *e, topY ); + e->ycurr = topY; + } + e = e->nextInAEL; + } + } + + //3. Process horizontals at the top of the scanbeam ... + ProcessHorizontals(); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while( e ) + { + if( IsIntermediate( e, topY ) ) + { + if( e->outIdx >= 0 ) AddOutPt(e, 0, IntPoint(e->xtop,e->ytop)); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && + e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->prevInAEL, 0, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->prevInAEL); + } + else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && + e->nextInAEL->ycurr > e->nextInAEL->ytop && + e->nextInAEL->ycurr < e->nextInAEL->ybot && + e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->nextInAEL, 0, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->nextInAEL); + } + } + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outRec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = 0; + outRec.pts = outRec.bottomPt; + OutPt *pp = outRec.bottomPt; + + for (;;) + { + if (pp->prev == pp || pp->prev == pp->next ) + { + DisposeOutPts(pp); + outRec.pts = 0; + outRec.bottomPt = 0; + return; + } + //test for duplicate points and for same slope (cross-product) ... + if ( PointsEqual(pp->pt, pp->next->pt) || + SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) + { + lastOK = 0; + OutPt *tmp = pp; + if (pp == outRec.bottomPt) + { + if (tmp->prev->pt.Y > tmp->next->pt.Y) + outRec.bottomPt = tmp->prev; else + outRec.bottomPt = tmp->next; + outRec.pts = outRec.bottomPt; + outRec.bottomPt->idx = outRec.idx; + } + pp->prev->next = pp->next; + pp->next->prev = pp->prev; + pp = pp->prev; + delete tmp; + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->next; + } + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Polygons &polys) +{ + int k = 0; + polys.resize(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + if (m_PolyOuts[i]->pts) + { + Polygon* pg = &polys[k]; + pg->clear(); + OutPt* p = m_PolyOuts[i]->pts; + do + { + pg->push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + //make sure each polygon has at least 3 vertices ... + if (pg->size() < 3) pg->clear(); else k++; + } + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResultEx(ExPolygons &polys) +{ + PolyOutList::size_type i = 0; + int k = 0; + polys.resize(0); + polys.reserve(m_PolyOuts.size()); + while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) + { + ExPolygon epg; + OutPt* p = m_PolyOuts[i]->pts; + do { + epg.outer.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + i++; + //make sure polygons have at least 3 vertices ... + if (epg.outer.size() < 3) continue; + while (i < m_PolyOuts.size() + && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) + { + Polygon pg; + p = m_PolyOuts[i]->pts; + do { + pg.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + epg.holes.push_back(pg); + i++; + } + polys.push_back(epg); + k++; + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +{ + TEdge *e1 = int1.edge1; + TEdge *e2 = int1.edge2; + IntPoint p = int1.pt; + + int1.edge1 = int2.edge1; + int1.edge2 = int2.edge2; + int1.pt = int2.pt; + + int2.edge1 = e1; + int2.edge2 = e2; + int2.pt = p; +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersections() +{ + if ( !m_IntersectNodes->next ) return true; + + CopyAELToSEL(); + IntersectNode *int1 = m_IntersectNodes; + IntersectNode *int2 = m_IntersectNodes->next; + while (int2) + { + TEdge *e1 = int1->edge1; + TEdge *e2; + if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; + else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; + else + { + //The current intersection is out of order, so try and swap it with + //a subsequent intersection ... + while (int2) + { + if (int2->edge1->nextInSEL == int2->edge2 || + int2->edge1->prevInSEL == int2->edge2) break; + else int2 = int2->next; + } + if ( !int2 ) return false; //oops!!! + + //found an intersect node that can be swapped ... + SwapIntersectNodes(*int1, *int2); + e1 = int1->edge1; + e2 = int1->edge2; + } + SwapPositionsInSEL(e1, e2); + int1 = int1->next; + int2 = int1->next; + } + + m_SortedEdges = 0; + + //finally, check the last intersection too ... + return (int1->edge1->prevInSEL == int1->edge2 || + int1->edge1->nextInSEL == int1->edge2); +} +//------------------------------------------------------------------------------ + +bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx; + else return e2.xcurr < e1.xcurr; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge) +{ + edge->prevInAEL = 0; + edge->nextInAEL = 0; + if( !m_ActiveEdges ) + { + m_ActiveEdges = edge; + } + else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) + { + edge->nextInAEL = m_ActiveEdges; + m_ActiveEdges->prevInAEL = edge; + m_ActiveEdges = edge; + } else + { + TEdge* e = m_ActiveEdges; + while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) + e = e->nextInAEL; + edge->nextInAEL = e->nextInAEL; + if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; + edge->prevInAEL = e; + e->nextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, edge2, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge2, edge1, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, edge2, pt); + AddOutPt(edge2, edge1, pt); + SwapSides( *edge1 , *edge2 ); + SwapPolyIndexes( *edge1 , *edge2 ); +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) +{ + //when a polygon is split into 2 polygons, make sure any holes the original + //polygon contained link to the correct polygon ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *orec = m_PolyOuts[i]; + if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && + !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) + orec->FirstLeft = outRec2; + } +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) +{ + //if a hole is owned by outRec2 then make it owned by outRec1 ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && + m_PolyOuts[i]->FirstLeft == outRec2) + m_PolyOuts[i]->FirstLeft = outRec1; +} +//---------------------------------------------------------------------- + +void Clipper::JoinCommonEdges(bool fixHoleLinkages) +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + { + JoinRec* j = m_Joins[i]; + OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; + OutPt *pp1a = outRec1->pts; + OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; + OutPt *pp2a = outRec2->pts; + IntPoint pt1 = j->pt2a, pt2 = j->pt2b; + IntPoint pt3 = j->pt1a, pt4 = j->pt1b; + if (!FindSegment(pp1a, pt1, pt2)) continue; + if (j->poly1Idx == j->poly2Idx) + { + //we're searching the same polygon for overlapping segments so + //segment 2 mustn't be the same as segment 1 ... + pp2a = pp1a->next; + if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; + } + else if (!FindSegment(pp2a, pt3, pt4)) continue; + + if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; + + OutPt *p1, *p2, *p3, *p4; + OutPt *prev = pp1a->prev; + //get p1 & p2 polypts - the overlap start & endpoints on poly1 + if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; + else if (PointsEqual(prev->pt, pt1)) p1 = prev; + else p1 = InsertPolyPtBetween(pp1a, prev, pt1); + + if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; + else if (PointsEqual(prev->pt, pt2)) p2 = prev; + else if ((p1 == pp1a) || (p1 == prev)) + p2 = InsertPolyPtBetween(pp1a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) + p2 = InsertPolyPtBetween(pp1a, p1, pt2); else + p2 = InsertPolyPtBetween(p1, prev, pt2); + + //get p3 & p4 polypts - the overlap start & endpoints on poly2 + prev = pp2a->prev; + if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; + else if (PointsEqual(prev->pt, pt1)) p3 = prev; + else p3 = InsertPolyPtBetween(pp2a, prev, pt1); + + if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; + else if (PointsEqual(prev->pt, pt2)) p4 = prev; + else if ((p3 == pp2a) || (p3 == prev)) + p4 = InsertPolyPtBetween(pp2a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) + p4 = InsertPolyPtBetween(pp2a, p3, pt2); else + p4 = InsertPolyPtBetween(p3, prev, pt2); + + //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... + if (p1->next == p2 && p3->prev == p4) + { + p1->next = p3; + p3->prev = p1; + p2->prev = p4; + p4->next = p2; + } + else if (p1->prev == p2 && p3->next == p4) + { + p1->prev = p3; + p3->next = p1; + p2->next = p4; + p4->prev = p2; + } + else + continue; //an orientation is probably wrong + + if (j->poly2Idx == j->poly1Idx) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->pts = PolygonBottom(p1); + outRec1->bottomPt = outRec1->pts; + outRec1->bottomPt->idx = outRec1->idx; + outRec2 = CreateOutRec(); + m_PolyOuts.push_back(outRec2); + outRec2->idx = (int)m_PolyOuts.size()-1; + j->poly2Idx = outRec2->idx; + outRec2->pts = PolygonBottom(p2); + outRec2->bottomPt = outRec2->pts; + outRec2->bottomPt->idx = outRec2->idx; + + if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) + { + outRec2->isHole = !outRec1->isHole; + outRec2->FirstLeft = outRec1; + if (outRec2->isHole == Orientation(outRec2, m_UseFullRange)) + ReversePolyPtLinks(*outRec2->pts); + } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) + { + outRec2->isHole = outRec1->isHole; + outRec1->isHole = !outRec2->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + if (outRec1->isHole == Orientation(outRec1, m_UseFullRange)) + ReversePolyPtLinks(*outRec1->pts); + } else + { + outRec2->isHole = outRec1->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + //make sure any contained holes now link to the correct polygon ... + if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); + } + + //now fixup any subsequent joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) + j2->poly1Idx = j->poly2Idx; + if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) + j2->poly2Idx = j->poly2Idx; + } + + //now cleanup redundant edges too ... + FixupOutPolygon(*outRec1); + FixupOutPolygon(*outRec2); + } else + { + //joined 2 polygons together ... + + //make sure any holes contained by outRec2 now link to outRec1 ... + if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); + + //delete the obsolete pointer ... + int OKIdx = outRec1->idx; + int ObsoleteIdx = outRec2->idx; + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + //holes are practically always joined to outers, not vice versa ... + if (outRec1->isHole && !outRec2->isHole) outRec1->isHole = false; + + //now fixup any subsequent Joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; + if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; + } + + //now cleanup redundant edges too ... + if (outRec1->pts) + FixupOutPolygon(*outRec1); + else + FixupOutPolygon(*outRec2); + } + } +} +//------------------------------------------------------------------------------ + +void ReversePoints(Polygon& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePoints(Polygons& p) +{ + for (Polygons::size_type i = 0; i < p.size(); ++i) + ReversePoints(p[i]); +} + +//------------------------------------------------------------------------------ +// OffsetPolygon functions ... +//------------------------------------------------------------------------------ + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} +}; +//------------------------------------------------------------------------------ + +Polygon BuildArc(const IntPoint &pt, + const double a1, const double a2, const double r) +{ + int steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); + Polygon result(steps); + int n = steps - 1; + double da = (a2 - a1) / n; + double a = a1; + for (int i = 0; i <= n; ++i) + { + result[i].X = pt.X + Round(std::cos(a)*r); + result[i].Y = pt.Y + Round(std::sin(a)*r); + a += da; + } + return result; +} +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); + dx *= f; + dy *= f; + return DoublePoint(dy, -dx); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class PolyOffsetBuilder +{ +private: + Polygons m_p; + Polygon* m_curr_poly; + std::vector normals; + double m_delta, m_RMin, m_R; + size_t m_i, m_j, m_k; + static const int buffLength = 128; + JoinType m_jointype; + +public: + +PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + //nb precondition - out_polys != ptsin_polys + if (NEAR_ZERO(delta)) + { + out_polys = in_polys; + return; + } + + this->m_p = in_polys; + this->m_delta = delta; + this->m_jointype = jointype; + if (MiterLimit <= 1) MiterLimit = 1; + m_RMin = 2/(MiterLimit*MiterLimit); + + double deltaSq = delta*delta; + out_polys.clear(); + out_polys.resize(in_polys.size()); + for (m_i = 0; m_i < in_polys.size(); m_i++) + { + m_curr_poly = &out_polys[m_i]; + size_t len = in_polys[m_i].size(); + if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && + m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; + + //when 'shrinking' polygons - to minimize artefacts + //strip those polygons that have an area < pi * delta^2 ... + double a1 = Area(in_polys[m_i]); + if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } + else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area + + if (len == 0 || (len < 3 && delta <= 0)) + continue; + else if (len == 1) + { + Polygon arc; + arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); + out_polys[m_i] = arc; + continue; + } + + //build normals ... + normals.clear(); + normals.resize(len); + normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); + for (m_j = 0; m_j < len -1; ++m_j) + normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); + + m_k = len -1; + for (m_j = 0; m_j < len; ++m_j) + { + switch (jointype) + { + case jtMiter: + { + m_R = 1 + (normals[m_j].X*normals[m_k].X + + normals[m_j].Y*normals[m_k].Y); + if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); + break; + } + case jtSquare: DoSquare(); break; + case jtRound: DoRound(); break; + } + m_k = m_j; + } + } + + //finally, clean up untidy corners using Clipper ... + Clipper clpr; + clpr.AddPolygons(out_polys, ptSubject); + if (delta > 0) + { + if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) + out_polys.clear(); + } + else + { + IntRect r = clpr.GetBounds(); + Polygon outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPolygon(outer, ptSubject); + if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) + { + out_polys.erase(out_polys.begin()); + ReversePoints(out_polys); + + } else + out_polys.clear(); + } +} +//------------------------------------------------------------------------------ + +private: + +void AddPoint(const IntPoint& pt) +{ + Polygon::size_type len = m_curr_poly->size(); + if (len == m_curr_poly->capacity()) + m_curr_poly->reserve(len + buffLength); + m_curr_poly->push_back(pt); +} +//------------------------------------------------------------------------------ + +void DoSquare(double mul = 1.0) +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); + a1 = std::fabs(a2 - a1); + if (a1 > pi) a1 = pi * 2 - a1; + double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); + pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), + (long64)(pt1.Y + normals[m_k].X * dx)); + AddPoint(pt1); + pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), + (long64)(pt2.Y -normals[m_j].X * dx)); + AddPoint(pt2); + } + else + { + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoMiter() +{ + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double q = m_delta / m_R; + AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + + (normals[m_k].X + normals[m_j].X) * q), + (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); + } + else + { + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoRound() +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). + if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) + { + if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); + if (m_delta > 0 && a2 < a1) a2 += pi *2; + else if (m_delta < 0 && a2 > a1) a2 -= pi *2; + Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); + for (Polygon::size_type m = 0; m < arc.size(); m++) + AddPoint(arc[m]); + } + } + else + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); +} +//-------------------------------------------------------------------------- + +}; //end PolyOffsetBuilder + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + if (&out_polys == &in_polys) + { + Polygons poly2(in_polys); + PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); + } + else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, IntPoint& p) +{ + s << p.X << ' ' << p.Y << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygon &p) +{ + for (Polygon::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygons &p) +{ + for (Polygons::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +} //ClipperLib namespace diff -Nru mapserver-7.0.7/renderers/mvt/vector_tile.proto mapserver-7.6.4/renderers/mvt/vector_tile.proto --- mapserver-7.0.7/renderers/mvt/vector_tile.proto 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/renderers/mvt/vector_tile.proto 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,81 @@ +//set version statement to avoid warnings thrown in protobuf >= 3 +syntax = "proto2"; + +package vector_tile; + +option optimize_for = LITE_RUNTIME; + +message Tile { + + // GeomType is described in section 4.3.4 of the specification + enum GeomType { + UNKNOWN = 0; + POINT = 1; + LINESTRING = 2; + POLYGON = 3; + } + + // Variant type encoding + // The use of values is described in section 4.1 of the specification + message Value { + // Exactly one of these values must be present in a valid message + optional string string_value = 1; + optional float float_value = 2; + optional double double_value = 3; + optional int64 int_value = 4; + optional uint64 uint_value = 5; + optional sint64 sint_value = 6; + optional bool bool_value = 7; + + extensions 8 to max; + } + + // Features are described in section 4.2 of the specification + message Feature { + optional uint64 id = 1 [ default = 0 ]; + + // Tags of this feature are encoded as repeated pairs of + // integers. + // A detailed description of tags is located in sections + // 4.2 and 4.4 of the specification + repeated uint32 tags = 2 [ packed = true ]; + + // The type of geometry stored in this feature. + optional GeomType type = 3 [ default = UNKNOWN ]; + + // Contains a stream of commands and parameters (vertices). + // A detailed description on geometry encoding is located in + // section 4.3 of the specification. + repeated uint32 geometry = 4 [ packed = true ]; + } + + // Layers are described in section 4.1 of the specification + message Layer { + // Any compliant implementation must first read the version + // number encoded in this message and choose the correct + // implementation for this version number before proceeding to + // decode other parts of this message. + required uint32 version = 15 [ default = 1 ]; + + required string name = 1; + + // The actual features in this tile. + repeated Feature features = 2; + + // Dictionary encoding for keys + repeated string keys = 3; + + // Dictionary encoding for values + repeated Value values = 4; + + // Although this is an "optional" field it is required by the specification. + // See https://github.com/mapbox/vector-tile-spec/issues/47 + optional uint32 extent = 5 [ default = 4096 ]; + + extensions 16 to max; + } + + repeated Layer layers = 3; + + extensions 16 to 8191; +} diff -Nru mapserver-7.0.7/scripts/docker/Dockerfile mapserver-7.6.4/scripts/docker/Dockerfile --- mapserver-7.0.7/scripts/docker/Dockerfile 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/scripts/docker/Dockerfile 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,164 @@ +FROM ubuntu:xenial +MAINTAINER Michael Smith + +#Setup user +ARG UID +ARG GID +ARG MRSID_DOWNLOAD_URL +RUN addgroup --gid $GID msgroup +RUN adduser --no-create-home --disabled-login msuser --gecos "" --uid $UID --gid $GID + +ENV LIBKML_DOWNLOAD=install-libkml-r864-64bit.tar.gz +ENV FILEGDBAPI_DOWNLOAD=FileGDB_API_1_2-64.tar.gz +ENV MRSID_DIR=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482 +ENV MRSID_DOWNLOAD=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482.tar.gz + +# Setup build env +RUN mkdir /build +RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 16126D3A3E5C1192 \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends software-properties-common \ + && add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends gcc-4.9 g++-4.9 build-essential ca-certificates curl wget git make cmake python-dev \ + python-software-properties software-properties-common libc6-dev openssh-client libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev \ + libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev swig \ + libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev libwebp-dev libepsilon-dev libpcre3-dev gfortran libarpack2-dev \ + libpq-dev libflann-dev libhdf5-serial-dev libhdf5-dev libjsoncpp-dev clang-3.8 libhdf4-alt-dev libsqlite3-dev \ + libltdl-dev libcurl4-openssl-dev ninja python-pip libpng-dev python-dev libprotobuf-c-dev protobuf-c-compiler\ + libboost-filesystem1.58-dev libboost-iostreams1.58-dev libboost-program-options1.58-dev libboost-system1.58-dev libboost-thread1.58-dev libogdi3.2-dev time \ + && apt-get remove --purge -y $BUILD_PACKAGES && rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20 && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20 + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${LIBKML_DOWNLOAD} -O /build/${LIBKML_DOWNLOAD} && \ + tar -C /build -xzf /build/${LIBKML_DOWNLOAD} && \ + cp -r /build/install-libkml/include/* /usr/local/include && \ + cp -r /build/install-libkml/lib/* /usr/local/lib \ + && rm -Rf /build/install-libkml + +RUN curl -L ${$MRSID_DOWNLOAD_URL}/${MRSID_DOWNLOAD} -o /build/${MRSID_DOWNLOAD} && \ + tar -C /build -xzf /build/${MRSID_DOWNLOAD} && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/include/* /usr/local/include && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/lib/* /usr/local/lib \ + && rm -Rf /build/${MRSID_DIR} + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${FILEGDBAPI_DOWNLOAD} -O /build/${FILEGDBAPI_DOWNLOAD} && \ + tar -C /build -xzf /build/${FILEGDBAPI_DOWNLOAD} && \ + cp -r /build/FileGDB_API/include/* /usr/local/include && \ + cp -r /build/FileGDB_API/lib/* /usr/local/lib \ + && rm -Rf /build/FileGDB_API + +RUN cd /build && curl -LO https://github.com/uclouvain/openjpeg/archive/v2.3.0.tar.gz && \ + tar -zxf /build/v2.3.0.tar.gz && \ + cd /build/openjpeg-2.3.0 && \ + mkdir -v build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr .. && \ + make -j && make install && \ + rm -Rf /build/openjpeg* + +RUN wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py && python get-pip.py && pip install --upgrade pip wheel numpy + +ARG GDAL_VERSION +RUN cd /build && \ + git clone https://github.com/OSGeo/gdal.git && \ + cd /build/gdal && \ + git checkout ${GDAL_VERSION} && \ + cd /build/gdal/gdal && \ + ./configure --prefix=/usr \ + --with-png=internal \ + --with-jpeg=internal \ + --with-libz=internal \ + --with-libtiff=internal \ + --with-geotiff=internal \ + --with-gif=internal \ + --with-libjson-c=internal \ + --with-poppler \ + --with-spatialite \ + --with-python \ + --with-liblzma \ + --with-openjpeg \ + --with-ogdi \ + --with-webp \ + --with-pg \ + --with-mrsid=/usr/local \ + --with-libkml \ + --with-filegdb \ + --with-hdf5=/usr/lib/x86_64-linux-gnu/hdf5/serial \ + --with-openjpeg && \ + make && \ + make install && \ + cd swig/python && python setup.py build && python setup.py install && \ + ldconfig && \ + rm -Rf /build/gdal + +RUN apt-get update && apt-get install -y --fix-missing --no-install-recommends build-essential ca-certificates curl wget \ + subversion git libaio1 make cmake python-numpy python-dev python-software-properties software-properties-common libv8-dev libc6-dev libfreetype6-dev \ + libcairo2-dev libpq-dev libharfbuzz-dev libfribidi-dev flex bison libfcgi-dev libxml2 libxml2-dev bzip2 apache2 apache2-utils apache2-dev \ + libaprutil1-dev libapr1-dev libpng12-dev libjpeg-dev libcurl4-gnutls-dev libpcre3-dev libpixman-1-dev libgeos-dev libsqlite3-dev libdb-dev libtiff-dev sudo \ + && rm -rf /var/lib/apt/lists/partial/* /tmp/* /var/tmp/* +RUN echo "msuser ALL=NOPASSWD: ALL" >> /etc/sudoers + +ARG MAPSERVER_VERSION +RUN cd /build && \ + git clone https://github.com/mapserver/mapserver.git mapserver && \ + cd /build/mapserver && \ + git checkout ${MAPSERVER_VERSION} \ + && mkdir /build/mapserver/build \ + && cd /build/mapserver/build \ + && cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DHARFBUZZ_INCLUDE_DIR=/usr/include/harfbuzz \ + -DWITH_CLIENT_WFS=ON \ + -DWITH_CLIENT_WMS=ON \ + -DWITH_CURL=ON \ + -DWITH_GDAL=ON \ + -DWITH_GIF=ON \ + -DWITH_ICONV=ON \ + -DWITH_KML=ON \ + -DWITH_LIBXML2=ON \ + -DWITH_OGR=ON \ + -DWITH_POINT_Z_M=ON \ + -DWITH_PROJ=ON \ + -DWITH_SOS=ON \ + -DWITH_THREAD_SAFETY=ON \ + -DWITH_WCS=ON \ + -DWITH_WFS=ON \ + -DWITH_WMS=ON \ + -DWITH_FCGI=ON \ + -DWITH_FRIBIDI=ON \ + -DWITH_CAIRO=ON \ + -DWITH_HARFBUZZ=ON \ + -DWITH_POSTGIS=on \ + -DWITH_V8=OFF \ + .. \ + && make \ + && make install \ + && ldconfig \ + && rm -Rf /build/mapserver + +#RUN mkdir /vdatum \ +# && cd /vdatum \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid1999.zip && unzip -j -u usa_geoid1999.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconc.gtx && mv vertconc.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertcone.gtx && mv vertcone.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconw.gtx && mv vertconw.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj \ +# && rm -rf /vdatum + +# Force buit libraries dependencies +RUN ldconfig + +# Enable these Apache modules +RUN a2enmod actions cgi alias headers + +RUN chmod o+x /usr/local/bin/mapserv +RUN ln -s /usr/local/bin/mapserv /usr/lib/cgi-bin/mapserv +RUN chmod 755 /usr/lib/cgi-bin + +ENV HOST_IP `ifconfig | grep inet | grep Mask:255.255.255.0 | cut -d ' ' -f 12 | cut -d ':' -f 2` + +CMD sudo service apache2 start && bash + +USER msuser \ No newline at end of file diff -Nru mapserver-7.0.7/scripts/docker/Dockerfile_mapcache mapserver-7.6.4/scripts/docker/Dockerfile_mapcache --- mapserver-7.0.7/scripts/docker/Dockerfile_mapcache 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/scripts/docker/Dockerfile_mapcache 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,190 @@ +FROM ubuntu:xenial +MAINTAINER Michael Smith + +#Setup user +ARG UID +ARG GID +ARG MRSID_DOWNLOAD_URL +RUN addgroup --gid $GID msgroup +RUN adduser --no-create-home --disabled-login msuser --gecos "" --uid $UID --gid $GID + +ENV LIBKML_DOWNLOAD=install-libkml-r864-64bit.tar.gz +ENV FILEGDBAPI_DOWNLOAD=FileGDB_API_1_2-64.tar.gz +ENV MRSID_DIR=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482 +ENV MRSID_DOWNLOAD=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482.tar.gz + +# Setup build env +RUN mkdir /build +RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 16126D3A3E5C1192 \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends software-properties-common \ + && add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends gcc-4.9 g++-4.9 build-essential ca-certificates curl wget git make cmake python-dev \ + python-software-properties software-properties-common libc6-dev openssh-client libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev \ + libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev swig \ + libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev libwebp-dev libepsilon-dev libpcre3-dev gfortran libarpack2-dev \ + libpq-dev libflann-dev libhdf5-serial-dev libhdf5-dev libjsoncpp-dev clang-3.8 libhdf4-alt-dev libsqlite3-dev \ + libltdl-dev libcurl4-openssl-dev ninja python-pip libpng-dev python-dev libprotobuf-c-dev protobuf-c-compiler\ + libboost-filesystem1.58-dev libboost-iostreams1.58-dev libboost-program-options1.58-dev libboost-system1.58-dev libboost-thread1.58-dev libogdi3.2-dev time \ + && apt-get remove --purge -y $BUILD_PACKAGES && rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20 && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20 + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${LIBKML_DOWNLOAD} -O /build/${LIBKML_DOWNLOAD} && \ + tar -C /build -xzf /build/${LIBKML_DOWNLOAD} && \ + cp -r /build/install-libkml/include/* /usr/local/include && \ + cp -r /build/install-libkml/lib/* /usr/local/lib \ + && rm -Rf /build/install-libkml + +RUN curl -L ${$MRSID_DOWNLOAD_URL}/${MRSID_DOWNLOAD} -o /build/${MRSID_DOWNLOAD} && \ + tar -C /build -xzf /build/${MRSID_DOWNLOAD} && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/include/* /usr/local/include && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/lib/* /usr/local/lib \ + && rm -Rf /build/${MRSID_DIR} + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${FILEGDBAPI_DOWNLOAD} -O /build/${FILEGDBAPI_DOWNLOAD} && \ + tar -C /build -xzf /build/${FILEGDBAPI_DOWNLOAD} && \ + cp -r /build/FileGDB_API/include/* /usr/local/include && \ + cp -r /build/FileGDB_API/lib/* /usr/local/lib \ + && rm -Rf /build/FileGDB_API + +RUN cd /build && curl -LO https://github.com/uclouvain/openjpeg/archive/v2.3.0.tar.gz && \ + tar -zxf /build/v2.3.0.tar.gz && \ + cd /build/openjpeg-2.3.0 && \ + mkdir -v build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr .. && \ + make -j && make install && \ + rm -Rf /build/openjpeg* + +RUN wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py && python get-pip.py && pip install --upgrade pip wheel numpy + +ARG GDAL_VERSION +RUN cd /build && \ + git clone https://github.com/OSGeo/gdal.git && \ + cd /build/gdal && \ + git checkout ${GDAL_VERSION} && \ + cd /build/gdal/gdal && \ + ./configure --prefix=/usr \ + --with-png=internal \ + --with-jpeg=internal \ + --with-libz=internal \ + --with-libtiff=internal \ + --with-geotiff=internal \ + --with-gif=internal \ + --with-libjson-c=internal \ + --with-poppler \ + --with-spatialite \ + --with-python \ + --with-liblzma \ + --with-openjpeg \ + --with-ogdi \ + --with-webp \ + --with-pg \ + --with-mrsid=/usr/local \ + --with-libkml \ + --with-filegdb \ + --with-hdf5=/usr/lib/x86_64-linux-gnu/hdf5/serial \ + --with-openjpeg && \ + make && \ + make install && \ + cd swig/python && python setup.py build && python setup.py install && \ + ldconfig && \ + rm -Rf /build/gdal + +RUN apt-get update && apt-get install -y --fix-missing --no-install-recommends build-essential ca-certificates curl wget \ + subversion git libaio1 make cmake python-numpy python-dev python-software-properties software-properties-common libv8-dev libc6-dev libfreetype6-dev \ + libcairo2-dev libpq-dev libharfbuzz-dev libfribidi-dev flex bison libfcgi-dev libxml2 libxml2-dev bzip2 apache2 apache2-utils apache2-dev \ + libaprutil1-dev libapr1-dev libpng12-dev libjpeg-dev libcurl4-gnutls-dev libpcre3-dev libpixman-1-dev libgeos-dev libsqlite3-dev libdb-dev libtiff-dev sudo \ + && rm -rf /var/lib/apt/lists/partial/* /tmp/* /var/tmp/* +RUN echo "msuser ALL=NOPASSWD: ALL" >> /etc/sudoers + +ARG MAPSERVER_VERSION +RUN cd /build && \ + git clone https://github.com/mapserver/mapserver.git mapserver && \ + cd /build/mapserver && \ + git checkout ${MAPSERVER_VERSION} \ + && mkdir /build/mapserver/build \ + && cd /build/mapserver/build \ + && cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DHARFBUZZ_INCLUDE_DIR=/usr/include/harfbuzz \ + -DWITH_CLIENT_WFS=ON \ + -DWITH_CLIENT_WMS=ON \ + -DWITH_CURL=ON \ + -DWITH_GDAL=ON \ + -DWITH_GIF=ON \ + -DWITH_ICONV=ON \ + -DWITH_KML=ON \ + -DWITH_LIBXML2=ON \ + -DWITH_OGR=ON \ + -DWITH_POINT_Z_M=ON \ + -DWITH_PROJ=ON \ + -DWITH_SOS=ON \ + -DWITH_THREAD_SAFETY=ON \ + -DWITH_WCS=ON \ + -DWITH_WFS=ON \ + -DWITH_WMS=ON \ + -DWITH_FCGI=ON \ + -DWITH_FRIBIDI=ON \ + -DWITH_CAIRO=ON \ + -DWITH_HARFBUZZ=ON \ + -DWITH_POSTGIS=on \ + -DWITH_V8=OFF \ + .. \ + && make \ + && make install \ + && ldconfig \ + && rm -Rf /build/mapserver + +# Install Mapcache itself +ARG MAPCACHE_VERSION +RUN cd /build \ + && mkdir -p /msconfig/mapcache \ + && git clone https://github.com/mapserver/mapcache/ \ + && cd /build/mapcache \ + && git checkout ${MAPCACHE_VERSION} \ + && mkdir /build/mapcache/build \ + && cd /build/mapcache/build \ + && cmake ../ \ + -DWITH_FCGI=0 -DWITH_APACHE=1 -DWITH_PCRE=1 \ + -DWITH_TIFF=1 -DWITH_BERKELEY_DB=1 -DWITH_MEMCACHE=1 \ + -DCMAKE_PREFIX_PATH="/etc/apache2" && \ + make && \ + make install + +#RUN mkdir /vdatum \ +# && cd /vdatum \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid1999.zip && unzip -j -u usa_geoid1999.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconc.gtx && mv vertconc.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertcone.gtx && mv vertcone.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconw.gtx && mv vertconw.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj \ +# && rm -rf /vdatum + +# Force buit libraries dependencies +RUN ldconfig + +# Apache configuration for mapcache +RUN echo "LoadModule mapcache_module /usr/lib/apache2/modules/mod_mapcache.so" > /etc/apache2/mods-available/mapcache.load +RUN echo ' \n\ + \n\ + Require all granted \n\ + \n\ + MapCacheAlias /mapcache "/msconfig/mapcache/mapcache.xml" \n\ + \n'\ +> /etc/apache2/mods-available/mapcache.conf + +# Enable these Apache modules +RUN a2enmod actions cgi alias headers mapcache + +RUN chmod o+x /usr/local/bin/mapserv +RUN ln -s /usr/local/bin/mapserv /usr/lib/cgi-bin/mapserv +RUN chmod 755 /usr/lib/cgi-bin + +ENV HOST_IP `ifconfig | grep inet | grep Mask:255.255.255.0 | cut -d ' ' -f 12 | cut -d ':' -f 2` + +CMD sudo service apache2 start && bash + +USER msuser \ No newline at end of file diff -Nru mapserver-7.0.7/scripts/docker/Dockerfile_oracle_mapcache mapserver-7.6.4/scripts/docker/Dockerfile_oracle_mapcache --- mapserver-7.0.7/scripts/docker/Dockerfile_oracle_mapcache 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/scripts/docker/Dockerfile_oracle_mapcache 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,202 @@ +FROM ubuntu:xenial +MAINTAINER Michael Smith + +# Set up Instant Client +COPY instantclient_12_1 /opt/instantclient/ +RUN ln -s /opt/instantclient/ /opt/instantclient/lib + +#Setup user +ARG UID +ARG GID +ARG MRSID_DOWNLOAD_URL +RUN addgroup --gid $GID msgroup +RUN adduser --no-create-home --disabled-login msuser --gecos "" --uid $UID --gid $GID + +ENV ORACLE_HOME=/opt/instantclient +ENV LD_LIBRARY_PATH=${ORACLE_HOME}:/usr/lib:/usr/local/lib +ENV LIBKML_DOWNLOAD=install-libkml-r864-64bit.tar.gz +ENV FILEGDBAPI_DOWNLOAD=FileGDB_API_1_2-64.tar.gz +ENV MRSID_DIR=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482 +ENV MRSID_DOWNLOAD=MrSID_DSDK-9.5.4.4703-rhel6.x86-64.gcc482.tar.gz + +# Setup build env +RUN mkdir /build +RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 16126D3A3E5C1192 \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends software-properties-common \ + && add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y \ + && apt-get update && apt-get install -y --fix-missing --no-install-recommends gcc-4.9 g++-4.9 build-essential ca-certificates curl wget git libaio1 make cmake python-dev \ + python-software-properties software-properties-common libc6-dev openssh-client libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev \ + libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev swig \ + libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev libwebp-dev libepsilon-dev libpcre3-dev gfortran libarpack2-dev \ + libpq-dev libflann-dev libhdf5-serial-dev libhdf5-dev libjsoncpp-dev clang-3.8 libhdf4-alt-dev libsqlite3-dev \ + libltdl-dev libcurl4-openssl-dev ninja python-pip libpng-dev python-dev libprotobuf-c-dev protobuf-c-compiler\ + libboost-filesystem1.58-dev libboost-iostreams1.58-dev libboost-program-options1.58-dev libboost-system1.58-dev libboost-thread1.58-dev libogdi3.2-dev time \ + && apt-get remove --purge -y $BUILD_PACKAGES && rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20 && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20 + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${LIBKML_DOWNLOAD} -O /build/${LIBKML_DOWNLOAD} && \ + tar -C /build -xzf /build/${LIBKML_DOWNLOAD} && \ + cp -r /build/install-libkml/include/* /usr/local/include && \ + cp -r /build/install-libkml/lib/* /usr/local/lib \ + && rm -Rf /build/install-libkml + +RUN curl -L ${$MRSID_DOWNLOAD_URL}/${MRSID_DOWNLOAD} -o /build/${MRSID_DOWNLOAD} && \ + tar -C /build -xzf /build/${MRSID_DOWNLOAD} && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/include/* /usr/local/include && \ + cp -r /build/${MRSID_DIR}/Raster_DSDK/lib/* /usr/local/lib \ + && rm -Rf /build/${MRSID_DIR} + +RUN wget --no-verbose http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/${FILEGDBAPI_DOWNLOAD} -O /build/${FILEGDBAPI_DOWNLOAD} && \ + tar -C /build -xzf /build/${FILEGDBAPI_DOWNLOAD} && \ + cp -r /build/FileGDB_API/include/* /usr/local/include && \ + cp -r /build/FileGDB_API/lib/* /usr/local/lib \ + && rm -Rf /build/FileGDB_API + +RUN cd /build && curl -LO https://github.com/uclouvain/openjpeg/archive/v2.3.0.tar.gz && \ + tar -zxf /build/v2.3.0.tar.gz && \ + cd /build/openjpeg-2.3.0 && \ + mkdir -v build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr .. && \ + make -j && make install && \ + rm -Rf /build/openjpeg* + +RUN wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py && python get-pip.py && pip install --upgrade pip wheel numpy + +ARG GDAL_VERSION +RUN cd /build && \ + git clone https://github.com/OSGeo/gdal.git && \ + cd /build/gdal && \ + git checkout ${GDAL_VERSION} && \ + cd /build/gdal/gdal && \ + ./configure --prefix=/usr \ + --with-png=internal \ + --with-jpeg=internal \ + --with-libz=internal \ + --with-libtiff=internal \ + --with-geotiff=internal \ + --with-gif=internal \ + --with-libjson-c=internal \ + --with-poppler \ + --with-spatialite \ + --with-python \ + --with-liblzma \ + --with-openjpeg \ + --with-ogdi \ + --with-webp \ + --with-oci-include=${ORACLE_HOME}/sdk/include \ + --with-oci-lib=${ORACLE_HOME} \ + --with-pg \ + --with-mrsid=/usr/local \ + --with-libkml \ + --with-filegdb \ + --with-hdf5=/usr/lib/x86_64-linux-gnu/hdf5/serial \ + --with-openjpeg && \ + make && \ + make install && \ + cd swig/python && python setup.py build && python setup.py install && \ + ldconfig && \ + rm -Rf /build/gdal + +RUN apt-get update && apt-get install -y --fix-missing --no-install-recommends build-essential ca-certificates curl wget \ + subversion git libaio1 make cmake python-numpy python-dev python-software-properties software-properties-common libv8-dev libc6-dev libfreetype6-dev \ + libcairo2-dev libpq-dev libharfbuzz-dev libfribidi-dev flex bison libfcgi-dev libxml2 libxml2-dev bzip2 apache2 apache2-utils apache2-dev \ + libaprutil1-dev libapr1-dev libpng12-dev libjpeg-dev libcurl4-gnutls-dev libpcre3-dev libpixman-1-dev libgeos-dev libsqlite3-dev libdb-dev libtiff-dev sudo \ + && rm -rf /var/lib/apt/lists/partial/* /tmp/* /var/tmp/* +RUN echo "msuser ALL=NOPASSWD: ALL" >> /etc/sudoers + +ENV ORACLE_HOME=/opt/instantclient +ENV LD_LIBRARY_PATH=${ORACLE_HOME}:/usr/lib + +ARG MAPSERVER_VERSION +RUN cd /build && \ + git clone https://github.com/mapserver/mapserver.git mapserver && \ + cd /build/mapserver && \ + git checkout ${MAPSERVER_VERSION} \ + && mkdir /build/mapserver/build \ + && cd /build/mapserver/build \ + && cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DHARFBUZZ_INCLUDE_DIR=/usr/include/harfbuzz \ + -DWITH_CLIENT_WFS=ON \ + -DWITH_CLIENT_WMS=ON \ + -DWITH_CURL=ON \ + -DWITH_GDAL=ON \ + -DWITH_GIF=ON \ + -DWITH_ICONV=ON \ + -DWITH_KML=ON \ + -DWITH_LIBXML2=ON \ + -DWITH_OGR=ON \ + -DWITH_ORACLESPATIAL=ON \ + -DWITH_POINT_Z_M=ON \ + -DWITH_PROJ=ON \ + -DWITH_SOS=ON \ + -DWITH_THREAD_SAFETY=ON \ + -DWITH_WCS=ON \ + -DWITH_WFS=ON \ + -DWITH_WMS=ON \ + -DWITH_FCGI=ON \ + -DWITH_FRIBIDI=ON \ + -DWITH_CAIRO=ON \ + -DWITH_HARFBUZZ=ON \ + -DWITH_POSTGIS=on \ + -DWITH_V8=OFF \ + .. \ + && make \ + && make install \ + && ldconfig \ + && rm -Rf /build/mapserver + +# Install Mapcache itself +ARG MAPCACHE_VERSION +RUN cd /build \ + && mkdir -p /msconfig/mapcache \ + && git clone https://github.com/mapserver/mapcache/ \ + && cd /build/mapcache \ + && git checkout ${MAPCACHE_VERSION} \ + && mkdir /build/mapcache/build \ + && cd /build/mapcache/build \ + && cmake ../ \ + -DWITH_FCGI=0 -DWITH_APACHE=1 -DWITH_PCRE=1 \ + -DWITH_TIFF=1 -DWITH_BERKELEY_DB=1 -DWITH_MEMCACHE=1 \ + -DCMAKE_PREFIX_PATH="/etc/apache2" && \ + make && \ + make install + +#RUN mkdir /vdatum \ +# && cd /vdatum \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/usa_geoid1999.zip && unzip -j -u usa_geoid1999.zip -d /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconc.gtx && mv vertconc.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertcone.gtx && mv vertcone.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/vertcon/vertconw.gtx && mv vertconw.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj \ +# && wget http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj \ +# && rm -rf /vdatum + +# Force buit libraries dependencies +RUN ldconfig + +# Apache configuration for mapcache +RUN echo "LoadModule mapcache_module /usr/lib/apache2/modules/mod_mapcache.so" > /etc/apache2/mods-available/mapcache.load +RUN echo ' \n\ + \n\ + Require all granted \n\ + \n\ + MapCacheAlias /mapcache "/msconfig/mapcache/mapcache.xml" \n\ + \n'\ +> /etc/apache2/mods-available/mapcache.conf + +# Enable these Apache modules +RUN a2enmod actions cgi alias headers mapcache + +RUN chmod o+x /usr/local/bin/mapserv +RUN ln -s /usr/local/bin/mapserv /usr/lib/cgi-bin/mapserv +RUN chmod 755 /usr/lib/cgi-bin + +ENV HOST_IP `ifconfig | grep inet | grep Mask:255.255.255.0 | cut -d ' ' -f 12 | cut -d ':' -f 2` + +CMD sudo service apache2 start && bash + +USER msuser \ No newline at end of file diff -Nru mapserver-7.0.7/scripts/vagrant/mapserver.sh mapserver-7.6.4/scripts/vagrant/mapserver.sh --- mapserver-7.0.7/scripts/vagrant/mapserver.sh 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/scripts/vagrant/mapserver.sh 2021-07-12 20:16:21.000000000 +0000 @@ -1,16 +1,8 @@ -#!/bin/sh +#!/bin/bash -NUMTHREADS=2 # we have 2 cpus configured +NUMTHREADS=$(nproc) export NUMTHREADS -cd /tmp -wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.38.tar.bz2 -tar xjf harfbuzz-0.9.38.tar.bz2 -cd harfbuzz-0.9.38 -./configure --without-cairo --without-glib --without-icu -make -j $NUMTHREADS -sudo make install && sudo ldconfig - cd /vagrant cd msautotest @@ -28,7 +20,24 @@ -DWITH_PYTHON=1 -DWITH_JAVA=0 -DWITH_THREAD_SAFETY=1 \ -DWITH_FCGI=0 -DWITH_EXEMPI=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DWITH_RSVG=1 -DWITH_CURL=1 -DWITH_FRIBIDI=1 -DWITH_HARFBUZZ=1 \ + -DPROJ_INCLUDE_DIR=/vagrant/install-vagrant-proj-6/include_proj4_api_only -DPROJ_LIBRARY=/vagrant/install-vagrant-proj-6/lib/libproj.so.15 \ + -DCMAKE_C_FLAGS="-DACCEPT_USE_OF_DEPRECATED_PROJ_API_H -DPROJ_RENAME_SYMBOLS" -DCMAKE_CXX_FLAGS="-DACCEPT_USE_OF_DEPRECATED_PROJ_API_H -DPROJ_RENAME_SYMBOLS" \ .. make -j $NUMTHREADS sudo make install +cd .. + +mkdir build_vagrant_proj6 +cd build_vagrant_proj6 +cmake -G "Unix Makefiles" -DWITH_CLIENT_WMS=1 \ + -DWITH_CLIENT_WFS=1 -DWITH_KML=1 -DWITH_SOS=1 -DWITH_PHP=1 \ + -DWITH_PYTHON=1 -DWITH_JAVA=0 -DWITH_THREAD_SAFETY=1 \ + -DWITH_FCGI=0 -DWITH_EXEMPI=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWITH_RSVG=1 -DWITH_CURL=1 -DWITH_FRIBIDI=1 -DWITH_HARFBUZZ=1 \ + -DPROJ_INCLUDE_DIR=/vagrant/install-vagrant-proj-6/include -DPROJ_LIBRARY=/vagrant/install-vagrant-proj-6/lib/libproj.so.15 \ + -DCMAKE_C_FLAGS="-DPROJ_RENAME_SYMBOLS" -DCMAKE_CXX_FLAGS="-DPROJ_RENAME_SYMBOLS" \ + .. + +make -j $NUMTHREADS +cd .. diff -Nru mapserver-7.0.7/scripts/vagrant/packages.sh mapserver-7.6.4/scripts/vagrant/packages.sh --- mapserver-7.0.7/scripts/vagrant/packages.sh 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/scripts/vagrant/packages.sh 2021-07-12 20:16:21.000000000 +0000 @@ -6,14 +6,22 @@ apt-get update apt-get install -y python-software-properties -add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable +add-apt-repository -y ppa:ubuntugis/ppa +add-apt-repository -y ppa:ubuntugis/ubuntugis-testing +add-apt-repository -y ppa:dluxen/cmake-backports apt-get update apt-get -y upgrade # install packages we need -apt-get install -q -y git build-essential pkg-config cmake libgeos-dev rake \ +apt-get install -q -y git build-essential pkg-config cmake3 libgeos-dev rake \ libpq-dev python-all-dev libproj-dev libxml2-dev postgis php5-dev \ - postgresql-server-dev-9.1 postgresql-9.1-postgis-2.1 vim bison flex swig \ + postgresql-server-dev-9.3 postgresql-9.3-postgis-2.2 vim bison flex swig \ librsvg2-dev libpng12-dev libjpeg-dev libgif-dev \ libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev \ - libgdal1-dev libfribidi-dev libexempi-dev + libgdal1-dev libfribidi-dev libexempi-dev \ + libprotobuf-dev libprotobuf-c0-dev protobuf-c-compiler libharfbuzz-dev gdal-bin \ + curl sqlite3 + +curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py +python get-pip.py +pip install -U -r /vagrant/msautotest/requirements.txt diff -Nru mapserver-7.0.7/scripts/vagrant/postgis.sh mapserver-7.6.4/scripts/vagrant/postgis.sh --- mapserver-7.0.7/scripts/vagrant/postgis.sh 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/scripts/vagrant/postgis.sh 2021-07-12 20:16:21.000000000 +0000 @@ -2,8 +2,8 @@ cd /vagrant/msautotest -sed -i 's/md5/trust/' /etc/postgresql/9.1/main/pg_hba.conf -sed -i 's/peer/trust/' /etc/postgresql/9.1/main/pg_hba.conf +sed -i 's/md5/trust/' /etc/postgresql/9.3/main/pg_hba.conf +sed -i 's/peer/trust/' /etc/postgresql/9.3/main/pg_hba.conf service postgresql restart diff -Nru mapserver-7.0.7/scripts/vagrant/proj6.sh mapserver-7.6.4/scripts/vagrant/proj6.sh --- mapserver-7.0.7/scripts/vagrant/proj6.sh 1970-01-01 00:00:00.000000000 +0000 +++ mapserver-7.6.4/scripts/vagrant/proj6.sh 2021-07-12 20:16:21.000000000 +0000 @@ -0,0 +1,17 @@ +#!/bin/bash + +set -eu + +NUMTHREADS=$(nproc) +export NUMTHREADS + +cd /vagrant +curl -s http://download.osgeo.org/proj/proj-6.1.1.tar.gz > proj-6.1.1.tar.gz +tar xzf proj-6.1.1.tar.gz +rm -rf vagrant-proj +rm -rf /vagrant/install-vagrant-proj-6 +mv proj-6.1.1 vagrant-proj +(cd vagrant-proj/data && curl -s http://download.osgeo.org/proj/proj-datumgrid-1.8.tar.gz > proj-datumgrid-1.8.tar.gz && tar xvzf proj-datumgrid-1.8.tar.gz) +(cd vagrant-proj; CFLAGS='-DPROJ_RENAME_SYMBOLS -O2' CXXFLAGS='-DPROJ_RENAME_SYMBOLS -O2' ./configure --disable-static --prefix=/vagrant/install-vagrant-proj-6 && make -j $NUMTHREADS && make -j $NUMTHREADS install) +cp -r /vagrant/install-vagrant-proj-6/include /vagrant/install-vagrant-proj-6/include_proj4_api_only +rm -f /vagrant/install-vagrant-proj-6/include_proj4_api_only/proj.h diff -Nru mapserver-7.0.7/shptree.c mapserver-7.6.4/shptree.c --- mapserver-7.0.7/shptree.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/shptree.c 2021-07-12 20:16:21.000000000 +0000 @@ -44,7 +44,7 @@ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(Filename)+5); strcpy( pszBasename, Filename ); - for( i = strlen(pszBasename)-1; + for( i = (int)strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} diff -Nru mapserver-7.0.7/shptreetst.c mapserver-7.6.4/shptreetst.c --- mapserver-7.0.7/shptreetst.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/shptreetst.c 2021-07-12 20:16:21.000000000 +0000 @@ -55,7 +55,7 @@ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(Filename)+5); strcpy( pszBasename, Filename ); - for( i = strlen(pszBasename)-1; + for( i = (int)strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} @@ -155,7 +155,7 @@ rect.maxy = node->rect.maxy; } - bitmap = msSearchDiskTree( argv[1], rect, 0 /* no debug*/ ); + bitmap = msSearchDiskTree( argv[1], rect, 0 /* no debug*/, j ); if ( bitmap ) { printf ("result of rectangle search was \n"); diff -Nru mapserver-7.0.7/sortshp.c mapserver-7.6.4/sortshp.c --- mapserver-7.0.7/sortshp.c 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/sortshp.c 2021-07-12 20:16:21.000000000 +0000 @@ -131,7 +131,7 @@ for(i=0; iface = fcache; if(UNLIKELY(!fcache)) return MS_FAILURE; for(i=0; ilength; i++) { - int codepoint = msGetGlyphIndex(fcache, glyphs->unicodes[run->offset+i]); + unsigned int codepoint = msGetGlyphIndex(fcache, glyphs->unicodes[run->offset+i]); if(codepoint || ignore_missing) + { + if( codepoint == 0 ) + { + msDebug("Unable to find glyph for codepoint %u. Using ? as fallback.\n", glyphs->unicodes[run->offset+i]); + codepoint = msGetGlyphIndex(fcache, '?'); + } glyphs->codepoints[run->offset+i] = codepoint; + } else return MS_FAILURE; } return MS_SUCCESS; } -int WARN_UNUSED get_face_for_run(fontSetObj *fontset, char *fontlist, text_run *run, TextInfo *glyphs) { +static int get_face_for_run(fontSetObj *fontset, char *fontlist, text_run *run, TextInfo *glyphs) { char *startfont, *endfont; int ok; #if defined(USE_HARFBUZZ) && defined(USE_FRIBIDI) @@ -521,7 +528,6 @@ } } - if(ts->label->wrap || ts->label->maxlength > 0) { if(ts->label->wrap && ts->label->maxlength == 0) { for(i=0;ilabel->maxlength > 0); - if(ts->label->wrap != ' '){ - for(i=0;ilabel->wrap) - glyphs.unicodes[i]= ' '; - } - } if(num_glyphs > ts->label->maxlength) { + int num_cur_glyph_on_line = 0; /*count for the number of glyphs on the current line*/ for(i=0; i= ts->label->maxlength) { - glyphs.unicodes[i]= '\n'; - num_cur_glyph_on_line = 0; - } else { - num_cur_glyph_on_line++; - } + /* wrap at wrap character or at ZERO WIDTH SPACE (unicode 0x200b), if + * current line is too long */ + if((glyphs.unicodes[i] == ts->label->wrap || glyphs.unicodes[i] == 0x200b) + && num_cur_glyph_on_line >= ts->label->maxlength) { + glyphs.unicodes[i]= '\n'; + num_cur_glyph_on_line = 0; + } else { + num_cur_glyph_on_line++; } } } @@ -785,10 +781,10 @@ if(tgret->numlines > 1) { int max_line_length = 0; int line = -1; - double cur_line_offset; + double cur_line_offset = 0; int prev_default_align = MS_ALIGN_LEFT; /* if we have mixed rtl status, use the alignment of the previous line. this defaults to left-alignment if the first line is mixed */ - int cur_default_align; + int cur_default_align = 0; for(i=0; inumlines; i++) { if(line_descs[i].length > max_line_length) { max_line_length = line_descs[i].length; diff -Nru mapserver-7.0.7/Vagrantfile mapserver-7.6.4/Vagrantfile --- mapserver-7.0.7/Vagrantfile 2017-11-15 19:24:35.000000000 +0000 +++ mapserver-7.6.4/Vagrantfile 2021-07-12 20:16:21.000000000 +0000 @@ -6,23 +6,45 @@ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" +$set_environment_variables = <