summaryrefslogtreecommitdiff
path: root/src/svg/qsvggenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/svg/qsvggenerator.cpp')
-rw-r--r--src/svg/qsvggenerator.cpp68
1 files changed, 65 insertions, 3 deletions
diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp
index 5829a1a..3f4e545 100644
--- a/src/svg/qsvggenerator.cpp
+++ b/src/svg/qsvggenerator.cpp
@@ -52,6 +52,7 @@
#include "qtextstream.h"
#include "qbuffer.h"
#include "qmath.h"
+#include "qbitmap.h"
#include "qdebug.h"
@@ -128,6 +129,9 @@ public:
QString currentGradientName;
int numGradients;
+ QStringList savedPatternBrushes;
+ QStringList savedPatternMasks;
+
struct _attributes {
QString document_title;
QString document_description;
@@ -145,12 +149,13 @@ static inline QPaintEngine::PaintEngineFeatures svgEngineFeatures()
{
return QPaintEngine::PaintEngineFeatures(
QPaintEngine::AllFeatures
- & ~QPaintEngine::PatternBrush
& ~QPaintEngine::PerspectiveTransform
& ~QPaintEngine::ConicalGradientFill
& ~QPaintEngine::PorterDuff);
}
+Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
+
class QSvgPaintEngine : public QPaintEngine
{
Q_DECLARE_PRIVATE(QSvgPaintEngine)
@@ -212,6 +217,41 @@ public:
Q_ASSERT(!isActive());
d_func()->resolution = resolution;
}
+
+ QString savePatternMask(Qt::BrushStyle style)
+ {
+ QString maskId = QString(QStringLiteral("patternmask%1")).arg(style);
+ if (!d_func()->savedPatternMasks.contains(maskId)) {
+ QImage img = qt_imageForBrush(style, true);
+ QRegion reg(QBitmap::fromData(img.size(), img.constBits()));
+ QString rct(QStringLiteral("<rect x=\"%1\" y=\"%2\" width=\"%3\" height=\"%4\" />"));
+ QTextStream str(&d_func()->defs, QIODevice::Append);
+ str << "<mask id=\"" << maskId << "\" x=\"0\" y=\"0\" width=\"8\" height=\"8\" "
+ << "stroke=\"none\" fill=\"#ffffff\" patternUnits=\"userSpaceOnUse\" >" << endl;
+ for (QRect r : reg.rects()) {
+ str << rct.arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()) << endl;
+ }
+ str << QStringLiteral("</mask>") << endl << endl;
+ d_func()->savedPatternMasks.append(maskId);
+ }
+ return maskId;
+ }
+
+ QString savePatternBrush(const QString &color, const QBrush &brush)
+ {
+ QString patternId = QString(QStringLiteral("fillpattern%1_")).arg(brush.style()) + color.midRef(1);
+ if (!d_func()->savedPatternBrushes.contains(patternId)) {
+ QString maskId = savePatternMask(brush.style());
+ QString geo(QStringLiteral("x=\"0\" y=\"0\" width=\"8\" height=\"8\""));
+ QTextStream str(&d_func()->defs, QIODevice::Append);
+ str << QString(QStringLiteral("<pattern id=\"%1\" %2 patternUnits=\"userSpaceOnUse\" >")).arg(patternId, geo) << endl;
+ str << QString(QStringLiteral("<rect %1 stroke=\"none\" fill=\"%2\" mask=\"url(#%3);\" />")).arg(geo, color, maskId) << endl;
+ str << QStringLiteral("</pattern>") << endl << endl;
+ d_func()->savedPatternBrushes.append(patternId);
+ }
+ return patternId;
+ }
+
void saveLinearGradientBrush(const QGradient *g)
{
QTextStream str(&d_func()->defs, QIODevice::Append);
@@ -242,7 +282,7 @@ public:
<< QLatin1String("fx=\"") <<grad->focalPoint().x() << QLatin1String("\" ")
<< QLatin1String("fy=\"") <<grad->focalPoint().y() << QLatin1String("\" ");
}
- str << QLatin1String("xml:id=\"") <<d_func()->generateGradientName()<< QLatin1String("\">\n");
+ str << QLatin1String("id=\"") <<d_func()->generateGradientName()<< QLatin1String("\">\n");
saveGradientStops(str, g);
str << QLatin1String("</radialGradient>") << endl;
}
@@ -421,6 +461,28 @@ public:
d_func()->attributes.fillOpacity = colorOpacity;
}
break;
+ case Qt::Dense1Pattern:
+ case Qt::Dense2Pattern:
+ case Qt::Dense3Pattern:
+ case Qt::Dense4Pattern:
+ case Qt::Dense5Pattern:
+ case Qt::Dense6Pattern:
+ case Qt::Dense7Pattern:
+ case Qt::HorPattern:
+ case Qt::VerPattern:
+ case Qt::CrossPattern:
+ case Qt::BDiagPattern:
+ case Qt::FDiagPattern:
+ case Qt::DiagCrossPattern: {
+ QString color, colorOpacity;
+ translate_color(sbrush.color(), &color, &colorOpacity);
+ QString patternId = savePatternBrush(color, sbrush);
+ QString patternRef = QString(QStringLiteral("url(#%1)")).arg(patternId);
+ stream() << "fill=\"" << patternRef << "\" fill-opacity=\"" << colorOpacity << "\" ";
+ d_func()->attributes.fill = patternRef;
+ d_func()->attributes.fillOpacity = colorOpacity;
+ break;
+ }
case Qt::LinearGradientPattern:
saveLinearGradientBrush(sbrush.gradient());
d_func()->attributes.fill = QString::fromLatin1("url(#%1)").arg(d_func()->currentGradientName);
@@ -1062,7 +1124,7 @@ void QSvgPaintEngine::drawRects(const QRectF *rects, int rectCount)
Q_D(QSvgPaintEngine);
for (int i=0; i < rectCount; ++i) {
- const QRectF &rect = rects[i];
+ const QRectF &rect = rects[i].normalized();
*d->stream << "<rect";
if (state->pen().isCosmetic())
*d->stream << " vector-effect=\"non-scaling-stroke\"";