Commit 95034944 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Don't write stroke and fill of a <tspan> if it is inherited

Basically, we put stroke and fill into the properties object and
use already prepared framework to distinguish the values of the
parent and a child.
parent 1b211b76
......@@ -66,6 +66,9 @@ void SvgStyleWriter::saveSvgStyle(KoShape *shape, SvgSavingContext &context)
{
saveSvgBasicStyle(shape, context);
saveSvgFill(shape, context);
saveSvgStroke(shape, context);
saveSvgEffects(shape, context);
saveSvgClipping(shape, context);
saveSvgMasking(shape, context);
......@@ -74,8 +77,6 @@ void SvgStyleWriter::saveSvgStyle(KoShape *shape, SvgSavingContext &context)
void SvgStyleWriter::saveSvgBasicStyle(KoShape *shape, SvgSavingContext &context)
{
saveSvgFill(shape, context);
saveSvgStroke(shape, context);
if (! shape->isVisible()) {
context.shapeWriter().addAttribute("display", "none");
} if (shape->transparency() > 0.0) {
......
......@@ -50,11 +50,12 @@ public:
/// Saves only stroke, fill and transparency of the shape
static void saveSvgBasicStyle(KoShape *shape, SvgSavingContext &context);
protected:
/// Saves fill style of specified shape
static void saveSvgFill(KoShape *shape, SvgSavingContext &context);
/// Saves stroke style of specified shape
static void saveSvgStroke(KoShape *shape, SvgSavingContext &context);
protected:
/// Saves effects of specified shape
static void saveSvgEffects(KoShape *shape, SvgSavingContext &context);
/// Saves clipping of specified shape
......
......@@ -854,6 +854,30 @@ void TestSvgText::testNbspHandling()
t.test_standard("text_nbsp", QSize(30, 30), 72.0);
}
void TestSvgText::testMulticolorText()
{
const QString data =
"<svg width=\"100px\" height=\"30px\""
" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
"<g id=\"test\">"
" <rect id=\"boundingRect\" x=\"4\" y=\"5\" width=\"89\" height=\"19\""
" fill=\"none\" stroke=\"red\"/>"
" <text id=\"testRect\" x=\"2\" y=\"24\""
" font-family=\"Verdana\" font-size=\"15\" fill=\"blue\" >"
" S<tspan fill=\"red\">A</tspan>"
" </text>"
"</g>"
"</svg>";
SvgRenderTester t (data);
t.test_standard("text_multicolor", QSize(30, 30), 72.0);
}
QTEST_MAIN(TestSvgText)
......@@ -46,6 +46,7 @@ private Q_SLOTS:
void testTextOutlineSolid();
void testNbspHandling();
void testMulticolorText();
};
#endif // TESTSVGTEXT_H
......@@ -23,6 +23,11 @@
#include <QDebug>
#include "kis_dom_utils.h"
#include <KoColorBackground.h>
#include <KoGradientBackground.h>
#include <KoVectorPatternBackground.h>
#include <KoShapeStroke.h>
namespace {
......@@ -32,9 +37,13 @@ struct TextPropertiesStaticRegistrar {
QMetaType::registerEqualsComparator<KoSvgText::AutoValue>();
QMetaType::registerDebugStreamOperator<KoSvgText::AutoValue>();
qRegisterMetaType<KoSvgText::TextDecorations>("KoSvgText::TextDecorations");
QMetaType::registerEqualsComparator<KoSvgText::TextDecorations>();
QMetaType::registerDebugStreamOperator<KoSvgText::TextDecorations>();
qRegisterMetaType<KoSvgText::BackgroundProperty>("KoSvgText::BackgroundProperty");
QMetaType::registerEqualsComparator<KoSvgText::BackgroundProperty>();
QMetaType::registerDebugStreamOperator<KoSvgText::BackgroundProperty>();
qRegisterMetaType<KoSvgText::StrokeProperty>("KoSvgText::StrokeProperty");
QMetaType::registerEqualsComparator<KoSvgText::StrokeProperty>();
QMetaType::registerDebugStreamOperator<KoSvgText::StrokeProperty>();
}
};
......@@ -348,6 +357,44 @@ QDebug operator<<(QDebug dbg, const CharTransformation &t)
return dbg.space();
}
QDebug operator<<(QDebug dbg, const BackgroundProperty &prop)
{
dbg.nospace() << "BackgroundProperty(";
dbg.nospace() << prop.property.data();
if (KoColorBackground *fill = dynamic_cast<KoColorBackground*>(prop.property.data())) {
dbg.nospace() << ", color, " << fill->color();
}
if (KoGradientBackground *fill = dynamic_cast<KoGradientBackground*>(prop.property.data())) {
dbg.nospace() << ", gradient, " << fill->gradient();
}
if (KoVectorPatternBackground *fill = dynamic_cast<KoVectorPatternBackground*>(prop.property.data())) {
dbg.nospace() << ", pattern, num shapes: " << fill->shapes().size();
}
dbg.nospace() << ")";
return dbg.space();
}
QDebug operator<<(QDebug dbg, const StrokeProperty &prop)
{
dbg.nospace() << "StrokeProperty(";
dbg.nospace() << prop.property.data();
if (KoShapeStroke *stroke = dynamic_cast<KoShapeStroke*>(prop.property.data())) {
dbg.nospace() << ", " << stroke->resultLinePen();
}
dbg.nospace() << ")";
return dbg.space();
}
}
......@@ -27,6 +27,10 @@
#include <boost/optional.hpp>
#include <boost/operators.hpp>
#include <QSharedPointer>
#include <KoShapeBackground.h>
#include <KoShapeStrokeModel.h>
#include <kritaflake_export.h>
class KoXmlElement;
......@@ -153,7 +157,7 @@ QString writeAlignmentBaseline(AlignmentBaseline value);
QString writeBaselineShiftMode(BaselineShiftMode value, qreal portion);
QString writeLengthAdjust(LengthAdjust value);
struct CharTransformation : public boost::equality_comparable<AutoValue>
struct CharTransformation : public boost::equality_comparable<CharTransformation>
{
boost::optional<qreal> xPos;
boost::optional<qreal> yPos;
......@@ -212,42 +216,43 @@ struct KoSvgCharChunkFormat : public QTextCharFormat
};
struct Style
struct BackgroundProperty : public boost::equality_comparable<BackgroundProperty>
{
QList<qreal> globalX;
QList<qreal> globalY;
QList<qreal> globalDX;
QList<qreal> globalDY;
QList<qreal> globalRotate;
BackgroundProperty() {}
BackgroundProperty(QSharedPointer<KoShapeBackground> p) : property(p) {}
qreal expectedLength = -1.0;
//// inheriting properties
bool operator==(const BackgroundProperty &rhs) const {
return (!property && !rhs.property) ||
(property && rhs.property &&
property->compareTo(rhs.property.data()));
}
QList<QFont> fontList;
QSharedPointer<KoShapeBackground> property;
};
boost::optional<AutoValue> kerning;
boost::optional<WritingMode> writingMode;
boost::optional<Direction> direction;
boost::optional<UnicodeBidi> unicodeBidi;
QDebug KRITAFLAKE_EXPORT operator<<(QDebug dbg, const KoSvgText::BackgroundProperty &prop);
boost::optional<AutoValue> glyphOrientationVertical;
boost::optional<AutoValue> glyphOrientationHorizontal;
struct StrokeProperty : public boost::equality_comparable<StrokeProperty>
{
StrokeProperty() {}
StrokeProperty(QSharedPointer<KoShapeStrokeModel> p) : property(p) {}
boost::optional<TextAnchor> textAnchor;
bool operator==(const StrokeProperty &rhs) const {
return (!property && !rhs.property) ||
(property && rhs.property &&
property->compareFillTo(rhs.property.data()) && property->compareStyleTo(rhs.property.data()));
}
//// non-inheriting properties
DominantBaseline dominantBaseline = DominantBaselineAuto;
AlignmentBaseline alignmentBaseline = AlignmentBaselineAuto;
BaselineShiftMode baselineShiftMode = ShiftNone;
qreal baselineShiftPercentage = 0;
QSharedPointer<KoShapeStrokeModel> property;
};
QDebug KRITAFLAKE_EXPORT operator<<(QDebug dbg, const KoSvgText::StrokeProperty &prop);
}
Q_DECLARE_METATYPE(KoSvgText::AutoValue)
Q_DECLARE_METATYPE(KoSvgText::TextDecorations)
Q_DECLARE_METATYPE(KoSvgText::BackgroundProperty)
Q_DECLARE_METATYPE(KoSvgText::StrokeProperty)
#endif // KOSVGTEXT_H
......@@ -356,6 +356,18 @@ bool KoSvgTextChunkShape::saveSvg(SvgSavingContext &context)
KoSvgTextProperties ownProperties = textProperties().ownProperties(parentProperties);
QMap<QString,QString> attributes = ownProperties.convertToSvgTextAttributes();
// we write down stroke/fill iff they are different from the parent's value
if (!isRootTextNode()) {
if (ownProperties.hasProperty(KoSvgTextProperties::FillId)) {
SvgStyleWriter::saveSvgFill(this, context);
}
if (ownProperties.hasProperty(KoSvgTextProperties::StrokeId)) {
SvgStyleWriter::saveSvgStroke(this, context);
}
}
for (auto it = attributes.constBegin(); it != attributes.constEnd(); ++it) {
context.shapeWriter().addAttribute(it.key().toLatin1().data(), it.value());
}
......@@ -508,7 +520,12 @@ void KoSvgTextChunkShape::normalizeCharTransformations()
KoSvgTextProperties KoSvgTextChunkShape::textProperties() const
{
Q_D(const KoSvgTextChunkShape);
return d->properties;
KoSvgTextProperties properties = d->properties;
properties.setProperty(KoSvgTextProperties::FillId, QVariant::fromValue(KoSvgText::BackgroundProperty(background())));
properties.setProperty(KoSvgTextProperties::StrokeId, QVariant::fromValue(KoSvgText::StrokeProperty(stroke())));
return properties;
}
bool KoSvgTextChunkShape::isTextNode() const
......
......@@ -54,6 +54,9 @@ public:
FontSizeId,
FontSizeAdjustId,
TextDecorationId,
FillId,
StrokeId
};
public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment