Commit b179a46d authored by Bas Couwenberg's avatar Bas Couwenberg

Imported Upstream version 7.0.4

parent 7bf4afe5
......@@ -17,7 +17,7 @@ include(CheckCSourceCompiles)
set (MapServer_VERSION_MAJOR 7)
set (MapServer_VERSION_MINOR 0)
set (MapServer_VERSION_REVISION 3)
set (MapServer_VERSION_REVISION 4)
set (MapServer_VERSION_SUFFIX "")
set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR})
......
......@@ -67,7 +67,7 @@ License
::
Copyright (c) 2008-2016 Open Source Geospatial Foundation.
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
......
......@@ -22,40 +22,108 @@ IMPORTANT - READ THIS FIRST:
--------------------------------------------------------------------
For the developers using MSVC++, a NMAKE makefile (Makefile.vc + nmake.opt)
to build the MapServer library and executable programs is included with
the distribution.
The easyest way to build Mapserver on Windows on your own is to use the
build-system from http://gisinternals.com/.
GISInternals provide a complete set of sources and dependencies and even
makefiles for the full version of Visual Studio (not Express oder Community).
You don't have to download and compile them all by your own.
If you are not using full version of Visual Studio you can not use the makefiles
from GISInternals but you can still use the downloads to make your life easier.
Building with the full version of Visual Studio is easy.
Download the SDK for you version and follow the readme inside the packages.
This Readme will cover the compilation with Visual Studio 2012 Express on
Windows with CMake and the GISInternals-Packages for the following reasons:
- not everybody wants to buy Visual Studio and there is no reason to force
you to buy it just tu build Mapserver on Windows
- CMake is the configuration-system for Linux. Why should you use something
else which needs to be maintainerd?
- as of today, PHP-Mapscript is not suppored for PHP-7. PHP-5.6 is build
with VC11. To make PHP-Mapscript compatible with the downloadable
PHP-Version you need to build with VC11 wich is Visual Studio 2012.
- GISInternals Downloads contain most dependencies. it's way easier
If you want to compile Mapserver with any other version of Visual Studio you
can for sure use this documentation as help but maybe, some things here won't
work for you.
To build the package using the Makefile.vc and NMAKE:
--------------------------------------------------------------------
Prerequisites
--------------------------------------------------------------------
To build Mapserver on Windows with Visual Studio 2012 Express you need
Visual Studio 2012 Express installed.
Install CMake (https://cmake.org/) and add CMake bin-directory to your PATH
environment variable. You can even to this after opening VS2012 x86 Native
Tools Command Prompt by entering:
set PATH=%PATH%;"C:\Program Files\CMake\bin"
... if CMake is installed to "C:\Program Files\CMake" ;)
- Edit nmake.opt to select (or deselect) optional components of
the MapServer. Please read the notes below about each component
before you move ahead with the compilation.
--------------------------------------------------------------------
Downloading dependencies
--------------------------------------------------------------------
- Open a DOS prompt window
For our first build, we will use stable releases to build mapserver.
Download MSVC 2012 win32 Packages for GDAL-2.1.2 and Mapserver-7.0.2 from http://gisinternals.com/release.php.
We need "Compiled binaries in a single .zip package", "GDAL and MapServer sources" and "Compiled libraries and headers".
Download the MSVC 2012 win32 Developement Kit from http://gisinternals.com/sdk.php.
Extract everything to C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2.
There should be the directories inside now: bin, doc, gdal, include, lib, regex-0.12, relase-1700, ...
After you got this done, feel free to use other packages which fit your needs better.
- Run the VCVARS32.BAT script to initialize the VC++ environment
variables. VCVARS32.BAT is automatically generated by the MSVC++
install procedure and should be located in the BIN sub-directory of
your MSVC++ installation.
--------------------------------------------------------------------
Mapserver-sources
--------------------------------------------------------------------
- Then start the build with:
nmake /f Makefile.vc
Download at least Mapserver-7.0.3 or current 7.0-Branch from github
and extract or clone from github to C:\dev\work\mapserver.
This will create "mapserv.exe" (the main MapServer CGI program), the
other command-line utilities, "mapserver.lib" and "libmap.dll" that is
used by theMapScript modules.
--------------------------------------------------------------------
Building Mapserver
--------------------------------------------------------------------
After downloading and extracting everything, to build Mapserver, follow this steps:
1. Open VS2012 x86 Native Tools Command Prompt (i'm german, hope it is translated
correctly).
2. Add CMake-bin to your PATH:
set PATH=%PATH%;"C:\Program Files\CMake\bin"
3. Create build-Directory:
mkdir C:\dev\work\mapserver\build
cd C:\dev\work\mapserver\build
4. Configure:
cmake .. -G "NMake Makefiles" -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -Wno-dev
cmake .. -DCMAKE_PREFIX_PATH=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\bin;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\include
cmake .. -DREGEX_DIR=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\regex-0.12
cmake .. -DWITH_POSTGIS=0 -DWITH_SOS=1 -DWITH_KML=1
cmake .. -DWITH_CLIENT_WMS=1 -DWITH_CLIENT_WFS=1
cmake .. -DWITH_THREAD_SAFETY=1 -DWITH_FCGI=1
cmake .. -DWITH_CAIRO=1 -DCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\cairo.lib
cmake .. -DWITH_SVGCAIRO=1 -DSVGCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg-cairo.lib
cmake .. -DSVG_LIBRARY=1 -DSVG_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg.lib
5. build
nmake
Thats it.
You can use all CMake parameters and options as you are used from CMake to fit mapserver to your needs from here.
Enjoy!
--------------------------------------------------------------------
MapScript
--------------------------------------------------------------------
To compile the various versions of MapScript (Perl, PHP, etc) first compile
the main mapserver directory and then see the README files in the
mapscript/perl, mapscript/php3 or mapscript/python directory for specific
the main mapserver directory and then see the README files in the
mapscript/perl, mapscript/php or mapscript/python directory for specific
instructions.
--------------------------------------------------------------------
Dependencies Part 2
--------------------------------------------------------------------
The following sections descripe how to get mapserver dependencies when not
downloading GISInternals packages.
--------------------------------------------------------------------
GD library
......@@ -168,27 +236,6 @@ instructions.
with the PNG support, make sure that the libpng that you use in mapserver
is the same as the one used in GDAL.
------------------------------------------------------------
Notes on PDF suuport
------------------------------------------------------------
The PDF support allows the output of a map file as a PDF file.
To be able to build mapserver with the PDF support, you need to download
and build a PDF library from www.pdflib.com (http://www.pdflib.com/pdflib/download/index.html).
The best option is to download the zip file containing the source code and build it. Please refer to the docs inside the zip for informations on how to build the library. Here are some quick notes that can help in building mapserver with PDF :
1) Build the PDF lib
- open the project PDFLib.dsw
- build the project pdflib_dll
- after a sucessful build, you should have a pdflib.lib and pdblib.dll under the
pdflib directory
- copy the pdflib.dll under your system directory (ex : c:/winnt/system32)
2) Build mapserver with PDF
- uncomment in the nmake.opt the flags related to PDF
$Id$
......@@ -1440,7 +1440,12 @@ int msClusterLayerOpen(layerObj *layer)
return MS_FAILURE;
if (layer->layerinfo)
return MS_SUCCESS; /* already open */
{
if (layer->vtable->LayerOpen != msClusterLayerOpen)
msLayerClose(layer);
else
return MS_SUCCESS; /* already open */
}
layerinfo = msClusterInitialize(layer);
......@@ -1506,7 +1511,10 @@ int msClusterLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *
return MS_FAILURE;
}
return layerinfo->srcLayer.vtable->LayerTranslateFilter(&layerinfo->srcLayer, filter, filteritem);
if (layerinfo->srcLayer.filter.type == MS_EXPRESSION && layerinfo->srcLayer.filter.tokens == NULL)
msTokenizeExpression(&(layerinfo->srcLayer.filter), layer->items, &(layer->numitems));
return layerinfo->srcLayer.vtable->LayerTranslateFilter(&layerinfo->srcLayer, &layerinfo->srcLayer.filter, filteritem);
}
char* msClusterLayerEscapeSQLParam(layerObj *layer, const char* pszString)
......
......@@ -32,7 +32,7 @@
#include "mapserver.h"
#include "mapresample.h"
#include "mapthread.h"
#include "maptime.h"
extern int InvGeoTransform( double *gt_in, double *gt_out );
......@@ -1717,6 +1717,9 @@ msDrawRasterLayerGDAL_16BitClassification(
unsigned char *rb_cmap[4];
CPLErr eErr;
rasterBufferObj *mask_rb = NULL;
int lastC;
struct mstimeval starttime, endtime;
if(layer->mask) {
int ret;
layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask));
......@@ -1875,6 +1878,12 @@ msDrawRasterLayerGDAL_16BitClassification(
rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount);
rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount);
if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
msGettimeofday(&starttime, NULL);
}
lastC = -1;
for(i=0; i < nBucketCount; i++) {
double dfOriginalValue;
......@@ -1882,7 +1891,11 @@ msDrawRasterLayerGDAL_16BitClassification(
dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin;
c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1);
/* The creation of buckets takes a significant time when they are many, and many classes
as well. When iterating over buckets, a faster strategy is to reuse first the last used
class index. */
c = msGetClass_FloatRGB_WithFirstClassToTry(layer, (float) dfOriginalValue, -1, -1, -1, lastC);
lastC = c;
if( c != -1 ) {
int s;
......@@ -1904,6 +1917,13 @@ msDrawRasterLayerGDAL_16BitClassification(
}
}
if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
msGettimeofday(&endtime, NULL);
msDebug("msDrawRasterGDAL_16BitClassification() bucket creation time: %.3fs\n",
(endtime.tv_sec+endtime.tv_usec/1.0e6)-
(starttime.tv_sec+starttime.tv_usec/1.0e6) );
}
/* ==================================================================== */
/* Now process the data, applying to the working imageObj. */
/* ==================================================================== */
......
......@@ -35,6 +35,54 @@
#define VMARGIN 5 /* margin at top and bottom of legend graphic */
#define HMARGIN 5 /* margin at left and right of legend graphic */
static int msDrawGradientSymbol(rendererVTableObj* renderer,
imageObj* image_draw,
double x_center,
double y_center,
int width,
int height,
styleObj* style)
{
int i, j;
unsigned char *r,*g,*b,*a;
symbolObj symbol;
rasterBufferObj* rb;
symbolStyleObj symbolStyle;
int ret;
initSymbol(&symbol);
rb = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj));
symbol.pixmap_buffer = rb;
rb->type = MS_BUFFER_BYTE_RGBA;
rb->width = width;
rb->height = height;
rb->data.rgba.row_step = rb->width * 4;
rb->data.rgba.pixel_step = 4;
rb->data.rgba.pixels = (unsigned char*)malloc(
rb->width*rb->height*4*sizeof(unsigned char));
b = rb->data.rgba.b = &rb->data.rgba.pixels[0];
g = rb->data.rgba.g = &rb->data.rgba.pixels[1];
r = rb->data.rgba.r = &rb->data.rgba.pixels[2];
a = rb->data.rgba.a = &rb->data.rgba.pixels[3];
for( j = 0; j < rb->height; j++ )
{
for( i = 0; i < rb->width; i++ )
{
msValueToRange(style, style->minvalue +
(double)i / rb->width * (style->maxvalue - style->minvalue), MS_COLORSPACE_RGB);
b[4*(j * rb->width + i)] = style->color.blue;
g[4*(j * rb->width + i)] = style->color.green;
r[4*(j * rb->width + i)] = style->color.red;
a[4*(j * rb->width + i)] = style->color.alpha;
}
}
INIT_SYMBOL_STYLE(symbolStyle);
ret = renderer->renderPixmapSymbol(image_draw, x_center, y_center, &symbol, &symbolStyle);
msFreeSymbol(&symbol);
return ret;
}
/*
* generic function for drawing a legend icon. (added for bug #2348)
* renderer specific drawing functions shouldn't be called directly, but through
......@@ -262,8 +310,22 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass,
if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE ||
theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
if (MS_VALID_COLOR(theclass->styles[i]->mincolor))
{
ret = msDrawGradientSymbol(renderer,
image_draw,
dstX + width / 2.,
dstY + height / 2.0,
width - 2 * polygon_contraction,
height - 2 * polygon_contraction,
theclass->styles[i]);
}
else
{
ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
}
if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
}
else {
ret = msDrawTransformedShape(map, image_draw, &box,
......@@ -394,7 +456,6 @@ legend_icon_cleanup:
return ret;
}
imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* class, int width, int height, int scale_independant)
{
imageObj *image;
......
......@@ -673,7 +673,7 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F",
"use_default_extent_for_getfeature");
if( pszUseDefaultExtent && CSLTestBoolean(pszUseDefaultExtent) &&
if( pszUseDefaultExtent && !CSLTestBoolean(pszUseDefaultExtent) &&
lp->connectiontype == MS_OGR )
{
const rectObj rectInvalid = MS_INIT_INVALID_RECT;
......@@ -3004,6 +3004,8 @@ char *FLTGetIsLikeComparisonExpression(FilterEncodingNode *psFilterNode)
pszValue = psFilterNode->psRightNode->pszValue;
nLength = strlen(pszValue);
if( 1 + 2 * nLength + 1 + 1 >= sizeof(szTmp) )
return NULL;
iTmp =0;
if (nLength > 0 && pszValue[0] != pszWild[0] &&
......
......@@ -88,6 +88,8 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode)
pszValue = psFilterNode->psRightNode->pszValue;
nLength = strlen(pszValue);
if( 1 + 2 * nLength + 1 + 1 >= sizeof(szTmp) )
return NULL;
iTmp =0;
if (nLength > 0 && pszValue[0] != pszWild[0] && pszValue[0] != pszSingle[0] && pszValue[0] != pszEscape[0]) {
......
......@@ -504,6 +504,9 @@ int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *psShape,
// Special field index codes for handling text string and angle coming from
// OGR style strings.
#define MSOGR_FID_INDEX -99
#define MSOGR_LABELNUMITEMS 21
#define MSOGR_LABELFONTNAMENAME "OGR:LabelFont"
#define MSOGR_LABELFONTNAMEINDEX -100
......@@ -602,6 +605,9 @@ static char **msOGRGetValues(layerObj *layer, OGRFeatureH hFeature)
if (itemindexes[i] >= 0) {
// Extract regular attributes
values[i] = msStrdup(OGR_F_GetFieldAsString( hFeature, itemindexes[i]));
} else if (itemindexes[i] == MSOGR_FID_INDEX ) {
values[i] = msStrdup(CPLSPrintf(CPL_FRMT_GIB,
(GIntBig) OGR_F_GetFID(hFeature)));
} else {
// Handle special OGR attributes coming from StyleString
if (!hStyleMgr) {
......@@ -1283,6 +1289,16 @@ msOGRFileOpen(layerObj *layer, const char *connection )
psInfo->last_record_index_read = -1;
psInfo->dialect = NULL;
psInfo->pszSelect = NULL;
psInfo->pszSpatialFilterTableName = NULL;
psInfo->pszSpatialFilterGeometryColumn = NULL;
psInfo->pszMainTableName = NULL;
psInfo->pszRowId = NULL;
psInfo->bIsOKForSQLCompose = true;
psInfo->bPaging = false;
psInfo->bHasSpatialIndex = false;
psInfo->pszTablePrefix = NULL;
// GDAL 1.x API
OGRSFDriverH dr = OGR_DS_GetDriver(hDS);
const char *name = OGR_Dr_GetName(dr);
......@@ -1321,18 +1337,60 @@ msOGRFileOpen(layerObj *layer, const char *connection )
psInfo->dialect = "PostgreSQL";
// todo: PostgreSQL not yet tested
} // todo: other dialects, for example OGR SQL
} else if (strcmp(name, "GPKG") == 0 && nLayerIndex >= 0 &&
atoi(GDALVersionInfo("VERSION_NUM")) >= 2000000) {
bool has_rtree = false;
const char* test_rtree =
CPLSPrintf("SELECT 1 FROM sqlite_master WHERE name = 'rtree_%s_%s'",
OGR_L_GetName(hLayer), OGR_L_GetGeometryColumn(hLayer));
OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_rtree, NULL, NULL);
if( l )
{
if( OGR_L_GetFeatureCount(l, TRUE) == 1 )
{
has_rtree = true;
}
OGR_DS_ReleaseResultSet(hDS, l);
}
if( has_rtree )
{
bool have_gpkg_spatialite = false;
CPLPushErrorHandler(CPLQuietErrorHandler);
psInfo->pszSelect = NULL;
psInfo->pszSpatialFilterTableName = NULL;
psInfo->pszSpatialFilterGeometryColumn = NULL;
psInfo->pszMainTableName = NULL;
psInfo->pszRowId = NULL;
psInfo->bIsOKForSQLCompose = true;
psInfo->bPaging = false;
psInfo->bHasSpatialIndex = false;
psInfo->pszTablePrefix = NULL;
// test for Spatialite >= 4.3 support in driver
const char *test_spatialite = "SELECT spatialite_version()";
l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL);
if (l) {
OGRFeatureH hFeat = OGR_L_GetNextFeature(l);
if( hFeat )
{
const char* pszVersion = OGR_F_GetFieldAsString(hFeat, 0);
have_gpkg_spatialite = atof(pszVersion) >= 4.3;
OGR_F_Destroy(hFeat);
}
OGR_DS_ReleaseResultSet(hDS, l);
}
CPLPopErrorHandler();
if( have_gpkg_spatialite )
{
psInfo->pszMainTableName = msStrdup( OGR_L_GetName(hLayer) );
psInfo->pszSpatialFilterTableName = msStrdup( OGR_L_GetName(hLayer) );
psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(hLayer) );
psInfo->dialect = "GPKG";
psInfo->bPaging = true;
psInfo->bHasSpatialIndex = true;
}
else
msDebug("msOGRFileOpen: Spatialite support in GPKG not enabled\n");
}
else
{
msDebug("msOGRFileOpen: RTree index not available\n");
}
}
if( psInfo->dialect != NULL && EQUAL(psInfo->dialect, "Spatialite") )
msOGRFileOpenSpatialite(layer, pszLayerDef, psInfo);
......@@ -1806,7 +1864,7 @@ char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) {
char wild_any = '%';
char wild_one = '_';
if (EQUAL(info->dialect, "Spatialite")) {
if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG")) {
if (case_sensitive) {
op = "GLOB";
wild_any = '*';
......@@ -1926,7 +1984,7 @@ char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) {
else
{
const char *SQLtype = "float(16)";
if (EQUAL(info->dialect, "Spatialite"))
if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG"))
SQLtype = "REAL";
else if (EQUAL(info->dialect, "PostgreSQL"))
SQLtype = "double precision";
......@@ -2205,17 +2263,19 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}
psInfo->rect = rect;
bool bSpatialiteAddOrderByFID = false;
bool bSpatialiteOrGPKGAddOrderByFID = false;
if( psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") &&
psInfo->pszMainTableName != NULL && psInfo->bHasSpatialIndex &&
if( psInfo->dialect && psInfo->pszMainTableName != NULL &&
( (EQUAL(psInfo->dialect, "Spatialite") && psInfo->bHasSpatialIndex)
|| EQUAL(psInfo->dialect, "GPKG") ) &&
bIsValidRect )
{
select = msStringConcatenate(select, " JOIN ");
char szSpatialIndexName[256];
snprintf( szSpatialIndexName, sizeof(szSpatialIndexName),
"idx_%s_%s",
"%s_%s_%s",
EQUAL(psInfo->dialect, "Spatialite") ? "idx" : "rtree",
psInfo->pszSpatialFilterTableName,
psInfo->pszSpatialFilterGeometryColumn );
char* pszEscapedSpatialIndexName = msLayerEscapePropertyName(
......@@ -2240,20 +2300,35 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}
else
select = msStringConcatenate(select, "ROWID");
select = msStringConcatenate(select, " = ms_spat_idx.pkid AND ");
if( EQUAL(psInfo->dialect, "Spatialite") )
select = msStringConcatenate(select, " = ms_spat_idx.pkid AND ");
else
select = msStringConcatenate(select, " = ms_spat_idx.id AND ");
char szCond[256];
snprintf(szCond, sizeof(szCond),
if( EQUAL(psInfo->dialect, "Spatialite") )
{
snprintf(szCond, sizeof(szCond),
"ms_spat_idx.xmin <= %.15g AND ms_spat_idx.xmax >= %.15g AND "
"ms_spat_idx.ymin <= %.15g AND ms_spat_idx.ymax >= %.15g",
rect.maxx, rect.minx, rect.maxy, rect.miny);
}
else
{
snprintf(szCond, sizeof(szCond),
"ms_spat_idx.minx <= %.15g AND ms_spat_idx.maxx >= %.15g AND "
"ms_spat_idx.miny <= %.15g AND ms_spat_idx.maxy >= %.15g",
rect.maxx, rect.minx, rect.maxy, rect.miny);
}
select = msStringConcatenate(select, szCond);
bSpatialiteAddOrderByFID = true;
bSpatialiteOrGPKGAddOrderByFID = true;
}
if (psInfo->dialect) {
if (EQUAL(psInfo->dialect, "Spatialite") || EQUAL(psInfo->dialect, "PostgreSQL")) {
if (EQUAL(psInfo->dialect, "Spatialite") ||
EQUAL(psInfo->dialect, "GPKG") ||
EQUAL(psInfo->dialect, "PostgreSQL")) {
const char *sql = layer->filter.native_string;
if (sql && *sql != '\0') {
if (filter) filter = msStringConcatenate(filter, "AND ");
......@@ -2318,7 +2393,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}
}
if( bSpatialiteAddOrderByFID )
if( bSpatialiteOrGPKGAddOrderByFID )
{
if( sort == NULL )
sort = msStringConcatenate(NULL, " ORDER BY ");
......@@ -2429,13 +2504,15 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon );
OGR_G_DestroyGeometry( hSpatialFilterPolygon );
}
if (layer->debug >= MS_DEBUGLEVEL_VVV)
{
msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy );
}
}
psInfo->rect = rect;
if (layer->debug >= MS_DEBUGLEVEL_VVV)
msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy );
/* ------------------------------------------------------------------
* Apply an attribute filter if we have one prefixed with a WHERE
* keyword in the filter string. Otherwise, ensure the attribute
......@@ -3575,7 +3652,16 @@ static int msOGRLayerInitItemInfo(layerObj *layer)
itemindexes[i] = MSOGR_SYMBOLPARAMINDEX
+ atoi(layer->items[i] + MSOGR_SYMBOLPARAMNAMELEN);
else
{
itemindexes[i] = OGR_FD_GetFieldIndex( hDefn, layer->items[i] );
if( itemindexes[i] == -1 )
{
if( EQUAL( layer->items[i], OGR_L_GetFIDColumn( psInfo->hLayer ) ) )
{
itemindexes[i] = MSOGR_FID_INDEX;
}
}
}
if(itemindexes[i] == -1) {
msSetError(MS_OGRERR,
"Invalid Field name: %s",
......
......@@ -60,7 +60,7 @@ extern parseResultObj yypresult; /* result of parsing, true/false */
/* msGetClass_String() */
/************************************************************************/
static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value )
static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value, int firstClassToTry )
{
int i;
......@@ -80,9 +80,18 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
/* Setup values list for expressions. */
/* -------------------------------------------------------------------- */
numitems = 4;
sprintf( red_value, "%d", color->red );
sprintf( green_value, "%d", color->green );
sprintf( blue_value, "%d", color->blue );
if( color->red == -1 && color->green == -1 && color->blue == -1 )
{
strcpy(red_value, "-1");
strcpy(green_value, "-1");
strcpy(blue_value, "-1");
}
else
{
sprintf( red_value, "%d", color->red );
sprintf( green_value, "%d", color->green );
sprintf( blue_value, "%d", color->blue );
}
item_values[0] = (char *)pixel_value;
item_values[1] = red_value;
......@@ -92,18 +101,24 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
/* -------------------------------------------------------------------- */
/* Loop over classes till we find a match. */
/* -------------------------------------------------------------------- */
for(i=0; i<layer->numclasses; i++) {
for(i= (firstClassToTry < 0 ) ? 0 : -1; i<layer->numclasses; i++) {
int idx = i;
if( i < 0 )
idx = firstClassToTry;
else if( i == firstClassToTry )
continue;
/* check for correct classgroup, if set */
if ( layer->class[i]->group && layer->classgroup &&
strcasecmp(layer->class[i]->group, layer->classgroup) != 0 )
if ( layer->class[idx]->group && layer->classgroup &&
strcasecmp(layer->class[idx]->group, layer->classgroup) != 0 )
continue;
/* Empty expression - always matches */
if (layer->class[i]->expression.string == NULL)
if (layer->class[idx]->expression.string == NULL)
return(i);
switch(layer->class[i]->expression.type) {
switch(layer->class[idx]->expression.type) {
/* -------------------------------------------------------------------- */
/* Simple string match */
......@@ -114,22 +129,22 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
while( *tmpstr1 == ' ' )
tmpstr1++;
if(strcmp(layer->class[i]->expression.string, tmpstr1) == 0) return(i); /* matched */
if(strcmp(layer->class[idx]->expression.string, tmpstr1) == 0) return(idx); /* matched */
break;
/* -------------------------------------------------------------------- */
/* Regular expression. Rarely used for raster. */
/* -------------------------------------------------------------------- */
case(MS_REGEX):
if(!layer->class[i]->expression.compiled) {
if(ms_regcomp(&(layer->class[i]->expression.regex), layer->class[i]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
if(!layer->class[idx]->expression.compiled) {
if(ms_regcomp(&(layer->class[idx]->expression.regex), layer->class[idx]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()");
return(-1);
}
layer->class[i]->expression.compiled = MS_TRUE;
layer->class[idx]->expression.compiled = MS_TRUE;
}
if(ms_regexec(&(layer->class[i]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(i); /* got a match */
if(ms_regexec(&(layer->class[idx]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(idx); /* got a match */
break;
/* -------------------------------------------------------------------- */
......@@ -139,7 +154,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
int status;
parseObj p;
shapeObj dummy_shape;
expressionObj *expression = &(layer->class[i]->expression);
expressionObj *expression = &(layer->class[idx]->expression);
dummy_shape.numvalues = numitems;
dummy_shape.values = item_values;
......@@ -160,7 +175,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
}
if( p.result.intval )
return i;
return idx;
break;
}
}
......@@ -179,7 +194,7 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index );
return msGetClass_String( layer, color, pixel_value );
return msGetClass_String( layer, color, pixel_value, -1 );
}
/************************************************************************/
......@@ -190,6 +205,13 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
/************************************************************************/
int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue )
{
return msGetClass_FloatRGB_WithFirstClassToTry(
layer, fValue, red, green, blue, -1);
}
int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry )
{
char pixel_value[100];
colorObj color;
......@@ -200,7 +222,7 @@ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int b
snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue );
return msGetClass_String( layer, &color, pixel_value );
return msGetClass_String( layer, &color, pixel_value, firstClassToTry );