Skip to content
Permalink
Browse files

Port DXF labeling to new labeling engine

This code has been funded by Tuscany Region (Italy) - SITA (CIG: 63526840AE) and commissioned to Gis3W s.a.s.
  • Loading branch information
wonder-sk committed Sep 21, 2015
1 parent f0bc2e9 commit c7b394d9b748fa2bcc7d6aa624a9c6b558b9533a
@@ -876,16 +876,42 @@ void QgsDxfExport::writeBlocks()
endSection();
}


void QgsDxfExport::writeEntities()
{
startSection();
writeGroup( 2, "ENTITIES" );

mBlockHandle = QString( "%1" ).arg( mBlockHandles[ "*Model_Space" ], 0, 16 );

QgsRectangle bbox = mExtent.isEmpty() ? dxfExtent() : mExtent;

QgsMapSettings mapSettings;
mapSettings.setMapUnits( mMapUnits );
mapSettings.setExtent( bbox );

int dpi = 96;
double factor = 1000 * dpi / mSymbologyScaleDenominator / 25.4 * QGis::fromUnitToUnitFactor( mMapUnits, QGis::Meters );
mapSettings.setOutputSize( QSize( bbox.width() * factor, bbox.height() * factor ) );
mapSettings.setOutputDpi( dpi );
mapSettings.setCrsTransformEnabled( false );

QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
image.setDotsPerMeterX( 96 / 25.4 * 1000 );
image.setDotsPerMeterY( 96 / 25.4 * 1000 );
QPainter painter( &image );
QgsRenderContext ctx;
ctx.setPainter( &painter );
ctx.setRendererScale( mSymbologyScaleDenominator );
ctx.setExtent( bbox );
ctx.setScaleFactor( 96.0 / 25.4 );
Q_NOWARN_DEPRECATED_PUSH
ctx.setMapToPixel( QgsMapToPixel( 1.0 / factor, bbox.xMinimum(), bbox.yMinimum(), bbox.height() * factor ) );
Q_NOWARN_DEPRECATED_POP

// label engine
QgsDxfPalLabeling labelEngine( this, mExtent.isEmpty() ? dxfExtent() : mExtent, mSymbologyScaleDenominator, mMapUnits );
QgsRenderContext& ctx = labelEngine.renderContext();
QgsLabelingEngineV2 engine;
engine.setMapSettings( mapSettings );

// iterate through the maplayers
QList< QPair< QgsVectorLayer*, int > >::iterator layerIt = mLayers.begin();
@@ -913,7 +939,13 @@ void QgsDxfExport::writeEntities()
attributes << layerAttr;
}

bool labelLayer = labelEngine.prepareLayer( vl, attributes, ctx ) != 0;
QgsDxfLabelProvider* lp = new QgsDxfLabelProvider( vl, this );
engine.addProvider( lp );
if ( !lp->prepare( ctx, attributes ) )
{
engine.removeProvider( lp );
lp = 0;
}

if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology &&
( renderer->capabilities() & QgsFeatureRendererV2::SymbolLevels ) &&
@@ -973,17 +1005,18 @@ void QgsDxfExport::writeEntities()
addFeature( sctx, layerName, s->symbolLayer( 0 ), s );
}

if ( labelLayer )
if ( lp )
{
labelEngine.registerFeature( vl->id(), fet, ctx, layerName );
lp->registerDxfFeature( fet, ctx, layerName );
}
}
}

renderer->stopRender( ctx );
}

labelEngine.drawLabeling( ctx );
engine.run( ctx );

endSection();
}

@@ -18,60 +18,22 @@
#include "qgsdxfpallabeling.h"
#include "qgsdxfexport.h"
#include "qgspalgeometry.h"
#include "qgspallabeling.h"
#include "qgsmapsettings.h"

#include "pal/pointset.h"
#include "pal/labelposition.h"

using namespace pal;

QgsDxfPalLabeling::QgsDxfPalLabeling( QgsDxfExport* dxf, const QgsRectangle& bbox, double scale, QGis::UnitType mapUnits )
: QgsPalLabeling()
QgsDxfLabelProvider::QgsDxfLabelProvider( QgsVectorLayer* layer , QgsDxfExport* dxf )
: QgsVectorLayerLabelProvider( layer, false )
, mDxfExport( dxf )
, mImage( 0 )
, mPainter( 0 )
{
mSettings = new QgsMapSettings;
mSettings->setMapUnits( mapUnits );
mSettings->setExtent( bbox );

int dpi = 96;
double factor = 1000 * dpi / scale / 25.4 * QGis::fromUnitToUnitFactor( mapUnits, QGis::Meters );
mSettings->setOutputSize( QSize( bbox.width() * factor, bbox.height() * factor ) );
mSettings->setOutputDpi( dpi );
mSettings->setCrsTransformEnabled( false );
init( *mSettings );

mImage = new QImage( 10, 10, QImage::Format_ARGB32_Premultiplied );
mImage->setDotsPerMeterX( 96 / 25.4 * 1000 );
mImage->setDotsPerMeterY( 96 / 25.4 * 1000 );
mPainter = new QPainter( mImage );
mRenderContext.setPainter( mPainter );
mRenderContext.setRendererScale( scale );
mRenderContext.setExtent( bbox );
mRenderContext.setScaleFactor( 96.0 / 25.4 );
Q_NOWARN_DEPRECATED_PUSH
mRenderContext.setMapToPixel( QgsMapToPixel( 1.0 / factor, bbox.xMinimum(), bbox.yMinimum(), bbox.height() * factor ) );
Q_NOWARN_DEPRECATED_POP
}

QgsDxfPalLabeling::~QgsDxfPalLabeling()
{
delete mPainter;
delete mImage;
delete mSettings;
}

void QgsDxfPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType, double dpiRatio )
void QgsDxfLabelProvider::drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const
{
Q_UNUSED( context );
Q_UNUSED( drawType );
Q_UNUSED( dpiRatio );

if ( drawType == QgsPalLabeling::LabelBuffer )
{
return;
}

//debug: print label infos
if ( mDxfExport )
@@ -80,20 +42,25 @@ void QgsDxfPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext&
if ( !g )
return;

const QgsPalLayerSettings& tmpLyr = mSettings;

//label text
QString txt = g->text( label->getPartId() );

//angle
double angle = label->getAlpha() * 180 / M_PI;

QgsFeatureId fid = STRING_TO_FID( label->getFeaturePart()->getUID() );
QString dxfLayer = mDxfLayerNames[fid];

//debug: show label rectangle
#if 0
QgsPolyline line;
for ( int i = 0; i < 4; ++i )
{
line.append( QgsPoint( label->getX( i ), label->getY( i ) ) );
}
mDxfExport->writePolyline( line, g->dxfLayer(), "CONTINUOUS", 1, 0.01, true );
mDxfExport->writePolyline( line, dxfLayer, "CONTINUOUS", 1, 0.01, true );
#endif

QString wrapchr = tmpLyr.wrapChar.isEmpty() ? "\n" : tmpLyr.wrapChar;
@@ -168,6 +135,12 @@ void QgsDxfPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext&
.arg( tmpLyr.textFont.bold() ? 1 : 0 )
.arg( label->getHeight() / ( 1 + txt.count( "\\P" ) ) * 0.75 ) );

mDxfExport->writeMText( g->dxfLayer(), txt, QgsPoint( label->getX(), label->getY() ), label->getWidth() * 1.1, angle, tmpLyr.textColor );
mDxfExport->writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth() * 1.1, angle, tmpLyr.textColor );
}
}

void QgsDxfLabelProvider::registerDxfFeature( QgsFeature& feature, const QgsRenderContext& context, const QString& dxfLayerName )
{
registerFeature( feature, context );
mDxfLayerNames[feature.id()] = dxfLayerName;
}
@@ -18,29 +18,34 @@
#ifndef QGSDXFPALLABELING_H
#define QGSDXFPALLABELING_H

#include "qgspallabeling.h"
#include "qgsmaprenderer.h"
#include "qgsrendercontext.h"
#include "qgsvectorlayerlabelprovider.h"

class QgsDxfExport;

class CORE_EXPORT QgsDxfPalLabeling : public QgsPalLabeling

/** Implements a derived label provider internally used for DXF export
*
* Internal class, not in public API. Added in QGIS 2.12
*/
class QgsDxfLabelProvider : public QgsVectorLayerLabelProvider
{
public:
QgsDxfPalLabeling( QgsDxfExport* dxf, const QgsRectangle& bbox, double scale, QGis::UnitType mapUnits );
~QgsDxfPalLabeling();
//! construct the provider
explicit QgsDxfLabelProvider( QgsVectorLayer* layer, QgsDxfExport* dxf );

QgsRenderContext& renderContext() { return mRenderContext; }
void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType, double dpiRatio = 1.0 ) override;
//! re-implementation that writes to DXF file instead of drawing with QPainter
virtual void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const override;

private:
QgsDxfExport* mDxfExport;
QgsRenderContext mRenderContext;
//! registration method that keeps track of DXF layer names of individual features
void registerDxfFeature( QgsFeature& feature, const QgsRenderContext& context, const QString& dxfLayerName );

//only used for render context
QImage* mImage;
QPainter* mPainter;
QgsMapSettings* mSettings;
protected:
//! pointer to parent DXF export where this instance is used
QgsDxfExport* mDxfExport;
//! DXF layer name for each label feature
QMap<QgsFeatureId, QString> mDxfLayerNames;
};

#endif // QGSDXFPALLABELING_H
@@ -153,9 +153,6 @@ class QgsPalGeometry : public PalGeometry
feature.setValid( true );
}

void setDxfLayer( QString dxfLayer ) { mDxfLayer = dxfLayer; }
QString dxfLayer() const { return mDxfLayer; }

protected:
GEOSGeometry* mG;
QString mText;
@@ -175,8 +172,6 @@ class QgsPalGeometry : public PalGeometry

/** Stores attribute values for diagram rendering*/
QgsAttributes mDiagramAttributes;

QString mDxfLayer;
};

#endif //QGSPALGEOMETRY_H
@@ -1471,11 +1471,13 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
// either used in QgsPalLabeling (palLayer is set) or in QgsLabelingEngineV2 (labelFeature is set)
Q_ASSERT( labelFeature );

Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider

if ( !drawLabels )
{
if ( obstacle )
{
registerObstacleFeature( f, context, dxfLayer, labelFeature );
registerObstacleFeature( f, context, QString(), labelFeature );
}
return;
}
@@ -2140,8 +2142,6 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
labelFont.wordSpacing(),
placement == QgsPalLayerSettings::Curved );

lbl->setDxfLayer( dxfLayer );

// record the created geometry - it will be deleted at the end.
geometries.append( lbl );

@@ -2296,6 +2296,8 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext

void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, const QgsRenderContext& context, QString dxfLayer , QgsLabelFeature** obstacleFeature )
{
Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider

mCurFeat = &f;

const QgsGeometry* geom = f.constGeometry();
@@ -2327,8 +2329,6 @@ void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, const QgsRende

QgsPalGeometry* lbl = new QgsPalGeometry( f.id(), QString(), geos_geom_clone );

lbl->setDxfLayer( dxfLayer );

// record the created geometry - it will be deleted at the end.
geometries.append( lbl );

@@ -3278,6 +3278,7 @@ int QgsPalLabeling::addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLaye

void QgsPalLabeling::registerFeature( const QString& layerID, QgsFeature& f, const QgsRenderContext& context, QString dxfLayer )
{
Q_UNUSED( dxfLayer ); // now handled by QgsDxfLabelProvider
if ( QgsVectorLayerLabelProvider* provider = mLabelProviders.value( layerID, 0 ) )
provider->registerFeature( f, context );
}
@@ -3967,9 +3968,6 @@ void QgsPalLabeling::drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* p
drawLabelCandidateRect( lp->getNextPart(), painter, xform, candidates );
}

void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType, double dpiRatio )
{
}

void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context,
const QgsLabelComponent& component,
@@ -886,10 +886,6 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
//! @note not available in python bindings
static void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform, QList<QgsLabelCandidate>* candidates = 0 );

//!drawLabel
//! @note not available in python bindings
virtual void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType, double dpiRatio = 1.0 );

static void drawLabelBuffer( QgsRenderContext& context,
const QgsLabelComponent &component,
const QgsPalLayerSettings& tmpLyr );

0 comments on commit c7b394d

Please sign in to comment.
You can’t perform that action at this time.