25 #include <QApplication>
26 #include <QCoreApplication>
28 #include <QDomDocument>
29 #include <QDomElement>
34 #include <QSvgRenderer>
36 #include <QNetworkReply>
37 #include <QNetworkRequest>
40 outline( Qt::black ), image( 0 ), picture( 0 )
71 size += (
image->width() *
image->height() * 32 );
93 , mLeastRecentEntry( 0 )
94 , mMostRecentEntry( 0 )
96 mMissingSvg = QString(
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toAscii();
101 QMultiHash< QString, QgsSvgCacheEntry* >::iterator it =
mEntryLookup.begin();
118 if ( !currentEntry->
image )
121 double hwRatio = 1.0;
122 if ( r.viewBoxF().width() > 0 )
124 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
126 long cachedDataSize = 0;
127 cachedDataSize += currentEntry->
svgContent.size();
128 cachedDataSize += ( int )( currentEntry->
size * currentEntry->
size * hwRatio * 32 );
132 delete currentEntry->
image;
133 currentEntry->
image = 0;
149 return *( currentEntry->
image );
165 return *( currentEntry->
picture );
200 void QgsSvgCache::containsParams(
const QString& path,
bool& hasFillParam, QColor& defaultFillColor,
bool& hasOutlineParam, QColor& defaultOutlineColor,
201 bool& hasOutlineWidthParam,
double& defaultOutlineWidth )
const
203 defaultFillColor = QColor( Qt::black );
204 defaultOutlineColor = QColor( Qt::black );
205 defaultOutlineWidth = 1.0;
213 QDomElement docElem = svgDoc.documentElement();
214 containsElemParams( docElem, hasFillParam, defaultFillColor, hasOutlineParam, defaultOutlineColor, hasOutlineWidthParam, defaultOutlineWidth );
231 QDomElement docElem = svgDoc.documentElement();
241 QFile svgFile( path );
242 if ( svgFile.exists() )
244 if ( svgFile.open( QIODevice::ReadOnly ) )
246 return svgFile.readAll();
255 if ( !path.contains(
"://" ) )
261 if ( !svgUrl.isValid() )
267 if ( svgUrl.scheme().compare(
"file", Qt::CaseInsensitive ) == 0 )
269 svgFile.setFileName( svgUrl.toLocalFile() );
270 if ( svgFile.exists() )
272 if ( svgFile.open( QIODevice::ReadOnly ) )
274 return svgFile.readAll();
283 QNetworkReply *reply = 0;
290 QgsDebugMsg( QString(
"get svg: %1" ).arg( svgUrl.toString() ) );
291 QNetworkRequest request( svgUrl );
292 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
293 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
302 while ( !reply->isFinished() )
304 QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, 500 );
307 if ( reply->error() != QNetworkReply::NoError )
309 QgsMessageLog::logMessage(
tr(
"SVG request failed [error: %1 - url: %2]" ).arg( reply->errorString() ).arg( reply->url().toString() ),
tr(
"SVG" ) );
311 reply->deleteLater();
315 QVariant redirect = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
316 if ( redirect.isNull() )
324 svgUrl = redirect.toUrl();
325 reply->deleteLater();
328 QVariant status = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
329 if ( !status.isNull() && status.toInt() >= 400 )
331 QVariant phrase = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute );
332 QgsMessageLog::logMessage(
tr(
"SVG request error [status: %1 - reason phrase: %2]" ).arg( status.toInt() ).arg( phrase.toString() ),
tr(
"SVG" ) );
334 reply->deleteLater();
338 QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
340 if ( !contentType.startsWith(
"image/svg+xml", Qt::CaseInsensitive ) )
342 reply->deleteLater();
347 QByteArray ba = reply->readAll();
348 reply->deleteLater();
364 double hwRatio = 1.0;
365 if ( r.viewBoxF().width() > 0 )
367 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
369 double wSize = entry->
size;
370 int wImgSize = ( int )wSize;
375 double hSize = wSize * hwRatio;
376 int hImgSize = ( int )hSize;
382 QImage* image =
new QImage( wImgSize, hImgSize, QImage::Format_ARGB32_Premultiplied );
386 if ( r.viewBoxF().width() == r.viewBoxF().height() )
392 QSizeF s( r.viewBoxF().size() );
393 s.scale( wSize, hSize, Qt::KeepAspectRatio );
394 QRectF rect(( wImgSize - s.width() ) / 2, ( hImgSize - s.height() ) / 2, s.width(), s.height() );
395 r.render( &p, rect );
398 entry->
image = image;
399 mTotalSize += ( image->width() * image->height() * 32 );
413 QPicture* picture =
new QPicture();
416 double hwRatio = 1.0;
417 if ( r.viewBoxF().width() > 0 )
419 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
422 if ( drawOnScreen && forceVectorOutput )
425 double wSize = entry->
size;
426 double hSize = wSize * hwRatio;
427 QSizeF s( r.viewBoxF().size() );
428 s.scale( wSize, hSize, Qt::KeepAspectRatio );
429 rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );
435 double wSize = scaledSize * picture->logicalDpiX();
436 double hSize = scaledSize * picture->logicalDpiY() * r.viewBoxF().height() / r.viewBoxF().width();
437 rect = QRectF( QPointF( -wSize / 2.0, -hSize / 2.0 ), QSizeF( wSize, hSize ) );
440 QPainter p( picture );
441 r.render( &p, rect );
451 QList<QgsSvgCacheEntry*> entries =
mEntryLookup.values( file );
453 QList<QgsSvgCacheEntry*>::iterator entryIt = entries.begin();
454 for ( ; entryIt != entries.end(); ++entryIt )
469 currentEntry =
insertSVG( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );
502 QDomNamedNodeMap attributes = elem.attributes();
503 int nAttributes = attributes.count();
504 for (
int i = 0; i < nAttributes; ++i )
506 QDomAttr attribute = attributes.item( i ).toAttr();
508 if ( attribute.name().compare(
"style", Qt::CaseInsensitive ) == 0 )
511 QString newAttributeString;
513 QStringList entryList = attribute.value().split(
';' );
514 QStringList::const_iterator entryIt = entryList.constBegin();
515 for ( ; entryIt != entryList.constEnd(); ++entryIt )
517 QStringList keyValueSplit = entryIt->split(
':' );
518 if ( keyValueSplit.size() < 2 )
522 QString key = keyValueSplit.at( 0 );
523 QString value = keyValueSplit.at( 1 );
524 if ( value.startsWith(
"param(fill" ) )
528 else if ( value.startsWith(
"param(outline)" ) )
530 value = outline.name();
532 else if ( value.startsWith(
"param(outline-width)" ) )
534 value = QString::number( outlineWidth );
537 if ( entryIt != entryList.constBegin() )
539 newAttributeString.append(
";" );
541 newAttributeString.append( key +
":" + value );
543 elem.setAttribute( attribute.name(), newAttributeString );
547 QString value = attribute.value();
548 if ( value.startsWith(
"param(fill)" ) )
550 elem.setAttribute( attribute.name(), fill.name() );
552 else if ( value.startsWith(
"param(outline)" ) )
554 elem.setAttribute( attribute.name(), outline.name() );
556 else if ( value.startsWith(
"param(outline-width)" ) )
558 elem.setAttribute( attribute.name(), QString::number( outlineWidth ) );
563 QDomNodeList childList = elem.childNodes();
564 int nChildren = childList.count();
565 for (
int i = 0; i < nChildren; ++i )
567 QDomElement childElem = childList.at( i ).toElement();
573 bool& hasOutlineWidthParam,
double& defaultOutlineWidth )
const
581 if ( hasFillParam && hasOutlineParam && hasOutlineWidthParam )
587 QDomNamedNodeMap attributes = elem.attributes();
588 int nAttributes = attributes.count();
590 QStringList valueSplit;
591 for (
int i = 0; i < nAttributes; ++i )
593 QDomAttr attribute = attributes.item( i ).toAttr();
594 if ( attribute.name().compare(
"style", Qt::CaseInsensitive ) == 0 )
597 QStringList entryList = attribute.value().split(
';' );
598 QStringList::const_iterator entryIt = entryList.constBegin();
599 for ( ; entryIt != entryList.constEnd(); ++entryIt )
601 QStringList keyValueSplit = entryIt->split(
':' );
602 if ( keyValueSplit.size() < 2 )
606 QString key = keyValueSplit.at( 0 );
607 QString value = keyValueSplit.at( 1 );
608 valueSplit = value.split(
" " );
609 if ( !hasFillParam && value.startsWith(
"param(fill)" ) )
612 if ( valueSplit.size() > 1 )
614 defaultFill = QColor( valueSplit.at( 1 ) );
617 else if ( !hasOutlineParam && value.startsWith(
"param(outline)" ) )
619 hasOutlineParam =
true;
620 if ( valueSplit.size() > 1 )
622 defaultOutline = QColor( valueSplit.at( 1 ) );
625 else if ( !hasOutlineWidthParam && value.startsWith(
"param(outline-width)" ) )
627 hasOutlineWidthParam =
true;
628 if ( valueSplit.size() > 1 )
630 defaultOutlineWidth = valueSplit.at( 1 ).toDouble();
637 QString value = attribute.value();
638 valueSplit = value.split(
" " );
639 if ( !hasFillParam && value.startsWith(
"param(fill)" ) )
642 if ( valueSplit.size() > 1 )
644 defaultFill = QColor( valueSplit.at( 1 ) );
647 else if ( !hasOutlineParam && value.startsWith(
"param(outline)" ) )
649 hasOutlineParam =
true;
650 if ( valueSplit.size() > 1 )
652 defaultOutline = QColor( valueSplit.at( 1 ) );
655 else if ( !hasOutlineWidthParam && value.startsWith(
"param(outline-width)" ) )
657 hasOutlineWidthParam =
true;
658 if ( valueSplit.size() > 1 )
660 defaultOutlineWidth = valueSplit.at( 1 ).toDouble();
667 QDomNodeList childList = elem.childNodes();
668 int nChildren = childList.count();
669 for (
int i = 0; i < nChildren; ++i )
671 QDomElement childElem = childList.at( i ).toElement();
672 containsElemParams( childElem, hasFillParam, defaultFill, hasOutlineParam, defaultOutline, hasOutlineWidthParam, defaultOutlineWidth );
684 QgsDebugMsg(
"****************svg cache entry list*************************" );
745 QString msg =
tr(
"%1 of %2 bytes of svg image downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QString(
"unknown number of" ) : QString::number( bytesTotal ) );