Skip to content

Commit 75f8269

Browse files
committedJun 13, 2014
Merge pull request #1286 from dakcarto/issue-3975_labeling-svg-as-text
Fix for issue 3975, labeling svg as text
2 parents b6d8331 + e257227 commit 75f8269

19 files changed

+317
-148
lines changed
 

‎python/core/qgsmapsettings.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class QgsMapSettings
7272
Flags flags() const;
7373
bool testFlag( Flag flag ) const;
7474

75+
//! sets format of internal QImage
76+
void setOutputImageFormat( QImage::Format format );
77+
//! format of internal QImage, default QImage::Format_ARGB32_Premultiplied
78+
QImage::Format outputImageFormat() const;
79+
7580
bool hasValidSettings() const;
7681
QgsRectangle visibleExtent() const;
7782
double mapUnitsPerPixel() const;

‎python/core/qgspallabeling.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,10 @@ class QgsPalLabeling : QgsLabelingEngineInterface
666666
bool isShowingPartialsLabels() const;
667667
void setShowingPartialsLabels( bool showing );
668668

669+
//! @note added in 2.4
670+
bool isDrawingOutlineLabels() const;
671+
void setDrawingOutlineLabels( bool outline );
672+
669673
// implemented methods from labeling engine interface
670674

671675
//! called when we're going to start with rendering

‎src/app/qgslabelengineconfigdialog.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ QgsLabelEngineConfigDialog::QgsLabelEngineConfigDialog( QWidget* parent )
4646
mShadowDebugRectChkBox->setChecked( lbl.isShowingShadowRectangles() );
4747

4848
chkShowPartialsLabels->setChecked( lbl.isShowingPartialsLabels() );
49+
mDrawOutlinesChkBox->setChecked( lbl.isDrawingOutlineLabels() );
4950
}
5051

5152

@@ -64,6 +65,7 @@ void QgsLabelEngineConfigDialog::onOK()
6465
lbl.setShowingShadowRectangles( mShadowDebugRectChkBox->isChecked() );
6566
lbl.setShowingAllLabels( chkShowAllLabels->isChecked() );
6667
lbl.setShowingPartialsLabels( chkShowPartialsLabels->isChecked() );
68+
lbl.setDrawingOutlineLabels( mDrawOutlinesChkBox->isChecked() );
6769

6870
lbl.saveEngineSettings();
6971

@@ -81,4 +83,5 @@ void QgsLabelEngineConfigDialog::setDefaults()
8183
chkShowAllLabels->setChecked( false );
8284
mShadowDebugRectChkBox->setChecked( false );
8385
chkShowPartialsLabels->setChecked( p.getShowPartial() );
86+
mDrawOutlinesChkBox->setChecked( true );
8487
}

‎src/core/composer/qgscomposermap.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const
186186
jobMapSettings.setMapUnits( ms.mapUnits() );
187187
jobMapSettings.setBackgroundColor( Qt::transparent );
188188
jobMapSettings.setShowSelection( false );
189+
jobMapSettings.setOutputImageFormat( ms.outputImageFormat() );
189190

190191
//set layers to render
191192
QStringList theLayerSet = layersToRender();

‎src/core/composer/qgscomposition.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2428,10 +2428,20 @@ void QgsComposition::deleteAndRemoveMultiFrames()
24282428

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

2441+
// TODO: add option for this in Composer
2442+
// May not work on Windows or non-X11 Linux. Works fine on Mac using QPrinter::NativeFormat
2443+
//printer.setFontEmbeddingEnabled( true );
2444+
24352445
QgsPaintEngineHack::fixEngineFlags( printer.paintEngine() );
24362446
}
24372447

‎src/core/qgsmaprendererjob.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ QgsMapRendererSequentialJob::QgsMapRendererSequentialJob( const QgsMapSettings&
5050
{
5151
QgsDebugMsg( "SEQUENTIAL construct" );
5252

53-
mImage = QImage( mSettings.outputSize(), QImage::Format_ARGB32_Premultiplied );
53+
mImage = QImage( mSettings.outputSize(), mSettings.outputImageFormat() );
5454
}
5555

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

916917
QImage QgsMapRendererJob::composeImage( const QgsMapSettings& settings, const LayerRenderJobs& jobs )
917918
{
918-
QImage image( settings.outputSize(), QImage::Format_ARGB32_Premultiplied );
919+
QImage image( settings.outputSize(), settings.outputImageFormat() );
919920
image.fill( settings.backgroundColor().rgb() );
920921

921922
QPainter painter( &image );

‎src/core/qgsmapsettings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ QgsMapSettings::QgsMapSettings()
2727
, mSelectionColor( Qt::yellow )
2828
, mShowSelection( true )
2929
, mFlags( Antialiasing | UseAdvancedEffects | DrawLabeling )
30+
, mImageFormat( QImage::Format_ARGB32_Premultiplied )
3031
{
3132
updateDerived();
3233

‎src/core/qgsmapsettings.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define QGSMAPSETTINGS_H
33

44
#include <QColor>
5+
#include <QImage>
56
#include <QSize>
67
#include <QStringList>
78

@@ -88,6 +89,11 @@ class CORE_EXPORT QgsMapSettings
8889
Flags flags() const;
8990
bool testFlag( Flag flag ) const;
9091

92+
//! sets format of internal QImage
93+
void setOutputImageFormat( QImage::Format format ) { mImageFormat = format; }
94+
//! format of internal QImage, default QImage::Format_ARGB32_Premultiplied
95+
QImage::Format outputImageFormat() const { return mImageFormat; }
96+
9197
bool hasValidSettings() const;
9298
QgsRectangle visibleExtent() const;
9399
double mapUnitsPerPixel() const;
@@ -178,6 +184,8 @@ class CORE_EXPORT QgsMapSettings
178184

179185
Flags mFlags;
180186

187+
QImage::Format mImageFormat;
188+
181189
// derived properties
182190
bool mValid; //!< whether the actual settings are valid (set in updateDerived())
183191
QgsRectangle mVisibleExtent; //!< extent with some additional white space that matches the output aspect ratio

‎src/core/qgspallabeling.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,6 +3211,7 @@ QgsPalLabeling::QgsPalLabeling()
32113211
mShowingShadowRects = false;
32123212
mShowingAllLabels = false;
32133213
mShowingPartialsLabels = p.getShowPartial();
3214+
mDrawOutlineLabels = true;
32143215
}
32153216

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

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

44664469
// scale for any print output or image saving @ specific dpi
44674470
painter->scale( component.dpiRatio(), component.dpiRatio() );
4468-
_fixQPictureDPI( painter );
4469-
painter->drawPicture( 0, 0, textPict );
4470-
4471-
// regular text draw, for testing optimization
4472-
// painter->setFont( tmpLyr.textFont );
4473-
// painter->setPen( tmpLyr.textColor );
4474-
// painter->drawText( 0, 0, multiLineList.at( i ) );
44754471

4472+
if ( mDrawOutlineLabels )
4473+
{
4474+
// draw outlined text
4475+
_fixQPictureDPI( painter );
4476+
painter->drawPicture( 0, 0, textPict );
4477+
}
4478+
else
4479+
{
4480+
// draw text as text (for SVG and PDF exports)
4481+
painter->setFont( tmpLyr.textFont );
4482+
painter->setPen( tmpLyr.textColor );
4483+
painter->setRenderHint( QPainter::TextAntialiasing );
4484+
painter->drawText( 0, 0, component.text() );
4485+
}
44764486
}
44774487
painter->restore();
44784488
}
@@ -5004,6 +5014,8 @@ void QgsPalLabeling::loadEngineSettings()
50045014
"PAL", "/ShowingAllLabels", false, &saved );
50055015
mShowingPartialsLabels = QgsProject::instance()->readBoolEntry(
50065016
"PAL", "/ShowingPartialsLabels", p.getShowPartial(), &saved );
5017+
mDrawOutlineLabels = QgsProject::instance()->readBoolEntry(
5018+
"PAL", "/DrawOutlineLabels", true, &saved );
50075019
}
50085020

50095021
void QgsPalLabeling::saveEngineSettings()
@@ -5016,6 +5028,7 @@ void QgsPalLabeling::saveEngineSettings()
50165028
QgsProject::instance()->writeEntry( "PAL", "/ShowingShadowRects", mShowingShadowRects );
50175029
QgsProject::instance()->writeEntry( "PAL", "/ShowingAllLabels", mShowingAllLabels );
50185030
QgsProject::instance()->writeEntry( "PAL", "/ShowingPartialsLabels", mShowingPartialsLabels );
5031+
QgsProject::instance()->writeEntry( "PAL", "/DrawOutlineLabels", mDrawOutlineLabels );
50195032
}
50205033

50215034
void QgsPalLabeling::clearEngineSettings()
@@ -5028,6 +5041,7 @@ void QgsPalLabeling::clearEngineSettings()
50285041
QgsProject::instance()->removeEntry( "PAL", "/ShowingShadowRects" );
50295042
QgsProject::instance()->removeEntry( "PAL", "/ShowingAllLabels" );
50305043
QgsProject::instance()->removeEntry( "PAL", "/ShowingPartialsLabels" );
5044+
QgsProject::instance()->removeEntry( "PAL", "/DrawOutlineLabels" );
50315045
}
50325046

50335047
QgsLabelingEngineInterface* QgsPalLabeling::clone()
@@ -5037,6 +5051,7 @@ QgsLabelingEngineInterface* QgsPalLabeling::clone()
50375051
lbl->mShowingCandidates = mShowingCandidates;
50385052
lbl->mShowingShadowRects = mShowingShadowRects;
50395053
lbl->mShowingPartialsLabels = mShowingPartialsLabels;
5054+
lbl->mDrawOutlineLabels = mDrawOutlineLabels;
50405055
return lbl;
50415056
}
50425057

‎src/core/qgspallabeling.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,10 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
740740
bool isShowingPartialsLabels() const { return mShowingPartialsLabels; }
741741
void setShowingPartialsLabels( bool showing ) { mShowingPartialsLabels = showing; }
742742

743+
//! @note added in 2.4
744+
bool isDrawingOutlineLabels() const { return mDrawOutlineLabels; }
745+
void setDrawingOutlineLabels( bool outline ) { mDrawOutlineLabels = outline; }
746+
743747
// implemented methods from labeling engine interface
744748

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

860865
QgsLabelingResults* mResults;
861866
};

‎src/ui/qgsengineconfigdialog.ui

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -215,43 +215,41 @@
215215
<property name="verticalSpacing">
216216
<number>6</number>
217217
</property>
218-
<item row="2" column="0">
219-
<spacer name="horizontalSpacer_3">
218+
<item row="1" column="0" colspan="3">
219+
<widget class="QCheckBox" name="chkShowPartialsLabels">
220+
<property name="text">
221+
<string>Show partials labels</string>
222+
</property>
223+
</widget>
224+
</item>
225+
<item row="5" column="0" colspan="3">
226+
<widget class="QCheckBox" name="mShadowDebugRectChkBox">
227+
<property name="text">
228+
<string>Show shadow rectangles (for debugging)</string>
229+
</property>
230+
</widget>
231+
</item>
232+
<item row="3" column="2">
233+
<spacer name="horizontalSpacer_4">
220234
<property name="orientation">
221235
<enum>Qt::Horizontal</enum>
222236
</property>
223-
<property name="sizeType">
224-
<enum>QSizePolicy::Fixed</enum>
225-
</property>
226237
<property name="sizeHint" stdset="0">
227238
<size>
228-
<width>8</width>
229-
<height>8</height>
239+
<width>0</width>
240+
<height>20</height>
230241
</size>
231242
</property>
232243
</spacer>
233244
</item>
234-
<item row="1" column="0" colspan="3">
235-
<widget class="QCheckBox" name="chkShowAllLabels">
236-
<property name="sizePolicy">
237-
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
238-
<horstretch>0</horstretch>
239-
<verstretch>0</verstretch>
240-
</sizepolicy>
241-
</property>
242-
<property name="text">
243-
<string>Show all labels and features for all layers</string>
244-
</property>
245-
</widget>
246-
</item>
247-
<item row="3" column="0" colspan="3">
245+
<item row="4" column="0" colspan="3">
248246
<widget class="QCheckBox" name="chkShowCandidates">
249247
<property name="text">
250248
<string>Show candidates (for debugging)</string>
251249
</property>
252250
</widget>
253251
</item>
254-
<item row="2" column="1">
252+
<item row="3" column="1">
255253
<widget class="QLabel" name="label_6">
256254
<property name="sizePolicy">
257255
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@@ -264,30 +262,39 @@
264262
</property>
265263
</widget>
266264
</item>
267-
<item row="2" column="2">
268-
<spacer name="horizontalSpacer_4">
265+
<item row="2" column="0" colspan="3">
266+
<widget class="QCheckBox" name="chkShowAllLabels">
267+
<property name="sizePolicy">
268+
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
269+
<horstretch>0</horstretch>
270+
<verstretch>0</verstretch>
271+
</sizepolicy>
272+
</property>
273+
<property name="text">
274+
<string>Show all labels and features for all layers</string>
275+
</property>
276+
</widget>
277+
</item>
278+
<item row="3" column="0">
279+
<spacer name="horizontalSpacer_3">
269280
<property name="orientation">
270281
<enum>Qt::Horizontal</enum>
271282
</property>
283+
<property name="sizeType">
284+
<enum>QSizePolicy::Fixed</enum>
285+
</property>
272286
<property name="sizeHint" stdset="0">
273287
<size>
274-
<width>0</width>
275-
<height>20</height>
288+
<width>8</width>
289+
<height>8</height>
276290
</size>
277291
</property>
278292
</spacer>
279293
</item>
280-
<item row="4" column="0" colspan="3">
281-
<widget class="QCheckBox" name="mShadowDebugRectChkBox">
282-
<property name="text">
283-
<string>Show shadow rectangles (for debugging)</string>
284-
</property>
285-
</widget>
286-
</item>
287294
<item row="0" column="0" colspan="3">
288-
<widget class="QCheckBox" name="chkShowPartialsLabels">
295+
<widget class="QCheckBox" name="mDrawOutlinesChkBox">
289296
<property name="text">
290-
<string>Show partials labels</string>
297+
<string>Draw text as outlines (recommended)</string>
291298
</property>
292299
</widget>
293300
</item>

‎tests/src/python/qgis_local_server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ def get_capabilities(self, params, browser=False):
430430
openInBrowserTab(url)
431431
return False, ''
432432

433-
success = ('perhaps you left off the .qgs extension' in xml or
433+
success = ('error reading the project file' in xml or
434434
'WMS_Capabilities' in xml)
435435
return success, xml
436436

@@ -525,7 +525,7 @@ def get_map(self, params, browser=False):
525525
'No valid PNG output'
526526
)
527527

528-
return success, filepath
528+
return success, filepath, url
529529

530530
def process_params(self, params):
531531
# set all keys to uppercase
@@ -821,7 +821,7 @@ def tearDown(self):
821821
try:
822822
local_srv.check_server_capabilities()
823823
# open resultant png with system
824-
result, png = local_srv.get_map(req_params)
824+
result, png, url = local_srv.get_map(req_params)
825825
finally:
826826
local_srv.shutdown()
827827

‎tests/src/python/test_qgis_local_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def test_convert_param_instances(self):
116116
# @unittest.skip('')
117117
def test_getmap(self):
118118
test_name = 'qgis_local_server'
119-
success, img_path = MAPSERV.get_map(self.getmap_params())
119+
success, img_path, url = MAPSERV.get_map(self.getmap_params())
120120
msg = '\nLocal server get_map failed'
121121
assert success, msg
122122

0 commit comments

Comments
 (0)
Please sign in to comment.