23 #include <QApplication>
24 #include <QCoreApplication>
26 #include <QDomDocument>
27 #include <QDomElement>
32 #include <QSvgRenderer>
34 #include <QNetworkReply>
35 #include <QNetworkRequest>
38 outline( Qt::black ), image( 0 ), picture( 0 )
69 size += (
image->width() *
image->height() * 32 );
96 , mLeastRecentEntry( 0 )
97 , mMostRecentEntry( 0 )
103 QMultiHash< QString, QgsSvgCacheEntry* >::iterator it =
mEntryLookup.begin();
120 if ( !currentEntry->
image )
123 double hwRatio = 1.0;
124 if ( r.viewBoxF().width() > 0 )
126 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
128 long cachedDataSize = 0;
129 cachedDataSize += currentEntry->
svgContent.size();
130 cachedDataSize += ( int )( currentEntry->
size * currentEntry->
size * hwRatio * 32 );
134 delete currentEntry->
image;
135 currentEntry->
image = 0;
151 return *( currentEntry->
image );
167 return *( currentEntry->
picture );
199 void QgsSvgCache::containsParams(
const QString& path,
bool& hasFillParam, QColor& defaultFillColor,
bool& hasOutlineParam, QColor& defaultOutlineColor,
200 bool& hasOutlineWidthParam,
double& defaultOutlineWidth )
const
202 defaultFillColor = QColor( Qt::black );
203 defaultOutlineColor = QColor( Qt::black );
204 defaultOutlineWidth = 1.0;
212 QDomElement docElem = svgDoc.documentElement();
213 containsElemParams( docElem, hasFillParam, defaultFillColor, hasOutlineParam, defaultOutlineColor, hasOutlineWidthParam, defaultOutlineWidth );
230 QDomElement docElem = svgDoc.documentElement();
240 QFile svgFile( path );
241 if ( svgFile.exists() )
243 if ( svgFile.open( QIODevice::ReadOnly ) )
245 return svgFile.readAll();
254 if ( !path.contains(
"://" ) )
260 if ( !svgUrl.isValid() )
266 if ( svgUrl.scheme().compare(
"file", Qt::CaseInsensitive ) == 0 )
268 svgFile.setFileName( svgUrl.toLocalFile() );
269 if ( svgFile.exists() )
271 if ( svgFile.open( QIODevice::ReadOnly ) )
273 return svgFile.readAll();
282 QNetworkReply *reply = 0;
289 QgsDebugMsg( QString(
"get svg: %1" ).arg( svgUrl.toString() ) );
290 QNetworkRequest request( svgUrl );
291 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
292 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
301 while ( !reply->isFinished() )
303 QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, 500 );
306 if ( reply->error() != QNetworkReply::NoError )
308 QgsMessageLog::logMessage(
tr(
"SVG request failed [error: %1 - url: %2]" ).arg( reply->errorString() ).arg( reply->url().toString() ),
tr(
"SVG" ) );
310 reply->deleteLater();
314 QVariant redirect = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
315 if ( redirect.isNull() )
323 svgUrl = redirect.toUrl();
324 reply->deleteLater();
327 QVariant status = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
328 if ( !status.isNull() && status.toInt() >= 400 )
330 QVariant phrase = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute );
331 QgsMessageLog::logMessage(
tr(
"SVG request error [status: %1 - reason phrase: %2]" ).arg( status.toInt() ).arg( phrase.toString() ),
tr(
"SVG" ) );
333 reply->deleteLater();
337 QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
339 if ( !contentType.startsWith(
"image/svg+xml", Qt::CaseInsensitive ) )
341 reply->deleteLater();
346 QByteArray ba = reply->readAll();
347 reply->deleteLater();
363 double hwRatio = 1.0;
364 if ( r.viewBoxF().width() > 0 )
366 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
368 double wSize = entry->
size;
369 int wImgSize = ( int )wSize;
374 double hSize = wSize * hwRatio;
375 int hImgSize = ( int )hSize;
381 QImage* image =
new QImage( wImgSize, hImgSize, QImage::Format_ARGB32_Premultiplied );
385 if ( r.viewBoxF().width() == r.viewBoxF().height() )
391 QSizeF s( r.viewBoxF().size() );
392 s.scale( wSize, hSize, Qt::KeepAspectRatio );
393 QRectF rect(( wImgSize - s.width() ) / 2, ( hImgSize - s.height() ) / 2, s.width(), s.height() );
394 r.render( &p, rect );
397 entry->
image = image;
398 mTotalSize += ( image->width() * image->height() * 32 );
412 QPicture* picture =
new QPicture();
415 double hwRatio = 1.0;
416 if ( r.viewBoxF().width() > 0 )
418 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
421 if ( drawOnScreen && forceVectorOutput )
424 double wSize = entry->
size;
425 double hSize = wSize * hwRatio;
426 QSizeF s( r.viewBoxF().size() );
427 s.scale( wSize, hSize, Qt::KeepAspectRatio );
428 rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );
434 double wSize = scaledSize * picture->logicalDpiX();
435 double hSize = scaledSize * picture->logicalDpiY() * r.viewBoxF().height() / r.viewBoxF().width();
436 rect = QRectF( QPointF( -wSize / 2.0, -hSize / 2.0 ), QSizeF( wSize, hSize ) );
439 QPainter p( picture );
440 r.render( &p, rect );
450 QList<QgsSvgCacheEntry*> entries =
mEntryLookup.values( file );
452 QList<QgsSvgCacheEntry*>::iterator entryIt = entries.begin();
453 for ( ; entryIt != entries.end(); ++entryIt )
468 currentEntry =
insertSVG( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );
501 QDomNamedNodeMap attributes = elem.attributes();
502 int nAttributes = attributes.count();
503 for (
int i = 0; i < nAttributes; ++i )
505 QDomAttr attribute = attributes.item( i ).toAttr();
507 if ( attribute.name().compare(
"style", Qt::CaseInsensitive ) == 0 )
510 QString newAttributeString;
512 QStringList entryList = attribute.value().split(
';' );
513 QStringList::const_iterator entryIt = entryList.constBegin();
514 for ( ; entryIt != entryList.constEnd(); ++entryIt )
516 QStringList keyValueSplit = entryIt->split(
':' );
517 if ( keyValueSplit.size() < 2 )
521 QString key = keyValueSplit.at( 0 );
522 QString value = keyValueSplit.at( 1 );
523 if ( value.startsWith(
"param(fill" ) )
527 else if ( value.startsWith(
"param(outline)" ) )
529 value = outline.name();
531 else if ( value.startsWith(
"param(outline-width)" ) )
533 value = QString::number( outlineWidth );
536 if ( entryIt != entryList.constBegin() )
538 newAttributeString.append(
";" );
540 newAttributeString.append( key +
":" + value );
542 elem.setAttribute( attribute.name(), newAttributeString );
546 QString value = attribute.value();
547 if ( value.startsWith(
"param(fill)" ) )
549 elem.setAttribute( attribute.name(), fill.name() );
551 else if ( value.startsWith(
"param(outline)" ) )
553 elem.setAttribute( attribute.name(), outline.name() );
555 else if ( value.startsWith(
"param(outline-width)" ) )
557 elem.setAttribute( attribute.name(), QString::number( outlineWidth ) );
562 QDomNodeList childList = elem.childNodes();
563 int nChildren = childList.count();
564 for (
int i = 0; i < nChildren; ++i )
566 QDomElement childElem = childList.at( i ).toElement();
572 bool& hasOutlineWidthParam,
double& defaultOutlineWidth )
const
580 if ( hasFillParam && hasOutlineParam && hasOutlineWidthParam )
586 QDomNamedNodeMap attributes = elem.attributes();
587 int nAttributes = attributes.count();
589 QStringList valueSplit;
590 for (
int i = 0; i < nAttributes; ++i )
592 QDomAttr attribute = attributes.item( i ).toAttr();
593 if ( attribute.name().compare(
"style", Qt::CaseInsensitive ) == 0 )
596 QStringList entryList = attribute.value().split(
';' );
597 QStringList::const_iterator entryIt = entryList.constBegin();
598 for ( ; entryIt != entryList.constEnd(); ++entryIt )
600 QStringList keyValueSplit = entryIt->split(
':' );
601 if ( keyValueSplit.size() < 2 )
605 QString key = keyValueSplit.at( 0 );
606 QString value = keyValueSplit.at( 1 );
607 valueSplit = value.split(
" " );
608 if ( !hasFillParam && value.startsWith(
"param(fill)" ) )
611 if ( valueSplit.size() > 1 )
613 defaultFill = QColor( valueSplit.at( 1 ) );
616 else if ( !hasOutlineParam && value.startsWith(
"param(outline)" ) )
618 hasOutlineParam =
true;
619 if ( valueSplit.size() > 1 )
621 defaultOutline = QColor( valueSplit.at( 1 ) );
624 else if ( !hasOutlineWidthParam && value.startsWith(
"param(outline-width)" ) )
626 hasOutlineWidthParam =
true;
627 if ( valueSplit.size() > 1 )
629 defaultOutlineWidth = valueSplit.at( 1 ).toDouble();
636 QString value = attribute.value();
637 valueSplit = value.split(
" " );
638 if ( !hasFillParam && value.startsWith(
"param(fill)" ) )
641 if ( valueSplit.size() > 1 )
643 defaultFill = QColor( valueSplit.at( 1 ) );
646 else if ( !hasOutlineParam && value.startsWith(
"param(outline)" ) )
648 hasOutlineParam =
true;
649 if ( valueSplit.size() > 1 )
651 defaultOutline = QColor( valueSplit.at( 1 ) );
654 else if ( !hasOutlineWidthParam && value.startsWith(
"param(outline-width)" ) )
656 hasOutlineWidthParam =
true;
657 if ( valueSplit.size() > 1 )
659 defaultOutlineWidth = valueSplit.at( 1 ).toDouble();
666 QDomNodeList childList = elem.childNodes();
667 int nChildren = childList.count();
668 for (
int i = 0; i < nChildren; ++i )
670 QDomElement childElem = childList.at( i ).toElement();
671 containsElemParams( childElem, hasFillParam, defaultFill, hasOutlineParam, defaultOutline, hasOutlineWidthParam, defaultOutlineWidth );
683 QgsDebugMsg(
"****************svg cache entry list*************************" );
744 QString msg =
tr(
"%1 of %2 bytes of svg image downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QString(
"unknown number of" ) : QString::number( bytesTotal ) );