Skip to content

Commit

Permalink
Add drop shadow option to labels
Browse files Browse the repository at this point in the history
- Add option to show debug rectangles for shadows to PAL engine properties
- Add small container class, QgsLabelComponent, for temporal values during generation of label components
- Add static image blurring function to QgsSymbolLayerV2Utils
- Fix rotational offset issue with label backgrounds
  • Loading branch information
dakcarto committed Apr 14, 2013
1 parent 6604d2f commit 8749b29
Show file tree
Hide file tree
Showing 11 changed files with 1,050 additions and 255 deletions.
87 changes: 83 additions & 4 deletions python/core/qgspallabeling.sip
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ class QgsPalLayerSettings
Percent
};

enum ShadowType
{
ShadowLowest = 0,
ShadowText,
ShadowBuffer,
ShadowShape
};

// update mDataDefinedNames QList in constructor when adding/deleting enum value
enum DataDefinedProperties
{
Expand Down Expand Up @@ -172,6 +180,21 @@ class QgsPalLayerSettings
int shapeTransparency;
QPainter::CompositionMode shapeBlendMode;

// drop shadow
bool shadowDraw;
ShadowType shadowUnder;
int shadowOffsetAngle;
double shadowOffsetDist;
SizeUnit shadowOffsetUnits;
bool shadowOffsetGlobal;
double shadowRadius;
SizeUnit shadowRadiusUnits;
bool shadowRadiusAlphaOnly;
int shadowTransparency;
int shadowScale;
QColor shadowColor;
QPainter::CompositionMode shadowBlendMode;

bool formatNumbers;
int decimals;
bool plusSign;
Expand Down Expand Up @@ -228,7 +251,7 @@ class QgsPalLayerSettings
* @param rasterfactor whether to consider oversampling
* @return font pixel size
*/
int sizeToPixel( double size, const QgsRenderContext& c , SizeUnit unit, bool rasterfactor ) const;
int sizeToPixel( double size, const QgsRenderContext& c , SizeUnit unit, bool rasterfactor = false ) const;

/** List of data defined enum names
* @note adding in 1.9
Expand All @@ -249,6 +272,53 @@ class QgsLabelCandidate
double cost;
};

/** \ingroup core
* Maintains current state of more grainular and temporal values when creating/painting
* component parts of an individual label (e.g. buffer, background, shadow, etc.).
*/
class QgsLabelComponent
{
%TypeHeaderCode
#include <qgspallabeling.h>
%End

public:
QgsLabelComponent();

const QString& text();
void setText( const QString& text );

const QgsPoint& origin();
void setOrigin( QgsPoint point );

bool useOrigin() const;
void setUseOrigin( bool use );

double rotation() const;
void setRotation( double rotation );

bool useRotation() const;
void setUseRotation( bool use );

const QgsPoint& center();
void setCenter( QgsPoint point );

bool useCenter() const;
void setUseCenter( bool use );

const QgsPoint& size();
void setSize( QgsPoint point );

const QgsPoint& offset();
void setOffset( QgsPoint point );

const QPicture* picture();
void setPicture( QPicture* picture );

double pictureBuffer() const;
void setPictureBuffer( double buffer );
};

class QgsPalLabeling : QgsLabelingEngineInterface
{
%TypeHeaderCode
Expand Down Expand Up @@ -282,6 +352,9 @@ class QgsPalLabeling : QgsLabelingEngineInterface
void setShowingCandidates( bool showing );
const QList<QgsLabelCandidate>& candidates();

bool isShowingShadowRectangles() const;
void setShowingShadowRectangles( bool showing );

bool isShowingAllLabels() const;
void setShowingAllLabels( bool showing );

Expand Down Expand Up @@ -313,14 +386,20 @@ class QgsPalLabeling : QgsLabelingEngineInterface
/*
void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );
//!drawLabel
void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmplyr, DrawLabelType drawType );
void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType );
*/
static void drawLabelBuffer( QgsRenderContext& context, QString text, const QgsPalLayerSettings& tmpLyr );
static void drawLabelBuffer( QgsRenderContext& context,
QgsLabelComponent component,
const QgsPalLayerSettings& tmpLyr );

static void drawLabelBackground( QgsRenderContext& context,
const QgsPoint& centerPt, double labelRotation, double labelWidth, double labelHeight,
QgsLabelComponent component,
const QgsPalLayerSettings& tmpLyr );

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

//! load/save engine settings to project file
//! @note added in QGIS 1.9
void loadEngineSettings();
Expand Down
5 changes: 5 additions & 0 deletions python/core/symbology-ng/qgssymbollayerv2utils.sip
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ class QgsSymbolLayerV2Utils
/**Multiplies opacity of image pixel values with a (global) transparency value*/
static void multiplyImageOpacity( QImage* image, qreal alpha );

/** Blurs an image in place, e.g. creating Qt-independent drop shadows
* @note added in 1.9
*/
static void blurImageInPlace( QImage& image, const QRect& rect, int radius, bool alphaOnly );

/**Sorts the passed list in requested order*/
static void sortVariantList( QList<QVariant>& list, Qt::SortOrder order );
/**Returns a point on the line from startPoint to directionPoint that is a certain distance away from the starting point*/
Expand Down
5 changes: 3 additions & 2 deletions src/app/qgslabelengineconfigdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ QgsLabelEngineConfigDialog::QgsLabelEngineConfigDialog( QgsPalLabeling* lbl, QWi
spinCandPolygon->setValue( candPolygon );

chkShowCandidates->setChecked( mLBL->isShowingCandidates() );

chkShowAllLabels->setChecked( mLBL->isShowingAllLabels() );
mShadowDebugRectChkBox->setChecked( mLBL->isShowingShadowRectangles() );

mSaveWithProjectChkBox->setChecked( mLBL->isStoredWithProject() );
}
Expand All @@ -56,7 +56,7 @@ void QgsLabelEngineConfigDialog::onOK()
spinCandPolygon->value() );

mLBL->setShowingCandidates( chkShowCandidates->isChecked() );

mLBL->setShowingShadowRectangles( mShadowDebugRectChkBox->isChecked() );
mLBL->setShowingAllLabels( chkShowAllLabels->isChecked() );

if ( mSaveWithProjectChkBox->isChecked() )
Expand All @@ -79,4 +79,5 @@ void QgsLabelEngineConfigDialog::setDefaults()
spinCandPolygon->setValue( p.getPolyP() );
chkShowCandidates->setChecked( false );
chkShowAllLabels->setChecked( false );
mShadowDebugRectChkBox->setChecked( false );
}
35 changes: 34 additions & 1 deletion src/app/qgslabelinggui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,27 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
mShapeCollisionsChkBx->setVisible( false ); // until implemented

// drop shadow
mShadowGrpBx->setVisible( false ); // until implemented
mShadowGrpBx->setChecked( lyr.shadowDraw );
mShadowUnderCmbBx->setCurrentIndex( lyr.shadowUnder );

connect( mShadowOffsetAngleDial, SIGNAL( valueChanged( int ) ), mShadowOffsetAngleSpnBx, SLOT( setValue( int ) ) );
connect( mShadowOffsetAngleSpnBx, SIGNAL( valueChanged( int ) ), mShadowOffsetAngleDial, SLOT( setValue( int ) ) );
mShadowOffsetAngleSpnBx->setValue( lyr.shadowOffsetAngle );
mShadowOffsetSpnBx->setValue( lyr.shadowOffsetDist );
mShadowOffsetUnitsCmbBx->setCurrentIndex( lyr.shadowOffsetUnits - 1 );
mShadowOffsetGlobalChkBx->setChecked( lyr.shadowOffsetGlobal );

mShadowRadiusDblSpnBx->setValue( lyr.shadowRadius );
mShadowRadiusUnitsCmbBx->setCurrentIndex( lyr.shadowRadiusUnits - 1 );
mShadowRadiusAlphaChkBx->setChecked( lyr.shadowRadiusAlphaOnly );

connect( mShadowTranspSlider, SIGNAL( valueChanged( int ) ), mShadowTranspSpnBx, SLOT( setValue( int ) ) );
connect( mShadowTranspSpnBx, SIGNAL( valueChanged( int ) ), mShadowTranspSlider, SLOT( setValue( int ) ) );
mShadowTranspSpnBx->setValue( lyr.shadowTransparency );
mShadowScaleSpnBx->setValue( lyr.shadowScale );

mShadowColorBtn->setColor( lyr.shadowColor );
mShadowBlendCmbBx->setBlendMode( lyr.shadowBlendMode );

updateUi();

Expand Down Expand Up @@ -553,6 +572,20 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.shapeTransparency = mShapeTranspSpinBox->value();
lyr.shapeBlendMode = mShapeBlendCmbBx->blendMode();

// drop shadow
lyr.shadowDraw = mShadowGrpBx->isChecked();
lyr.shadowUnder = ( QgsPalLayerSettings::ShadowType )mShadowUnderCmbBx->currentIndex();
lyr.shadowOffsetAngle = mShadowOffsetAngleSpnBx->value();
lyr.shadowOffsetDist = mShadowOffsetSpnBx->value();
lyr.shadowOffsetUnits = ( QgsPalLayerSettings::SizeUnit )( mShadowOffsetUnitsCmbBx->currentIndex() + 1 );
lyr.shadowOffsetGlobal = mShadowOffsetGlobalChkBx->isChecked();
lyr.shadowRadius = mShadowRadiusDblSpnBx->value();
lyr.shadowRadiusUnits = ( QgsPalLayerSettings::SizeUnit )( mShadowRadiusUnitsCmbBx->currentIndex() + 1 );
lyr.shadowRadiusAlphaOnly = mShadowRadiusAlphaChkBx->isChecked();
lyr.shadowTransparency = mShadowTranspSpnBx->value();
lyr.shadowScale = mShadowScaleSpnBx->value();
lyr.shadowColor = mShadowColorBtn->color();
lyr.shadowBlendMode = mShadowBlendCmbBx->blendMode();

if ( chkFormattedNumbers->isChecked() )
{
Expand Down
8 changes: 7 additions & 1 deletion src/app/qgslabelpreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
Q_UNUSED( e );
QPainter p( this );

// TODO: draw all label components when this preview is an actual map canvas
// for now, only preview label's text and buffer
mTmpLyr->shadowDraw = false;

p.setRenderHint( QPainter::Antialiasing );
p.setFont( font() );
QFontMetrics fm( font() );
Expand All @@ -77,7 +81,9 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
if ( mTmpLyr->bufferSize != 0 )
{
mContext->setPainter( &p );
QgsPalLabeling::drawLabelBuffer( *mContext, text(), *mTmpLyr );
QgsLabelComponent component;
component.setText( text() );
QgsPalLabeling::drawLabelBuffer( *mContext, component, *mTmpLyr );
}

QPainterPath path;
Expand Down
Loading

0 comments on commit 8749b29

Please sign in to comment.