00001
00002 #include "qgssymbollayerv2utils.h"
00003
00004 #include "qgssymbollayerv2.h"
00005 #include "qgssymbollayerv2registry.h"
00006 #include "qgssymbolv2.h"
00007 #include "qgsvectorcolorrampv2.h"
00008
00009 #include "qgslogger.h"
00010 #include "qgsrendercontext.h"
00011
00012 #include <QColor>
00013 #include <QDomNode>
00014 #include <QDomElement>
00015 #include <QIcon>
00016 #include <QPainter>
00017
00018 QString QgsSymbolLayerV2Utils::encodeColor( QColor color )
00019 {
00020 return QString( "%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
00021 }
00022
00023 QColor QgsSymbolLayerV2Utils::decodeColor( QString str )
00024 {
00025 QStringList lst = str.split( "," );
00026 if ( lst.count() < 3 )
00027 {
00028 return QColor();
00029 }
00030 int red, green, blue, alpha;
00031 red = lst[0].toInt();
00032 green = lst[1].toInt();
00033 blue = lst[2].toInt();
00034 alpha = 255;
00035 if ( lst.count() > 3 )
00036 {
00037 alpha = lst[3].toInt();
00038 }
00039 return QColor( red, green, blue, alpha );
00040 }
00041
00042 QString QgsSymbolLayerV2Utils::encodePenStyle( Qt::PenStyle style )
00043 {
00044 switch ( style )
00045 {
00046 case Qt::NoPen: return "no";
00047 case Qt::SolidLine: return "solid";
00048 case Qt::DashLine: return "dash";
00049 case Qt::DotLine: return "dot";
00050 case Qt::DashDotLine: return "dash dot";
00051 case Qt::DashDotDotLine: return "dash dot dot";
00052 default: return "???";
00053 }
00054 }
00055
00056 Qt::PenStyle QgsSymbolLayerV2Utils::decodePenStyle( QString str )
00057 {
00058 if ( str == "no" ) return Qt::NoPen;
00059 if ( str == "solid" ) return Qt::SolidLine;
00060 if ( str == "dash" ) return Qt::DashLine;
00061 if ( str == "dot" ) return Qt::DotLine;
00062 if ( str == "dash dot" ) return Qt::DashDotLine;
00063 if ( str == "dast dot dot" ) return Qt::DashDotDotLine;
00064 return Qt::SolidLine;
00065 }
00066
00067 QString QgsSymbolLayerV2Utils::encodePenJoinStyle( Qt::PenJoinStyle style )
00068 {
00069 switch ( style )
00070 {
00071 case Qt::BevelJoin: return "bevel";
00072 case Qt::MiterJoin: return "miter";
00073 case Qt::RoundJoin: return "round";
00074 default: return "???";
00075 }
00076 }
00077
00078 Qt::PenJoinStyle QgsSymbolLayerV2Utils::decodePenJoinStyle( QString str )
00079 {
00080 if ( str == "bevel" ) return Qt::BevelJoin;
00081 if ( str == "miter" ) return Qt::MiterJoin;
00082 if ( str == "round" ) return Qt::RoundJoin;
00083 return Qt::BevelJoin;
00084 }
00085
00086 QString QgsSymbolLayerV2Utils::encodePenCapStyle( Qt::PenCapStyle style )
00087 {
00088 switch ( style )
00089 {
00090 case Qt::SquareCap: return "square";
00091 case Qt::FlatCap: return "flat";
00092 case Qt::RoundCap: return "round";
00093 default: return "???";
00094 }
00095 }
00096
00097 Qt::PenCapStyle QgsSymbolLayerV2Utils::decodePenCapStyle( QString str )
00098 {
00099 if ( str == "square" ) return Qt::SquareCap;
00100 if ( str == "flat" ) return Qt::FlatCap;
00101 if ( str == "round" ) return Qt::RoundCap;
00102 return Qt::SquareCap;
00103 }
00104
00105
00106 QString QgsSymbolLayerV2Utils::encodeBrushStyle( Qt::BrushStyle style )
00107 {
00108 switch ( style )
00109 {
00110 case Qt::SolidPattern : return "solid";
00111 case Qt::HorPattern : return "horizontal";
00112 case Qt::VerPattern : return "vertical";
00113 case Qt::CrossPattern : return "cross";
00114 case Qt::BDiagPattern : return "b_diagonal";
00115 case Qt::FDiagPattern : return "f_diagonal";
00116 case Qt::DiagCrossPattern : return "diagonal_x";
00117 case Qt::Dense1Pattern : return "dense1";
00118 case Qt::Dense2Pattern : return "dense2";
00119 case Qt::Dense3Pattern : return "dense3";
00120 case Qt::Dense4Pattern : return "dense4";
00121 case Qt::Dense5Pattern : return "dense5";
00122 case Qt::Dense6Pattern : return "dense6";
00123 case Qt::Dense7Pattern : return "dense7";
00124 case Qt::NoBrush : return "no";
00125 default: return "???";
00126 }
00127 }
00128
00129 Qt::BrushStyle QgsSymbolLayerV2Utils::decodeBrushStyle( QString str )
00130 {
00131 if ( str == "solid" ) return Qt::SolidPattern;
00132 if ( str == "horizontal" ) return Qt::HorPattern;
00133 if ( str == "vertical" ) return Qt::VerPattern;
00134 if ( str == "cross" ) return Qt::CrossPattern;
00135 if ( str == "b_diagonal" ) return Qt::BDiagPattern;
00136 if ( str == "f_diagonal" ) return Qt::FDiagPattern;
00137 if ( str == "diagonal_x" ) return Qt::DiagCrossPattern;
00138 if ( str == "dense1" ) return Qt::Dense1Pattern;
00139 if ( str == "dense2" ) return Qt::Dense2Pattern;
00140 if ( str == "dense3" ) return Qt::Dense3Pattern;
00141 if ( str == "dense4" ) return Qt::Dense4Pattern;
00142 if ( str == "dense5" ) return Qt::Dense5Pattern;
00143 if ( str == "dense6" ) return Qt::Dense6Pattern;
00144 if ( str == "dense7" ) return Qt::Dense7Pattern;
00145 if ( str == "no" ) return Qt::NoBrush;
00146 return Qt::SolidPattern;
00147 }
00148
00149 QString QgsSymbolLayerV2Utils::encodePoint( QPointF point )
00150 {
00151 return QString( "%1,%2" ).arg( point.x() ).arg( point.y() );
00152 }
00153
00154 QPointF QgsSymbolLayerV2Utils::decodePoint( QString str )
00155 {
00156 QStringList lst = str.split( ',' );
00157 if ( lst.count() != 2 )
00158 return QPointF( 0, 0 );
00159 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
00160 }
00161
00162 QString QgsSymbolLayerV2Utils::encodeOutputUnit( QgsSymbolV2::OutputUnit unit )
00163 {
00164 switch ( unit )
00165 {
00166 case QgsSymbolV2::MM:
00167 return "MM";
00168 case QgsSymbolV2::MapUnit:
00169 return "MapUnit";
00170 default:
00171 return "MM";
00172 }
00173 }
00174
00175 QgsSymbolV2::OutputUnit QgsSymbolLayerV2Utils::decodeOutputUnit( QString str )
00176 {
00177 if ( str == "MM" )
00178 {
00179 return QgsSymbolV2::MM;
00180 }
00181 else if ( str == "MapUnit" )
00182 {
00183 return QgsSymbolV2::MapUnit;
00184 }
00185
00186
00187 return QgsSymbolV2::MM;
00188 }
00189
00190 QString QgsSymbolLayerV2Utils::encodeRealVector( const QVector<qreal>& v )
00191 {
00192 QString vectorString;
00193 QVector<qreal>::const_iterator it = v.constBegin();
00194 for ( ; it != v.constEnd(); ++it )
00195 {
00196 if ( it != v.constBegin() )
00197 {
00198 vectorString.append( ";" );
00199 }
00200 vectorString.append( QString::number( *it ) );
00201 }
00202 return vectorString;
00203 }
00204
00205 QVector<qreal> QgsSymbolLayerV2Utils::decodeRealVector( const QString& s )
00206 {
00207 QVector<qreal> resultVector;
00208
00209 QStringList realList = s.split( ";" );
00210 QStringList::const_iterator it = realList.constBegin();
00211 for ( ; it != realList.constEnd(); ++it )
00212 {
00213 resultVector.append( it->toDouble() );
00214 }
00215
00216 return resultVector;
00217 }
00218
00219 QIcon QgsSymbolLayerV2Utils::symbolPreviewIcon( QgsSymbolV2* symbol, QSize size )
00220 {
00221 return QIcon( symbolPreviewPixmap( symbol, size ) );
00222 }
00223
00224 QPixmap QgsSymbolLayerV2Utils::symbolPreviewPixmap( QgsSymbolV2* symbol, QSize size )
00225 {
00226 Q_ASSERT( symbol );
00227
00228 QPixmap pixmap( size );
00229 QPainter painter;
00230 painter.begin( &pixmap );
00231 painter.setRenderHint( QPainter::Antialiasing );
00232 painter.eraseRect( QRect( QPoint( 0, 0 ), size ) );
00233 symbol->drawPreviewIcon( &painter, size );
00234 painter.end();
00235 return pixmap;
00236 }
00237
00238
00239 QIcon QgsSymbolLayerV2Utils::symbolLayerPreviewIcon( QgsSymbolLayerV2* layer, QgsSymbolV2::OutputUnit u, QSize size )
00240 {
00241 QPixmap pixmap( size );
00242 QPainter painter;
00243 painter.begin( &pixmap );
00244 painter.setRenderHint( QPainter::Antialiasing );
00245 painter.eraseRect( QRect( QPoint( 0, 0 ), size ) );
00246 QgsRenderContext renderContext = createRenderContext( &painter );
00247 QgsSymbolV2RenderContext symbolContext( renderContext, u );
00248 layer->drawPreviewIcon( symbolContext, size );
00249 painter.end();
00250 return QIcon( pixmap );
00251 }
00252
00253 QIcon QgsSymbolLayerV2Utils::colorRampPreviewIcon( QgsVectorColorRampV2* ramp, QSize size )
00254 {
00255 return QIcon( colorRampPreviewPixmap( ramp, size ) );
00256 }
00257
00258 QPixmap QgsSymbolLayerV2Utils::colorRampPreviewPixmap( QgsVectorColorRampV2* ramp, QSize size )
00259 {
00260 QPixmap pixmap( size );
00261 QPainter painter;
00262 painter.begin( &pixmap );
00263 painter.setRenderHint( QPainter::Antialiasing );
00264 painter.eraseRect( QRect( QPoint( 0, 0 ), size ) );
00265 for ( int i = 0; i < size.width(); i++ )
00266 {
00267 QPen pen( ramp->color(( double ) i / size.width() ) );
00268 painter.setPen( pen );
00269 painter.drawLine( i, 0, i, size.height() - 1 );
00270 }
00271 painter.end();
00272 return pixmap;
00273 }
00274
00275
00276 #include <QPolygonF>
00277
00278 #include <cmath>
00279 #include <cfloat>
00280
00281
00282
00283 static bool lineInfo( QPointF p1, QPointF p2, double& angle, double& t )
00284 {
00285 double x1 = p1.x(), y1 = p1.y(), x2 = p2.x(), y2 = p2.y();
00286
00287 if ( x1 == x2 && y1 == y2 )
00288 return false;
00289
00290
00291 t = ( x1 == x2 ? DBL_MAX : ( y2 - y1 ) / ( x2 - x1 ) );
00292
00293
00294 if ( t == DBL_MAX )
00295 angle = ( y2 > y1 ? M_PI / 2 : M_PI * 3 / 2 );
00296 else if ( t == 0 )
00297 angle = ( x2 > x1 ? 0 : M_PI );
00298 else if ( t >= 0 )
00299 angle = ( y2 > y1 ? atan( t ) : M_PI + atan( t ) );
00300 else
00301 angle = ( y2 > y1 ? M_PI + atan( t ) : atan( t ) );
00302
00303 return true;
00304 }
00305
00306
00307 static QPointF offsetPoint( QPointF pt, double angle, double dist )
00308 {
00309 return QPointF( pt.x() + dist * cos( angle ), pt.y() + dist * sin( angle ) );
00310 }
00311
00312
00313 static QPointF linesIntersection( QPointF p1, double t1, QPointF p2, double t2 )
00314 {
00315
00316 if (( t1 == DBL_MAX && t2 == DBL_MAX ) || fabs( t1 - t2 ) < 0.001 )
00317 return QPointF();
00318
00319 double x, y;
00320 if ( t1 == DBL_MAX || t2 == DBL_MAX )
00321 {
00322
00323
00324 if ( t1 == DBL_MAX )
00325 {
00326 QPointF pSwp = p1; p1 = p2; p2 = pSwp;
00327 double tSwp = t1; t1 = t2; t2 = tSwp;
00328 }
00329
00330 x = p2.x();
00331 }
00332 else
00333 {
00334
00335 x = (( p1.y() - p2.y() ) + t2 * p2.x() - t1 * p1.x() ) / ( t2 - t1 );
00336 }
00337
00338 y = p1.y() + t1 * ( x - p1.x() );
00339 return QPointF( x, y );
00340 }
00341
00342
00343 QPolygonF offsetLine( QPolygonF polyline, double dist )
00344 {
00345 QPolygonF newLine;
00346
00347 if ( polyline.count() < 2 )
00348 return newLine;
00349
00350 double angle = 0.0, t_new, t_old = 0;
00351 QPointF pt_old, pt_new;
00352 QPointF p1 = polyline[0], p2;
00353 bool first_point = true;
00354
00355 for ( int i = 1; i < polyline.count(); i++ )
00356 {
00357 p2 = polyline[i];
00358
00359 if ( !lineInfo( p1, p2, angle, t_new ) )
00360 continue;
00361
00362 pt_new = offsetPoint( p1, angle + M_PI / 2, dist );
00363
00364 if ( ! first_point )
00365 {
00366
00367
00368 QPointF pt_tmp = linesIntersection( pt_old, t_old, pt_new, t_new );
00369 if ( !pt_tmp.isNull() ) pt_new = pt_tmp;
00370 }
00371
00372 newLine.append( pt_new );
00373
00374 pt_old = pt_new;
00375 t_old = t_new;
00376 p1 = p2;
00377 first_point = false;
00378 }
00379
00380
00381 pt_new = offsetPoint( p2, angle + M_PI / 2, dist );
00382 newLine.append( pt_new );
00383 return newLine;
00384 }
00385
00387
00388
00389 QgsSymbolV2* QgsSymbolLayerV2Utils::loadSymbol( QDomElement& element )
00390 {
00391 QgsSymbolLayerV2List layers;
00392 QDomNode layerNode = element.firstChild();
00393
00394 while ( !layerNode.isNull() )
00395 {
00396 QDomElement e = layerNode.toElement();
00397 if ( !e.isNull() )
00398 {
00399 if ( e.tagName() != "layer" )
00400 {
00401 QgsDebugMsg( "unknown tag " + e.tagName() );
00402 }
00403 else
00404 {
00405 QgsSymbolLayerV2* layer = loadSymbolLayer( e );
00406 if ( layer != NULL )
00407 layers.append( layer );
00408 }
00409 }
00410 layerNode = layerNode.nextSibling();
00411 }
00412
00413 if ( layers.count() == 0 )
00414 {
00415 QgsDebugMsg( "no layers for symbol" );
00416 return NULL;
00417 }
00418
00419 QString symbolType = element.attribute( "type" );
00420
00421 QgsSymbolV2* symbol = 0;
00422 if ( symbolType == "line" )
00423 symbol = new QgsLineSymbolV2( layers );
00424 else if ( symbolType == "fill" )
00425 symbol = new QgsFillSymbolV2( layers );
00426 else if ( symbolType == "marker" )
00427 symbol = new QgsMarkerSymbolV2( layers );
00428 else
00429 {
00430 QgsDebugMsg( "unknown symbol type " + symbolType );
00431 return NULL;
00432 }
00433
00434 symbol->setOutputUnit( decodeOutputUnit( element.attribute( "outputUnit" ) ) );
00435 symbol->setAlpha( element.attribute( "alpha", "1.0" ).toDouble() );
00436
00437 return symbol;
00438 }
00439
00440 QgsSymbolLayerV2* QgsSymbolLayerV2Utils::loadSymbolLayer( QDomElement& element )
00441 {
00442 QString layerClass = element.attribute( "class" );
00443 bool locked = element.attribute( "locked" ).toInt();
00444 int pass = element.attribute( "pass" ).toInt();
00445
00446
00447 QgsStringMap props = parseProperties( element );
00448
00449 QgsSymbolLayerV2* layer;
00450 layer = QgsSymbolLayerV2Registry::instance()->createSymbolLayer( layerClass, props );
00451 if ( layer )
00452 {
00453 layer->setLocked( locked );
00454 layer->setRenderingPass( pass );
00455 return layer;
00456 }
00457 else
00458 {
00459 QgsDebugMsg( "unknown class " + layerClass );
00460 return NULL;
00461 }
00462 }
00463
00464 static QString _nameForSymbolType( QgsSymbolV2::SymbolType type )
00465 {
00466 switch ( type )
00467 {
00468 case QgsSymbolV2::Line: return "line";
00469 case QgsSymbolV2::Marker: return "marker";
00470 case QgsSymbolV2::Fill: return "fill";
00471 default: return "";
00472 }
00473 }
00474
00475 QDomElement QgsSymbolLayerV2Utils::saveSymbol( QString name, QgsSymbolV2* symbol, QDomDocument& doc, QgsSymbolV2Map* subSymbols )
00476 {
00477 Q_ASSERT( symbol );
00478
00479 QDomElement symEl = doc.createElement( "symbol" );
00480 symEl.setAttribute( "type", _nameForSymbolType( symbol->type() ) );
00481 symEl.setAttribute( "name", name );
00482 symEl.setAttribute( "outputUnit", encodeOutputUnit( symbol->outputUnit() ) );
00483 symEl.setAttribute( "alpha", symbol->alpha() );
00484 QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
00485 for ( int i = 0; i < symbol->symbolLayerCount(); i++ )
00486 {
00487 QgsSymbolLayerV2* layer = symbol->symbolLayer( i );
00488
00489 QDomElement layerEl = doc.createElement( "layer" );
00490 layerEl.setAttribute( "class", layer->layerType() );
00491 layerEl.setAttribute( "locked", layer->isLocked() );
00492 layerEl.setAttribute( "pass", layer->renderingPass() );
00493
00494 if ( subSymbols != NULL && layer->subSymbol() != NULL )
00495 {
00496 QString subname = QString( "@%1@%2" ).arg( name ).arg( i );
00497 subSymbols->insert( subname, layer->subSymbol() );
00498 }
00499
00500 saveProperties( layer->properties(), doc, layerEl );
00501 symEl.appendChild( layerEl );
00502 }
00503
00504 return symEl;
00505 }
00506
00507
00508 QgsStringMap QgsSymbolLayerV2Utils::parseProperties( QDomElement& element )
00509 {
00510 QgsStringMap props;
00511 QDomElement e = element.firstChildElement();
00512 while ( !e.isNull() )
00513 {
00514 if ( e.tagName() != "prop" )
00515 {
00516 QgsDebugMsg( "unknown tag " + e.tagName() );
00517 }
00518 else
00519 {
00520 QString propKey = e.attribute( "k" );
00521 QString propValue = e.attribute( "v" );
00522 props[propKey] = propValue;
00523 }
00524 e = e.nextSiblingElement();
00525 }
00526 return props;
00527 }
00528
00529
00530 void QgsSymbolLayerV2Utils::saveProperties( QgsStringMap props, QDomDocument& doc, QDomElement& element )
00531 {
00532 for ( QgsStringMap::iterator it = props.begin(); it != props.end(); ++it )
00533 {
00534 QDomElement propEl = doc.createElement( "prop" );
00535 propEl.setAttribute( "k", it.key() );
00536 propEl.setAttribute( "v", it.value() );
00537 element.appendChild( propEl );
00538 }
00539 }
00540
00541 QgsSymbolV2Map QgsSymbolLayerV2Utils::loadSymbols( QDomElement& element )
00542 {
00543
00544
00545 QgsSymbolV2Map symbols;
00546 QDomElement e = element.firstChildElement();
00547
00548 while ( !e.isNull() )
00549 {
00550 if ( e.tagName() == "symbol" )
00551 {
00552 QgsSymbolV2* symbol = QgsSymbolLayerV2Utils::loadSymbol( e );
00553 if ( symbol != NULL )
00554 symbols.insert( e.attribute( "name" ), symbol );
00555 }
00556 else
00557 {
00558 QgsDebugMsg( "unknown tag: " + e.tagName() );
00559 }
00560 e = e.nextSiblingElement();
00561 }
00562
00563
00564
00565
00566
00567 QStringList subsymbols;
00568
00569 for ( QMap<QString, QgsSymbolV2*>::iterator it = symbols.begin(); it != symbols.end(); ++it )
00570 {
00571 if ( it.key()[0] != '@' )
00572 continue;
00573
00574
00575 subsymbols.append( it.key() );
00576
00577 QStringList parts = it.key().split( "@" );
00578 if ( parts.count() < 3 )
00579 {
00580 QgsDebugMsg( "found subsymbol with invalid name: " + it.key() );
00581 delete it.value();
00582 continue;
00583 }
00584 QString symname = parts[1];
00585 int symlayer = parts[2].toInt();
00586
00587 if ( !symbols.contains( symname ) )
00588 {
00589 QgsDebugMsg( "subsymbol references invalid symbol: " + symname );
00590 delete it.value();
00591 continue;
00592 }
00593
00594 QgsSymbolV2* sym = symbols[symname];
00595 if ( symlayer < 0 || symlayer >= sym->symbolLayerCount() )
00596 {
00597 QgsDebugMsg( "subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
00598 delete it.value();
00599 continue;
00600 }
00601
00602
00603 bool res = sym->symbolLayer( symlayer )->setSubSymbol( it.value() );
00604 if ( !res )
00605 {
00606 QgsDebugMsg( "symbol layer refused subsymbol: " + it.key() );
00607 }
00608
00609
00610 }
00611
00612
00613 for ( int i = 0; i < subsymbols.count(); i++ )
00614 symbols.take( subsymbols[i] );
00615
00616 return symbols;
00617 }
00618
00619 QDomElement QgsSymbolLayerV2Utils::saveSymbols( QgsSymbolV2Map& symbols, QString tagName, QDomDocument& doc )
00620 {
00621 QDomElement symbolsElem = doc.createElement( tagName );
00622
00623 QMap<QString, QgsSymbolV2*> subSymbols;
00624
00625
00626 for ( QMap<QString, QgsSymbolV2*>::iterator its = symbols.begin(); its != symbols.end(); ++its )
00627 {
00628 QDomElement symEl = saveSymbol( its.key(), its.value(), doc, &subSymbols );
00629 symbolsElem.appendChild( symEl );
00630 }
00631
00632
00633 for ( QMap<QString, QgsSymbolV2*>::iterator itsub = subSymbols.begin(); itsub != subSymbols.end(); ++itsub )
00634 {
00635 QDomElement subsymEl = saveSymbol( itsub.key(), itsub.value(), doc );
00636 symbolsElem.appendChild( subsymEl );
00637 }
00638
00639 return symbolsElem;
00640 }
00641
00642 void QgsSymbolLayerV2Utils::clearSymbolMap( QgsSymbolV2Map& symbols )
00643 {
00644 foreach( QString name, symbols.keys() )
00645 delete symbols.value( name );
00646 symbols.clear();
00647 }
00648
00649
00650 QgsVectorColorRampV2* QgsSymbolLayerV2Utils::loadColorRamp( QDomElement& element )
00651 {
00652 QString rampType = element.attribute( "type" );
00653
00654
00655 QgsStringMap props = QgsSymbolLayerV2Utils::parseProperties( element );
00656
00657 if ( rampType == "gradient" )
00658 return QgsVectorGradientColorRampV2::create( props );
00659 else if ( rampType == "random" )
00660 return QgsVectorRandomColorRampV2::create( props );
00661 else if ( rampType == "colorbrewer" )
00662 return QgsVectorColorBrewerColorRampV2::create( props );
00663 else
00664 {
00665 QgsDebugMsg( "unknown colorramp type " + rampType );
00666 return NULL;
00667 }
00668 }
00669
00670
00671 QDomElement QgsSymbolLayerV2Utils::saveColorRamp( QString name, QgsVectorColorRampV2* ramp, QDomDocument& doc )
00672 {
00673 QDomElement rampEl = doc.createElement( "colorramp" );
00674 rampEl.setAttribute( "type", ramp->type() );
00675 rampEl.setAttribute( "name", name );
00676
00677 QgsSymbolLayerV2Utils::saveProperties( ramp->properties(), doc, rampEl );
00678 return rampEl;
00679 }
00680
00681 double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
00682 {
00683
00684 if ( u == QgsSymbolV2::MM )
00685 {
00686 return c.scaleFactor();
00687 }
00688 else
00689 {
00690 double mup = c.mapToPixel().mapUnitsPerPixel();
00691 if ( mup > 0 )
00692 {
00693 return 1.0 / mup;
00694 }
00695 else
00696 {
00697 return 1.0;
00698 }
00699 }
00700 }
00701
00702 double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
00703 {
00704 if ( u == QgsSymbolV2::MM )
00705 {
00706 return ( c.scaleFactor() * c.rasterScaleFactor() );
00707 }
00708 else
00709 {
00710 double mup = c.mapToPixel().mapUnitsPerPixel();
00711 if ( mup > 0 )
00712 {
00713 return c.rasterScaleFactor() / c.mapToPixel().mapUnitsPerPixel();
00714 }
00715 else
00716 {
00717 return 1.0;
00718 }
00719 }
00720 }
00721
00722 QgsRenderContext QgsSymbolLayerV2Utils::createRenderContext( QPainter* p )
00723 {
00724 QgsRenderContext context;
00725 context.setPainter( p );
00726 context.setRasterScaleFactor( 1.0 );
00727 if ( p && p->device() )
00728 {
00729 context.setScaleFactor( p->device()->logicalDpiX() / 25.4 );
00730 }
00731 else
00732 {
00733 context.setScaleFactor( 3.465 );
00734 }
00735 return context;
00736 }
00737
00738 void QgsSymbolLayerV2Utils::multiplyImageOpacity( QImage* image, qreal alpha )
00739 {
00740 if ( !image )
00741 {
00742 return;
00743 }
00744
00745 QRgb myRgb;
00746 QImage::Format format = image->format();
00747 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
00748 {
00749 QgsDebugMsg( "no alpha channel." );
00750 return;
00751 }
00752
00753
00754 for ( int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
00755 {
00756 QRgb* scanLine = ( QRgb* )image->scanLine( heightIndex );
00757 for ( int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
00758 {
00759 myRgb = scanLine[widthIndex];
00760 if ( format == QImage::Format_ARGB32_Premultiplied )
00761 scanLine[widthIndex] = qRgba( alpha * qRed( myRgb ), alpha * qGreen( myRgb ), alpha * qBlue( myRgb ), alpha * qAlpha( myRgb ) );
00762 else
00763 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), alpha * qAlpha( myRgb ) );
00764 }
00765 }
00766 }