Merge pull request #3809 from pblottiere/render

replace QgsMapRenderer
This commit is contained in:
rldhont 2016-12-12 14:07:37 +01:00 committed by GitHub
commit 7028eee198
60 changed files with 3464 additions and 4173 deletions

View File

@ -33,4 +33,11 @@ class QgsDatumTransformStore
void writeXml( QDomNode& parentNode, QDomDocument& theDoc ) const;
struct Entry
{
QString srcAuthId;
QString destAuthId;
int srcDatumTransform; //-1 if unknown or not specified
int destDatumTransform;
};
};

View File

@ -65,6 +65,18 @@ class QgsMapRendererJob : QObject
//! Get pointer to internal labeling engine (in order to get access to the results)
virtual QgsLabelingResults* takeLabelingResults() = 0 /Transfer/;
//! @note Added in QGIS 3.0
//! Set the feature filter provider used by the QgsRenderContext of
//! each LayerRenderJob.
//! Ownership is not transferred and the provider must not be deleted
//! before the render job.
void setFeatureFilterProvider( const QgsFeatureFilterProvider *f );
//! @note Added in QGIS 3.0
//! Returns the feature filter provider used by the QgsRenderContext of
//! each LayerRenderJob.
const QgsFeatureFilterProvider* featureFilterProvider() const;
struct Error
{
Error( const QString& lid, const QString& msg );

View File

@ -1,278 +0,0 @@
struct QgsLayerCoordinateTransform
{
%TypeHeaderCode
#include <qgsmaprenderer.h>
%End
QString srcAuthId;
QString destAuthId;
int srcDatumTransform; //-1 if unknown or not specified
int destDatumTransform;
};
// ### QGIS 3: remove QgsMapRenderer in favor of QgsMapRendererJob
/** \ingroup core
* A non GUI class for rendering a map layer set onto a QPainter.
*/
class QgsMapRenderer : QObject
{
%TypeHeaderCode
#include <qgsmaprenderer.h>
%End
public:
/** Output units for pen width and point marker width/height*/
enum OutputUnits
{
Millimeters,
Pixels
//MAP_UNITS probably supported in future versions
};
//! constructor
QgsMapRenderer();
//! destructor
~QgsMapRenderer();
//! starts rendering
//! @param painter painter to render to
//! @param forceWidthScale Force a specific scale factor for line widths and marker sizes. Automatically calculated from output device DPI if 0
void render( QPainter* painter, double* forceWidthScale = 0 );
//! sets extent and checks whether suitable (returns false if not)
bool setExtent( const QgsRectangle& extent );
//! returns current extent
QgsRectangle extent() const;
//! sets rotation
//! value in clockwise degrees
//! @note added in 2.8
void setRotation( double degrees );
//! returns current rotation in clockwise degrees
//! @note added in 2.8
double rotation() const;
const QgsMapToPixel* coordinateTransform();
//! Scale denominator
double scale() const;
/** Sets scale for scale based visibility. Normally, the scale is calculated automatically. This
function is only used to force a preview scale (e.g. for print composer)*/
void setScale( double scale );
double mapUnitsPerPixel() const;
int width() const;
int height() const;
//! Recalculate the map scale
void updateScale();
/** Returns the distance units which are used for map units.
* @see setMapUnits()
*/
QgsUnitTypes::DistanceUnit mapUnits() const;
/** Sets the distance units which will be used for map units.
* @see mapUnits()
*/
void setMapUnits( QgsUnitTypes::DistanceUnit u );
//! sets whether map image will be for overview
void enableOverviewMode( bool isOverview = true );
/** Sets the desired size of the rendered map image.
* @param size size in pixels
* @param dpi resolution to render map using
* @see outputSize()
*/
void setOutputSize( QSize size, double dpi );
/** Sets the desired size of the rendered map image.
* @param size size in pixels
* @param dpi resolution to render map using
* @see outputSizeF()
*/
void setOutputSize( QSizeF size, double dpi );
//!accessor for output dpi
double outputDpi();
/** Returns the size which the map will be rendered at.
* @see setOutputSize()
* @see outputSizeF()
*/
QSize outputSize() const;
/** Returns the size which the map will be rendered at.
* @see setOutputSize()
* @see outputSize()
*/
QSizeF outputSizeF() const;
/**
* @brief transform bounding box from layer's CRS to output CRS
* @see layerToMapCoordinates( QgsMapLayer* theLayer, QgsRectangle rect ) if you want to transform a rectangle
* @return a bounding box (aligned rectangle) containing the transformed extent
*/
QgsRectangle layerExtentToOutputExtent( QgsMapLayer* theLayer, QgsRectangle extent );
/**
* @brief transform bounding box from output CRS to layer's CRS
* @see mapToLayerCoordinates( QgsMapLayer* theLayer,QgsRectangle rect ) if you want to transform a rectangle
* @return a bounding box (aligned rectangle) containing the transformed extent
*/
QgsRectangle outputExtentToLayerExtent( QgsMapLayer* theLayer, QgsRectangle extent );
/**
* @brief transform point coordinates from layer's CRS to output CRS
* @return the transformed point
*/
QgsPoint layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint point );
/**
* @brief transform rectangle from layer's CRS to output CRS
* @see layerExtentToOutputExtent() if you want to transform a bounding box
* @return the transformed rectangle
*/
QgsRectangle layerToMapCoordinates( QgsMapLayer* theLayer, QgsRectangle rect );
/**
* @brief transform point coordinates from output CRS to layer's CRS
* @return the transformed point
*/
QgsPoint mapToLayerCoordinates( QgsMapLayer* theLayer, QgsPoint point );
/**
* @brief transform rectangle from output CRS to layer's CRS
* @see outputExtentToLayerExtent() if you want to transform a bounding box
* @return the transformed rectangle
*/
QgsRectangle mapToLayerCoordinates( QgsMapLayer* theLayer, QgsRectangle rect );
//! sets whether to use projections for this layer set
void setProjectionsEnabled( bool enabled );
//! returns true if projections are enabled for this layer set
bool hasCrsTransformEnabled() const;
//! sets destination coordinate reference system
void setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo = true, bool transformExtent = true );
//! returns CRS of destination coordinate reference system
const QgsCoordinateReferenceSystem& destinationCrs() const;
void setOutputUnits( OutputUnits u );
OutputUnits outputUnits() const;
//! returns current extent of layer set
QgsRectangle fullExtent();
//! returns current layer set
QStringList& layerSet();
//! change current layer set
void setLayerSet( const QStringList& layers );
//! updates extent of the layer set
void updateFullExtent();
//! read settings
bool readXml( QDomNode & theNode );
//! write settings
bool writeXml( QDomNode & theNode, QDomDocument & theDoc );
//! Accessor for render context
QgsRenderContext* rendererContext();
//! Labeling engine (nullptr if there's no custom engine)
QgsLabelingEngineInterface* labelingEngine();
//! Set labeling engine. Previous engine (if any) is deleted.
//! Takes ownership of the engine.
void setLabelingEngine( QgsLabelingEngineInterface* iface /Transfer/ );
void addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform = -1, int destDatumTransform = -1 );
void clearLayerCoordinateTransforms();
/** Returns the coordinate transform associated with a renderered layer,
* or an invalid transform is no transform is required for the layer.
*/
QgsCoordinateTransform transformation( const QgsMapLayer *layer ) const;
//! bridge to QgsMapSettings
//! @note added in 2.4
const QgsMapSettings& mapSettings();
/** Convenience function to project an extent into the layer source
* CRS, but also split it into two extents if it crosses
* the +/- 180 degree line. Modifies the given extent to be in the
* source CRS coordinates, and if it was split, returns true, and
* also sets the contents of the r2 parameter
*/
bool splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent /In,Out/, QgsRectangle& r2 /Out/ );
/** Set a feature filter provider to filter the features shown in the map.
* @param ffp the feature filter provider
* @note added in QGIS 2.14
*/
void setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp );
signals:
//! @deprecated in 2.4 - not emitted anymore
void drawingProgress( int current, int total );
/** This signal is emitted when CRS transformation is enabled/disabled.
* @param flag true if transformation is enabled.
* @deprecated Use hasCrsTransformEnabledChanged( bool flag )
* to avoid conflict with method of the same name). */
void hasCrsTransformEnabled( bool flag ) /Deprecated/;
/** This signal is emitted when CRS transformation is enabled/disabled.
* @param flag true if transformation is enabled.
* @note Added in 2.4 */
void hasCrsTransformEnabledChanged( bool flag );
//! Emitted when the renderer's destination CRS is changed
void destinationCrsChanged();
//! @deprecated in 2.4 - not emitted anymore
void updateMap();
void mapUnitsChanged();
//! emitted when layer's draw() returned false
void drawError( QgsMapLayer* );
//! emitted when the current extent gets changed
//! @note added in 2.4
void extentsChanged();
//! emitted when the current rotation gets changed
//! @note added in 2.8
void rotationChanged( double );
//! Notifies higher level components to show the datum transform dialog and add a QgsLayerCoordinateTransformInfo for that layer
//! @note not available in Python bindings
//void datumTransformInfoRequested( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId ) const;
public slots:
//! @deprecated in 2.4 - does nothing
void onDrawingProgress( int current, int total ) /Deprecated/;
protected:
//! adjust extent to fit the pixmap size
void adjustExtentToSize();
};

View File

@ -86,7 +86,7 @@ class QgsServerProjectParser
QList<QDomElement> publishedComposerElements() const;
//QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const;
//QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const;
/** Returns the text of the <layername> element for a layer element
@return id or a null string in case of error*/

View File

@ -33,7 +33,6 @@ class QgsComposerLegendItem;
class QgsComposition;
class QgsFields;
class QgsMapLayer;
class QgsMapRenderer;
class QgsPoint;
class QgsRasterLayer;
class QgsConfigParser;

View File

@ -45,7 +45,7 @@ class QgsWmsConfigParser
virtual QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const = 0;
/** Returns if output are MM or PIXEL*/
virtual QgsMapRenderer::OutputUnits outputUnits() const = 0;
virtual QgsUnitTypes::RenderUnit outputUnits() const = 0;
/** Returns an ID-list of layers which are not queryable (comes from <properties> -> <Identify> -> <disabledLayers in the project file*/
virtual QStringList identifyDisabledLayers() const = 0;
@ -71,8 +71,8 @@ class QgsWmsConfigParser
/** Draw text annotation items from the QGIS projectfile*/
virtual void drawOverlays( QPainter* p, int dpi, int width, int height ) const = 0;
/** Load PAL engine settings from the QGIS projectfile*/
virtual void loadLabelSettings( QgsLabelingEngineInterface* lbl ) const = 0;
/** Load PAL engine settings into global project instance*/
virtual void loadLabelSettings() const = 0;
virtual QString serviceUrl() const = 0;
@ -101,13 +101,10 @@ class QgsWmsConfigParser
//printing
/** Creates a print composition, usually for a GetPrint request. Replaces map and label parameters*/
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const;
/** Creates a print composition, usually for a GetPrint request. Replaces map and label parameters*/
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
QgsComposition* createPrintComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
/** Creates a composition from the project file (probably delegated to the fallback parser)*/
//virtual QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList /Out/, QList< QgsComposerLegend* >& legendList /Out/, QList< QgsComposerLabel* >& labelList /Out/, QList<const QgsComposerHtml *>& htmlFrameList /Out/ ) const = 0;
//virtual QgsComposition* initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const = 0;
/** Adds print capabilities to xml document. ParentElem usually is the <Capabilities> element*/
virtual void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0;
@ -115,7 +112,7 @@ class QgsWmsConfigParser
virtual void setScaleDenominator( double denom ) = 0;
virtual void addExternalGMLData( const QString& layerName, QDomDocument* gmlDoc ) = 0;
virtual QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const = 0;
virtual QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const = 0;
virtual int nLayers() const = 0;

View File

@ -32,7 +32,7 @@ class QgsConfigParser;
class QgsFeature;
class QgsFeatureRenderer;
class QgsMapLayer;
class QgsMapRenderer;
class QgsMapSettings;
class QgsPoint;
class QgsRasterLayer;
class QgsRasterRenderer;
@ -41,6 +41,8 @@ class QgsRenderContext;
class QgsVectorLayer;
class QgsSymbol;
class QgsSymbol;
class QgsAccessControl;
class QColor;
class QFile;
class QFont;
@ -57,9 +59,8 @@ class QgsWmsServer: public QgsOWSServer
{
public:
/** Constructor. Does _NOT_ take ownership of
QgsConfigParser, QgsCapabilitiesCache and QgsMapRenderer*/
QgsWmsServer( const QString& configFilePath, QMap<QString, QString> &parameters, QgsWmsConfigParser* cp, QgsRequestHandler* rh,
QgsMapRenderer* renderer, QgsCapabilitiesCache* capCache, const QgsAccessControl* accessControl );
QgsConfigParser, QgsCapabilitiesCache*/
QgsWmsServer( const QString& configFilePath, QMap<QString, QString> &parameters, QgsWmsConfigParser* cp, QgsRequestHandler* rh, QgsCapabilitiesCache* capCache, const QgsAccessControl* accessControl );
~QgsWmsServer();
void executeRequest() override;

View File

@ -55,7 +55,7 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
int wmsPrecision() const /*override*/ ;
//printing
//QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap* >& mapList, //QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const /*override*/ ;
//QgsComposition* initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap* >& mapList, //QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const /*override*/ ;
void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const /*override*/ ;
@ -63,7 +63,7 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
void setScaleDenominator( double ) /*override*/;
void addExternalGMLData( const QString&, QDomDocument* ) /*override*/ ;
QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const /*override*/ ;
QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const /*override*/ ;
/** Fills a layer and a style list. The two list have the same number of entries and the style and the layer at a position belong together (similar to the HTTP parameters 'Layers' and 'Styles'. Returns 0 in case of success*/
int layersAndStyles( QStringList& layers, QStringList& styles ) const /*override*/ ;
@ -78,7 +78,7 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const /*override*/ ;
/** Returns if output are MM or PIXEL*/
QgsMapRenderer::OutputUnits outputUnits() const /*override*/ ;
QgsUnitTypes::RenderUnit outputUnits() const /*override*/ ;
/** True if the feature info response should contain the wkt geometry for vector features*/
bool featureInfoWithWktGeometry() const /*override*/ ;
@ -102,8 +102,8 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
/** Draw text annotation items from the QGIS projectfile*/
void drawOverlays( QPainter* p, int dpi, int width, int height ) const /*override*/ ;
/** Load PAL engine settings from projectfile*/
void loadLabelSettings( QgsLabelingEngineInterface* lbl ) const /*override*/ ;
/** Load PAL engine settings into global project instance*/
void loadLabelSettings() const /*override*/ ;
int nLayers() const /*override*/ ;

View File

@ -18,7 +18,6 @@
%Include qgsaccesscontrol.sip
%End
%Include qgsmaprenderer.sip
%Include qgsmapserviceexception.sip
%Include qgscapabilitiescache.sip
%Include qgsrequesthandler.sip

View File

@ -38,6 +38,7 @@ QgsMapRendererJob::QgsMapRendererJob( const QgsMapSettings& settings )
: mSettings( settings )
, mCache( nullptr )
, mRenderingTime( 0 )
, mFeatureFilterProvider( nullptr )
{
}
@ -249,6 +250,9 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsLabelingEn
job.context.setCoordinateTransform( ct );
job.context.setExtent( r1 );
if ( mFeatureFilterProvider )
job.context.setFeatureFilterProvider( mFeatureFilterProvider );
// if we can use the cache, let's do it and avoid rendering!
if ( mCache && !mCache->cacheImage( ml->id() ).isNull() )
{

View File

@ -34,6 +34,7 @@ class QgsLabelingResults;
class QgsMapLayerRenderer;
class QgsMapRendererCache;
class QgsPalLabeling;
class QgsFeatureFilterProvider;
/** \ingroup core
@ -105,6 +106,18 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
//! Get pointer to internal labeling engine (in order to get access to the results)
virtual QgsLabelingResults* takeLabelingResults() = 0;
//! @note Added in QGIS 3.0
//! Set the feature filter provider used by the QgsRenderContext of
//! each LayerRenderJob.
//! Ownership is not transferred and the provider must not be deleted
//! before the render job.
void setFeatureFilterProvider( const QgsFeatureFilterProvider *f ) { mFeatureFilterProvider = f; };
//! @note Added in QGIS 3.0
//! Returns the feature filter provider used by the QgsRenderContext of
//! each LayerRenderJob.
const QgsFeatureFilterProvider* featureFilterProvider() const { return mFeatureFilterProvider; };
struct Error
{
Error( const QString& lid, const QString& msg )
@ -182,7 +195,6 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
//! called when rendering has finished to update all layers' geometry caches
void updateLayerGeometryCaches();
QgsMapSettings mSettings;
Errors mErrors;
@ -195,6 +207,8 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
QTime mRenderingStart;
int mRenderingTime;
const QgsFeatureFilterProvider *mFeatureFilterProvider;
};

View File

@ -31,7 +31,6 @@ SET ( qgis_mapserv_SRCS
qgswfsserver.cpp
qgswcsserver.cpp
qgsmapserviceexception.cpp
qgsmaprenderer.cpp
qgsmslayercache.cpp
qgsmslayerbuilder.cpp
qgshostedvdsbuilder.cpp
@ -41,7 +40,7 @@ SET ( qgis_mapserv_SRCS
qgsremotedatasourcebuilder.cpp
qgssentdatasourcebuilder.cpp
qgsserverlogger.cpp
qgsmsutils.cpp
qgsmapserverutils.cpp
qgswcsprojectparser.cpp
qgswfsprojectparser.cpp
qgswmsconfigparser.cpp
@ -67,7 +66,6 @@ SET (qgis_mapserv_MOC_HDRS
qgscapabilitiescache.h
qgsconfigcache.h
# qgshttptransaction.h
qgsmaprenderer.h
qgsmslayercache.h
qgsserverlogger.h
qgsserverstreamingdevice.h

File diff suppressed because it is too large Load Diff

View File

@ -1,395 +0,0 @@
/***************************************************************************
qgsmaprender.h - class for rendering map layer set
----------------------
begin : January 2006
copyright : (C) 2006 by Martin Dobias
email : wonder.sk at gmail dot com
***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSMAPRENDER_H
#define QGSMAPRENDER_H
#include <QMutex>
#include <QSize>
#include <QStringList>
#include <QVector>
#include <QPainter>
#include "qgis.h"
#include "qgsrectangle.h"
#include "qgsrendercontext.h"
#include "qgsmapsettings.h"
#include "qgspallabeling.h"
class QDomDocument;
class QDomNode;
class QPainter;
class QgsMapToPixel;
class QgsMapLayer;
class QgsScaleCalculator;
class QgsCoordinateReferenceSystem;
class QgsDistanceArea;
class QgsVectorLayer;
struct SERVER_EXPORT QgsLayerCoordinateTransform
{
QString srcAuthId;
QString destAuthId;
int srcDatumTransform; //-1 if unknown or not specified
int destDatumTransform;
};
// ### QGIS 3: remove QgsMapRenderer in favor of QgsMapRendererJob
/** \ingroup core
* A non GUI class for rendering a map layer set onto a QPainter.
*/
class SERVER_EXPORT QgsMapRenderer : public QObject
{
Q_OBJECT
public:
//! Output units for pen width and point marker width/height
enum OutputUnits
{
Millimeters,
Pixels
//MAP_UNITS probably supported in future versions
};
//! constructor
QgsMapRenderer();
//! destructor
~QgsMapRenderer();
//! starts rendering
//! @param painter painter to render to
//! @param forceWidthScale Force a specific scale factor for line widths and marker sizes. Automatically calculated from output device DPI if 0
void render( QPainter* painter, double* forceWidthScale = nullptr );
//! sets extent and checks whether suitable (returns false if not)
bool setExtent( const QgsRectangle& extent );
//! returns current extent
QgsRectangle extent() const;
//! sets rotation
//! value in clockwise degrees
//! @note added in 2.8
void setRotation( double degrees );
//! returns current rotation in clockwise degrees
//! @note added in 2.8
double rotation() const;
const QgsMapToPixel* coordinateTransform() { return &( mRenderContext.mapToPixel() ); }
//! Scale denominator
double scale() const { return mScale; }
/** Sets scale for scale based visibility. Normally, the scale is calculated automatically. This
function is only used to force a preview scale (e.g. for print composer)*/
void setScale( double scale ) {mScale = scale;}
double mapUnitsPerPixel() const { return mMapUnitsPerPixel; }
int width() const { return static_cast< int >( mSize.width() ); }
int height() const { return static_cast< int >( mSize.height() ); }
//! Recalculate the map scale
void updateScale();
/** Returns the distance units which are used for map units.
* @see setMapUnits()
*/
QgsUnitTypes::DistanceUnit mapUnits() const;
/** Sets the distance units which will be used for map units.
* @see mapUnits()
*/
void setMapUnits( QgsUnitTypes::DistanceUnit u );
//! sets whether map image will be for overview
void enableOverviewMode( bool isOverview = true ) { mOverview = isOverview; }
/** Sets the desired size of the rendered map image.
* @param size size in pixels
* @param dpi resolution to render map using
* @see outputSize()
*/
void setOutputSize( QSize size, double dpi );
/** Sets the desired size of the rendered map image.
* @param size size in pixels
* @param dpi resolution to render map using
* @see outputSizeF()
*/
void setOutputSize( QSizeF size, double dpi );
//!accessor for output dpi
double outputDpi();
/** Returns the size which the map will be rendered at.
* @see setOutputSize()
* @see outputSizeF()
*/
QSize outputSize() const;
/** Returns the size which the map will be rendered at.
* @see setOutputSize()
* @see outputSize()
*/
QSizeF outputSizeF() const;
/**
* @brief transform bounding box from layer's CRS to output CRS
* @see layerToMapCoordinates( QgsMapLayer* theLayer, QgsRectangle rect ) if you want to transform a rectangle
* @return a bounding box (aligned rectangle) containing the transformed extent
*/
QgsRectangle layerExtentToOutputExtent( QgsMapLayer* theLayer, QgsRectangle extent );
/**
* @brief transform bounding box from output CRS to layer's CRS
* @see mapToLayerCoordinates( QgsMapLayer* theLayer,QgsRectangle rect ) if you want to transform a rectangle
* @return a bounding box (aligned rectangle) containing the transformed extent
*/
QgsRectangle outputExtentToLayerExtent( QgsMapLayer* theLayer, QgsRectangle extent );
/**
* @brief transform point coordinates from layer's CRS to output CRS
* @return the transformed point
*/
QgsPoint layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint point );
/**
* @brief transform rectangle from layer's CRS to output CRS
* @see layerExtentToOutputExtent() if you want to transform a bounding box
* @return the transformed rectangle
*/
QgsRectangle layerToMapCoordinates( QgsMapLayer* theLayer, QgsRectangle rect );
/**
* @brief transform point coordinates from output CRS to layer's CRS
* @return the transformed point
*/
QgsPoint mapToLayerCoordinates( QgsMapLayer* theLayer, QgsPoint point );
/**
* @brief transform rectangle from output CRS to layer's CRS
* @see outputExtentToLayerExtent() if you want to transform a bounding box
* @return the transformed rectangle
*/
QgsRectangle mapToLayerCoordinates( QgsMapLayer* theLayer, QgsRectangle rect );
//! sets whether to use projections for this layer set
void setProjectionsEnabled( bool enabled );
//! returns true if projections are enabled for this layer set
bool hasCrsTransformEnabled() const;
//! sets destination coordinate reference system
void setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo = true, bool transformExtent = true );
//! returns CRS of destination coordinate reference system
const QgsCoordinateReferenceSystem& destinationCrs() const;
void setOutputUnits( OutputUnits u ) {mOutputUnits = u;}
OutputUnits outputUnits() const {return mOutputUnits;}
//! returns current extent of layer set
QgsRectangle fullExtent();
//! returns current layer set
QStringList& layerSet();
//! change current layer set
void setLayerSet( const QStringList& layers );
//! returns current list of layers
QList<QgsMapLayer*> layers();
//! updates extent of the layer set
void updateFullExtent();
//! read settings
bool readXml( QDomNode & theNode );
//! write settings
bool writeXml( QDomNode & theNode, QDomDocument & theDoc );
//! Accessor for render context
QgsRenderContext* rendererContext() {return &mRenderContext;}
//! Labeling engine (nullptr if there's no custom engine)
QgsLabelingEngineInterface* labelingEngine() { return mLabelingEngine; }
//! Set labeling engine. Previous engine (if any) is deleted.
//! Takes ownership of the engine.
void setLabelingEngine( QgsLabelingEngineInterface* iface );
void addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform = -1, int destDatumTransform = -1 );
void clearLayerCoordinateTransforms();
/** Returns the coordinate transform associated with a renderered layer,
* or an invalid transform is no transform is required for the layer.
*/
QgsCoordinateTransform transformation( const QgsMapLayer *layer ) const;
//! bridge to QgsMapSettings
//! @note added in 2.4
const QgsMapSettings& mapSettings();
/** Convenience function to project an extent into the layer source
* CRS, but also split it into two extents if it crosses
* the +/- 180 degree line. Modifies the given extent to be in the
* source CRS coordinates, and if it was split, returns true, and
* also sets the contents of the r2 parameter
*/
bool splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent, QgsRectangle& r2 );
/** Set a feature filter provider to filter the features shown in the map.
* @param ffp the feature filter provider
* @note added in QGIS 2.14
*/
void setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp )
{
mRenderContext.setFeatureFilterProvider( ffp );
}
signals:
//! @deprecated in 2.4 - not emitted anymore
void drawingProgress( int current, int total );
/** This signal is emitted when CRS transformation is enabled/disabled.
* @param flag true if transformation is enabled.
* @deprecated Use hasCrsTransformEnabledChanged( bool flag )
* to avoid conflict with method of the same name). */
#ifndef Q_MOC_RUN
Q_DECL_DEPRECATED
#endif
void hasCrsTransformEnabled( bool flag );
/** This signal is emitted when CRS transformation is enabled/disabled.
* @param flag true if transformation is enabled.
* @note Added in 2.4 */
void hasCrsTransformEnabledChanged( bool flag );
//! Emitted when the renderer's destination CRS is changed
void destinationCrsChanged();
//! @deprecated in 2.4 - not emitted anymore
void updateMap();
void mapUnitsChanged();
//! emitted when layer's draw() returned false
void drawError( QgsMapLayer* );
//! emitted when the current extent gets changed
//! @note added in 2.4
void extentsChanged();
//! emitted when the current rotation gets changed
//! @note added in 2.8
void rotationChanged( double );
//! Notifies higher level components to show the datum transform dialog and add a QgsLayerCoordinateTransformInfo for that layer
//! @note not available in Python bindings
void datumTransformInfoRequested( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId ) const;
public slots:
//! @deprecated in 2.4 - does nothing
Q_DECL_DEPRECATED void onDrawingProgress( int current, int total );
protected:
//! adjust extent to fit the pixmap size
void adjustExtentToSize();
//! indicates drawing in progress
static bool mDrawing;
//! map units per pixel
double mMapUnitsPerPixel;
//! Map scale denominator at its current zoom level
double mScale;
//! Map rotation
double mRotation;
//! scale calculator
QgsScaleCalculator * mScaleCalculator;
//! current extent to be drawn
QgsRectangle mExtent;
//
/** Last extent to we drew so we know if we can
used layer render caching or not. Note there are no
accessors for this as it is intended to internal
use only. */
QgsRectangle mLastExtent;
//! indicates whether it's map image for overview
bool mOverview;
QSizeF mSize;
//! detemines whether on the fly projection support is enabled
bool mProjectionsEnabled;
//! destination spatial reference system of the projection
// TODO QGIS 3.0 - make object, not pointer
QgsCoordinateReferenceSystem* mDestCRS;
//! stores array of layers to be rendered (identified by string)
QStringList mLayerSet;
//! full extent of the layer set
QgsRectangle mFullExtent;
//! tool for measuring
QgsDistanceArea* mDistArea;
//!Encapsulates context of rendering
QgsRenderContext mRenderContext;
//!Output units
OutputUnits mOutputUnits;
//! Labeling engine (nullptr by default)
QgsLabelingEngineInterface* mLabelingEngine;
//! Locks rendering loop for concurrent draws
QMutex mRenderMutex;
//! map settings - used only for export in mapSettings() for use in classes that deal with QgsMapSettings
QgsMapSettings mMapSettings;
QHash< QString, QgsLayerCoordinateTransform > mLayerCoordinateTransformInfo;
QHash< QPair< QString, QString >, QPair< int, int > > mDefaultDatumTransformations;
private:
void readDefaultDatumTransformations();
};
#endif

View File

@ -1,5 +1,5 @@
/***************************************************************************
qgsmsutils.cpp
qgsmapserverutils.cpp
---------------------
begin : August 2010
copyright : (C) 2010 by Marco Hugentobler
@ -12,7 +12,7 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsmsutils.h"
#include "qgsmapserverutils.h"
#include "qgslogger.h"
#include <stdlib.h>
#include <time.h>
@ -20,7 +20,7 @@
#include <QFileInfo>
#include <QTextStream>
QString QgsMSUtils::createTempFilePath()
QString QgsMapServerUtils::createTempFilePath()
{
@ -67,7 +67,7 @@ QString QgsMSUtils::createTempFilePath()
return tempFilePath;
}
int QgsMSUtils::createTextFile( const QString& filePath, const QString& text )
int QgsMapServerUtils::createTextFile( const QString& filePath, const QString& text )
{
QFile file( filePath );
if ( file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )

View File

@ -1,5 +1,5 @@
/***************************************************************************
qgsmsutils.h
qgsmapserverutils.h
---------------------
begin : August 2010
copyright : (C) 2010 by Marco Hugentobler
@ -12,13 +12,13 @@
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSMSUTILS_H
#define QGSMSUTILS_H
#ifndef QGSMAPSERVERUTILS_H
#define QGSMAPSERVERUTILS_H
#include <QString>
//! Some utility functions that may be included from everywhere in the code
namespace QgsMSUtils
namespace QgsMapServerUtils
{
/** Creates a ramdom filename for a temporary file. This function also creates the directory to store

View File

@ -22,6 +22,7 @@
#include "qgsconfig.h"
#include "qgsserver.h"
#include "qgsmapsettings.h"
#include "qgsauthmanager.h"
#include "qgscapabilitiescache.h"
#include "qgsfontutils.h"
@ -61,7 +62,6 @@
QString* QgsServer::sConfigFilePath = nullptr;
QgsCapabilitiesCache* QgsServer::sCapabilitiesCache = nullptr;
QgsMapRenderer* QgsServer::sMapRenderer = nullptr;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsServerInterfaceImpl*QgsServer::sServerInterface = nullptr;
#endif
@ -386,8 +386,6 @@ bool QgsServer::init( )
//create cache for capabilities XML
sCapabilitiesCache = new QgsCapabilitiesCache();
sMapRenderer = new QgsMapRenderer;
sMapRenderer->setLabelingEngine( new QgsPalLabeling() );
#ifdef ENABLE_MS_TESTS
QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Roman" ) << QStringLiteral( "Bold" ) );
@ -440,12 +438,6 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
QTime time; //used for measuring request time if loglevel < 1
QgsProject::instance()->removeAllMapLayers();
// Clean up Expression Context
// because each call to QgsMapLayer::draw add items to QgsExpressionContext scope
// list. This prevent the scope list to grow indefinitely and seriously deteriorate
// performances and memory in the long run
sMapRenderer->rendererContext()->setExpressionContext( QgsExpressionContext() );
qApp->processEvents();
if ( logLevel < 1 )
@ -594,7 +586,6 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
, parameterMap
, p
, theRequestHandler.data()
, sMapRenderer
, sCapabilitiesCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, accessControl

View File

@ -30,9 +30,9 @@
#include <QFileInfo>
#include "qgsrequesthandler.h"
#include "qgsapplication.h"
#include "qgsmaprenderer.h"
#include "qgsconfigcache.h"
#include "qgscapabilitiescache.h"
#include "qgsmapsettings.h"
#ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsserverplugins.h"
@ -121,7 +121,6 @@ class SERVER_EXPORT QgsServer
// Status
static QString* sConfigFilePath;
static QgsCapabilitiesCache* sCapabilitiesCache;
static QgsMapRenderer* sMapRenderer;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
static QgsServerInterfaceImpl* sServerInterface;
#endif

View File

@ -24,7 +24,6 @@
#include "qgsgetrequesthandler.h"
#include "qgspostrequesthandler.h"
#include "qgssoaprequesthandler.h"
#include "qgsmaprenderer.h"
/**
* QgsServerInterface

View File

@ -22,7 +22,7 @@
#include "qgslogger.h"
#include "qgspythonutils.h"
#include "qgsserverlogger.h"
#include "qgsmsutils.h"
#include "qgsmapserverutils.h"
#include <QLibrary>

View File

@ -1463,9 +1463,9 @@ QList<QDomElement> QgsServerProjectParser::publishedComposerElements() const
return composerElemList;
}
QList< QPair< QString, QgsLayerCoordinateTransform > > QgsServerProjectParser::layerCoordinateTransforms() const
QList< QPair< QString, QgsDatumTransformStore::Entry > > QgsServerProjectParser::layerCoordinateTransforms() const
{
QList< QPair< QString, QgsLayerCoordinateTransform > > layerTransformList;
QList< QPair< QString, QgsDatumTransformStore::Entry > > layerTransformList;
QDomElement coordTransformInfoElem = mXMLDoc->documentElement().firstChildElement( QStringLiteral( "mapcanvas" ) ).firstChildElement( QStringLiteral( "layer_coordinate_transform_info" ) );
if ( coordTransformInfoElem.isNull() )
@ -1477,10 +1477,10 @@ QList< QPair< QString, QgsLayerCoordinateTransform > > QgsServerProjectParser::l
layerTransformList.reserve( layerTransformNodeList.size() );
for ( int i = 0; i < layerTransformNodeList.size(); ++i )
{
QPair< QString, QgsLayerCoordinateTransform > layerEntry;
QPair< QString, QgsDatumTransformStore::Entry > layerEntry;
QDomElement layerTransformElem = layerTransformNodeList.at( i ).toElement();
layerEntry.first = layerTransformElem.attribute( QStringLiteral( "layerid" ) );
QgsLayerCoordinateTransform t;
QgsDatumTransformStore::Entry t;
t.srcAuthId = layerTransformElem.attribute( QStringLiteral( "srcAuthId" ) );
t.destAuthId = layerTransformElem.attribute( QStringLiteral( "destAuthId" ) );
t.srcDatumTransform = layerTransformElem.attribute( QStringLiteral( "srcDatumTransform" ), QStringLiteral( "-1" ) ).toInt();

View File

@ -20,7 +20,7 @@
#include "qgsconfig.h"
#include "qgsvectorlayer.h"
#include "qgsmaprenderer.h"
#include "qgsdatumtransformstore.h"
#include <QDomElement>
#include <QHash>
@ -99,7 +99,7 @@ class SERVER_EXPORT QgsServerProjectParser
QList<QDomElement> publishedComposerElements() const;
QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const;
QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const;
/** Returns the text of the <layername> element for a layer element
@return name or a null string in case of error*/

View File

@ -60,7 +60,7 @@ QgsSLDConfigParser::QgsSLDConfigParser( QDomDocument* doc, const QMap<QString, Q
, mXMLDoc( doc )
, mParameterMap( parameters )
, mSLDNamespace( QStringLiteral( "http://www.opengis.net/sld" ) )
, mOutputUnits( QgsMapRenderer::Pixels )
, mOutputUnits( QgsUnitTypes::RenderUnit::RenderPixels )
, mFallbackParser( nullptr )
{
@ -76,11 +76,11 @@ QgsSLDConfigParser::QgsSLDConfigParser( QDomDocument* doc, const QMap<QString, Q
{
if ( unitString == QLatin1String( "mm" ) )
{
mOutputUnits = QgsMapRenderer::Millimeters;
mOutputUnits = QgsUnitTypes::RenderUnit::RenderMillimeters;
}
else if ( unitString == QLatin1String( "pixel" ) )
{
mOutputUnits = QgsMapRenderer::Pixels;
mOutputUnits = QgsUnitTypes::RenderUnit::RenderPixels;
}
}
}
@ -490,7 +490,7 @@ QDomDocument QgsSLDConfigParser::describeLayer( QStringList& layerList, const QS
return QDomDocument();
}
QgsMapRenderer::OutputUnits QgsSLDConfigParser::outputUnits() const
QgsUnitTypes::RenderUnit QgsSLDConfigParser::outputUnits() const
{
return mOutputUnits;
}
@ -564,11 +564,11 @@ void QgsSLDConfigParser::drawOverlays( QPainter* p, int dpi, int width, int heig
}
}
void QgsSLDConfigParser::loadLabelSettings( QgsLabelingEngineInterface * lbl ) const
void QgsSLDConfigParser::loadLabelSettings() const
{
if ( mFallbackParser )
{
mFallbackParser->loadLabelSettings( lbl );
mFallbackParser->loadLabelSettings();
}
}
@ -724,20 +724,11 @@ bool QgsSLDConfigParser::wmsInspireActivated() const
return false;
}
QgsComposition* QgsSLDConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const
QgsComposition* QgsSLDConfigParser::initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const
{
if ( mFallbackParser )
{
return mFallbackParser->createPrintComposition( composerTemplate, mapRenderer, parameterMap, highlightLayers );
}
return nullptr;
}
QgsComposition* QgsSLDConfigParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const
{
if ( mFallbackParser )
{
return mFallbackParser->initComposition( composerTemplate, mapRenderer, mapList, legendList, labelList, htmlFrameList );
return mFallbackParser->initComposition( composerTemplate, mapSettings, mapList, legendList, labelList, htmlFrameList );
}
return nullptr;
}
@ -768,9 +759,9 @@ void QgsSLDConfigParser::addExternalGMLData( const QString &, QDomDocument * )
//soon...
}
QList< QPair< QString, QgsLayerCoordinateTransform > > QgsSLDConfigParser::layerCoordinateTransforms() const
QList< QPair< QString, QgsDatumTransformStore::Entry > > QgsSLDConfigParser::layerCoordinateTransforms() const
{
return QList< QPair< QString, QgsLayerCoordinateTransform > >();
return QList< QPair< QString, QgsDatumTransformStore::Entry > >();
}
int QgsSLDConfigParser::nLayers() const

View File

@ -57,7 +57,7 @@ class QgsSLDConfigParser : public QgsWmsConfigParser
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const override;
//! Returns if output are MM or PIXEL
QgsMapRenderer::OutputUnits outputUnits() const override;
QgsUnitTypes::RenderUnit outputUnits() const override;
//! Returns an ID-list of layers which are not queryable (comes from <properties> -> <Identify> -> <disabledLayers in the project file
QStringList identifyDisabledLayers() const override;
@ -83,8 +83,8 @@ class QgsSLDConfigParser : public QgsWmsConfigParser
//! Draw text annotation items from the QGIS projectfile
void drawOverlays( QPainter* p, int dpi, int width, int height ) const override;
//! Load PAL engine settings from projectfile
void loadLabelSettings( QgsLabelingEngineInterface* lbl ) const override;
//! Load PAL engine settings into global project instance
void loadLabelSettings() const override;
QString serviceUrl() const override;
@ -116,10 +116,10 @@ class QgsSLDConfigParser : public QgsWmsConfigParser
//printing
//! Creates a print composition, usually for a GetPrint request. Replaces map and label parameters
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
QgsComposition* createPrintComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
//! Creates a composition from the project file (probably delegated to the fallback parser)
QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const override;
QgsComposition* initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const override;
//! Adds print capabilities to xml document. ParentElem usually is the <Capabilities> element
void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const override;
@ -127,7 +127,7 @@ class QgsSLDConfigParser : public QgsWmsConfigParser
void setScaleDenominator( double denom ) override;
void addExternalGMLData( const QString& layerName, QDomDocument* gmlDoc ) override;
QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const override;
QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const override;
int nLayers() const override;
@ -146,7 +146,7 @@ class QgsSLDConfigParser : public QgsWmsConfigParser
QString mSLDNamespace;
//! Output units (pixel or mm)
QgsMapRenderer::OutputUnits mOutputUnits;
QgsUnitTypes::RenderUnit mOutputUnits;
QgsWmsConfigParser *mFallbackParser;

View File

@ -20,7 +20,6 @@
#include "qgsfeatureiterator.h"
#include "qgsgeometry.h"
#include "qgsmaplayer.h"
#include "qgsmaprenderer.h"
#include "qgsmaptopixel.h"
#include "qgsmessagelog.h"
#include "qgspallabeling.h"

View File

@ -31,7 +31,6 @@ class QgsCoordinateReferenceSystem;
class QgsComposition;
class QgsFields;
class QgsMapLayer;
class QgsMapRenderer;
class QgsPoint;
class QgsRasterLayer;
class QgsConfigParser;

View File

@ -27,6 +27,7 @@
#include "qgscomposerhtml.h"
#include "qgscomposerframe.h"
#include "qgscomposition.h"
#include "qgsmapsettings.h"
#include "qgslayertreegroup.h"
#include "qgslayertreelayer.h"
@ -45,20 +46,14 @@ QgsWmsConfigParser::~QgsWmsConfigParser()
}
QgsComposition* QgsWmsConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const
{
QStringList highlightLayers;
return createPrintComposition( composerTemplate, mapRenderer, parameterMap, highlightLayers );
}
QgsComposition* QgsWmsConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const
QgsComposition* QgsWmsConfigParser::createPrintComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const
{
QList<QgsComposerMap*> composerMaps;
QList<QgsComposerLegend*> composerLegends;
QList<QgsComposerLabel*> composerLabels;
QList<const QgsComposerHtml*> composerHtmls;
QgsComposition* c = initComposition( composerTemplate, mapRenderer, composerMaps, composerLegends, composerLabels, composerHtmls );
QgsComposition* c = initComposition( composerTemplate, mapSettings, composerMaps, composerLegends, composerLabels, composerHtmls );
if ( !c )
{
return nullptr;
@ -113,7 +108,7 @@ QgsComposition* QgsWmsConfigParser::createPrintComposition( const QString& compo
//Change x- and y- of extent for WMS 1.3.0 if axis inverted
QString version = parameterMap.value( QStringLiteral( "VERSION" ) );
if ( version == QLatin1String( "1.3.0" ) && mapRenderer && mapRenderer->destinationCrs().hasAxisInverted() )
if ( version == QLatin1String( "1.3.0" ) && mapSettings.destinationCrs().hasAxisInverted() )
{
r.invert();
}

View File

@ -18,8 +18,12 @@
#ifndef QGSWMSCONFIGPARSER_H
#define QGSWMSCONFIGPARSER_H
#include "qgsmaprenderer.h"
#include "qgsunittypes.h"
#include "qgspallabeling.h"
#include "qgsdatumtransformstore.h"
class QPainter;
class QDomDocument;
class QgsComposerHtml;
class QgsComposerLabel;
class QgsComposerLegend;
@ -27,6 +31,7 @@ class QgsComposerMap;
class QgsComposition;
class QgsMapLayer;
class QgsLegendModel;
class QgsMapSettings;
class SERVER_EXPORT QgsWmsConfigParser
@ -56,7 +61,7 @@ class SERVER_EXPORT QgsWmsConfigParser
virtual QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const = 0;
//! Returns if output are MM or PIXEL
virtual QgsMapRenderer::OutputUnits outputUnits() const = 0;
virtual QgsUnitTypes::RenderUnit outputUnits() const = 0;
//! Returns an ID-list of layers which are not queryable (comes from <properties> -> <Identify> -> <disabledLayers in the project file
virtual QStringList identifyDisabledLayers() const = 0;
@ -82,8 +87,8 @@ class SERVER_EXPORT QgsWmsConfigParser
//! Draw text annotation items from the QGIS projectfile
virtual void drawOverlays( QPainter* p, int dpi, int width, int height ) const = 0;
//! Load PAL engine settings from the QGIS projectfile
virtual void loadLabelSettings( QgsLabelingEngineInterface* lbl ) const = 0;
//! Load PAL engine settings into global project instance
virtual void loadLabelSettings() const = 0;
virtual QString serviceUrl() const = 0;
@ -115,15 +120,10 @@ class SERVER_EXPORT QgsWmsConfigParser
virtual void inspireCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0;
//printing
//! Creates a print composition, usually for a GetPrint request. Replaces map and label parameters
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const;
//! Creates a print composition, usually for a GetPrint request. Replaces map and label parameters
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
QgsComposition* createPrintComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, const QMap< QString, QString >& parameterMap, QStringList& highlightLayers ) const;
//! Creates a composition from the project file (probably delegated to the fallback parser)
virtual QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const = 0;
virtual QgsComposition* initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap*>& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const = 0;
//! Adds print capabilities to xml document. ParentElem usually is the <Capabilities> element
virtual void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0;
@ -131,7 +131,7 @@ class SERVER_EXPORT QgsWmsConfigParser
virtual void setScaleDenominator( double denom ) = 0;
virtual void addExternalGMLData( const QString& layerName, QDomDocument* gmlDoc ) = 0;
virtual QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const = 0;
virtual QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const = 0;
virtual int nLayers() const = 0;

View File

@ -468,7 +468,7 @@ bool QgsWmsProjectParser::wmsInspireActivated() const
return inspireActivated;
}
QgsComposition* QgsWmsProjectParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap* >& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlList ) const
QgsComposition* QgsWmsProjectParser::initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap* >& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlList ) const
{
//Create composition from xml
QDomElement composerElem = composerByName( composerTemplate );
@ -483,7 +483,7 @@ QgsComposition* QgsWmsProjectParser::initComposition( const QString& composerTem
return nullptr;
}
QgsComposition* composition = new QgsComposition( mapRenderer->mapSettings() ); //set resolution, paper size from composer element attributes
QgsComposition* composition = new QgsComposition( mapSettings ); //set resolution, paper size from composer element attributes
if ( !composition->readXml( compositionElem, *( mProjectParser->xmlDocument() ) ) )
{
delete composition;
@ -799,7 +799,7 @@ void QgsWmsProjectParser::inspireCapabilities( QDomElement& parentElement, QDomD
parentElement.appendChild( inspireCapabilitiesElem );
}
QList< QPair< QString, QgsLayerCoordinateTransform > > QgsWmsProjectParser::layerCoordinateTransforms() const
QList< QPair< QString, QgsDatumTransformStore::Entry > > QgsWmsProjectParser::layerCoordinateTransforms() const
{
return mProjectParser->layerCoordinateTransforms();
}
@ -1992,9 +1992,9 @@ QDomDocument QgsWmsProjectParser::describeLayer( QStringList& layerList, const Q
return myDocument;
}
QgsMapRenderer::OutputUnits QgsWmsProjectParser::outputUnits() const
QgsUnitTypes::RenderUnit QgsWmsProjectParser::outputUnits() const
{
return QgsMapRenderer::Millimeters;
return QgsUnitTypes::RenderUnit::RenderMillimeters;
}
bool QgsWmsProjectParser::featureInfoWithWktGeometry() const
@ -2233,77 +2233,89 @@ void QgsWmsProjectParser::drawOverlays( QPainter* p, int dpi, int width, int hei
}
}
void QgsWmsProjectParser::loadLabelSettings( QgsLabelingEngineInterface* lbl ) const
void QgsWmsProjectParser::loadLabelSettings() const
{
QgsPalLabeling* pal = dynamic_cast<QgsPalLabeling*>( lbl );
if ( pal )
int searchMethod, nCandPoint, nCandLine, nCandPoly;
bool showingCandidates, drawRectOnly, showingShadowRects, showingAllLabels, showingPartialsLabels, drawOutlineLabels;
readLabelSettings( searchMethod, nCandPoint, nCandLine, nCandPoly, showingCandidates, drawRectOnly, showingShadowRects, showingAllLabels, showingPartialsLabels, drawOutlineLabels );
QgsProject::instance()->writeEntry( "PAL", "/SearchMethod", searchMethod );
QgsProject::instance()->writeEntry( "PAL", "/CandidatesPoint", nCandPoint );
QgsProject::instance()->writeEntry( "PAL", "/CandidatesLine", nCandLine );
QgsProject::instance()->writeEntry( "PAL", "/CandidatesPolygon", nCandPoly );
QgsProject::instance()->writeEntry( "PAL", "/ShowingCandidates", showingCandidates );
QgsProject::instance()->writeEntry( "PAL", "/DrawRectOnly", drawRectOnly );
QgsProject::instance()->writeEntry( "PAL", "/ShowingShadowRects", showingShadowRects );
QgsProject::instance()->writeEntry( "PAL", "/ShowingAllLabels", showingAllLabels );
QgsProject::instance()->writeEntry( "PAL", "/ShowingPartialsLabels", showingPartialsLabels );
QgsProject::instance()->writeEntry( "PAL", "/DrawOutlineLabels", drawOutlineLabels );
}
void QgsWmsProjectParser::readLabelSettings( int& searchMethod, int& nCandPoint, int& nCandLine, int& nCandPoly, bool& showingCandidates, bool& drawRectOnly, bool& showingShadowRects, bool& showingAllLabels, bool& showingPartialsLabels, bool& drawOutlineLabels ) const
{
searchMethod = static_cast< int >( QgsPalLabeling::Chain );
nCandPoint = 8;
nCandLine = 8;
nCandPoly = 8;
showingCandidates = false;
drawRectOnly = false;
showingShadowRects = false;
showingAllLabels = false;
showingPartialsLabels = true;
drawOutlineLabels = true;
QDomElement propertiesElem = mProjectParser->propertiesElem();
if ( propertiesElem.isNull() )
{
QDomElement propertiesElem = mProjectParser->propertiesElem();
if ( propertiesElem.isNull() )
{
return;
}
return;
}
QDomElement palElem = propertiesElem.firstChildElement( QStringLiteral( "PAL" ) );
if ( palElem.isNull() )
{
return;
}
QDomElement palElem = propertiesElem.firstChildElement( "PAL" );
if ( palElem.isNull() )
{
return;
}
//pal::Pal default positions for candidates;
int candPoint, candLine, candPoly;
pal->numCandidatePositions( candPoint, candLine, candPoly );
QDomElement candPointElem = palElem.firstChildElement( "CandidatesPoint" );
if ( !candPointElem.isNull() )
{
nCandPoint = candPointElem.text().toInt();
}
QDomElement candLineElem = palElem.firstChildElement( "CandidatesLine" );
if ( !candLineElem.isNull() )
{
nCandLine = candLineElem.text().toInt();
}
QDomElement candPolyElem = palElem.firstChildElement( "CandidatesPolygon" );
if ( !candPolyElem.isNull() )
{
nCandPoly = candPolyElem.text().toInt();
}
//mCandPoint
QDomElement candPointElem = palElem.firstChildElement( QStringLiteral( "CandidatesPoint" ) );
if ( !candPointElem.isNull() )
{
candPoint = candPointElem.text().toInt();
}
QDomElement showCandElem = palElem.firstChildElement( "ShowingCandidates" );
if ( !showCandElem.isNull() )
{
showingCandidates = showCandElem.text().compare( "true", Qt::CaseInsensitive ) == 0;
}
//mCandLine
QDomElement candLineElem = palElem.firstChildElement( QStringLiteral( "CandidatesLine" ) );
if ( !candLineElem.isNull() )
{
candLine = candLineElem.text().toInt();
}
QDomElement showAllLabelsElem = palElem.firstChildElement( "ShowingAllLabels" );
if ( !showAllLabelsElem.isNull() )
{
showingAllLabels = showAllLabelsElem.text().compare( "true", Qt::CaseInsensitive ) == 0;
}
//mCandPolygon
QDomElement candPolyElem = palElem.firstChildElement( QStringLiteral( "CandidatesPolygon" ) );
if ( !candPolyElem.isNull() )
{
candPoly = candPolyElem.text().toInt();
}
QDomElement showPartialsLabelsElem = palElem.firstChildElement( "ShowingPartialsLabels" );
if ( !showPartialsLabelsElem.isNull() )
{
showingPartialsLabels = showPartialsLabelsElem.text().compare( "true", Qt::CaseInsensitive ) == 0;
}
pal->setNumCandidatePositions( candPoint, candLine, candPoly );
//mShowingCandidates
QDomElement showCandElem = palElem.firstChildElement( QStringLiteral( "ShowingCandidates" ) );
if ( !showCandElem.isNull() )
{
pal->setShowingCandidates( showCandElem.text().compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
}
//mShowingAllLabels
QDomElement showAllLabelsElem = palElem.firstChildElement( QStringLiteral( "ShowingAllLabels" ) );
if ( !showAllLabelsElem.isNull() )
{
pal->setShowingAllLabels( showAllLabelsElem.text().compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
}
//mShowingPartialsLabels
QDomElement showPartialsLabelsElem = palElem.firstChildElement( QStringLiteral( "ShowingPartialsLabels" ) );
if ( !showPartialsLabelsElem.isNull() )
{
pal->setShowingPartialsLabels( showPartialsLabelsElem.text().compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
}
//mDrawOutlineLabels
// TODO: This should probably always be true (already default) for WMS, regardless of any project setting.
// Not much sense to output text-as-text, when text-as-outlines gives better results.
//save settings into global project instance (QgsMapRendererCustomPainterJob reads label settings from there)
pal->saveEngineSettings();
QDomElement drawOutlineLabelsElem = palElem.firstChildElement( "DrawOutlineLabels" );
if ( !drawOutlineLabelsElem.isNull() )
{
drawOutlineLabels = drawOutlineLabelsElem.text().compare( "true", Qt::CaseInsensitive ) == 0;
}
}

View File

@ -28,6 +28,7 @@ class QgsAccessControl;
class QTextDocument;
class QSvgRenderer;
class QgsMapSettings;
class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
{
@ -73,14 +74,14 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
void inspireCapabilities( QDomElement& parentElement, QDomDocument& doc ) const override;
//printing
QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap* >& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const override;
QgsComposition* initComposition( const QString& composerTemplate, const QgsMapSettings& mapSettings, QList< QgsComposerMap* >& mapList, QList< QgsComposerLegend* >& legendList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const override;
void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const override;
//todo: fixme
void setScaleDenominator( double ) override {}
void addExternalGMLData( const QString&, QDomDocument* ) override {}
QList< QPair< QString, QgsLayerCoordinateTransform > > layerCoordinateTransforms() const override;
QList< QPair< QString, QgsDatumTransformStore::Entry > > layerCoordinateTransforms() const override;
//! Fills a layer and a style list. The two list have the same number of entries and the style and the layer at a position belong together (similar to the HTTP parameters 'Layers' and 'Styles'. Returns 0 in case of success
int layersAndStyles( QStringList& layers, QStringList& styles ) const override;
@ -95,7 +96,7 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const override;
//! Returns if output are MM or PIXEL
QgsMapRenderer::OutputUnits outputUnits() const override;
QgsUnitTypes::RenderUnit outputUnits() const override;
//! True if the feature info response should contain the wkt geometry for vector features
bool featureInfoWithWktGeometry() const override;
@ -118,8 +119,8 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
//! Draw text annotation items from the QGIS projectfile
void drawOverlays( QPainter* p, int dpi, int width, int height ) const override;
//! Load PAL engine settings from projectfile
void loadLabelSettings( QgsLabelingEngineInterface* lbl ) const override;
//! Load PAL engine settings into global project instance
void loadLabelSettings() const override;
int nLayers() const override;
@ -182,6 +183,8 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
void cleanupTextAnnotationItems();
QString getCapaServiceUrl( QDomDocument& doc ) const;
void readLabelSettings( int& searchMethod, int& nCandPoint, int& nCandLine, int& nCandPoly, bool& showingCandidates, bool& drawRectOnly, bool& showingShadowRects, bool& showingAllLabels, bool& showingPartialsLabels, bool& drawOutlineLabels ) const;
};
#endif // QGSWMSPROJECTPARSER_H

View File

@ -29,7 +29,6 @@
#include "qgslegendrenderer.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerlegend.h"
#include "qgsmaprenderer.h"
#include "qgsmaptopixel.h"
#include "qgsproject.h"
#include "qgsrasteridentifyresult.h"
@ -52,6 +51,7 @@
#include "qgsserverstreamingdevice.h"
#include "qgsaccesscontrol.h"
#include "qgsfeaturerequest.h"
#include "qgsmaprenderercustompainterjob.h"
#include <QImage>
#include <QPainter>
@ -73,7 +73,6 @@ QgsWmsServer::QgsWmsServer(
, QMap<QString, QString> &parameters
, QgsWmsConfigParser* cp
, QgsRequestHandler* rh
, QgsMapRenderer* renderer
, QgsCapabilitiesCache* capCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, const QgsAccessControl* accessControl
@ -87,16 +86,12 @@ QgsWmsServer::QgsWmsServer(
, accessControl
#endif
)
, mMapRenderer( renderer )
, mCapabilitiesCache( capCache )
, mConfigParser( cp )
, mOwnsConfigParser( false )
, mDrawLegendLayerLabel( true )
, mDrawLegendItemLabel( true )
{
#ifdef HAVE_SERVER_PYTHON_PLUGINS
mMapRenderer->setFeatureFilterProvider( mAccessControl );
#endif
}
QgsWmsServer::QgsWmsServer()
@ -108,7 +103,6 @@ QgsWmsServer::QgsWmsServer()
, nullptr
#endif
)
, mMapRenderer( nullptr )
, mCapabilitiesCache()
, mConfigParser( nullptr )
, mOwnsConfigParser( false )
@ -133,7 +127,7 @@ void QgsWmsServer::cleanupAfterRequest()
void QgsWmsServer::executeRequest()
{
if ( !mMapRenderer || !mConfigParser || !mRequestHandler || !mCapabilitiesCache )
if ( !mConfigParser || !mRequestHandler || !mCapabilitiesCache )
{
return; //TODO: error handling
}
@ -727,7 +721,7 @@ static QgsRectangle _parseBBOX( const QString &bboxStr, bool &ok )
QImage* QgsWmsServer::getLegendGraphics()
{
if ( !mConfigParser || !mMapRenderer )
if ( !mConfigParser )
{
return nullptr;
}
@ -853,15 +847,14 @@ QImage* QgsWmsServer::getLegendGraphics()
}
QgsLayerTreeModel legendModel( &rootGroup );
QList<QgsLayerTreeNode*> rootChildren = rootGroup.children();
if ( scaleDenominator > 0 )
legendModel.setLegendFilterByScale( scaleDenominator );
QgsMapSettings contentBasedMapSettings;
if ( contentBasedLegend )
{
HitTest hitTest;
getMap( &hitTest );
getMap( contentBasedMapSettings, &hitTest );
Q_FOREACH ( QgsLayerTreeNode* node, rootGroup.children() )
{
@ -894,7 +887,7 @@ QImage* QgsWmsServer::getLegendGraphics()
}
// find out DPI
QImage* tmpImage = createImage( 1, 1 );
QImage* tmpImage = createImage( 1, 1, false );
if ( !tmpImage )
return nullptr;
qreal dpmm = tmpImage->dotsPerMeterX() / 1000.0;
@ -916,15 +909,13 @@ QImage* QgsWmsServer::getLegendGraphics()
if ( contentBasedLegend )
{
legendSettings.setMapScale( mMapRenderer->scale() );
double scaleFactor = mMapRenderer->outputUnits() == QgsMapRenderer::Millimeters ? mMapRenderer->outputDpi() / 25.4 : 1.0;
legendSettings.setMmPerMapUnit( 1 / ( mMapRenderer->mapUnitsPerPixel() * scaleFactor ) );
legendSettings.setMapScale( contentBasedMapSettings.scale() );
}
if ( !rule.isEmpty() )
{
//create second image with the right dimensions
QImage* paintImage = createImage( ruleSymbolWidth, ruleSymbolHeight );
QImage* paintImage = createImage( ruleSymbolWidth, ruleSymbolHeight, false );
//go through the items a second time for painting
QPainter p( paintImage );
@ -946,6 +937,7 @@ QImage* QgsWmsServer::getLegendGraphics()
return paintImage;
}
QList<QgsLayerTreeNode*> rootChildren = rootGroup.children();
Q_FOREACH ( QgsLayerTreeNode* node, rootChildren )
{
if ( QgsLayerTree::isLayer( node ) )
@ -985,7 +977,7 @@ QImage* QgsWmsServer::getLegendGraphics()
QSizeF minSize = legendRenderer.minimumSize();
QSize s( minSize.width() * dpmm, minSize.height() * dpmm );
QImage* paintImage = createImage( s.width(), s.height() );
QImage* paintImage = createImage( s.width(), s.height(), false );
QPainter p( paintImage );
p.setRenderHint( QPainter::Antialiasing, true );
@ -1007,40 +999,28 @@ QImage* QgsWmsServer::getLegendGraphics()
}
void QgsWmsServer::runHitTest( QPainter* painter, HitTest& hitTest )
void QgsWmsServer::runHitTest( const QgsMapSettings& mapSettings, QPainter* painter, HitTest& hitTest )
{
QPaintDevice* thePaintDevice = painter->device();
// setup QgsRenderContext in the same way as QgsMapRenderer does
QgsRenderContext context;
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
context.setPainter( painter ); // we are not going to draw anything, but we still need a working painter
context.setRenderingStopped( false );
context.setRasterScaleFactor(( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / mMapRenderer->outputDpi() );
context.setScaleFactor( mMapRenderer->outputUnits() == QgsMapRenderer::Millimeters ? mMapRenderer->outputDpi() / 25.4 : 1.0 );
context.setRendererScale( mMapRenderer->scale() );
context.setMapToPixel( *mMapRenderer->coordinateTransform() );
context.setExtent( mMapRenderer->extent() );
Q_FOREACH ( const QString& layerID, mMapRenderer->layerSet() )
Q_FOREACH ( const QString& layerID, mapSettings.layerIds() )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsProject::instance()->mapLayer( layerID ) );
if ( !vl || !vl->renderer() )
continue;
if ( vl->hasScaleBasedVisibility() && ( mMapRenderer->scale() < vl->minimumScale() || mMapRenderer->scale() > vl->maximumScale() ) )
if ( vl->hasScaleBasedVisibility() && vl->isInScaleRange( mapSettings.scale() ) )
{
hitTest[vl] = SymbolSet(); // no symbols -> will not be shown
continue;
}
if ( mMapRenderer->hasCrsTransformEnabled() )
if ( mapSettings.hasCrsTransformEnabled() )
{
QgsRectangle r1 = mMapRenderer->extent(), r2;
mMapRenderer->splitLayersExtent( vl, r1, r2 );
if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
continue;
context.setCoordinateTransform( mMapRenderer->transformation( vl ) );
context.setExtent( r1 );
QgsCoordinateTransform tr = mapSettings.layerTransform( vl );
context.setCoordinateTransform( tr );
context.setExtent( tr.transformBoundingBox( mapSettings.extent(), QgsCoordinateTransform::ReverseTransform ) );
}
SymbolSet& usedSymbols = hitTest[vl];
@ -1278,7 +1258,8 @@ QDomDocument QgsWmsServer::describeLayer()
QByteArray* QgsWmsServer::getPrint( const QString& formatString )
{
QStringList layersList, stylesList, layerIdList;
QImage* theImage = initializeRendering( layersList, stylesList, layerIdList );
QgsMapSettings mapSettings;
QImage* theImage = initializeRendering( layersList, stylesList, layerIdList, mapSettings );
if ( !theImage )
{
return nullptr;
@ -1299,7 +1280,7 @@ QByteArray* QgsWmsServer::getPrint( const QString& formatString )
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
QScopedPointer< QgsOWSServerFilterRestorer > filterRestorer( new QgsOWSServerFilterRestorer() );
applyRequestedLayerFilters( layersList, filterRestorer->originalFilters() );
applyRequestedLayerFilters( layersList, mapSettings, filterRestorer->originalFilters() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
applyAccessControlLayersFilters( layersList, filterRestorer->originalFilters() );
@ -1322,7 +1303,7 @@ QByteArray* QgsWmsServer::getPrint( const QString& formatString )
applyOpacities( layersList, bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
QStringList highlightLayers;
QgsComposition* c = mConfigParser->createPrintComposition( mParameters[ QStringLiteral( "TEMPLATE" )], mMapRenderer, QMap<QString, QString>( mParameters ), highlightLayers );
QgsComposition* c = mConfigParser->createPrintComposition( mParameters[ QStringLiteral( "TEMPLATE" )], mapSettings, QMap<QString, QString>( mParameters ), highlightLayers );
if ( !c )
{
restoreOpacities( bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
@ -1418,20 +1399,33 @@ QImage* QgsWMSServer::printCompositionToImage( QgsComposition* c ) const
#endif
QImage* QgsWmsServer::getMap( HitTest* hitTest )
{
QgsMapSettings mapSettings;
return getMap( mapSettings, hitTest );
}
QImage* QgsWmsServer::getMap( QgsMapSettings& mapSettings, HitTest* hitTest )
{
if ( !checkMaximumWidthHeight() )
{
throw QgsMapServiceException( QStringLiteral( "Size error" ), QStringLiteral( "The requested map size is too large" ) );
}
QStringList layersList, stylesList, layerIdList;
QImage* theImage = initializeRendering( layersList, stylesList, layerIdList );
QImage* theImage = initializeRendering( layersList, stylesList, layerIdList, mapSettings );
QPainter thePainter( theImage );
thePainter.setRenderHint( QPainter::Antialiasing ); //make it look nicer
QStringList layerSet = mMapRenderer->layerSet();
QStringList highlightLayers = QgsWmsConfigParser::addHighlightLayers( mParameters, layerSet );
mMapRenderer->setLayerSet( layerSet );
QStringList layerSetIds = mapSettings.layerIds();
QStringList highlightLayersId = QgsWmsConfigParser::addHighlightLayers( mParameters, layerSetIds );
QList<QgsMapLayer *> layerSet;
Q_FOREACH ( QString layerSetId, layerSetIds )
{
layerSet.append( QgsProject::instance()->mapLayer( layerSetId ) );
}
mapSettings.setLayers( layerSet );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
Q_FOREACH ( QgsMapLayer *layer, QgsProject::instance()->mapLayers() )
@ -1447,7 +1441,7 @@ QImage* QgsWmsServer::getMap( HitTest* hitTest )
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
QScopedPointer< QgsOWSServerFilterRestorer > filterRestorer( new QgsOWSServerFilterRestorer() );
applyRequestedLayerFilters( layersList, filterRestorer->originalFilters() );
applyRequestedLayerFilters( layersList, mapSettings, filterRestorer->originalFilters() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
applyAccessControlLayersFilters( layersList, filterRestorer->originalFilters() );
@ -1463,10 +1457,14 @@ QImage* QgsWmsServer::getMap( HitTest* hitTest )
applyOpacities( layersList, bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
if ( hitTest )
runHitTest( &thePainter, *hitTest );
runHitTest( mapSettings, &thePainter, *hitTest );
else
{
mMapRenderer->render( &thePainter );
QgsMapRendererCustomPainterJob renderJob( mapSettings, &thePainter );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
renderJob.setFeatureFilterProvider( mAccessControl );
#endif
renderJob.renderSynchronously();
}
if ( mConfigParser )
@ -1477,7 +1475,7 @@ QImage* QgsWmsServer::getMap( HitTest* hitTest )
restoreOpacities( bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
clearFeatureSelections( selectedLayerIdList );
QgsWmsConfigParser::removeHighlightLayers( highlightLayers );
QgsWmsConfigParser::removeHighlightLayers( highlightLayersId );
// QgsMessageLog::logMessage( "clearing filters" );
if ( !hitTest )
@ -1575,7 +1573,7 @@ void QgsWmsServer::getMapAsDxf()
int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
{
if ( !mMapRenderer || !mConfigParser )
if ( !mConfigParser )
{
return 1;
}
@ -1598,25 +1596,26 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
return 0;
}
QgsMapSettings mapSettings;
QImage* outputImage = createImage();
if ( !outputImage )
{
return 1;
}
if ( configureMapRender( outputImage ) != 0 )
if ( configureMapSettings( outputImage, mapSettings ) != 0 )
{
delete outputImage;
return 2;
}
QgsMessageLog::logMessage( "mMapRenderer->extent(): " + mMapRenderer->extent().toString() );
QgsMessageLog::logMessage( QStringLiteral( "mMapRenderer width = %1 height = %2" ).arg( mMapRenderer->outputSize().width() ).arg( mMapRenderer->outputSize().height() ) );
QgsMessageLog::logMessage( QStringLiteral( "mMapRenderer->mapUnitsPerPixel() = %1" ).arg( mMapRenderer->mapUnitsPerPixel() ) );
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings width = %1 height = %2" ).arg( mapSettings.outputSize().width() ).arg( mapSettings.outputSize().height() ) );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings.mapUnitsPerPixel() = %1" ).arg( mapSettings.mapUnitsPerPixel() ) );
//find out the current scale denominator and set it to the SLD parser
QgsScaleCalculator scaleCalc(( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mMapRenderer->destinationCrs().mapUnits() );
QgsRectangle mapExtent = mMapRenderer->extent();
QgsScaleCalculator scaleCalc(( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
QgsRectangle mapExtent = mapSettings.extent();
double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() );
mConfigParser->setScaleDenominator( scaleDenominator );
@ -1688,19 +1687,19 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
else
{
infoPoint.reset( new QgsPoint() );
if ( !infoPointToMapCoordinates( i, j, infoPoint.data(), mMapRenderer ) )
if ( !infoPointToMapCoordinates( i, j, infoPoint.data(), mapSettings ) )
{
return 5;
}
}
//get the layer registered in QgsProject and apply possible filters
( void )layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
//get the layer registered in QgsMapLayerRegistry and apply possible filters
( void )layerSet( layersList, stylesList, mapSettings.destinationCrs() );
//scoped pointer to restore all original layer filters (subsetStrings) when pointer goes out of scope
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
QScopedPointer< QgsOWSServerFilterRestorer > filterRestorer( new QgsOWSServerFilterRestorer() );
applyRequestedLayerFilters( layersList, filterRestorer->originalFilters() );
applyRequestedLayerFilters( layersList, mapSettings, filterRestorer->originalFilters() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
applyAccessControlLayersFilters( layersList, filterRestorer->originalFilters() );
@ -1745,16 +1744,7 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
QStringList nonIdentifiableLayers = mConfigParser->identifyDisabledLayers();
//Render context is needed to determine feature visibility for vector layers
QgsRenderContext renderContext;
if ( mMapRenderer )
{
renderContext.setExtent( mMapRenderer->extent() );
renderContext.setRasterScaleFactor( 1.0 );
renderContext.setMapToPixel( *( mMapRenderer->coordinateTransform() ) );
renderContext.setRendererScale( mMapRenderer->scale() );
renderContext.setScaleFactor( mMapRenderer->outputDpi() / 25.4 );
renderContext.setPainter( nullptr );
}
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
bool sia2045 = mConfigParser->featureInfoFormatSIA2045();
@ -1829,8 +1819,7 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
if ( vectorLayer )
{
if ( featureInfoFromVectorLayer( vectorLayer, infoPoint.data(), featureCount, result, layerElement, mMapRenderer, renderContext,
version, infoFormat, featuresRect ) != 0 )
if ( featureInfoFromVectorLayer( vectorLayer, infoPoint.data(), featureCount, result, layerElement, mapSettings, renderContext, version, infoFormat, featuresRect ) != 0 )
{
continue;
}
@ -1850,8 +1839,8 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
{
continue;
}
QgsPoint layerInfoPoint = mMapRenderer->mapToLayerCoordinates( currentLayer, *( infoPoint.data() ) );
if ( featureInfoFromRasterLayer( rasterLayer, &layerInfoPoint, result, layerElement, version, infoFormat ) != 0 )
QgsPoint layerInfoPoint = mapSettings.mapToLayerCoordinates( currentLayer, *( infoPoint.data() ) );
if ( featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version, infoFormat ) != 0 )
{
continue;
}
@ -1880,7 +1869,7 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( featuresRect, result, 8 );
}
QgsCoordinateReferenceSystem crs = mMapRenderer->destinationCrs();
QgsCoordinateReferenceSystem crs = mapSettings.destinationCrs();
if ( crs.isValid() )
{
boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
@ -1891,7 +1880,7 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
else
{
QDomElement bBoxElem = result.createElement( QStringLiteral( "BoundingBox" ) );
bBoxElem.setAttribute( QStringLiteral( "CRS" ), mMapRenderer->destinationCrs().authid() );
bBoxElem.setAttribute( QStringLiteral( "CRS" ), mapSettings.destinationCrs().authid() );
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( featuresRect->xMinimum(), 8 ) );
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( featuresRect->xMaximum(), 8 ) );
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( featuresRect->yMinimum(), 8 ) );
@ -1913,7 +1902,7 @@ int QgsWmsServer::getFeatureInfo( QDomDocument& result, const QString& version )
return 0;
}
QImage* QgsWmsServer::initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList )
QImage* QgsWmsServer::initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList, QgsMapSettings& mapSettings )
{
if ( !mConfigParser )
{
@ -1921,12 +1910,6 @@ QImage* QgsWmsServer::initializeRendering( QStringList& layersList, QStringList&
return nullptr;
}
if ( !mMapRenderer )
{
QgsMessageLog::logMessage( QStringLiteral( "Error: mMapRenderer is 0" ) );
return nullptr;
}
if ( readLayersAndStyles( layersList, stylesList ) != 0 )
{
QgsMessageLog::logMessage( QStringLiteral( "error reading layers and styles" ) );
@ -1966,30 +1949,36 @@ QImage* QgsWmsServer::initializeRendering( QStringList& layersList, QStringList&
return nullptr;
}
if ( configureMapRender( theImage ) != 0 )
if ( configureMapSettings( theImage, mapSettings ) != 0 )
{
delete theImage;
return nullptr;
}
//find out the current scale denominater and set it to the SLD parser
QgsScaleCalculator scaleCalc(( theImage->logicalDpiX() + theImage->logicalDpiY() ) / 2, mMapRenderer->destinationCrs().mapUnits() );
QgsRectangle mapExtent = mMapRenderer->extent();
QgsScaleCalculator scaleCalc(( theImage->logicalDpiX() + theImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
QgsRectangle mapExtent = mapSettings.extent();
mConfigParser->setScaleDenominator( scaleCalc.calculate( mapExtent, theImage->width() ) );
layerIdList = layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
layerIdList = layerSet( layersList, stylesList, mapSettings.destinationCrs() );
#ifdef QGISDEBUG
QgsMessageLog::logMessage( QStringLiteral( "Number of layers to be rendered. %1" ).arg( layerIdList.count() ) );
#endif
mMapRenderer->setLayerSet( layerIdList );
QList<QgsMapLayer *> layers;
Q_FOREACH ( QString layerId, layerIdList )
{
layers.append( QgsProject::instance()->mapLayer( layerId ) );
}
mapSettings.setLayers( layers );
// load label settings
mConfigParser->loadLabelSettings( mMapRenderer->labelingEngine() );
mConfigParser->loadLabelSettings();
return theImage;
}
QImage* QgsWmsServer::createImage( int width, int height ) const
QImage* QgsWmsServer::createImage( int width, int height, bool useBbox ) const
{
bool conversionSuccess;
@ -2011,23 +2000,26 @@ QImage* QgsWmsServer::createImage( int width, int height ) const
//Adapt width / height if the aspect ratio does not correspond with the BBOX.
//Required by WMS spec. 1.3.
bool bboxOk;
QgsRectangle mapExtent = _parseBBOX( mParameters.value( "BBOX" ), bboxOk );
if ( bboxOk )
if ( useBbox )
{
double mapWidthHeightRatio = mapExtent.width() / mapExtent.height();
double imageWidthHeightRatio = ( double )width / ( double )height;
if ( !qgsDoubleNear( mapWidthHeightRatio, imageWidthHeightRatio, 0.0001 ) )
bool bboxOk;
QgsRectangle mapExtent = _parseBBOX( mParameters.value( "BBOX" ), bboxOk );
if ( bboxOk )
{
if ( mapWidthHeightRatio >= imageWidthHeightRatio )
double mapWidthHeightRatio = mapExtent.width() / mapExtent.height();
double imageWidthHeightRatio = ( double )width / ( double )height;
if ( !qgsDoubleNear( mapWidthHeightRatio, imageWidthHeightRatio, 0.0001 ) )
{
//decrease image height
height = width / mapWidthHeightRatio;
}
else
{
//decrease image width
width = height * mapWidthHeightRatio;
if ( mapWidthHeightRatio >= imageWidthHeightRatio )
{
//decrease image height
height = width / mapWidthHeightRatio;
}
else
{
//decrease image width
width = height * mapWidthHeightRatio;
}
}
}
}
@ -2095,15 +2087,16 @@ QImage* QgsWmsServer::createImage( int width, int height ) const
return theImage;
}
int QgsWmsServer::configureMapRender( const QPaintDevice* paintDevice ) const
int QgsWmsServer::configureMapSettings( const QPaintDevice* paintDevice, QgsMapSettings& mapSettings ) const
{
if ( !mMapRenderer || !paintDevice )
if ( !paintDevice )
{
return 1; //paint device is needed for height, width, dpi
}
mMapRenderer->clearLayerCoordinateTransforms();
mMapRenderer->setOutputSize( QSize( paintDevice->width(), paintDevice->height() ), paintDevice->logicalDpiX() );
mapSettings.datumTransformStore().clear();
mapSettings.setOutputSize( QSize( paintDevice->width(), paintDevice->height() ) );
mapSettings.setOutputDpi( paintDevice->logicalDpiX() );
//map extent
bool bboxOk = true;
@ -2156,24 +2149,12 @@ int QgsWmsServer::configureMapRender( const QPaintDevice* paintDevice ) const
throw QgsMapServiceException( QStringLiteral( "InvalidCRS" ), QStringLiteral( "Could not create output CRS" ) );
}
//read layer coordinate transforms from project file (e.g. ct with special datum shift)
if ( mConfigParser )
{
QList< QPair< QString, QgsLayerCoordinateTransform > > lt = mConfigParser->layerCoordinateTransforms();
QList< QPair< QString, QgsLayerCoordinateTransform > >::const_iterator ltIt = lt.constBegin();
for ( ; ltIt != lt.constEnd(); ++ltIt )
{
QgsLayerCoordinateTransform t = ltIt->second;
mMapRenderer->addLayerCoordinateTransform( ltIt->first, t.srcAuthId, t.destAuthId, t.srcDatumTransform, t.destDatumTransform );
}
}
//then set destinationCrs
mMapRenderer->setDestinationCrs( outputCRS );
mMapRenderer->setProjectionsEnabled( true );
mapSettings.setDestinationCrs( outputCRS );
mapSettings.setCrsTransformEnabled( true );
mapUnits = outputCRS.mapUnits();
}
mMapRenderer->setMapUnits( mapUnits );
mapSettings.setMapUnits( mapUnits );
// Change x- and y- of BBOX for WMS 1.3.0 if axis inverted
QString version = mParameters.value( QStringLiteral( "VERSION" ), QStringLiteral( "1.3.0" ) );
@ -2182,16 +2163,7 @@ int QgsWmsServer::configureMapRender( const QPaintDevice* paintDevice ) const
mapExtent.invert();
}
mMapRenderer->setExtent( mapExtent );
if ( mConfigParser )
{
mMapRenderer->setOutputUnits( mConfigParser->outputUnits() );
}
else
{
mMapRenderer->setOutputUnits( QgsMapRenderer::Pixels ); //SLD units are in pixels normally
}
mapSettings.setExtent( mapExtent );
return 0;
}
@ -2251,23 +2223,23 @@ int QgsWmsServer::initializeSLDParser( QStringList& layersList, QStringList& sty
return 0;
}
bool QgsWmsServer::infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer )
bool QgsWmsServer::infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, const QgsMapSettings& mapSettings )
{
if ( !mapRenderer || !infoPoint )
if ( !infoPoint )
{
return false;
}
//check if i, j are in the pixel range of the image
if ( i < 0 || i > mapRenderer->width() || j < 0 || j > mapRenderer->height() )
if ( i < 0 || i > mapSettings.outputSize().width() || j < 0 || j > mapSettings.outputSize().height() )
{
throw QgsMapServiceException( "InvalidPoint", "I/J parameters not within the pixel range" );
}
double xRes = mapRenderer->extent().width() / mapRenderer->width();
double yRes = mapRenderer->extent().height() / mapRenderer->height();
infoPoint->setX( mapRenderer->extent().xMinimum() + i * xRes + xRes / 2.0 );
infoPoint->setY( mapRenderer->extent().yMaximum() - j * yRes - yRes / 2.0 );
double xRes = mapSettings.extent().width() / mapSettings.outputSize().width();
double yRes = mapSettings.extent().height() / mapSettings.outputSize().height();
infoPoint->setX( mapSettings.extent().xMinimum() + i * xRes + xRes / 2.0 );
infoPoint->setY( mapSettings.extent().yMaximum() - j * yRes - yRes / 2.0 );
return true;
}
@ -2276,20 +2248,20 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
int nFeatures,
QDomDocument& infoDocument,
QDomElement& layerElement,
QgsMapRenderer* mapRender,
const QgsMapSettings& mapSettings,
QgsRenderContext& renderContext,
const QString& version,
const QString& infoFormat,
QgsRectangle* featureBBox ) const
{
if ( !layer || !mapRender )
if ( !layer )
{
return 1;
}
//we need a selection rect (0.01 of map width)
QgsRectangle mapRect = mapRender->extent();
QgsRectangle layerRect = mapRender->mapToLayerCoordinates( layer, mapRect );
QgsRectangle mapRect = mapSettings.extent();
QgsRectangle layerRect = mapSettings.mapToLayerCoordinates( layer, mapRect );
QgsRectangle searchRect;
@ -2297,7 +2269,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
//info point could be 0 in case there is only an attribute filter
if ( infoPoint )
{
searchRect = featureInfoSearchRect( layer, mapRender, renderContext, *infoPoint );
searchRect = featureInfoSearchRect( layer, mapSettings, renderContext, *infoPoint );
}
else if ( mParameters.contains( QStringLiteral( "BBOX" ) ) )
{
@ -2382,7 +2354,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
QgsRectangle box;
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry )
{
box = mapRender->layerExtentToOutputExtent( layer, feature.geometry().boundingBox() );
box = mapSettings.layerExtentToOutputExtent( layer, feature.geometry().boundingBox() );
if ( featureBBox ) //extend feature info bounding box if requested
{
if ( !featureBBoxInitialized && featureBBox->isEmpty() )
@ -2398,9 +2370,9 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
QgsCoordinateReferenceSystem outputCrs = layer->crs();
if ( layer->crs() != mapRender->destinationCrs() && mapRender->hasCrsTransformEnabled() )
if ( layer->crs() != mapSettings.destinationCrs() && mapSettings.hasCrsTransformEnabled() )
{
outputCrs = mapRender->destinationCrs();
outputCrs = mapSettings.destinationCrs();
}
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
@ -2413,7 +2385,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
else if ( !layer->shortName().isEmpty() )
typeName = layer->shortName();
QDomElement elem = createFeatureGML(
&feature, layer, infoDocument, outputCrs, typeName, withGeom, version
&feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, version
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, &attributes
#endif
@ -2471,7 +2443,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
//append feature bounding box to feature info xml
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry && mapRender && mConfigParser )
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry && mConfigParser )
{
QDomElement bBoxElem = infoDocument.createElement( QStringLiteral( "BoundingBox" ) );
bBoxElem.setAttribute( version == QLatin1String( "1.1.1" ) ? "SRS" : "CRS", outputCrs.authid() );
@ -2490,7 +2462,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
{
if ( layer->crs() != outputCrs )
{
QgsCoordinateTransform transform = mapRender->transformation( layer );
QgsCoordinateTransform transform = mapSettings.layerTransform( layer );
if ( transform.isValid() )
geom.transform( transform );
}
@ -2525,6 +2497,7 @@ int QgsWmsServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
int QgsWmsServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
const QgsMapSettings& mapSettings,
const QgsPoint* infoPoint,
QDomDocument& infoDocument,
QDomElement& layerElement,
@ -2548,13 +2521,13 @@ int QgsWmsServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
// use context extent, width height (comes with request) to use WCS cache
// We can only use context if raster is not reprojected, otherwise it is difficult
// to guess correct source resolution
if ( mMapRenderer->hasCrsTransformEnabled() && layer->dataProvider()->crs() != mMapRenderer->destinationCrs() )
if ( mapSettings.hasCrsTransformEnabled() && layer->dataProvider()->crs() != mapSettings.destinationCrs() )
{
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue ).results();
}
else
{
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue, mMapRenderer->extent(), mMapRenderer->outputSize().width(), mMapRenderer->outputSize().height() ).results();
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue, mapSettings.extent(), mapSettings.outputSize().width(), mapSettings.outputSize().height() ).results();
}
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
@ -2578,7 +2551,7 @@ int QgsWmsServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
else if ( !layer->shortName().isEmpty() )
typeName = layer->shortName();
QDomElement elem = createFeatureGML(
&feature, nullptr, infoDocument, layerCrs, typeName, false, version, nullptr );
&feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, version, nullptr );
layerElement.appendChild( elem );
}
else
@ -2662,7 +2635,7 @@ QStringList QgsWmsServer::layerSet( const QStringList &layersList,
}
void QgsWmsServer::applyRequestedLayerFilters( const QStringList& layerList , QHash<QgsMapLayer*, QString>& originalFilters ) const
void QgsWmsServer::applyRequestedLayerFilters( const QStringList& layerList , QgsMapSettings& mapSettings, QHash<QgsMapLayer*, QString>& originalFilters ) const
{
if ( layerList.isEmpty() )
{
@ -2727,7 +2700,7 @@ void QgsWmsServer::applyRequestedLayerFilters( const QStringList& layerList , QH
//No BBOX parameter in request. We use the union of the filtered layer
//to provide the functionality of zooming to selected records via (enhanced) WMS.
if ( mMapRenderer && mMapRenderer->extent().isEmpty() )
if ( mapSettings.extent().isEmpty() )
{
QgsRectangle filterExtent;
QHash<QgsMapLayer*, QString>::const_iterator filterIt = originalFilters.constBegin();
@ -2739,7 +2712,7 @@ void QgsWmsServer::applyRequestedLayerFilters( const QStringList& layerList , QH
continue;
}
QgsRectangle layerExtent = mMapRenderer->layerToMapCoordinates( mapLayer, mapLayer->extent() );
QgsRectangle layerExtent = mapSettings.layerToMapCoordinates( mapLayer, mapLayer->extent() );
if ( filterExtent.isEmpty() )
{
filterExtent = layerExtent;
@ -2749,7 +2722,7 @@ void QgsWmsServer::applyRequestedLayerFilters( const QStringList& layerList , QH
filterExtent.combineExtentWith( layerExtent );
}
}
mMapRenderer->setExtent( filterExtent );
mapSettings.setExtent( filterExtent );
}
}
}
@ -3326,6 +3299,7 @@ QDomElement QgsWmsServer::createFeatureGML(
QgsVectorLayer* layer,
QDomDocument& doc,
QgsCoordinateReferenceSystem& crs,
const QgsMapSettings& mapSettings,
const QString& typeName,
bool withGeom,
int version,
@ -3338,7 +3312,7 @@ QDomElement QgsWmsServer::createFeatureGML(
QgsCoordinateTransform transform;
if ( layer && layer->crs() != crs )
{
transform = mMapRenderer->transformation( layer );
transform = mapSettings.layerTransform( layer );
}
QgsGeometry geom = feat->geometry();
@ -3522,9 +3496,9 @@ int QgsWmsServer::getWMSPrecision( int defaultValue = 8 ) const
return WMSPrecision;
}
QgsRectangle QgsWmsServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const
QgsRectangle QgsWmsServer::featureInfoSearchRect( QgsVectorLayer* ml, const QgsMapSettings& mapSettings, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const
{
if ( !ml || !mr )
if ( !ml )
{
return QgsRectangle();
}
@ -3539,7 +3513,7 @@ QgsRectangle QgsWmsServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRend
}
else
{
mapUnitTolerance = mr->extent().width() / 400.0;
mapUnitTolerance = mapSettings.extent().width() / 400.0;
}
}
else if ( ml->geometryType() == QgsWkbTypes::LineGeometry )
@ -3551,7 +3525,7 @@ QgsRectangle QgsWmsServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRend
}
else
{
mapUnitTolerance = mr->extent().width() / 200.0;
mapUnitTolerance = mapSettings.extent().width() / 200.0;
}
}
else //points
@ -3563,13 +3537,13 @@ QgsRectangle QgsWmsServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRend
}
else
{
mapUnitTolerance = mr->extent().width() / 100.0;
mapUnitTolerance = mapSettings.extent().width() / 100.0;
}
}
QgsRectangle mapRectangle( infoPoint.x() - mapUnitTolerance, infoPoint.y() - mapUnitTolerance,
infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
return( mr->mapToLayerCoordinates( ml, mapRectangle ) );
return( mapSettings.mapToLayerCoordinates( ml, mapRectangle ) );
}
void QgsWmsServer::readFormatOptions( QMap<QString, QString>& formatOptions ) const

View File

@ -33,7 +33,7 @@ class QgsConfigParser;
class QgsFeature;
class QgsFeatureRenderer;
class QgsMapLayer;
class QgsMapRenderer;
class QgsMapSettings;
class QgsPoint;
class QgsRasterLayer;
class QgsRasterRenderer;
@ -61,13 +61,12 @@ class QgsWmsServer: public QgsOWSServer
public:
/** Constructor. Does _NOT_ take ownership of
QgsConfigParser, QgsCapabilitiesCache and QgsMapRenderer*/
QgsConfigParser and QgsCapabilitiesCache*/
QgsWmsServer(
const QString& configFilePath
, QMap<QString, QString> &parameters
, QgsWmsConfigParser* cp
, QgsRequestHandler* rh
, QgsMapRenderer* renderer
, QgsCapabilitiesCache* capCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, const QgsAccessControl* accessControl
@ -95,6 +94,10 @@ class QgsWmsServer: public QgsOWSServer
of the image object). If an instance to existing hit test structure is passed, instead of rendering
it will fill the structure with symbols that would be used for rendering */
QImage* getMap( HitTest* hitTest = nullptr );
/** Identical to getMap( HitTest* hitTest ) and updates the map settings actually used.
@note added in QGIS 3.0 */
QImage* getMap( QgsMapSettings &mapSettings, HitTest* hitTest = nullptr );
//! GetMap request with vector format output. This output is usually symbolized (difference to WFS GetFeature)
void getMapAsDxf();
//! Returns an SLD file with the style of the requested layer. Exception is raised in case of troubles :-)
@ -123,24 +126,25 @@ class QgsWmsServer: public QgsOWSServer
//! Don't use the default constructor
QgsWmsServer();
/** Initializes WMS layers and configures mMapRendering.
/** Initializes WMS layers and configures rendering.
@param layersList out: list with WMS layer names
@param stylesList out: list with WMS style names
@param layerIdList out: list with QGIS layer ids
@return image configured together with mMapRenderer (or 0 in case of error). The calling function takes ownership of the image*/
QImage* initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList );
@return image configured (or 0 in case of error). The calling function takes ownership of the image*/
QImage* initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList, QgsMapSettings& mapSettings );
/** Creates a QImage from the HEIGHT and WIDTH parameters
@param width image width (or -1 if width should be taken from WIDTH wms parameter)
@param height image height (or -1 if height should be taken from HEIGHT wms parameter)
@param useBbox flag to indicate if the BBOX has to be used to adapt aspect ratio
@return 0 in case of error*/
QImage* createImage( int width = -1, int height = -1 ) const;
QImage* createImage( int width = -1, int height = -1, bool useBbox = true ) const;
/** Configures mMapRenderer to the parameters
/** Configures mapSettings to the parameters
HEIGHT, WIDTH, BBOX, CRS.
@param paintDevice the device that is used for painting (for dpi)
@return 0 in case of success*/
int configureMapRender( const QPaintDevice* paintDevice ) const;
int configureMapSettings( const QPaintDevice* paintDevice, QgsMapSettings& mapSettings ) const;
/** Reads the layers and style lists from the parameters LAYERS and STYLES
@return 0 in case of success*/
@ -150,7 +154,7 @@ class QgsWmsServer: public QgsOWSServer
set to the layer and style names according to the SLD
@return 0 in case of success*/
int initializeSLDParser( QStringList& layersList, QStringList& stylesList );
static bool infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer );
static bool infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, const QgsMapSettings& mapSettings );
/** Appends feature info xml for the layer to the layer element of the feature info dom document
@param featureBBox the bounding box of the selected features in output CRS
@ -160,25 +164,26 @@ class QgsWmsServer: public QgsOWSServer
int nFeatures,
QDomDocument& infoDocument,
QDomElement& layerElement,
QgsMapRenderer* mapRender,
const QgsMapSettings& mapSettings,
QgsRenderContext& renderContext,
const QString& version,
const QString& infoFormat,
QgsRectangle* featureBBox = nullptr ) const;
//! Appends feature info xml for the layer to the layer element of the dom document
int featureInfoFromRasterLayer( QgsRasterLayer* layer,
const QgsMapSettings& mapSettings,
const QgsPoint* infoPoint,
QDomDocument& infoDocument,
QDomElement& layerElement,
const QString& version,
const QString& infoFormat ) const;
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a QgsMapRenderer. Usually used in conjunction with readLayersAndStyles
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a renderer. Usually used in conjunction with readLayersAndStyles
@param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;
//! Record which symbols would be used if the map was in the current configuration of mMapRenderer. This is useful for content-based legend
void runHitTest( QPainter* painter, HitTest& hitTest );
//! Record which symbols would be used if the map was in the current configuration of renderer. This is useful for content-based legend
void runHitTest( const QgsMapSettings& mapSettings, QPainter* painter, HitTest& hitTest );
//! Record which symbols within one layer would be rendered with the given renderer context
void runHitTestLayer( QgsVectorLayer* vl, SymbolSet& usedSymbols, QgsRenderContext& context );
@ -197,7 +202,7 @@ class QgsWmsServer: public QgsOWSServer
* to ensure that the original filters are always correctly restored, regardless of whether exceptions
* are thrown or functions are terminated early.
*/
void applyRequestedLayerFilters( const QStringList& layerList, QHash<QgsMapLayer*, QString>& originalFilters ) const;
void applyRequestedLayerFilters( const QStringList& layerList, QgsMapSettings& mapSettings, QHash<QgsMapLayer*, QString>& originalFilters ) const;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -252,8 +257,6 @@ class QgsWmsServer: public QgsOWSServer
void cleanupAfterRequest();
//! Map containing the WMS parameters
QgsMapRenderer* mMapRenderer;
QgsCapabilitiesCache* mCapabilitiesCache;
QgsWmsConfigParser* mConfigParser;
@ -269,6 +272,7 @@ class QgsWmsServer: public QgsOWSServer
QgsVectorLayer* layer,
QDomDocument& doc,
QgsCoordinateReferenceSystem& crs,
const QgsMapSettings& mapSettings,
const QString& typeName,
bool withGeom,
int version,
@ -284,7 +288,7 @@ class QgsWmsServer: public QgsOWSServer
int getWMSPrecision( int defaultValue ) const;
//! Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, const QgsMapSettings& ms, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
//! Reads and extracts the different options in the FORMAT_OPTIONS parameter
void readFormatOptions( QMap<QString, QString>& formatOptions ) const;

View File

@ -53,10 +53,8 @@ class TestQgsServer(unittest.TestCase):
#print("---->%s\t%s == %s" % (line_no, expected_line, response_line))
# Compare attributes
if re.match(RE_ATTRIBUTES, expected_line): # has attrs
expected_attrs = re.findall(RE_ATTRIBUTES, expected_line)
expected_attrs.sort()
response_attrs = re.findall(RE_ATTRIBUTES, response_line)
response_attrs.sort()
expected_attrs = sorted(re.findall(RE_ATTRIBUTES, expected_line))
response_attrs = sorted(re.findall(RE_ATTRIBUTES, response_line))
self.assertEqual(expected_attrs, response_attrs, msg=msg + "\nXML attributes differ at line {0}: {1} != {2}".format(line_no, expected_attrs, response_attrs))
line_no += 1
@ -71,6 +69,10 @@ class TestQgsServer(unittest.TestCase):
def setUp(self):
"""Create the server instance"""
self.testdata_path = unitTestDataPath('qgis_server') + '/'
d = unitTestDataPath('qgis_server_accesscontrol') + '/'
self.projectPath = os.path.join(d, "project.qgs")
# Clean env just to be sure
env_vars = ['QUERY_STRING', 'QGIS_PROJECT_FILE']
for ev in env_vars:
@ -416,6 +418,230 @@ class TestQgsServer(unittest.TestCase):
for id, req in tests:
self.wfs_getfeature_post_compare(id, req)
def test_wms_getmap_order(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Hello,Country",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_LayerOrder")
def test_wms_getmap_srs(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country,Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-151.7,-38.9,51.0,78.0",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:4326"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_SRS")
def test_wms_getmap_style(self):
# default style
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country_Labels",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_StyleDefault")
# custom style
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country_Labels",
"STYLES": "custom",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_StyleCustom")
def test_wms_getmap_filter(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country,Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857",
"FILTER": "Country:\"name\" = 'eurasia'"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_Filter")
def test_wms_getmap_selection(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country,Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"SELECTION": "Country_Labels: 4"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_Selection")
def test_wms_getmap_opacities(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country,Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857",
"OPACITIES": "125, 50"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_Opacities")
def test_wms_getprint_basic(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"map0:LAYERS": "Country,Hello",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Basic")
def test_wms_getprint_srs(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"map0:EXTENT": "-309.015,-133.011,312.179,133.949",
"map0:LAYERS": "Country,Hello",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:4326"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetPrint_SRS")
def test_wms_getprint_scale(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"map0:LAYERS": "Country,Hello",
"map0:SCALE": "36293562",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Scale")
def test_wms_getprint_grid(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"map0:LAYERS": "Country,Hello",
"map0:GRID_INTERVAL_X": "1000000",
"map0:GRID_INTERVAL_Y": "2000000",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Grid")
def test_wms_getprint_rotation(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"map0:LAYERS": "Country,Hello",
"map0:ROTATION": "45",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Rotation")
def test_getLegendGraphics(self):
"""Test that does not return an exception but an image"""
parms = {
@ -429,7 +655,6 @@ class TestQgsServer(unittest.TestCase):
'LAYER': 'testlayer%20èé',
}
qs = '&'.join(["%s=%s" % (k, v) for k, v in parms.items()])
print(qs)
h, r = self.server.handleRequest(qs)
self.assertEqual(-1, h.find(b'Content-Type: text/xml; charset=utf-8'), "Header: %s\nResponse:\n%s" % (h, r))
self.assertNotEqual(-1, h.find(b'Content-Type: image/png'), "Header: %s\nResponse:\n%s" % (h, r))
@ -466,6 +691,132 @@ class TestQgsServer(unittest.TestCase):
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_test_layertitle_false", 250, QSize(10, 10))
def test_wms_GetLegendGraphic_Basic(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello",
"LAYERTITLE": "FALSE",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_Basic")
def test_wms_GetLegendGraphic_BoxSpace(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello",
"LAYERTITLE": "FALSE",
"BOXSPACE": "100",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_BoxSpace")
def test_wms_GetLegendGraphic_SymbolSpace(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello",
"LAYERTITLE": "FALSE",
"SYMBOLSPACE": "100",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_SymbolSpace")
def test_wms_GetLegendGraphic_IconLabelSpace(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello",
"LAYERTITLE": "FALSE",
"ICONLABELSPACE": "100",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_IconLabelSpace")
def test_wms_GetLegendGraphic_SymbolSize(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello",
"LAYERTITLE": "FALSE",
"SYMBOLWIDTH": "50",
"SYMBOLHEIGHT": "30",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_SymbolSize")
def test_wms_GetLegendGraphic_BBox(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello,db_point",
"LAYERTITLE": "FALSE",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"BBOX": "-151.7,-38.9,51.0,78.0",
"CRS": "EPSG:4326"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_BBox")
def test_wms_GetLegendGraphic_BBox2(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetLegendGraphic",
"LAYER": "Country,Hello,db_point",
"LAYERTITLE": "FALSE",
"FORMAT": "image/png",
"HEIGHT": "500",
"WIDTH": "500",
"BBOX": "-76.08,-6.4,-19.38,38.04",
"SRS": "EPSG:4326"
}.items())])
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_BBox2")
def _result(self, data):
headers = {}
for line in data[0].decode('UTF-8').split("\n"):

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

File diff suppressed because it is too large Load Diff