26 #include <QApplication> 27 #include <QCoreApplication> 29 #include <QDomDocument> 30 #include <QDomElement> 35 #include <QSvgRenderer> 37 #include <QNetworkReply> 38 #include <QNetworkRequest> 46 QgsSvgCacheEntry::QgsSvgCacheEntry(
const QString &path,
double size,
double strokeWidth,
double widthScaleFactor,
const QColor &fill,
const QColor &stroke,
double fixedAspectRatio )
49 , strokeWidth( strokeWidth )
50 , widthScaleFactor( widthScaleFactor )
51 , fixedAspectRatio( fixedAspectRatio )
59 const QgsSvgCacheEntry *otherSvg =
dynamic_cast< const QgsSvgCacheEntry *
>( other );
62 || !
qgsDoubleNear( otherSvg->fixedAspectRatio, fixedAspectRatio )
65 || !
qgsDoubleNear( otherSvg->widthScaleFactor, widthScaleFactor )
66 || otherSvg->fill != fill
67 || otherSvg->stroke != stroke
68 || otherSvg->path != path )
74 int QgsSvgCacheEntry::dataSize()
const 76 int size = svgContent.size();
79 size += picture->size();
83 size += ( image->width() * image->height() * 32 );
88 void QgsSvgCacheEntry::dump()
const 90 QgsDebugMsg( QStringLiteral(
"path: %1, size %2, width scale factor %3" ).arg( path ).arg( size ).arg( widthScaleFactor ) );
102 mMissingSvg = QStringLiteral(
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
105 if ( QFile::exists( downloadingSvgPath ) )
107 QFile file( downloadingSvgPath );
108 if ( file.open( QIODevice::ReadOnly ) )
110 mFetchingSvg = file.readAll();
114 if ( mFetchingSvg.isEmpty() )
116 mFetchingSvg = QStringLiteral(
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
122 QImage
QgsSvgCache::svgAsImage(
const QString &file,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
123 double widthScaleFactor,
bool &fitsInCache,
double fixedAspectRatio )
125 QMutexLocker locker( &
mMutex );
128 QgsSvgCacheEntry *currentEntry = cacheEntry( file, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );
135 if ( !currentEntry->image )
137 QSvgRenderer r( currentEntry->svgContent );
138 double hwRatio = 1.0;
139 if ( r.viewBoxF().width() > 0 )
141 if ( currentEntry->fixedAspectRatio > 0 )
143 hwRatio = currentEntry->fixedAspectRatio;
147 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
150 long cachedDataSize = 0;
151 cachedDataSize += currentEntry->svgContent.size();
152 cachedDataSize +=
static_cast< int >( currentEntry->size * currentEntry->size * hwRatio * 32 );
156 currentEntry->image.reset();
159 if ( !currentEntry->picture )
161 cachePicture( currentEntry,
false );
165 result = imageFromCachedPicture( *currentEntry );
169 cacheImage( currentEntry );
170 result = *( currentEntry->image );
176 result = *( currentEntry->image );
183 double widthScaleFactor,
bool forceVectorOutput,
double fixedAspectRatio )
185 QMutexLocker locker( &
mMutex );
187 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );
191 if ( !currentEntry->picture )
193 cachePicture( currentEntry, forceVectorOutput );
202 p.setData( currentEntry->picture->data(), currentEntry->picture->size() );
206 QByteArray
QgsSvgCache::svgContent(
const QString &path,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
207 double widthScaleFactor,
double fixedAspectRatio )
209 QMutexLocker locker( &
mMutex );
211 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );
213 return currentEntry->svgContent;
216 QSizeF
QgsSvgCache::svgViewboxSize(
const QString &path,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
double widthScaleFactor,
double fixedAspectRatio )
218 QMutexLocker locker( &
mMutex );
220 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );
221 return currentEntry->viewboxSize;
224 void QgsSvgCache::containsParams(
const QString &path,
bool &hasFillParam, QColor &defaultFillColor,
bool &hasStrokeParam, QColor &defaultStrokeColor,
225 bool &hasStrokeWidthParam,
double &defaultStrokeWidth )
const 227 bool hasDefaultFillColor =
false;
228 bool hasFillOpacityParam =
false;
229 bool hasDefaultFillOpacity =
false;
230 double defaultFillOpacity = 1.0;
231 bool hasDefaultStrokeColor =
false;
232 bool hasDefaultStrokeWidth =
false;
233 bool hasStrokeOpacityParam =
false;
234 bool hasDefaultStrokeOpacity =
false;
235 double defaultStrokeOpacity = 1.0;
237 containsParams( path, hasFillParam, hasDefaultFillColor, defaultFillColor,
238 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
239 hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
240 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
241 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
245 bool &hasFillParam,
bool &hasDefaultFillParam, QColor &defaultFillColor,
246 bool &hasFillOpacityParam,
bool &hasDefaultFillOpacity,
double &defaultFillOpacity,
247 bool &hasStrokeParam,
bool &hasDefaultStrokeColor, QColor &defaultStrokeColor,
248 bool &hasStrokeWidthParam,
bool &hasDefaultStrokeWidth,
double &defaultStrokeWidth,
249 bool &hasStrokeOpacityParam,
bool &hasDefaultStrokeOpacity,
double &defaultStrokeOpacity )
const 251 hasFillParam =
false;
252 hasFillOpacityParam =
false;
253 hasStrokeParam =
false;
254 hasStrokeWidthParam =
false;
255 hasStrokeOpacityParam =
false;
256 defaultFillColor = QColor( Qt::white );
257 defaultFillOpacity = 1.0;
258 defaultStrokeColor = QColor( Qt::black );
259 defaultStrokeWidth = 0.2;
260 defaultStrokeOpacity = 1.0;
262 hasDefaultFillParam =
false;
263 hasDefaultFillOpacity =
false;
264 hasDefaultStrokeColor =
false;
265 hasDefaultStrokeWidth =
false;
266 hasDefaultStrokeOpacity =
false;
269 if ( !svgDoc.setContent(
getContent( path, mMissingSvg, mFetchingSvg ) ) )
274 QDomElement docElem = svgDoc.documentElement();
275 containsElemParams( docElem, hasFillParam, hasDefaultFillParam, defaultFillColor,
276 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
277 hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
278 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
279 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
282 void QgsSvgCache::replaceParamsAndCacheSvg( QgsSvgCacheEntry *entry )
290 if ( !svgDoc.setContent(
getContent( entry->path, mMissingSvg, mFetchingSvg ) ) )
296 QDomElement docElem = svgDoc.documentElement();
299 double sizeScaleFactor = calcSizeScaleFactor( entry, docElem, viewboxSize );
300 entry->viewboxSize = viewboxSize;
301 replaceElemParams( docElem, entry->fill, entry->stroke, entry->strokeWidth * sizeScaleFactor );
303 entry->svgContent = svgDoc.toByteArray( 0 );
307 entry->svgContent.replace(
"\n<tspan",
"<tspan" );
308 entry->svgContent.replace(
"</tspan>\n",
"</tspan>" );
313 double QgsSvgCache::calcSizeScaleFactor( QgsSvgCacheEntry *entry,
const QDomElement &docElem, QSizeF &viewboxSize )
const 323 if ( docElem.tagName() == QLatin1String(
"svg" ) && docElem.hasAttribute( QStringLiteral(
"viewBox" ) ) )
325 viewBox = docElem.attribute( QStringLiteral(
"viewBox" ), QString() );
327 else if ( docElem.tagName() == QLatin1String(
"svg" ) && docElem.hasAttribute( QStringLiteral(
"viewbox" ) ) )
329 viewBox = docElem.attribute( QStringLiteral(
"viewbox" ), QString() );
333 QDomElement svgElem = docElem.firstChildElement( QStringLiteral(
"svg" ) );
334 if ( !svgElem.isNull() )
336 if ( svgElem.hasAttribute( QStringLiteral(
"viewBox" ) ) )
337 viewBox = svgElem.attribute( QStringLiteral(
"viewBox" ), QString() );
338 else if ( svgElem.hasAttribute( QStringLiteral(
"viewbox" ) ) )
339 viewBox = svgElem.attribute( QStringLiteral(
"viewbox" ), QString() );
344 if ( viewBox.isEmpty() )
348 QStringList parts = viewBox.split(
' ' );
349 if ( parts.count() != 4 )
352 bool heightOk =
false;
353 double height = parts.at( 3 ).toDouble( &heightOk );
355 bool widthOk =
false;
356 double width = parts.at( 2 ).toDouble( &widthOk );
360 viewboxSize = QSizeF( width, height );
361 return width / entry->size;
370 return getContent( path, mMissingSvg, mFetchingSvg );
377 QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
378 if ( !contentType.startsWith( QLatin1String(
"image/svg+xml" ), Qt::CaseInsensitive )
379 && !contentType.startsWith( QLatin1String(
"text/plain" ), Qt::CaseInsensitive ) )
387 void QgsSvgCache::cacheImage( QgsSvgCacheEntry *entry )
394 entry->image.reset();
398 QSize imageSize = sizeForImage( *entry, viewBoxSize, scaledSize );
401 std::unique_ptr< QImage > image = qgis::make_unique< QImage >( imageSize, QImage::Format_ARGB32_Premultiplied );
404 QPainter p( image.get() );
405 QSvgRenderer r( entry->svgContent );
406 if (
qgsDoubleNear( viewBoxSize.width(), viewBoxSize.height() ) )
412 QSizeF s( viewBoxSize );
413 s.scale( scaledSize.width(), scaledSize.height(), Qt::KeepAspectRatio );
414 QRectF rect( ( imageSize.width() - s.width() ) / 2, ( imageSize.height() - s.height() ) / 2, s.width(), s.height() );
415 r.render( &p, rect );
418 mTotalSize += ( image->width() * image->height() * 32 );
419 entry->image = std::move( image );
422 void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry,
bool forceVectorOutput )
424 Q_UNUSED( forceVectorOutput );
430 entry->picture.reset();
432 bool isFixedAR = entry->fixedAspectRatio > 0;
435 std::unique_ptr< QPicture > picture = qgis::make_unique< QPicture >();
437 QSvgRenderer r( entry->svgContent );
438 double hwRatio = 1.0;
439 if ( r.viewBoxF().width() > 0 )
443 hwRatio = entry->fixedAspectRatio;
447 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
451 double wSize = entry->size;
452 double hSize = wSize * hwRatio;
454 QSizeF s( r.viewBoxF().size() );
455 s.scale( wSize, hSize, isFixedAR ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio );
456 rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );
458 QPainter p( picture.get() );
459 r.render( &p, rect );
460 entry->picture = std::move( picture );
464 QgsSvgCacheEntry *QgsSvgCache::cacheEntry(
const QString &path,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
465 double widthScaleFactor,
double fixedAspectRatio )
467 QgsSvgCacheEntry *currentEntry =
findExistingEntry(
new QgsSvgCacheEntry( path, size, strokeWidth, widthScaleFactor, fill, stroke, fixedAspectRatio ) );
469 if ( currentEntry->svgContent.isEmpty() )
471 replaceParamsAndCacheSvg( currentEntry );
478 void QgsSvgCache::replaceElemParams( QDomElement &elem,
const QColor &fill,
const QColor &stroke,
double strokeWidth )
486 QDomNamedNodeMap attributes = elem.attributes();
487 int nAttributes = attributes.count();
488 for (
int i = 0; i < nAttributes; ++i )
490 QDomAttr attribute = attributes.item( i ).toAttr();
492 if ( attribute.name().compare( QLatin1String(
"style" ), Qt::CaseInsensitive ) == 0 )
495 QString newAttributeString;
497 QStringList entryList = attribute.value().split(
';' );
498 QStringList::const_iterator entryIt = entryList.constBegin();
499 for ( ; entryIt != entryList.constEnd(); ++entryIt )
501 QStringList keyValueSplit = entryIt->split(
':' );
502 if ( keyValueSplit.size() < 2 )
506 QString key = keyValueSplit.at( 0 );
507 QString value = keyValueSplit.at( 1 );
508 if ( value.startsWith( QLatin1String(
"param(fill)" ) ) )
512 else if ( value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
514 value = fill.alphaF();
516 else if ( value.startsWith( QLatin1String(
"param(outline)" ) ) )
518 value = stroke.name();
520 else if ( value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
522 value = stroke.alphaF();
524 else if ( value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
526 value = QString::number( strokeWidth );
529 if ( entryIt != entryList.constBegin() )
531 newAttributeString.append(
';' );
533 newAttributeString.append( key +
':' + value );
535 elem.setAttribute( attribute.name(), newAttributeString );
539 QString value = attribute.value();
540 if ( value.startsWith( QLatin1String(
"param(fill)" ) ) )
542 elem.setAttribute( attribute.name(), fill.name() );
544 else if ( value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
546 elem.setAttribute( attribute.name(), fill.alphaF() );
548 else if ( value.startsWith( QLatin1String(
"param(outline)" ) ) )
550 elem.setAttribute( attribute.name(), stroke.name() );
552 else if ( value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
554 elem.setAttribute( attribute.name(), stroke.alphaF() );
556 else if ( value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
558 elem.setAttribute( attribute.name(), QString::number( strokeWidth ) );
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();
568 replaceElemParams( childElem, fill, stroke, strokeWidth );
572 void QgsSvgCache::containsElemParams(
const QDomElement &elem,
bool &hasFillParam,
bool &hasDefaultFill, QColor &defaultFill,
573 bool &hasFillOpacityParam,
bool &hasDefaultFillOpacity,
double &defaultFillOpacity,
574 bool &hasStrokeParam,
bool &hasDefaultStroke, QColor &defaultStroke,
575 bool &hasStrokeWidthParam,
bool &hasDefaultStrokeWidth,
double &defaultStrokeWidth,
576 bool &hasStrokeOpacityParam,
bool &hasDefaultStrokeOpacity,
double &defaultStrokeOpacity )
const 584 if ( hasFillParam && hasStrokeParam && hasStrokeWidthParam && hasFillOpacityParam && hasStrokeOpacityParam )
590 QDomNamedNodeMap attributes = elem.attributes();
591 int nAttributes = attributes.count();
593 QStringList valueSplit;
594 for (
int i = 0; i < nAttributes; ++i )
596 QDomAttr attribute = attributes.item( i ).toAttr();
597 if ( attribute.name().compare( QLatin1String(
"style" ), Qt::CaseInsensitive ) == 0 )
600 QStringList entryList = attribute.value().split(
';' );
601 QStringList::const_iterator entryIt = entryList.constBegin();
602 for ( ; entryIt != entryList.constEnd(); ++entryIt )
604 QStringList keyValueSplit = entryIt->split(
':' );
605 if ( keyValueSplit.size() < 2 )
609 QString value = keyValueSplit.at( 1 );
610 valueSplit = value.split(
' ' );
611 if ( !hasFillParam && value.startsWith( QLatin1String(
"param(fill)" ) ) )
614 if ( valueSplit.size() > 1 )
616 defaultFill = QColor( valueSplit.at( 1 ) );
617 hasDefaultFill =
true;
620 else if ( !hasFillOpacityParam && value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
622 hasFillOpacityParam =
true;
623 if ( valueSplit.size() > 1 )
626 double opacity = valueSplit.at( 1 ).toDouble( &ok );
629 defaultFillOpacity = opacity;
630 hasDefaultFillOpacity =
true;
634 else if ( !hasStrokeParam && value.startsWith( QLatin1String(
"param(outline)" ) ) )
636 hasStrokeParam =
true;
637 if ( valueSplit.size() > 1 )
639 defaultStroke = QColor( valueSplit.at( 1 ) );
640 hasDefaultStroke =
true;
643 else if ( !hasStrokeWidthParam && value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
645 hasStrokeWidthParam =
true;
646 if ( valueSplit.size() > 1 )
648 defaultStrokeWidth = valueSplit.at( 1 ).toDouble();
649 hasDefaultStrokeWidth =
true;
652 else if ( !hasStrokeOpacityParam && value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
654 hasStrokeOpacityParam =
true;
655 if ( valueSplit.size() > 1 )
658 double opacity = valueSplit.at( 1 ).toDouble( &ok );
661 defaultStrokeOpacity = opacity;
662 hasDefaultStrokeOpacity =
true;
670 QString value = attribute.value();
671 valueSplit = value.split(
' ' );
672 if ( !hasFillParam && value.startsWith( QLatin1String(
"param(fill)" ) ) )
675 if ( valueSplit.size() > 1 )
677 defaultFill = QColor( valueSplit.at( 1 ) );
678 hasDefaultFill =
true;
681 else if ( !hasFillOpacityParam && value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
683 hasFillOpacityParam =
true;
684 if ( valueSplit.size() > 1 )
687 double opacity = valueSplit.at( 1 ).toDouble( &ok );
690 defaultFillOpacity = opacity;
691 hasDefaultFillOpacity =
true;
695 else if ( !hasStrokeParam && value.startsWith( QLatin1String(
"param(outline)" ) ) )
697 hasStrokeParam =
true;
698 if ( valueSplit.size() > 1 )
700 defaultStroke = QColor( valueSplit.at( 1 ) );
701 hasDefaultStroke =
true;
704 else if ( !hasStrokeWidthParam && value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
706 hasStrokeWidthParam =
true;
707 if ( valueSplit.size() > 1 )
709 defaultStrokeWidth = valueSplit.at( 1 ).toDouble();
710 hasDefaultStrokeWidth =
true;
713 else if ( !hasStrokeOpacityParam && value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
715 hasStrokeOpacityParam =
true;
716 if ( valueSplit.size() > 1 )
719 double opacity = valueSplit.at( 1 ).toDouble( &ok );
722 defaultStrokeOpacity = opacity;
723 hasDefaultStrokeOpacity =
true;
731 QDomNodeList childList = elem.childNodes();
732 int nChildren = childList.count();
733 for (
int i = 0; i < nChildren; ++i )
735 QDomElement childElem = childList.at( i ).toElement();
736 containsElemParams( childElem, hasFillParam, hasDefaultFill, defaultFill,
737 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
738 hasStrokeParam, hasDefaultStroke, defaultStroke,
739 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
740 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
744 QSize QgsSvgCache::sizeForImage(
const QgsSvgCacheEntry &entry, QSizeF &viewBoxSize, QSizeF &scaledSize )
const 746 bool isFixedAR = entry.fixedAspectRatio > 0;
748 QSvgRenderer r( entry.svgContent );
749 double hwRatio = 1.0;
750 viewBoxSize = r.viewBoxF().size();
751 if ( viewBoxSize.width() > 0 )
755 hwRatio = entry.fixedAspectRatio;
759 hwRatio = viewBoxSize.height() / viewBoxSize.width();
764 scaledSize.setWidth( entry.size );
765 int wImgSize =
static_cast< int >( scaledSize.width() );
770 scaledSize.setHeight( scaledSize.width() * hwRatio );
771 int hImgSize =
static_cast< int >( scaledSize.height() );
776 return QSize( wImgSize, hImgSize );
779 QImage QgsSvgCache::imageFromCachedPicture(
const QgsSvgCacheEntry &entry )
const 783 QImage image( sizeForImage( entry, viewBoxSize, scaledSize ), QImage::Format_ARGB32_Premultiplied );
786 QPainter p( &image );
787 p.drawPicture( QPoint( 0, 0 ), *entry.picture );
QPicture svgAsPicture(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput=false, double fixedAspectRatio=0)
Gets SVG as QPicture&.
Abstract base class for file content caches, such as SVG or raster image caches.
QByteArray getImageData(const QString &path) const
Gets image data.
static QString defaultThemePath()
Returns the path to the default theme directory.
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0)
Gets SVG as QImage.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Base class for entries in a QgsAbstractContentCache.
void remoteContentFetched(const QString &url)
Emitted when the cache has finished retrieving content from a remote url.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
QgsSvgCache(QObject *parent=nullptr)
Constructor for QgsSvgCache.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth) const
Tests if an svg file contains parameters for fill, stroke color, stroke width.
QgsSvgCacheEntry * findExistingEntry(QgsSvgCacheEntry *entryTemplate)
Returns the existing entry from the cache which matches entryTemplate (deleting entryTemplate when do...
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0)
Gets SVG content.
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
long mMaxCacheSize
Maximum cache size.
QByteArray getContent(const QString &path, const QByteArray &missingContent, const QByteArray &fetchingContent) const
Gets the file content corresponding to the given path.
QSizeF svgViewboxSize(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0)
Calculates the viewbox size of a (possibly cached) SVG file.
long mTotalSize
Estimated total size of all cached content.
void trimToMaximumSize()
Removes the least used cache entries until the maximum cache size is under the predefined size limit...
bool checkReply(QNetworkReply *reply, const QString &path) const override
Runs additional checks on a network reply to ensure that the reply content is consistent with that re...