From 5aa46b1052b05d34cbfef175caaf941928520964 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 27 Jul 2009 13:20:14 +0200 Subject: Added support for 'vector-effect' in QtSvg. Task-number: 254040 Reviewed-by: Tor Arne --- src/svg/qsvghandler.cpp | 232 +++++++++++++++++++++++++++++++----------------- 1 file changed, 150 insertions(+), 82 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index f10b26f..b829a22 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -697,85 +697,152 @@ static void parseQPen(QPen &pen, QSvgNode *node, QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString(); QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString(); QString width = attributes.value(QLatin1String("stroke-width")).toString(); + QString vectorEffect = attributes.value(QLatin1String("vector-effect")).toString(); QString myId = someId(attributes); - if (!value.isEmpty() || !width.isEmpty()) { - if (value != QLatin1String("none")) { - if (!value.isEmpty()) { - if (node && value.startsWith(QLatin1String("url"))) { - value = value.remove(0, 3); - QSvgStyleProperty *style = styleFromUrl(node, value); - if (style) { - if (style->type() == QSvgStyleProperty::GRADIENT) { - QBrush b(*((QSvgGradientStyle*)style)->qgradient()); - pen.setBrush(b); - } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { - pen.setColor( - ((QSvgSolidColorStyle*)style)->qcolor()); - } - } else { - qWarning()<<"QSvgHandler::parsePen could not resolve property" << idFromUrl(value); - } - } else { - QColor color; - if (constructColor(value, opacity, color, handler)) - pen.setColor(color); - } - //since we could inherit stroke="none" - //we need to reset the style of our stroke to something - pen.setStyle(Qt::SolidLine); - } - if (!width.isEmpty()) { - QSvgHandler::LengthType lt; - qreal widthF = parseLength(width, lt, handler); - //### fixme - if (!widthF) { - pen.setStyle(Qt::NoPen); - return; - } - pen.setWidthF(widthF); - } - qreal penw = pen.widthF(); - - if (!linejoin.isEmpty()) { - if (linejoin == QLatin1String("miter")) - pen.setJoinStyle(Qt::SvgMiterJoin); - else if (linejoin == QLatin1String("round")) - pen.setJoinStyle(Qt::RoundJoin); - else if (linejoin == QLatin1String("bevel")) - pen.setJoinStyle(Qt::BevelJoin); - } - if (!miterlimit.isEmpty()) - pen.setMiterLimit(toDouble(miterlimit)); - - if (!linecap.isEmpty()) { - if (linecap == QLatin1String("butt")) - pen.setCapStyle(Qt::FlatCap); - else if (linecap == QLatin1String("round")) - pen.setCapStyle(Qt::RoundCap); - else if (linecap == QLatin1String("square")) - pen.setCapStyle(Qt::SquareCap); - } + QSvgStrokeStyle *inherited = + static_cast(node->parent()->styleProperty( + QSvgStyleProperty::STROKE)); - if (!dashArray.isEmpty()) { - const QChar *s = dashArray.constData(); - QVector dashes = parseNumbersList(s); - qreal *d = dashes.data(); - if (penw != 0) - for (int i = 0; i < dashes.size(); ++i) { - *d /= penw; - ++d; + bool stroke = false; + if (inherited) { + pen = inherited->qpen(); + stroke = inherited->strokePresent(); + } else { + pen = handler->defaultPen(); + } + + // stroke-opacity attribute handling + qreal strokeAlpha; + if (!opacity.isEmpty() && opacity != QLatin1String("inherit")) { + strokeAlpha = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); + } else { + strokeAlpha = pen.color().alphaF(); + } + + //stroke attribute handling + if (!value.isEmpty() && value != QLatin1String("inherit")) { + if (value.startsWith(QLatin1String("url"))) { + value = value.remove(0, 3); + QSvgStyleProperty *style = styleFromUrl(node, value); + if (style) { + if (style->type() == QSvgStyleProperty::GRADIENT) { + QBrush b(*((QSvgGradientStyle*)style)->qgradient()); + pen.setBrush(b); + } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { + pen.setColor(((QSvgSolidColorStyle*)style)->qcolor()); } - pen.setDashPattern(dashes); + stroke = true; + } else { + qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value); } - if (!dashOffset.isEmpty()) { - pen.setDashOffset(toDouble(dashOffset)); + } else if (value == QLatin1String("none")) { + QColor color; + color.setAlphaF(strokeAlpha); + pen.setColor(color); + stroke = false; + } else { + QColor color; + if (resolveColor(value, color, handler)) { + color.setAlphaF(strokeAlpha); + pen.setColor(color); } + stroke = true; + } + } else { + QColor color = pen.color(); + color.setAlphaF(strokeAlpha); + pen.setColor(color); + } - } else { - pen.setStyle(Qt::NoPen); + //stroke-width handling + if (!width.isEmpty() && width != QLatin1String("inherit")) { + qreal widthF; + QSvgHandler::LengthType lt; + widthF = parseLength(width, lt, handler); + pen.setWidthF(widthF); + } + + //stroke-linejoin attribute handling + if (!linejoin.isEmpty()) { + if (linejoin == QLatin1String("miter")) + pen.setJoinStyle(Qt::SvgMiterJoin); + else if (linejoin == QLatin1String("round")) + pen.setJoinStyle(Qt::RoundJoin); + else if (linejoin == QLatin1String("bevel")) + pen.setJoinStyle(Qt::BevelJoin); + } + + //stroke-linecap attribute handling + if (!linecap.isEmpty()) { + if (linecap == QLatin1String("butt")) + pen.setCapStyle(Qt::FlatCap); + else if (linecap == QLatin1String("round")) + pen.setCapStyle(Qt::RoundCap); + else if (linecap == QLatin1String("square")) + pen.setCapStyle(Qt::SquareCap); + } + + //strok-dasharray attribute handling + qreal penw = pen.widthF(); + if (!dashArray.isEmpty() && dashArray != QLatin1String("inherit")) { + const QChar *s = dashArray.constData(); + QVector dashes = parseNumbersList(s); + qreal *d = dashes.data(); + if (penw != 0) + for (int i = 0; i < dashes.size(); ++i) { + *d /= penw; + ++d; + } + // if the dash count is odd the dashes should be duplicated + if (dashes.size() % 2 != 0) + dashes << QVector(dashes); + pen.setDashPattern(dashes); + } else if (inherited) { + QVector dashes(inherited->qpen().dashPattern()); + qreal *d = dashes.data(); + if (!penw) + penw = 1.0; + qreal inheritpenw = inherited->qpen().widthF(); + if (!inheritpenw) + inheritpenw = 1.0; + for ( int i = 0; i < dashes.size(); ++i) { + *d *= (inheritpenw/ penw); + ++d; } + pen.setDashPattern(dashes); } + + //stroke-dashoffset attribute handling + if (!dashOffset.isEmpty() && dashOffset != QLatin1String("inherit")) { + qreal doffset = toDouble(dashOffset); + if (penw != 0) + doffset /= penw; + pen.setDashOffset(doffset); + } else if (inherited) { + qreal doffset = pen.dashOffset(); + if (!penw) + penw = 1.0; + qreal inheritpenw = inherited->qpen().widthF(); + if (!inheritpenw) + inheritpenw = 1.0; + doffset *= (inheritpenw / penw); + pen.setDashOffset(doffset); + } + + //vector-effect attribute handling + if (!vectorEffect.isEmpty()) { + if (vectorEffect == QLatin1String("non-scaling-stroke")) + pen.setCosmetic(true); + else if (vectorEffect == QLatin1String("none")) + pen.setCosmetic(false); + } + + if (!miterlimit.isEmpty() && miterlimit != QLatin1String("inherit")) + pen.setMiterLimit(toDouble(miterlimit)); + + if (!stroke) + pen.setStyle(Qt::NoPen); } static QMatrix parseTransformationMatrix(const QString &value) @@ -917,18 +984,15 @@ static void parsePen(QSvgNode *node, QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString(); QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString(); QString width = attributes.value(QLatin1String("stroke-width")).toString(); + QString vectorEffect = attributes.value(QLatin1String("vector-effect")).toString(); QString myId = someId(attributes); //qDebug()<<"Node "<type()<<", attrs are "<(node->parent()->styleProperty( QSvgStyleProperty::STROKE)); @@ -961,8 +1025,7 @@ static void parsePen(QSvgNode *node, pen.setColor( ((QSvgSolidColorStyle*)style)->qcolor()); } - pen.setStyle(Qt::SolidLine); - stroke = true; + stroke = true; } else { qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value); } @@ -991,9 +1054,6 @@ static void parsePen(QSvgNode *node, QSvgHandler::LengthType lt; widthF = parseLength(width, lt, handler); pen.setWidthF(widthF); - } else if (inherited){ - qreal widthF = inherited->qpen().widthF(); - pen.setWidthF(widthF); } //stroke-linejoin attribute handling @@ -1064,6 +1124,14 @@ static void parsePen(QSvgNode *node, pen.setDashOffset(doffset); } + //vector-effect attribute handling + if (!vectorEffect.isEmpty()) { + if (vectorEffect == QLatin1String("non-scaling-stroke")) + pen.setCosmetic(true); + else if (vectorEffect == QLatin1String("none")) + pen.setCosmetic(false); + } + if (!miterlimit.isEmpty() && miterlimit != QLatin1String("inherit")) pen.setMiterLimit(toDouble(miterlimit)); -- cgit v0.12