Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added layer transparency to symbol classes (with the exception of svg…
… marker, where I'm still looking for a solution with QPicture)

git-svn-id: http://svn.osgeo.org/qgis/trunk@12811 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Jan 21, 2010
1 parent 91fb7ed commit 95535cd
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 33 deletions.
11 changes: 9 additions & 2 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp
Expand Up @@ -43,7 +43,9 @@ QString QgsSimpleFillSymbolLayerV2::layerType() const

void QgsSimpleFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
mColor.setAlphaF( context.alpha() );
mBrush = QBrush( mColor, mBrushStyle );
mBorderColor.setAlphaF( context.alpha() );
mPen = QPen( mBorderColor );
mPen.setStyle( mBorderStyle );
mPen.setWidthF( context.outputLineWidth( mBorderWidth ) );
Expand Down Expand Up @@ -162,10 +164,10 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
}

//create QImage with appropriate dimensions
int pixelWidth = context.outputPixelSize( mPatternWidth );//mPatternWidth.value( context, QgsOutputUnit::Pixel );
int pixelWidth = context.outputPixelSize( mPatternWidth );
int pixelHeight = pixelWidth / mSvgViewBox.width() * mSvgViewBox.height();

QImage textureImage( pixelWidth, pixelHeight, QImage::Format_ARGB32_Premultiplied );
QImage textureImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
textureImage.fill( 0 ); // transparent background

//rasterise byte array to image
Expand All @@ -177,6 +179,11 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
}
r.render( &p );

if ( context.alpha() < 1.0 )
{
QgsSymbolLayerV2Utils::multiplyImageOpacity( &textureImage, context.alpha() );
}

QTransform brushTransform;
brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
mBrush.setTextureImage( textureImage );
Expand Down
10 changes: 8 additions & 2 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Expand Up @@ -58,7 +58,9 @@ QString QgsSimpleLineSymbolLayerV2::layerType() const

void QgsSimpleLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
mPen.setColor( mColor );
QColor penColor = mColor;
penColor.setAlphaF( context.alpha() );
mPen.setColor( penColor );
double scaledWidth = context.outputLineWidth( mWidth );
mPen.setWidthF( scaledWidth );
if ( mUseCustomDashPattern && scaledWidth != 0 )
Expand Down Expand Up @@ -242,6 +244,7 @@ void QgsMarkerLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context
// if being rotated, it gets initialized with every line segment
if ( !mRotateMarker )
{
mMarker->setAlpha( context.alpha() );
mMarker->startRender( context.renderContext() );
}
}
Expand Down Expand Up @@ -298,6 +301,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineNoOffset( const QPolygonF& points
// rotate marker (if desired)
if ( mRotateMarker )
{
mMarker->setAlpha( context.alpha() );
mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) );
mMarker->startRender( rc );
}
Expand Down Expand Up @@ -394,7 +398,9 @@ QString QgsLineDecorationSymbolLayerV2::layerType() const

void QgsLineDecorationSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
mPen.setColor( mColor );
QColor penColor = mColor;
penColor.setAlphaF( context.alpha() );
mPen.setColor( penColor );
}

void QgsLineDecorationSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
Expand Down
18 changes: 14 additions & 4 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -164,7 +164,7 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex

double center = (( double ) imageSize / 2 ) + 0.5; // add 1/2 pixel for proper rounding when the figure's coordinates are added

mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32 );
mCache.fill( 0 );

QPainter p;
Expand All @@ -175,6 +175,12 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex
p.translate( QPointF( center, center ) );
drawMarker( &p, context );
p.end();

//opacity
if ( context.alpha() < 1.0 )
{
QgsSymbolLayerV2Utils::multiplyImageOpacity( &mCache, context.alpha() );
}
}

void QgsSimpleMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
Expand Down Expand Up @@ -512,6 +518,8 @@ void QgsFontMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context
mFont = QFont( mFontFamily, MM2POINT( mSize ) );
QFontMetrics fm( mFont );
mChrOffset = QPointF( fm.width( mChr ) / 2, -fm.ascent() / 2 );


}

void QgsFontMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
Expand All @@ -521,15 +529,17 @@ void QgsFontMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
void QgsFontMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
p->setPen( mColor );
QColor penColor = mColor;
penColor.setAlphaF( context.alpha() );
p->setPen( penColor );
p->setFont( mFont );

p->save();
p->translate(point);
p->translate( point );
if ( mAngle != 0 )
p->rotate( mAngle );

p->drawText(-mChrOffset, mChr );
p->drawText( -mChrOffset, mChr );
p->restore();
}

Expand Down
27 changes: 27 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.cpp
Expand Up @@ -414,6 +414,7 @@ QgsSymbolV2* QgsSymbolLayerV2Utils::loadSymbol( QDomElement& element )
}

symbol->setOutputUnit( decodeOutputUnit( element.attribute( "outputUnit" ) ) );
symbol->setAlpha( element.attribute( "alpha", "1.0" ).toDouble() );

return symbol;
}
Expand Down Expand Up @@ -459,6 +460,7 @@ QDomElement QgsSymbolLayerV2Utils::saveSymbol( QString name, QgsSymbolV2* symbol
symEl.setAttribute( "type", _nameForSymbolType( symbol->type() ) );
symEl.setAttribute( "name", name );
symEl.setAttribute( "outputUnit", encodeOutputUnit( symbol->outputUnit() ) );
symEl.setAttribute( "alpha", symbol->alpha() );
QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
for ( int i = 0; i < symbol->symbolLayerCount(); i++ )
{
Expand Down Expand Up @@ -712,3 +714,28 @@ QgsRenderContext QgsSymbolLayerV2Utils::createRenderContext( QPainter* p )
}
return context;
}

void QgsSymbolLayerV2Utils::multiplyImageOpacity( QImage* image, qreal alpha )
{
if ( !image )
{
return;
}

//change the alpha component of every pixel
int widthIndex = 0;
int heightIndex = 0;
QRgb* scanLine = 0;
QRgb myRgb;

for ( ; heightIndex < image->height(); ++heightIndex )
{
scanLine = ( QRgb* )image->scanLine( heightIndex );
widthIndex = 0;
for ( ; widthIndex < image->width(); ++widthIndex )
{
myRgb = image->pixel( widthIndex, heightIndex );
scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), qAlpha( myRgb ) * alpha );
}
}
}
3 changes: 3 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.h
Expand Up @@ -80,6 +80,9 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static QgsRenderContext createRenderContext( QPainter* p );

static QString iconPath( QString iconFile );

/**Multiplies opacity of image pixel values with a (global) transparency value*/
static void multiplyImageOpacity( QImage* image, qreal alpha );
};

class QPolygonF;
Expand Down
19 changes: 11 additions & 8 deletions src/core/symbology-ng/qgssymbolv2.cpp
Expand Up @@ -17,7 +17,7 @@
#include <cmath>

QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers )
: mType( type ), mLayers( layers ), mOutputUnit( MM )
: mType( type ), mLayers( layers ), mOutputUnit( MM ), mAlpha( 1.0 )
{

// check they're all correct symbol layers
Expand Down Expand Up @@ -126,14 +126,14 @@ bool QgsSymbolV2::changeSymbolLayer( int index, QgsSymbolLayerV2* layer )

void QgsSymbolV2::startRender( QgsRenderContext& context )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit );
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
( *it )->startRender( symbolContext );
}

void QgsSymbolV2::stopRender( QgsRenderContext& context )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit );
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
( *it )->stopRender( symbolContext );
}
Expand Down Expand Up @@ -244,8 +244,8 @@ QgsSymbolLayerV2List QgsSymbolV2::cloneLayers() const

////////////////////

QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
: mRenderContext( c ), mOutputUnit( u )
QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha )
: mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha )
{

}
Expand Down Expand Up @@ -331,7 +331,7 @@ double QgsMarkerSymbolV2::size()

void QgsMarkerSymbolV2::renderPoint( const QPointF& point, QgsRenderContext& context, int layer )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit );
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
if ( layer != -1 )
{
if ( layer >= 0 && layer < mLayers.count() )
Expand All @@ -350,6 +350,7 @@ QgsSymbolV2* QgsMarkerSymbolV2::clone() const
{
QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
cloneSymbol->setOutputUnit( mOutputUnit );
cloneSymbol->setAlpha( mAlpha );
return cloneSymbol;
}

Expand Down Expand Up @@ -399,7 +400,7 @@ double QgsLineSymbolV2::width()

void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, QgsRenderContext& context, int layer )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit );
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
if ( layer != -1 )
{
if ( layer >= 0 && layer < mLayers.count() )
Expand All @@ -419,6 +420,7 @@ QgsSymbolV2* QgsLineSymbolV2::clone() const
{
QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
cloneSymbol->setOutputUnit( mOutputUnit );
cloneSymbol->setAlpha( mAlpha );
return cloneSymbol;
}

Expand All @@ -434,7 +436,7 @@ QgsFillSymbolV2::QgsFillSymbolV2( QgsSymbolLayerV2List layers )

void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsRenderContext& context, int layer )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit );
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
if ( layer != -1 )
{
if ( layer >= 0 && layer < mLayers.count() )
Expand All @@ -454,5 +456,6 @@ QgsSymbolV2* QgsFillSymbolV2::clone() const
{
QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
cloneSymbol->setOutputUnit( mOutputUnit );
cloneSymbol->setAlpha( mAlpha );
return cloneSymbol;
}
16 changes: 13 additions & 3 deletions src/core/symbology-ng/qgssymbolv2.h
Expand Up @@ -81,6 +81,9 @@ class CORE_EXPORT QgsSymbolV2
OutputUnit outputUnit() const { return mOutputUnit; }
void setOutputUnit( OutputUnit u ) { mOutputUnit = u; }

qreal alpha() const { return mAlpha; }
void setAlpha( qreal alpha ) { mAlpha = alpha; }

protected:
QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers ); // can't be instantiated

Expand All @@ -90,14 +93,17 @@ class CORE_EXPORT QgsSymbolV2
QgsSymbolLayerV2List mLayers;

OutputUnit mOutputUnit;

/**Symbol opacity (in the range 0 - 1)*/
qreal mAlpha;
};

///////////////////////

class CORE_EXPORT QgsSymbolV2RenderContext
{
public:
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u , qreal alpha = 1.0 );
~QgsSymbolV2RenderContext();

QgsRenderContext& renderContext() { return mRenderContext; }
Expand All @@ -106,12 +112,16 @@ class CORE_EXPORT QgsSymbolV2RenderContext
QgsSymbolV2::OutputUnit outputUnit() const { return mOutputUnit; }
void setOutputUnit( QgsSymbolV2::OutputUnit u ) { mOutputUnit = u; }

double outputLineWidth(double width) const;
double outputPixelSize(double size) const;
qreal alpha() const { return mAlpha; }
void setAlpha( qreal alpha ) { mAlpha = alpha; }

double outputLineWidth( double width ) const;
double outputPixelSize( double size ) const;

private:
QgsRenderContext& mRenderContext;
QgsSymbolV2::OutputUnit mOutputUnit;
qreal mAlpha;
};


Expand Down
34 changes: 27 additions & 7 deletions src/gui/symbology-ng/qgssymbolv2selectordialog.cpp
Expand Up @@ -41,10 +41,17 @@ QgsSymbolV2SelectorDialog::QgsSymbolV2SelectorDialog( QgsSymbolV2* symbol, QgsSt
updateSymbolPreview();
updateSymbolInfo();

// output unit
mSymbolUnitComboBox->blockSignals( true );
mSymbolUnitComboBox->setCurrentIndex( mSymbol->outputUnit() );
mSymbolUnitComboBox->blockSignals( false );
if ( mSymbol )
{
// output unit
mSymbolUnitComboBox->blockSignals( true );
mSymbolUnitComboBox->setCurrentIndex( mSymbol->outputUnit() );
mSymbolUnitComboBox->blockSignals( false );

mOpacitySlider->blockSignals( true );
mOpacitySlider->setValue( symbol->alpha() * 255 );
mOpacitySlider->blockSignals( false );
}

// select correct page in stacked widget
// there's a correspondence between symbol type number and page numbering => exploit it!
Expand Down Expand Up @@ -232,8 +239,21 @@ void QgsSymbolV2SelectorDialog::keyPressEvent( QKeyEvent * e )

void QgsSymbolV2SelectorDialog::on_mSymbolUnitComboBox_currentIndexChanged( const QString & text )
{
mSymbol->setOutputUnit( (QgsSymbolV2::OutputUnit) mSymbolUnitComboBox->currentIndex() );
if ( mSymbol )
{
mSymbol->setOutputUnit(( QgsSymbolV2::OutputUnit ) mSymbolUnitComboBox->currentIndex() );

updateSymbolPreview();
emit symbolModified();
updateSymbolPreview();
emit symbolModified();
}
}

void QgsSymbolV2SelectorDialog::on_mOpacitySlider_valueChanged( int value )
{
if ( mSymbol )
{
mSymbol->setAlpha( value / 255.0 );
updateSymbolPreview();
emit symbolModified();
}
}
1 change: 1 addition & 0 deletions src/gui/symbology-ng/qgssymbolv2selectordialog.h
Expand Up @@ -34,6 +34,7 @@ class GUI_EXPORT QgsSymbolV2SelectorDialog : public QDialog, private Ui::QgsSymb
void setLineWidth( double width );
void addSymbolToStyle();
void on_mSymbolUnitComboBox_currentIndexChanged( const QString & text );
void on_mOpacitySlider_valueChanged( int value );

signals:
void symbolModified();
Expand Down

0 comments on commit 95535cd

Please sign in to comment.