diff options
Diffstat (limited to 'src')
5 files changed, 115 insertions, 61 deletions
diff --git a/src/quickvectorimage/generator/qquickitemgenerator.cpp b/src/quickvectorimage/generator/qquickitemgenerator.cpp index c939ffccd7..1917c53013 100644 --- a/src/quickvectorimage/generator/qquickitemgenerator.cpp +++ b/src/quickvectorimage/generator/qquickitemgenerator.cpp @@ -123,12 +123,12 @@ void QQuickItemGenerator::outputShapePath(const PathNodeInfo &info, const QPaint Q_UNUSED(pathSelector) Q_ASSERT(painterPath || quadPath); - QString penName = info.strokeColor; - const bool noPen = penName.isEmpty() || penName == u"transparent"; + const bool noPen = info.strokeColor == QColorConstants::Transparent; if (pathSelector == QQuickVectorImageGenerator::StrokePath && noPen) return; - const bool noFill = info.grad.type() == QGradient::NoGradient && info.fillColor == u"transparent"; + const bool noFill = info.grad.type() == QGradient::NoGradient && info.fillColor == QColorConstants::Transparent; + if (pathSelector == QQuickVectorImageGenerator::FillPath && noFill) return; @@ -145,7 +145,7 @@ void QQuickItemGenerator::outputShapePath(const PathNodeInfo &info, const QPaint if (noPen || !(pathSelector & QQuickVectorImageGenerator::StrokePath)) { shapePath->setStrokeColor(Qt::transparent); } else { - shapePath->setStrokeColor(QColor::fromString(penName)); + shapePath->setStrokeColor(info.strokeColor); shapePath->setStrokeWidth(info.strokeWidth); } @@ -156,7 +156,7 @@ void QQuickItemGenerator::outputShapePath(const PathNodeInfo &info, const QPaint else if (info.grad.type() != QGradient::NoGradient) generateGradient(&info.grad, shapePath, boundingRect); else - shapePath->setFillColor(QColor::fromString(info.fillColor)); + shapePath->setFillColor(info.fillColor); shapePath->setFillRule(fillRule); @@ -179,7 +179,7 @@ void QQuickItemGenerator::generateGradient(const QGradient *grad, QQuickShapePat if (!shapePath) return; - auto setStops = [](QQuickShapeGradient *quickGrad, const QGradientStops &stops) { + auto setStops = [=](QQuickShapeGradient *quickGrad, const QGradientStops &stops) { auto stopsProp = quickGrad->stops(); for (auto &stop : stops) { auto *stopObj = new QQuickGradientStop(quickGrad); @@ -281,13 +281,13 @@ void QQuickItemGenerator::generateTextNode(const TextNodeInfo &info) } } - textItem->setColor(QColor::fromString(info.color)); + textItem->setColor(info.fillColor); textItem->setTextFormat(info.needsRichText ? QQuickText::RichText : QQuickText::StyledText); textItem->setText(info.text); textItem->setFont(info.font); - if (!info.strokeColor.isEmpty()) { - textItem->setStyleColor(QColor::fromString(info.strokeColor)); + if (info.strokeColor != QColorConstants::Transparent) { + textItem->setStyleColor(info.strokeColor); textItem->setStyle(QQuickText::Outline); } diff --git a/src/quickvectorimage/generator/qquicknodeinfo_p.h b/src/quickvectorimage/generator/qquicknodeinfo_p.h index 012e8f8c69..28629bf3e1 100644 --- a/src/quickvectorimage/generator/qquicknodeinfo_p.h +++ b/src/quickvectorimage/generator/qquicknodeinfo_p.h @@ -49,9 +49,9 @@ struct PathNodeInfo : NodeInfo QPainterPath painterPath; Qt::FillRule fillRule = Qt::FillRule::WindingFill; Qt::PenCapStyle capStyle = Qt::SquareCap; - QString strokeColor; + QColor strokeColor; qreal strokeWidth; - QString fillColor; + QColor fillColor; QGradient grad; }; @@ -64,8 +64,8 @@ struct TextNodeInfo : NodeInfo QString text; QFont font; Qt::Alignment alignment; - QString color; - QString strokeColor; + QColor fillColor; + QColor strokeColor; }; enum class StructureNodeStage diff --git a/src/quickvectorimage/generator/qquickqmlgenerator.cpp b/src/quickvectorimage/generator/qquickqmlgenerator.cpp index bdd3a29ed1..731d80f2da 100644 --- a/src/quickvectorimage/generator/qquickqmlgenerator.cpp +++ b/src/quickvectorimage/generator/qquickqmlgenerator.cpp @@ -220,9 +220,8 @@ void QQuickQmlGenerator::generateGradient(const QGradient *grad, const QRectF &b stream() << "y1: " << logRect.top(); stream() << "x2: " << logRect.right(); stream() << "y2: " << logRect.bottom(); - for (auto &stop : linGrad->stops()) { + for (auto &stop : linGrad->stops()) stream() << "GradientStop { position: " << stop.first << "; color: \"" << stop.second.name(QColor::HexArgb) << "\" }"; - } m_indentLevel--; stream() << "}"; } else if (grad->type() == QGradient::RadialGradient) { @@ -235,9 +234,8 @@ void QQuickQmlGenerator::generateGradient(const QGradient *grad, const QRectF &b stream() << "centerRadius: " << radGrad->radius(); stream() << "focalX:" << radGrad->focalPoint().x(); stream() << "focalY:" << radGrad->focalPoint().y(); - for (auto &stop : radGrad->stops()) { + for (auto &stop : radGrad->stops()) stream() << "GradientStop { position: " << stop.first << "; color: \"" << stop.second.name(QColor::HexArgb) << "\" }"; - } m_indentLevel--; stream() << "}"; } @@ -248,12 +246,12 @@ void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainte Q_UNUSED(pathSelector) Q_ASSERT(painterPath || quadPath); - QString penName = info.strokeColor; - const bool noPen = penName.isEmpty() || penName == u"transparent"; + const bool noPen = info.strokeColor == QColorConstants::Transparent; if (pathSelector == QQuickVectorImageGenerator::StrokePath && noPen) return; - const bool noFill = info.grad.type() == QGradient::NoGradient && info.fillColor == u"transparent"; + const bool noFill = info.grad.type() == QGradient::NoGradient && info.fillColor == QColorConstants::Transparent; + if (pathSelector == QQuickVectorImageGenerator::FillPath && noFill) return; @@ -277,7 +275,7 @@ void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainte if (noPen || !(pathSelector & QQuickVectorImageGenerator::StrokePath)) { stream() << "strokeColor: \"transparent\""; } else { - stream() << "strokeColor: \"" << penName << "\""; + stream() << "strokeColor: \"" << info.strokeColor.name(QColor::HexArgb) << "\""; stream() << "strokeWidth: " << info.strokeWidth; } if (info.capStyle == Qt::FlatCap) @@ -288,8 +286,7 @@ void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainte } else if (info.grad.type() != QGradient::NoGradient) { generateGradient(&info.grad, boundingRect); } else { - stream() << "fillColor: \"" << info.fillColor << "\""; - + stream() << "fillColor: \"" << info.fillColor.name(QColor::HexArgb) << "\""; } if (fillRule == QQuickShapePath::WindingFill) stream() << "fillRule: ShapePath.WindingFill"; @@ -368,7 +365,7 @@ void QQuickQmlGenerator::generateTextNode(const TextNodeInfo &info) } counter++; - stream() << "color: \"" << info.color << "\""; + stream() << "color: \"" << info.fillColor.name(QColor::HexArgb) << "\""; stream() << "textFormat:" << (info.needsRichText ? "Text.RichText" : "Text.StyledText"); QString s = info.text; @@ -386,8 +383,8 @@ void QQuickQmlGenerator::generateTextNode(const TextNodeInfo &info) if (info.font.italic()) stream() << "font.italic: true"; - if (!info.strokeColor.isEmpty()) { - stream() << "styleColor: \"" << info.strokeColor << "\""; + if (info.strokeColor != QColorConstants::Transparent) { + stream() << "styleColor: \"" << info.strokeColor.name(QColor::HexArgb) << "\""; stream() << "style: Text.Outline"; } diff --git a/src/quickvectorimage/generator/qsvgvisitorimpl.cpp b/src/quickvectorimage/generator/qsvgvisitorimpl.cpp index 6ccd51ee39..ce595f9a6b 100644 --- a/src/quickvectorimage/generator/qsvgvisitorimpl.cpp +++ b/src/quickvectorimage/generator/qsvgvisitorimpl.cpp @@ -87,9 +87,9 @@ public: { m_dummyImage = QImage(1, 1, QImage::Format_RGB32); m_dummyPainter.begin(&m_dummyImage); - QPen noPen(Qt::NoPen); - noPen.setBrush(Qt::NoBrush); - m_dummyPainter.setPen(noPen); + QPen defaultPen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin); + defaultPen.setMiterLimit(4); + m_dummyPainter.setPen(defaultPen); m_dummyPainter.setBrush(Qt::black); } @@ -101,16 +101,23 @@ public: QPainter& painter() { return m_dummyPainter; } QSvgExtraStates& states() { return m_svgState; } - QString currentFillColor() const + QColor currentFillColor() const { - if (m_dummyPainter.brush().style() != Qt::NoBrush) { - QColor c(m_dummyPainter.brush().color()); - c.setAlphaF(m_svgState.fillOpacity); - //qCDebug(lcQuickVectorGraphics) << "FILL" << c << m_svgState.fillOpacity << c.name(); - return c.name(QColor::HexArgb); - } else { - return QStringLiteral("transparent"); + if (m_dummyPainter.brush().style() == Qt::NoBrush || + m_dummyPainter.brush().color() == QColorConstants::Transparent) { + return QColor(QColorConstants::Transparent); } + + QColor fillColor; + fillColor = m_dummyPainter.brush().color(); + fillColor.setAlphaF(m_svgState.fillOpacity); + + return fillColor; + } + + qreal currentFillOpacity() const + { + return m_svgState.fillOpacity; } const QGradient *currentFillGradient() const @@ -120,13 +127,23 @@ public: return nullptr; } - QString currentStrokeColor() const + QColor currentStrokeColor() const + { + if (m_dummyPainter.pen().brush().style() == Qt::NoBrush || + m_dummyPainter.pen().brush().color() == QColorConstants::Transparent) { + return QColor(QColorConstants::Transparent); + } + + QColor strokeColor; + strokeColor = m_dummyPainter.pen().brush().color(); + strokeColor.setAlphaF(m_svgState.strokeOpacity); + + return strokeColor; + } + + qreal currentStrokeOpacity() const { - if (m_dummyPainter.pen().style() != Qt::NoPen) - return m_dummyPainter.pen().color().name(); - else if (m_dummyPainter.pen().brush().style() == Qt::SolidPattern) - return m_dummyPainter.pen().brush().color().name(); - return {}; + return m_svgState.strokeOpacity; } float currentStrokeWidth() const @@ -135,6 +152,20 @@ public: return penWidth ? penWidth : 1; } + static QGradient applyOpacityToGradient(const QGradient &gradient, float opacity) + { + QGradient grad = gradient; + QGradientStops stops; + for (auto &stop : grad.stops()) { + stop.second.setAlphaF(stop.second.alphaF() * opacity); + stops.append(stop); + } + + grad.setStops(stops); + + return grad; + } + protected: QPainter m_dummyPainter; QImage m_dummyImage; @@ -307,7 +338,7 @@ QString QSvgVisitorImpl::gradientCssDescription(const QGradient *gradient) cssDescription += ",stop:"_L1; cssDescription += QString::number(stop.first); cssDescription += u' '; - cssDescription += stop.second.name(); + cssDescription += stop.second.name(QColor::HexArgb); } cssDescription += ");"_L1; @@ -315,6 +346,18 @@ QString QSvgVisitorImpl::gradientCssDescription(const QGradient *gradient) return cssDescription; } +QString QSvgVisitorImpl::colorCssDescription(QColor color) +{ + QString cssDescription; + cssDescription += QStringLiteral("rgba("); + cssDescription += QString::number(color.red()) + QStringLiteral(","); + cssDescription += QString::number(color.blue()) + QStringLiteral(","); + cssDescription += QString::number(color.green()) + QStringLiteral(","); + cssDescription += QString::number(color.alphaF()) + QStringLiteral(")"); + + return cssDescription; +} + void QSvgVisitorImpl::visitTextNode(const QSvgText *node) { handleBaseNodeSetup(node); @@ -361,11 +404,12 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) if (styleResolver->currentFillGradient() != nullptr && styleResolver->currentFillGradient() != mainGradient) { - styleTagContent += gradientCssDescription(styleResolver->currentFillGradient()) + u';'; + const QGradient grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity()); + styleTagContent += gradientCssDescription(&grad) + u';'; needsPathNode = true; } - QString strokeColor = styleResolver->currentStrokeColor(); + QString strokeColor = colorCssDescription(styleResolver->currentStrokeColor()); if (!strokeColor.isEmpty()) { styleTagContent += QStringLiteral("-qt-stroke-color:%1;").arg(strokeColor); styleTagContent += QStringLiteral("-qt-stroke-width:%1;").arg(styleResolver->currentStrokeWidth()); @@ -379,6 +423,26 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) content.replace(QLatin1Char('\t'), QLatin1Char(' ')); content.replace(QLatin1Char('\n'), QLatin1Char(' ')); + bool fontTag = false; + if (!tspan->style().fill.isDefault()) { + auto &b = tspan->style().fill->qbrush(); + qCDebug(lcQuickVectorImage) << "tspan FILL:" << b; + if (b.style() != Qt::NoBrush) + { + if (qFuzzyCompare(b.color().alphaF() + 1.0, 2.0)) + { + QString spanColor = b.color().name(); + fontTag = !spanColor.isEmpty(); + if (fontTag) + text += QStringLiteral("<font color=\"%1\">").arg(spanColor); + } else { + QString spanColor = colorCssDescription(b.color()); + styleTagContent += QStringLiteral("color:%1").arg(spanColor); + } + } + } + + needsRichText = needsRichText || !styleTagContent.isEmpty(); if (!styleTagContent.isEmpty()) text += QStringLiteral("<span style=\"%1\">").arg(styleTagContent); @@ -389,16 +453,6 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) if (font.resolveMask() & QFont::StyleResolved && font.italic()) text += QStringLiteral("<i>"); - QString spanColor; - if (!tspan->style().fill.isDefault()) { - auto &b = tspan->style().fill->qbrush(); - qCDebug(lcQuickVectorImage) << "tspan FILL:" << b; - if (b.style() != Qt::NoBrush) - spanColor = b.color().name(); - } - bool fontTag = !spanColor.isEmpty(); - if (fontTag) - text += QStringLiteral("<font color=\"%1\">").arg(spanColor); if (font.resolveMask() & QFont::CapitalizationResolved) { switch (font.capitalization()) { @@ -462,7 +516,7 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) info.fillRule = fillStyle->fillRule(); if (fmt.hasProperty(QTextCharFormat::ForegroundBrush)) { - info.fillColor = fmt.foreground().color().name(); + info.fillColor = fmt.foreground().color(); if (fmt.foreground().gradient() != nullptr && fmt.foreground().gradient()->type() != QGradient::NoGradient) info.grad = *fmt.foreground().gradient(); } else { @@ -470,15 +524,17 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) } info.painterPath = p; + if (fmt.hasProperty(QTextCharFormat::TextOutline)) { info.strokeWidth = fmt.textOutline().widthF(); - info.strokeColor = fmt.textOutline().color().name(); + info.strokeColor = fmt.textOutline().color(); } else { info.strokeColor = styleResolver->currentStrokeColor(); info.strokeWidth = styleResolver->currentStrokeWidth(); } + if (info.grad.type() == QGradient::NoGradient && styleResolver->currentFillGradient() != nullptr) - info.grad = *styleResolver->currentFillGradient(); + info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity()); m_generator->generatePath(info); }; @@ -542,7 +598,7 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node) info.text = text; info.isTextArea = isTextArea; info.needsRichText = needsRichText; - info.color = styleResolver->currentFillColor(); + info.fillColor = styleResolver->currentFillColor(); info.alignment = styleResolver->states().textAnchor; info.strokeColor = styleResolver->currentStrokeColor(); @@ -698,7 +754,7 @@ void QSvgVisitorImpl::handlePathNode(const QSvgNode *node, const QPainterPath &p info.strokeColor = styleResolver->currentStrokeColor(); info.strokeWidth = styleResolver->currentStrokeWidth(); if (styleResolver->currentFillGradient() != nullptr) - info.grad = *styleResolver->currentFillGradient(); + info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity()); m_generator->generatePath(info); diff --git a/src/quickvectorimage/generator/qsvgvisitorimpl_p.h b/src/quickvectorimage/generator/qsvgvisitorimpl_p.h index 12da4b68ca..d80c9ec992 100644 --- a/src/quickvectorimage/generator/qsvgvisitorimpl_p.h +++ b/src/quickvectorimage/generator/qsvgvisitorimpl_p.h @@ -57,6 +57,7 @@ private: void handlePathNode(const QSvgNode *node, const QPainterPath &path, Qt::PenCapStyle capStyle = Qt::SquareCap); void outputShapePath(QPainterPath pathCopy, const PathNodeInfo &info); static QString gradientCssDescription(const QGradient *gradient); + static QString colorCssDescription(QColor color); private: QString m_svgFileName; |