Skip to content

Commit

Permalink
Merge pull request #1286 from dakcarto/issue-3975_labeling-svg-as-text
Browse files Browse the repository at this point in the history
Fix for issue 3975, labeling svg as text
  • Loading branch information
wonder-sk committed Jun 13, 2014
2 parents b6d8331 + e257227 commit 75f8269
Show file tree
Hide file tree
Showing 19 changed files with 317 additions and 148 deletions.
5 changes: 5 additions & 0 deletions python/core/qgsmapsettings.sip
Expand Up @@ -72,6 +72,11 @@ class QgsMapSettings
Flags flags() const;
bool testFlag( Flag flag ) const;

//! sets format of internal QImage
void setOutputImageFormat( QImage::Format format );
//! format of internal QImage, default QImage::Format_ARGB32_Premultiplied
QImage::Format outputImageFormat() const;

bool hasValidSettings() const;
QgsRectangle visibleExtent() const;
double mapUnitsPerPixel() const;
Expand Down
4 changes: 4 additions & 0 deletions python/core/qgspallabeling.sip
Expand Up @@ -666,6 +666,10 @@ class QgsPalLabeling : QgsLabelingEngineInterface
bool isShowingPartialsLabels() const;
void setShowingPartialsLabels( bool showing );

//! @note added in 2.4
bool isDrawingOutlineLabels() const;
void setDrawingOutlineLabels( bool outline );

// implemented methods from labeling engine interface

//! called when we're going to start with rendering
Expand Down
3 changes: 3 additions & 0 deletions src/app/qgslabelengineconfigdialog.cpp
Expand Up @@ -46,6 +46,7 @@ QgsLabelEngineConfigDialog::QgsLabelEngineConfigDialog( QWidget* parent )
mShadowDebugRectChkBox->setChecked( lbl.isShowingShadowRectangles() );

chkShowPartialsLabels->setChecked( lbl.isShowingPartialsLabels() );
mDrawOutlinesChkBox->setChecked( lbl.isDrawingOutlineLabels() );
}


Expand All @@ -64,6 +65,7 @@ void QgsLabelEngineConfigDialog::onOK()
lbl.setShowingShadowRectangles( mShadowDebugRectChkBox->isChecked() );
lbl.setShowingAllLabels( chkShowAllLabels->isChecked() );
lbl.setShowingPartialsLabels( chkShowPartialsLabels->isChecked() );
lbl.setDrawingOutlineLabels( mDrawOutlinesChkBox->isChecked() );

lbl.saveEngineSettings();

Expand All @@ -81,4 +83,5 @@ void QgsLabelEngineConfigDialog::setDefaults()
chkShowAllLabels->setChecked( false );
mShadowDebugRectChkBox->setChecked( false );
chkShowPartialsLabels->setChecked( p.getShowPartial() );
mDrawOutlinesChkBox->setChecked( true );
}
1 change: 1 addition & 0 deletions src/core/composer/qgscomposermap.cpp
Expand Up @@ -186,6 +186,7 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const
jobMapSettings.setMapUnits( ms.mapUnits() );
jobMapSettings.setBackgroundColor( Qt::transparent );
jobMapSettings.setShowSelection( false );
jobMapSettings.setOutputImageFormat( ms.outputImageFormat() );

//set layers to render
QStringList theLayerSet = layersToRender();
Expand Down
12 changes: 11 additions & 1 deletion src/core/composer/qgscomposition.cpp
Expand Up @@ -2428,10 +2428,20 @@ void QgsComposition::deleteAndRemoveMultiFrames()

void QgsComposition::beginPrintAsPDF( QPrinter& printer, const QString& file )
{
printer.setOutputFormat( QPrinter::PdfFormat );
printer.setOutputFileName( file );
// setOutputFormat should come after setOutputFileName, which auto-sets format to QPrinter::PdfFormat.
// [LS] This should be QPrinter::NativeFormat for Mac, otherwise fonts are not embed-able
// and text is not searchable; however, there are several bugs with <= Qt 4.8.5, 5.1.1, 5.2.0:
// https://bugreports.qt-project.org/browse/QTBUG-10094 - PDF font embedding fails
// https://bugreports.qt-project.org/browse/QTBUG-33583 - PDF output converts text to outline
// Also an issue with PDF paper size using QPrinter::NativeFormat on Mac (always outputs portrait letter-size)
printer.setOutputFormat( QPrinter::PdfFormat );
printer.setPaperSize( QSizeF( paperWidth(), paperHeight() ), QPrinter::Millimeter );

// TODO: add option for this in Composer
// May not work on Windows or non-X11 Linux. Works fine on Mac using QPrinter::NativeFormat
//printer.setFontEmbeddingEnabled( true );

QgsPaintEngineHack::fixEngineFlags( printer.paintEngine() );
}

Expand Down
7 changes: 4 additions & 3 deletions src/core/qgsmaprendererjob.cpp
Expand Up @@ -50,7 +50,7 @@ QgsMapRendererSequentialJob::QgsMapRendererSequentialJob( const QgsMapSettings&
{
QgsDebugMsg( "SEQUENTIAL construct" );

mImage = QImage( mSettings.outputSize(), QImage::Format_ARGB32_Premultiplied );
mImage = QImage( mSettings.outputSize(), mSettings.outputImageFormat() );
}

QgsMapRendererSequentialJob::~QgsMapRendererSequentialJob()
Expand Down Expand Up @@ -639,7 +639,8 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
// Flattened image for drawing when a blending mode is set
QImage * mypFlattenedImage = 0;
mypFlattenedImage = new QImage( mSettings.outputSize().width(),
mSettings.outputSize().height(), QImage::Format_ARGB32_Premultiplied );
mSettings.outputSize().height(),
mSettings.outputImageFormat() );
if ( mypFlattenedImage->isNull() )
{
mErrors.append( Error( layerId, "Insufficient memory for image " + QString::number( mSettings.outputSize().width() ) + "x" + QString::number( mSettings.outputSize().height() ) ) );
Expand Down Expand Up @@ -915,7 +916,7 @@ void QgsMapRendererParallelJob::renderLabelsStatic( QgsMapRendererParallelJob* s

QImage QgsMapRendererJob::composeImage( const QgsMapSettings& settings, const LayerRenderJobs& jobs )
{
QImage image( settings.outputSize(), QImage::Format_ARGB32_Premultiplied );
QImage image( settings.outputSize(), settings.outputImageFormat() );
image.fill( settings.backgroundColor().rgb() );

QPainter painter( &image );
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsmapsettings.cpp
Expand Up @@ -27,6 +27,7 @@ QgsMapSettings::QgsMapSettings()
, mSelectionColor( Qt::yellow )
, mShowSelection( true )
, mFlags( Antialiasing | UseAdvancedEffects | DrawLabeling )
, mImageFormat( QImage::Format_ARGB32_Premultiplied )
{
updateDerived();

Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsmapsettings.h
Expand Up @@ -2,6 +2,7 @@
#define QGSMAPSETTINGS_H

#include <QColor>
#include <QImage>
#include <QSize>
#include <QStringList>

Expand Down Expand Up @@ -88,6 +89,11 @@ class CORE_EXPORT QgsMapSettings
Flags flags() const;
bool testFlag( Flag flag ) const;

//! sets format of internal QImage
void setOutputImageFormat( QImage::Format format ) { mImageFormat = format; }
//! format of internal QImage, default QImage::Format_ARGB32_Premultiplied
QImage::Format outputImageFormat() const { return mImageFormat; }

bool hasValidSettings() const;
QgsRectangle visibleExtent() const;
double mapUnitsPerPixel() const;
Expand Down Expand Up @@ -178,6 +184,8 @@ class CORE_EXPORT QgsMapSettings

Flags mFlags;

QImage::Format mImageFormat;

// derived properties
bool mValid; //!< whether the actual settings are valid (set in updateDerived())
QgsRectangle mVisibleExtent; //!< extent with some additional white space that matches the output aspect ratio
Expand Down
35 changes: 25 additions & 10 deletions src/core/qgspallabeling.cpp
Expand Up @@ -3211,6 +3211,7 @@ QgsPalLabeling::QgsPalLabeling()
mShowingShadowRects = false;
mShowingAllLabels = false;
mShowingPartialsLabels = p.getShowPartial();
mDrawOutlineLabels = true;
}

QgsPalLabeling::~QgsPalLabeling()
Expand Down Expand Up @@ -4443,6 +4444,11 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& con
textp.setPen( Qt::NoPen );
textp.setBrush( tmpLyr.textColor );
textp.drawPath( path );
// TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture?
// e.g. some capitalization options, but not others
//textp.setFont( tmpLyr.textFont );
//textp.setPen( tmpLyr.textColor );
//textp.drawText( 0, 0, component.text() );
textp.end();

if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowText )
Expand All @@ -4459,20 +4465,24 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& con
{
painter->setCompositionMode( tmpLyr.blendMode );
}
// painter->setPen( Qt::NoPen );
// painter->setBrush( tmpLyr.textColor );
// painter->drawPath( path );

// scale for any print output or image saving @ specific dpi
painter->scale( component.dpiRatio(), component.dpiRatio() );
_fixQPictureDPI( painter );
painter->drawPicture( 0, 0, textPict );

// regular text draw, for testing optimization
// painter->setFont( tmpLyr.textFont );
// painter->setPen( tmpLyr.textColor );
// painter->drawText( 0, 0, multiLineList.at( i ) );

if ( mDrawOutlineLabels )
{
// draw outlined text
_fixQPictureDPI( painter );
painter->drawPicture( 0, 0, textPict );
}
else
{
// draw text as text (for SVG and PDF exports)
painter->setFont( tmpLyr.textFont );
painter->setPen( tmpLyr.textColor );
painter->setRenderHint( QPainter::TextAntialiasing );
painter->drawText( 0, 0, component.text() );
}
}
painter->restore();
}
Expand Down Expand Up @@ -5004,6 +5014,8 @@ void QgsPalLabeling::loadEngineSettings()
"PAL", "/ShowingAllLabels", false, &saved );
mShowingPartialsLabels = QgsProject::instance()->readBoolEntry(
"PAL", "/ShowingPartialsLabels", p.getShowPartial(), &saved );
mDrawOutlineLabels = QgsProject::instance()->readBoolEntry(
"PAL", "/DrawOutlineLabels", true, &saved );
}

void QgsPalLabeling::saveEngineSettings()
Expand All @@ -5016,6 +5028,7 @@ void QgsPalLabeling::saveEngineSettings()
QgsProject::instance()->writeEntry( "PAL", "/ShowingShadowRects", mShowingShadowRects );
QgsProject::instance()->writeEntry( "PAL", "/ShowingAllLabels", mShowingAllLabels );
QgsProject::instance()->writeEntry( "PAL", "/ShowingPartialsLabels", mShowingPartialsLabels );
QgsProject::instance()->writeEntry( "PAL", "/DrawOutlineLabels", mDrawOutlineLabels );
}

void QgsPalLabeling::clearEngineSettings()
Expand All @@ -5028,6 +5041,7 @@ void QgsPalLabeling::clearEngineSettings()
QgsProject::instance()->removeEntry( "PAL", "/ShowingShadowRects" );
QgsProject::instance()->removeEntry( "PAL", "/ShowingAllLabels" );
QgsProject::instance()->removeEntry( "PAL", "/ShowingPartialsLabels" );
QgsProject::instance()->removeEntry( "PAL", "/DrawOutlineLabels" );
}

QgsLabelingEngineInterface* QgsPalLabeling::clone()
Expand All @@ -5037,6 +5051,7 @@ QgsLabelingEngineInterface* QgsPalLabeling::clone()
lbl->mShowingCandidates = mShowingCandidates;
lbl->mShowingShadowRects = mShowingShadowRects;
lbl->mShowingPartialsLabels = mShowingPartialsLabels;
lbl->mDrawOutlineLabels = mDrawOutlineLabels;
return lbl;
}

Expand Down
5 changes: 5 additions & 0 deletions src/core/qgspallabeling.h
Expand Up @@ -740,6 +740,10 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
bool isShowingPartialsLabels() const { return mShowingPartialsLabels; }
void setShowingPartialsLabels( bool showing ) { mShowingPartialsLabels = showing; }

//! @note added in 2.4
bool isDrawingOutlineLabels() const { return mDrawOutlineLabels; }
void setDrawingOutlineLabels( bool outline ) { mDrawOutlineLabels = outline; }

// implemented methods from labeling engine interface

//! called when we're going to start with rendering
Expand Down Expand Up @@ -856,6 +860,7 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
bool mShowingAllLabels; // whether to avoid collisions or not
bool mShowingShadowRects; // whether to show debugging rectangles for drop shadows
bool mShowingPartialsLabels; // whether to avoid partials labels or not
bool mDrawOutlineLabels; // whether to draw labels as text or outlines

QgsLabelingResults* mResults;
};
Expand Down
77 changes: 42 additions & 35 deletions src/ui/qgsengineconfigdialog.ui
Expand Up @@ -215,43 +215,41 @@
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="2" column="0">
<spacer name="horizontalSpacer_3">
<item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="chkShowPartialsLabels">
<property name="text">
<string>Show partials labels</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="mShadowDebugRectChkBox">
<property name="text">
<string>Show shadow rectangles (for debugging)</string>
</property>
</widget>
</item>
<item row="3" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>8</width>
<height>8</height>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="chkShowAllLabels">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show all labels and features for all layers</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<item row="4" column="0" colspan="3">
<widget class="QCheckBox" name="chkShowCandidates">
<property name="text">
<string>Show candidates (for debugging)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
Expand All @@ -264,30 +262,39 @@
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_4">
<item row="2" column="0" colspan="3">
<widget class="QCheckBox" name="chkShowAllLabels">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show all labels and features for all layers</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
<width>8</width>
<height>8</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<widget class="QCheckBox" name="mShadowDebugRectChkBox">
<property name="text">
<string>Show shadow rectangles (for debugging)</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QCheckBox" name="chkShowPartialsLabels">
<widget class="QCheckBox" name="mDrawOutlinesChkBox">
<property name="text">
<string>Show partials labels</string>
<string>Draw text as outlines (recommended)</string>
</property>
</widget>
</item>
Expand Down
6 changes: 3 additions & 3 deletions tests/src/python/qgis_local_server.py
Expand Up @@ -430,7 +430,7 @@ def get_capabilities(self, params, browser=False):
openInBrowserTab(url)
return False, ''

success = ('perhaps you left off the .qgs extension' in xml or
success = ('error reading the project file' in xml or
'WMS_Capabilities' in xml)
return success, xml

Expand Down Expand Up @@ -525,7 +525,7 @@ def get_map(self, params, browser=False):
'No valid PNG output'
)

return success, filepath
return success, filepath, url

def process_params(self, params):
# set all keys to uppercase
Expand Down Expand Up @@ -821,7 +821,7 @@ def tearDown(self):
try:
local_srv.check_server_capabilities()
# open resultant png with system
result, png = local_srv.get_map(req_params)
result, png, url = local_srv.get_map(req_params)
finally:
local_srv.shutdown()

Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/test_qgis_local_server.py
Expand Up @@ -116,7 +116,7 @@ def test_convert_param_instances(self):
# @unittest.skip('')
def test_getmap(self):
test_name = 'qgis_local_server'
success, img_path = MAPSERV.get_map(self.getmap_params())
success, img_path, url = MAPSERV.get_map(self.getmap_params())
msg = '\nLocal server get_map failed'
assert success, msg

Expand Down

0 comments on commit 75f8269

Please sign in to comment.