26 #include <QApplication>
27 #include <QCoreApplication>
29 #include <QDomDocument>
30 #include <QDomElement>
35 #include <QRegularExpression>
36 #include <QSvgRenderer>
38 #include <QNetworkReply>
39 #include <QNetworkRequest>
47 QgsSvgCacheEntry::QgsSvgCacheEntry(
const QString &path,
double size,
double strokeWidth,
double widthScaleFactor,
const QColor &fill,
const QColor &stroke,
double fixedAspectRatio,
const QMap<QString, QString> ¶meters )
50 , strokeWidth( strokeWidth )
51 , widthScaleFactor( widthScaleFactor )
52 , fixedAspectRatio( fixedAspectRatio )
55 , parameters( parameters )
61 const QgsSvgCacheEntry *otherSvg =
dynamic_cast< const QgsSvgCacheEntry *
>( other );
64 || !
qgsDoubleNear( otherSvg->fixedAspectRatio, fixedAspectRatio )
67 || !
qgsDoubleNear( otherSvg->widthScaleFactor, widthScaleFactor )
68 || otherSvg->fill != fill
69 || otherSvg->stroke != stroke
70 || otherSvg->path != path
71 || otherSvg->parameters != parameters )
77 int QgsSvgCacheEntry::dataSize()
const
79 int size = svgContent.size();
82 size += picture->size();
86 size += ( image->width() * image->height() * 32 );
91 void QgsSvgCacheEntry::dump()
const
93 QgsDebugMsgLevel( QStringLiteral(
"path: %1, size %2, width scale factor %3" ).arg( path ).arg( size ).arg( widthScaleFactor ), 4 );
105 mMissingSvg = QStringLiteral(
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
108 if ( QFile::exists( downloadingSvgPath ) )
110 QFile file( downloadingSvgPath );
111 if ( file.open( QIODevice::ReadOnly ) )
113 mFetchingSvg = file.readAll();
117 if ( mFetchingSvg.isEmpty() )
119 mFetchingSvg = QStringLiteral(
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
125 QImage
QgsSvgCache::svgAsImage(
const QString &file,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
126 double widthScaleFactor,
bool &fitsInCache,
double fixedAspectRatio,
bool blocking,
const QMap<QString, QString> ¶meters )
128 const QMutexLocker locker( &
mMutex );
131 QgsSvgCacheEntry *currentEntry = cacheEntry( file, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio, parameters, blocking );
138 if ( !currentEntry->image )
140 const QSvgRenderer r( currentEntry->svgContent );
141 double hwRatio = 1.0;
142 if ( r.viewBoxF().width() > 0 )
144 if ( currentEntry->fixedAspectRatio > 0 )
146 hwRatio = currentEntry->fixedAspectRatio;
150 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
153 long cachedDataSize = 0;
154 cachedDataSize += currentEntry->svgContent.size();
155 cachedDataSize +=
static_cast< int >( currentEntry->size * currentEntry->size * hwRatio * 32 );
159 currentEntry->image.reset();
162 if ( !currentEntry->picture )
164 cachePicture( currentEntry,
false );
168 result = imageFromCachedPicture( *currentEntry );
172 cacheImage( currentEntry );
173 result = *( currentEntry->image );
179 result = *( currentEntry->image );
186 double widthScaleFactor,
bool forceVectorOutput,
double fixedAspectRatio,
bool blocking,
const QMap<QString, QString> ¶meters )
188 const QMutexLocker locker( &
mMutex );
190 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio, parameters, blocking );
194 if ( !currentEntry->picture )
196 cachePicture( currentEntry, forceVectorOutput );
205 p.setData( currentEntry->picture->data(), currentEntry->picture->size() );
209 QByteArray
QgsSvgCache::svgContent(
const QString &path,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
210 double widthScaleFactor,
double fixedAspectRatio,
bool blocking,
const QMap<QString, QString> ¶meters,
bool *isMissingImage )
212 const QMutexLocker locker( &
mMutex );
214 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio, parameters, blocking, isMissingImage );
216 return currentEntry->svgContent;
220 double widthScaleFactor,
double fixedAspectRatio,
bool blocking,
const QMap<QString, QString> ¶meters )
222 const QMutexLocker locker( &
mMutex );
224 QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio, parameters, blocking );
225 return currentEntry->viewboxSize;
228 void QgsSvgCache::containsParams(
const QString &path,
bool &hasFillParam, QColor &defaultFillColor,
bool &hasStrokeParam, QColor &defaultStrokeColor,
229 bool &hasStrokeWidthParam,
double &defaultStrokeWidth,
bool blocking )
const
231 bool hasDefaultFillColor =
false;
232 bool hasFillOpacityParam =
false;
233 bool hasDefaultFillOpacity =
false;
234 double defaultFillOpacity = 1.0;
235 bool hasDefaultStrokeColor =
false;
236 bool hasDefaultStrokeWidth =
false;
237 bool hasStrokeOpacityParam =
false;
238 bool hasDefaultStrokeOpacity =
false;
239 double defaultStrokeOpacity = 1.0;
241 containsParams( path, hasFillParam, hasDefaultFillColor, defaultFillColor,
242 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
243 hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
244 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
245 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity,
250 bool &hasFillParam,
bool &hasDefaultFillParam, QColor &defaultFillColor,
251 bool &hasFillOpacityParam,
bool &hasDefaultFillOpacity,
double &defaultFillOpacity,
252 bool &hasStrokeParam,
bool &hasDefaultStrokeColor, QColor &defaultStrokeColor,
253 bool &hasStrokeWidthParam,
bool &hasDefaultStrokeWidth,
double &defaultStrokeWidth,
254 bool &hasStrokeOpacityParam,
bool &hasDefaultStrokeOpacity,
double &defaultStrokeOpacity,
255 bool blocking )
const
257 hasFillParam =
false;
258 hasFillOpacityParam =
false;
259 hasStrokeParam =
false;
260 hasStrokeWidthParam =
false;
261 hasStrokeOpacityParam =
false;
262 defaultFillColor = QColor( Qt::white );
263 defaultFillOpacity = 1.0;
264 defaultStrokeColor = QColor( Qt::black );
265 defaultStrokeWidth = 0.2;
266 defaultStrokeOpacity = 1.0;
268 hasDefaultFillParam =
false;
269 hasDefaultFillOpacity =
false;
270 hasDefaultStrokeColor =
false;
271 hasDefaultStrokeWidth =
false;
272 hasDefaultStrokeOpacity =
false;
275 if ( !svgDoc.setContent(
getContent( path, mMissingSvg, mFetchingSvg, blocking ) ) )
280 const QDomElement docElem = svgDoc.documentElement();
281 containsElemParams( docElem, hasFillParam, hasDefaultFillParam, defaultFillColor,
282 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
283 hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
284 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
285 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
288 void QgsSvgCache::replaceParamsAndCacheSvg( QgsSvgCacheEntry *entry,
bool blocking )
295 const QByteArray content =
getContent( entry->path, mMissingSvg, mFetchingSvg, blocking ) ;
296 entry->isMissingImage = content == mMissingSvg;
298 if ( !svgDoc.setContent( content ) )
304 QDomElement docElem = svgDoc.documentElement();
307 const double sizeScaleFactor = calcSizeScaleFactor( entry, docElem, viewboxSize );
308 entry->viewboxSize = viewboxSize;
309 replaceElemParams( docElem, entry->fill, entry->stroke, entry->strokeWidth * sizeScaleFactor, entry->parameters );
311 entry->svgContent = svgDoc.toByteArray( 0 );
316 entry->svgContent.replace(
"\n<tspan",
"<tspan" );
317 entry->svgContent.replace(
"</tspan>\n",
"</tspan>" );
322 double QgsSvgCache::calcSizeScaleFactor( QgsSvgCacheEntry *entry,
const QDomElement &docElem, QSizeF &viewboxSize )
const
332 if ( docElem.tagName() == QLatin1String(
"svg" ) && docElem.hasAttribute( QStringLiteral(
"viewBox" ) ) )
334 viewBox = docElem.attribute( QStringLiteral(
"viewBox" ), QString() );
336 else if ( docElem.tagName() == QLatin1String(
"svg" ) && docElem.hasAttribute( QStringLiteral(
"viewbox" ) ) )
338 viewBox = docElem.attribute( QStringLiteral(
"viewbox" ), QString() );
342 const QDomElement svgElem = docElem.firstChildElement( QStringLiteral(
"svg" ) );
343 if ( !svgElem.isNull() )
345 if ( svgElem.hasAttribute( QStringLiteral(
"viewBox" ) ) )
346 viewBox = svgElem.attribute( QStringLiteral(
"viewBox" ), QString() );
347 else if ( svgElem.hasAttribute( QStringLiteral(
"viewbox" ) ) )
348 viewBox = svgElem.attribute( QStringLiteral(
"viewbox" ), QString() );
353 if ( viewBox.isEmpty() )
356 if ( docElem.tagName() == QLatin1String(
"svg" ) && docElem.hasAttribute( QStringLiteral(
"width" ) ) )
358 const QString widthString = docElem.attribute( QStringLiteral(
"width" ) );
359 const QRegularExpression measureRegEx( QStringLiteral(
"([\\d\\.]+).*?$" ) );
360 const QRegularExpressionMatch widthMatch = measureRegEx.match( widthString );
361 if ( widthMatch.hasMatch() )
363 const double width = widthMatch.captured( 1 ).toDouble();
364 const QString heightString = docElem.attribute( QStringLiteral(
"height" ) );
366 const QRegularExpressionMatch heightMatch = measureRegEx.match( heightString );
367 if ( heightMatch.hasMatch() )
369 const double height = heightMatch.captured( 1 ).toDouble();
370 viewboxSize = QSizeF( width, height );
371 return width / entry->size;
381 const QStringList parts = viewBox.split(
' ' );
382 if ( parts.count() != 4 )
385 bool heightOk =
false;
386 const double height = parts.at( 3 ).toDouble( &heightOk );
388 bool widthOk =
false;
389 const double width = parts.at( 2 ).toDouble( &widthOk );
393 viewboxSize = QSizeF( width, height );
394 return width / entry->size;
403 return getContent( path, mMissingSvg, mFetchingSvg, blocking );
410 const QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
411 if ( !contentType.startsWith( QLatin1String(
"image/svg+xml" ), Qt::CaseInsensitive )
412 && !contentType.startsWith( QLatin1String(
"text/plain" ), Qt::CaseInsensitive ) )
420 void QgsSvgCache::cacheImage( QgsSvgCacheEntry *entry )
427 entry->image.reset();
431 const QSize imageSize = sizeForImage( *entry, viewBoxSize, scaledSize );
434 std::unique_ptr< QImage > image = std::make_unique< QImage >( imageSize, QImage::Format_ARGB32_Premultiplied );
437 const bool isFixedAR = entry->fixedAspectRatio > 0;
439 QPainter p( image.get() );
440 QSvgRenderer r( entry->svgContent );
441 if (
qgsDoubleNear( viewBoxSize.width(), viewBoxSize.height() ) )
447 QSizeF s( viewBoxSize );
448 s.scale( scaledSize.width(), scaledSize.height(), isFixedAR ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio );
449 const QRectF rect( ( imageSize.width() - s.width() ) / 2, ( imageSize.height() - s.height() ) / 2, s.width(), s.height() );
450 r.render( &p, rect );
453 mTotalSize += ( image->width() * image->height() * 32 );
454 entry->image = std::move( image );
457 void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry,
bool forceVectorOutput )
459 Q_UNUSED( forceVectorOutput )
465 entry->picture.reset();
467 const bool isFixedAR = entry->fixedAspectRatio > 0;
470 std::unique_ptr< QPicture > picture = std::make_unique< QPicture >();
472 QSvgRenderer r( entry->svgContent );
473 double hwRatio = 1.0;
474 if ( r.viewBoxF().width() > 0 )
478 hwRatio = entry->fixedAspectRatio;
482 hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
486 const double wSize = entry->size;
487 const double hSize = wSize * hwRatio;
489 QSizeF s( r.viewBoxF().size() );
490 s.scale( wSize, hSize, isFixedAR ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio );
491 rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );
493 QPainter p( picture.get() );
494 r.render( &p, rect );
495 entry->picture = std::move( picture );
499 QgsSvgCacheEntry *QgsSvgCache::cacheEntry(
const QString &path,
double size,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
500 double widthScaleFactor,
double fixedAspectRatio,
const QMap<QString, QString> ¶meters,
bool blocking,
bool *isMissingImage )
502 QgsSvgCacheEntry *currentEntry =
findExistingEntry(
new QgsSvgCacheEntry( path, size, strokeWidth, widthScaleFactor, fill, stroke, fixedAspectRatio, parameters ) );
504 if ( currentEntry->svgContent.isEmpty() )
506 replaceParamsAndCacheSvg( currentEntry, blocking );
509 if ( isMissingImage )
510 *isMissingImage = currentEntry->isMissingImage;
516 void QgsSvgCache::replaceElemParams( QDomElement &elem,
const QColor &fill,
const QColor &stroke,
double strokeWidth,
const QMap<QString, QString> ¶meters )
524 const QDomNamedNodeMap attributes = elem.attributes();
525 const int nAttributes = attributes.count();
526 for (
int i = 0; i < nAttributes; ++i )
528 const QDomAttr attribute = attributes.item( i ).toAttr();
530 if ( attribute.name().compare( QLatin1String(
"style" ), Qt::CaseInsensitive ) == 0 )
533 QString newAttributeString;
535 const QStringList entryList = attribute.value().split(
';' );
536 QStringList::const_iterator entryIt = entryList.constBegin();
537 for ( ; entryIt != entryList.constEnd(); ++entryIt )
539 const QStringList keyValueSplit = entryIt->split(
':' );
540 if ( keyValueSplit.size() < 2 )
544 const QString key = keyValueSplit.at( 0 );
545 QString value = keyValueSplit.at( 1 );
546 QString newValue = value;
547 value = value.trimmed().toLower();
549 if ( value.startsWith( QLatin1String(
"param(fill)" ) ) )
551 newValue = fill.name();
553 else if ( value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
555 newValue = QString::number( fill.alphaF() );
557 else if ( value.startsWith( QLatin1String(
"param(outline)" ) ) )
559 newValue = stroke.name();
561 else if ( value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
563 newValue = QString::number( stroke.alphaF() );
565 else if ( value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
567 newValue = QString::number( strokeWidth );
570 if ( entryIt != entryList.constBegin() )
572 newAttributeString.append(
';' );
574 newAttributeString.append( key +
':' + newValue );
576 elem.setAttribute( attribute.name(), newAttributeString );
580 const QString value = attribute.value().trimmed().toLower();
581 if ( value.startsWith( QLatin1String(
"param(fill)" ) ) )
583 elem.setAttribute( attribute.name(), fill.name() );
585 else if ( value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
587 elem.setAttribute( attribute.name(), fill.alphaF() );
589 else if ( value.startsWith( QLatin1String(
"param(outline)" ) ) )
591 elem.setAttribute( attribute.name(), stroke.name() );
593 else if ( value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
595 elem.setAttribute( attribute.name(), stroke.alphaF() );
597 else if ( value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
599 elem.setAttribute( attribute.name(), QString::number( strokeWidth ) );
603 QMap<QString, QString>::const_iterator paramIt = parameters.constBegin();
604 for ( ; paramIt != parameters.constEnd(); ++paramIt )
606 if ( value.startsWith( QString( QLatin1String(
"param(%1)" ) ).arg( paramIt.key() ) ) )
608 elem.setAttribute( attribute.name(), paramIt.value() );
616 QDomNode child = elem.firstChild();
617 if ( child.isText() && child.nodeValue().startsWith(
"param(" ) )
619 QMap<QString, QString>::const_iterator paramIt = parameters.constBegin();
620 for ( ; paramIt != parameters.constEnd(); ++paramIt )
622 if ( child.toText().data().startsWith( QString( QLatin1String(
"param(%1)" ) ).arg( paramIt.key() ) ) )
624 child.setNodeValue( paramIt.value() );
630 const QDomNodeList childList = elem.childNodes();
631 const int nChildren = childList.count();
632 for (
int i = 0; i < nChildren; ++i )
634 QDomElement childElem = childList.at( i ).toElement();
635 replaceElemParams( childElem, fill, stroke, strokeWidth, parameters );
639 void QgsSvgCache::containsElemParams(
const QDomElement &elem,
bool &hasFillParam,
bool &hasDefaultFill, QColor &defaultFill,
640 bool &hasFillOpacityParam,
bool &hasDefaultFillOpacity,
double &defaultFillOpacity,
641 bool &hasStrokeParam,
bool &hasDefaultStroke, QColor &defaultStroke,
642 bool &hasStrokeWidthParam,
bool &hasDefaultStrokeWidth,
double &defaultStrokeWidth,
643 bool &hasStrokeOpacityParam,
bool &hasDefaultStrokeOpacity,
double &defaultStrokeOpacity )
const
651 if ( hasFillParam && hasStrokeParam && hasStrokeWidthParam && hasFillOpacityParam && hasStrokeOpacityParam )
657 const QDomNamedNodeMap attributes = elem.attributes();
658 const int nAttributes = attributes.count();
660 QStringList valueSplit;
661 for (
int i = 0; i < nAttributes; ++i )
663 const QDomAttr attribute = attributes.item( i ).toAttr();
664 if ( attribute.name().compare( QLatin1String(
"style" ), Qt::CaseInsensitive ) == 0 )
667 const QStringList entryList = attribute.value().split(
';' );
668 QStringList::const_iterator entryIt = entryList.constBegin();
669 for ( ; entryIt != entryList.constEnd(); ++entryIt )
671 const QStringList keyValueSplit = entryIt->split(
':' );
672 if ( keyValueSplit.size() < 2 )
676 const QString value = keyValueSplit.at( 1 );
677 valueSplit = value.split(
' ' );
678 if ( !hasFillParam && value.startsWith( QLatin1String(
"param(fill)" ) ) )
681 if ( valueSplit.size() > 1 )
683 defaultFill = QColor( valueSplit.at( 1 ) );
684 hasDefaultFill =
true;
687 else if ( !hasFillOpacityParam && value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
689 hasFillOpacityParam =
true;
690 if ( valueSplit.size() > 1 )
693 const double opacity = valueSplit.at( 1 ).toDouble( &ok );
696 defaultFillOpacity = opacity;
697 hasDefaultFillOpacity =
true;
701 else if ( !hasStrokeParam && value.startsWith( QLatin1String(
"param(outline)" ) ) )
703 hasStrokeParam =
true;
704 if ( valueSplit.size() > 1 )
706 defaultStroke = QColor( valueSplit.at( 1 ) );
707 hasDefaultStroke =
true;
710 else if ( !hasStrokeWidthParam && value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
712 hasStrokeWidthParam =
true;
713 if ( valueSplit.size() > 1 )
715 defaultStrokeWidth = valueSplit.at( 1 ).toDouble();
716 hasDefaultStrokeWidth =
true;
719 else if ( !hasStrokeOpacityParam && value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
721 hasStrokeOpacityParam =
true;
722 if ( valueSplit.size() > 1 )
725 const double opacity = valueSplit.at( 1 ).toDouble( &ok );
728 defaultStrokeOpacity = opacity;
729 hasDefaultStrokeOpacity =
true;
737 const QString value = attribute.value();
738 valueSplit = value.split(
' ' );
739 if ( !hasFillParam && value.startsWith( QLatin1String(
"param(fill)" ) ) )
742 if ( valueSplit.size() > 1 )
744 defaultFill = QColor( valueSplit.at( 1 ) );
745 hasDefaultFill =
true;
748 else if ( !hasFillOpacityParam && value.startsWith( QLatin1String(
"param(fill-opacity)" ) ) )
750 hasFillOpacityParam =
true;
751 if ( valueSplit.size() > 1 )
754 const double opacity = valueSplit.at( 1 ).toDouble( &ok );
757 defaultFillOpacity = opacity;
758 hasDefaultFillOpacity =
true;
762 else if ( !hasStrokeParam && value.startsWith( QLatin1String(
"param(outline)" ) ) )
764 hasStrokeParam =
true;
765 if ( valueSplit.size() > 1 )
767 defaultStroke = QColor( valueSplit.at( 1 ) );
768 hasDefaultStroke =
true;
771 else if ( !hasStrokeWidthParam && value.startsWith( QLatin1String(
"param(outline-width)" ) ) )
773 hasStrokeWidthParam =
true;
774 if ( valueSplit.size() > 1 )
776 defaultStrokeWidth = valueSplit.at( 1 ).toDouble();
777 hasDefaultStrokeWidth =
true;
780 else if ( !hasStrokeOpacityParam && value.startsWith( QLatin1String(
"param(outline-opacity)" ) ) )
782 hasStrokeOpacityParam =
true;
783 if ( valueSplit.size() > 1 )
786 const double opacity = valueSplit.at( 1 ).toDouble( &ok );
789 defaultStrokeOpacity = opacity;
790 hasDefaultStrokeOpacity =
true;
798 const QDomNodeList childList = elem.childNodes();
799 const int nChildren = childList.count();
800 for (
int i = 0; i < nChildren; ++i )
802 const QDomElement childElem = childList.at( i ).toElement();
803 containsElemParams( childElem, hasFillParam, hasDefaultFill, defaultFill,
804 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
805 hasStrokeParam, hasDefaultStroke, defaultStroke,
806 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
807 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
811 QSize QgsSvgCache::sizeForImage(
const QgsSvgCacheEntry &entry, QSizeF &viewBoxSize, QSizeF &scaledSize )
const
813 const bool isFixedAR = entry.fixedAspectRatio > 0;
815 const QSvgRenderer r( entry.svgContent );
816 double hwRatio = 1.0;
817 viewBoxSize = r.viewBoxF().size();
818 if ( viewBoxSize.width() > 0 )
822 hwRatio = entry.fixedAspectRatio;
826 hwRatio = viewBoxSize.height() / viewBoxSize.width();
831 scaledSize.setWidth( entry.size );
832 int wImgSize =
static_cast< int >( scaledSize.width() );
837 scaledSize.setHeight( scaledSize.width() * hwRatio );
838 int hImgSize =
static_cast< int >( scaledSize.height() );
843 return QSize( wImgSize, hImgSize );
846 QImage QgsSvgCache::imageFromCachedPicture(
const QgsSvgCacheEntry &entry )
const
850 QImage image( sizeForImage( entry, viewBoxSize, scaledSize ), QImage::Format_ARGB32_Premultiplied );
853 QPainter p( &image );
854 p.drawPicture( QPoint( 0, 0 ), *entry.picture );