[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [krita/kazakov/svg-loading] /: Implement 'color-profile' element parsing
From: Dmitry Kazakov <dimula73 () gmail ! com>
Date: 2016-10-13 13:37:05
Message-ID: E1bugC1-0002cw-2I () code ! kde ! org
[Download RAW message or body]
Git commit cb5815289dcc9d2d7865f009306d9fbd46765296 by Dmitry Kazakov.
Committed on 11/10/2016 at 15:12.
Pushed by dkazakov into branch 'kazakov/svg-loading'.
Implement 'color-profile' element parsing
The bad thing that this element is not used anywhere yet. The rest
of the color management work is postponed until KoShape supports
something except QPainter.
M +72 -0 libs/flake/svg/SvgLoadingContext.cpp
M +9 -0 libs/flake/svg/SvgLoadingContext.h
M +7 -0 libs/flake/svg/SvgParser.cpp
M +3 -0 libs/flake/svg/SvgParser.h
M +52 -0 libs/flake/tests/TestSvgParser.cpp
M +4 -0 libs/flake/tests/TestSvgParser.h
A +- -- libs/flake/tests/data/icc/sRGB-elle-V4-srgbtrc.icc
M +4 -1 libs/pigment/KoColorSpaceEngine.h
M +2 -1 libs/pigment/colorspaces/KoSimpleColorSpaceEngine.h
M +24 -3 plugins/color/lcms2engine/IccColorSpaceEngine.cpp
M +2 -1 plugins/color/lcms2engine/IccColorSpaceEngine.h
http://commits.kde.org/krita/cb5815289dcc9d2d7865f009306d9fbd46765296
diff --git a/libs/flake/svg/SvgLoadingContext.cpp \
b/libs/flake/svg/SvgLoadingContext.cpp index 63683ad..20730c7 100644
--- a/libs/flake/svg/SvgLoadingContext.cpp
+++ b/libs/flake/svg/SvgLoadingContext.cpp
@@ -23,6 +23,9 @@
#include <QFileInfo>
#include <QDir>
+#include <KoColorSpaceRegistry.h>
+#include <KoColorSpaceEngine.h>
+#include <KoColorProfile.h>
#include <KoDocumentResourceManager.h>
#include <FlakeDebug.h>
@@ -57,8 +60,10 @@ public:
KoDocumentResourceManager *documentResourceManager;
QHash<QString, KoShape*> loadedShapes;
QHash<QString, KoXmlElement> definitions;
+ QHash<QString, const KoColorProfile*> profiles;
SvgCssHelper cssStyles;
SvgStyleParser *styleParser;
+ FileFetcherFunc fileFetcher;
};
SvgLoadingContext::SvgLoadingContext(KoDocumentResourceManager \
*documentResourceManager) @@ -160,6 +165,22 @@ QString \
SvgLoadingContext::absoluteFilePath(const QString &href) return absFile;
}
+QString SvgLoadingContext::relativeFilePath(const QString &href)
+{
+ const SvgGraphicsContext *gc = currentGC();
+ if (!gc) return href;
+
+ QString result = href;
+
+ if (!gc->xmlBaseDir.isEmpty()) {
+ result = gc->xmlBaseDir + QDir::separator() + href;
+ } else if (!d->initialXmlBaseDir.isEmpty()) {
+ result = d->initialXmlBaseDir + QDir::separator() + href;
+ }
+
+ return QDir::cleanPath(result);
+}
+
int SvgLoadingContext::nextZIndex()
{
return d->zIndex++;
@@ -214,8 +235,59 @@ SvgStyleParser &SvgLoadingContext::styleParser()
return *d->styleParser;
}
+void SvgLoadingContext::parseProfile(const KoXmlElement &element)
+{
+ const QString href = element.attribute("xlink:href");
+ const QByteArray uniqueId = \
QByteArray::fromHex(element.attribute("local").toLatin1()); + const QString name = \
element.attribute("name"); +
+ if (element.attribute("rendering-intent", "auto") != "auto") {
+ // WARNING: Krita does *not* treat rendering intents attributes of the \
profile! + qDebug() << "WARNING: we do *not* treat rendering intents \
attributes of the profile!"; + }
+
+ if (d->profiles.contains(name)) {
+ qDebug() << "Profile already in the map!" << ppVar(name);
+ return;
+ }
+
+ const KoColorProfile *profile =
+ KoColorSpaceRegistry::instance()->profileByUniqueId(uniqueId);
+
+ if (!profile && d->fileFetcher) {
+ KoColorSpaceEngine *engine = \
KoColorSpaceEngineRegistry::instance()->get("icc"); + KIS_ASSERT(engine);
+ if (engine) {
+ const QString fileName = relativeFilePath(href);
+ const QByteArray profileData = d->fileFetcher(fileName);
+ if (!profileData.isEmpty()) {
+ profile = engine->addProfile(profileData);
+
+ if (profile->uniqueId() != uniqueId) {
+ qDebug() << "WARNING: ProfileID of the attached profile doesn't \
match the one mentioned in SVG element"; + qDebug() << " " \
<< ppVar(profile->uniqueId().toHex()); + qDebug() << " " << \
ppVar(uniqueId.toHex()); + }
+ } else {
+ qDebug() << "WARNING: couldn't fetch the ICCprofile file!" << \
fileName; + }
+ }
+ }
+
+ if (profile) {
+ d->profiles.insert(name, profile);
+ } else {
+ qDebug() << "WARNING: couldn't load SVG profile" << ppVar(name) << \
ppVar(href) << ppVar(uniqueId); + }
+}
+
bool SvgLoadingContext::isRootContext() const
{
KIS_ASSERT(!d->gcStack.isEmpty());
return d->gcStack.size() == 1;
}
+
+void SvgLoadingContext::setFileFetcher(SvgLoadingContext::FileFetcherFunc func)
+{
+ d->fileFetcher = func;
+}
diff --git a/libs/flake/svg/SvgLoadingContext.h b/libs/flake/svg/SvgLoadingContext.h
index e78e846..50b67c7 100644
--- a/libs/flake/svg/SvgLoadingContext.h
+++ b/libs/flake/svg/SvgLoadingContext.h
@@ -20,6 +20,7 @@
#ifndef SVGLOADINGCONTEXT_H
#define SVGLOADINGCONTEXT_H
+#include <functional>
#include <QStringList>
#include <KoXmlReader.h>
#include "kritaflake_export.h"
@@ -55,6 +56,8 @@ public:
/// Constructs an absolute file path from the given href and current xml base \
directory QString absoluteFilePath(const QString &href);
+ QString relativeFilePath(const QString &href);
+
/// Returns the next z-index
int nextZIndex();
@@ -85,8 +88,14 @@ public:
/// Returns a style parser to parse styles
SvgStyleParser &styleParser();
+ /// parses 'color-profile' tag and saves it in the context
+ void parseProfile(const KoXmlElement &element);
+
bool isRootContext() const;
+ typedef std::function<QByteArray(const QString&)> FileFetcherFunc;
+ void setFileFetcher(FileFetcherFunc func);
+
private:
class Private;
Private * const d;
diff --git a/libs/flake/svg/SvgParser.cpp b/libs/flake/svg/SvgParser.cpp
index bf016f8..d6f51f2 100644
--- a/libs/flake/svg/SvgParser.cpp
+++ b/libs/flake/svg/SvgParser.cpp
@@ -1093,6 +1093,11 @@ void SvgParser::applyViewBoxTransform(const KoXmlElement \
&element) }
}
+void SvgParser::setFileFetcher(SvgParser::FileFetcherFunc func)
+{
+ m_context.setFileFetcher(func);
+}
+
QList<KoShape*> SvgParser::parseContainer(const KoXmlElement &e)
{
QList<KoShape*> shapes;
@@ -1177,6 +1182,8 @@ QList<KoShape*> SvgParser::parseContainer(const KoXmlElement \
&e) shapes.append(shape);
} else if (b.tagName() == "use") {
shapes += parseUse(b);
+ } else if (b.tagName() == "color-profile") {
+ m_context.parseProfile(b);
} else {
// this is an unknown element, so try to load it anyway
// there might be a shape that handles that element
diff --git a/libs/flake/svg/SvgParser.h b/libs/flake/svg/SvgParser.h
index 3789d3c..60176d0 100644
--- a/libs/flake/svg/SvgParser.h
+++ b/libs/flake/svg/SvgParser.h
@@ -59,6 +59,9 @@ public:
/// Returns the list of all shapes of the svg document
QList<KoShape*> shapes() const;
+ typedef std::function<QByteArray(const QString&)> FileFetcherFunc;
+ void setFileFetcher(FileFetcherFunc func);
+
protected:
/// Parses a container element, returning a list of child shapes
diff --git a/libs/flake/tests/TestSvgParser.cpp b/libs/flake/tests/TestSvgParser.cpp
index 9ed67ca..8e30c74 100644
--- a/libs/flake/tests/TestSvgParser.cpp
+++ b/libs/flake/tests/TestSvgParser.cpp
@@ -1169,4 +1169,56 @@ void TestSvgParser::testRenderDisplayInheritance()
QCOMPARE(shape->isVisible(true), true);
}
+void TestSvgParser::testRenderStrokeWithInlineStyle()
+{
+ const QString data =
+ "<svg width=\"30px\" height=\"30px\""
+ " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
+
+ "<rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
+ " style = \"fill: cyan; stroke :blue; stroke-width:2;\"/>"
+
+ "</svg>";
+
+ SvgRenderTester t (data);
+ t.test_standard_30px_72ppi("stroke_blue_width_2");
+}
+
+void TestSvgParser::testIccColor()
+{
+ const QString data =
+ "<svg width=\"30px\" height=\"30px\""
+ " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
+
+ "<g xml:base=\"icc\">"
+ " <color-profile xlink:href=\"sRGB-elle-V4-srgbtrc.icc\""
+ " local=\"133a66607cffeebdd64dd433ada9bf4e\" \
name=\"default-profile\"/>" +
+ " <color-profile xlink:href=\"sRGB-elle-V4-srgbtrc.icc\""
+ " local=\"133a66607cffeebdd64dd433ada9bf4e\" \
name=\"some-other-name\"/>" +
+ " <rect id=\"testRect\" x=\"5\" y=\"5\" width=\"10\" height=\"20\""
+ " style = \"fill: cyan; stroke :blue; stroke-width:2;\"/>"
+ "</g>"
+
+ "</svg>";
+
+ SvgRenderTester t (data);
+
+ int numFetches = 0;
+
+ t.parser.setFileFetcher(
+ [&numFetches](const QString &name) {
+ numFetches++;
+ const QString fileName = TestUtil::fetchDataFileLazy(name);
+ QFile file(fileName);
+ KIS_ASSERT(file.exists());
+ file.open(QIODevice::ReadOnly);
+ return file.readAll();
+ });
+
+ t.test_standard_30px_72ppi("stroke_blue_width_2");
+ QCOMPARE(numFetches, 1);
+}
+
QTEST_GUILESS_MAIN(TestSvgParser)
diff --git a/libs/flake/tests/TestSvgParser.h b/libs/flake/tests/TestSvgParser.h
index 49fb6e2..8996381 100644
--- a/libs/flake/tests/TestSvgParser.h
+++ b/libs/flake/tests/TestSvgParser.h
@@ -81,6 +81,10 @@ private Q_SLOTS:
void testRenderVisibilityInheritance();
void testRenderDisplayInheritance();
+ void testRenderStrokeWithInlineStyle();
+
+ void testIccColor();
+
};
#endif // TESTSVGPARSER_H
diff --git a/libs/flake/tests/data/icc/sRGB-elle-V4-srgbtrc.icc \
b/libs/flake/tests/data/icc/sRGB-elle-V4-srgbtrc.icc new file mode 100644
index 0000000..f5794dc
Binary files /dev/null and b/libs/flake/tests/data/icc/sRGB-elle-V4-srgbtrc.icc \
differ
diff --git a/libs/pigment/KoColorSpaceEngine.h b/libs/pigment/KoColorSpaceEngine.h
index 115a8a6..3c67d9c 100644
--- a/libs/pigment/KoColorSpaceEngine.h
+++ b/libs/pigment/KoColorSpaceEngine.h
@@ -23,6 +23,8 @@
#include <KoColorConversionTransformationAbstractFactory.h>
#include <KoGenericRegistry.h>
+class KoColorProfile;
+
/**
* A KoColorSpaceEngine is a class use to create color conversion
* transformation between color spaces, for which all profiles can
@@ -43,7 +45,8 @@ public:
virtual ~KoColorSpaceEngine();
const QString& id() const;
const QString& name() const;
- virtual void addProfile(const QString &filename) = 0;
+ virtual const KoColorProfile* addProfile(const QString &filename) = 0;
+ virtual const KoColorProfile* addProfile(const QByteArray &data) = 0;
virtual void removeProfile(const QString &filename) = 0;
private:
diff --git a/libs/pigment/colorspaces/KoSimpleColorSpaceEngine.h \
b/libs/pigment/colorspaces/KoSimpleColorSpaceEngine.h index 11d6e0a..08bf8e7 100644
--- a/libs/pigment/colorspaces/KoSimpleColorSpaceEngine.h
+++ b/libs/pigment/colorspaces/KoSimpleColorSpaceEngine.h
@@ -31,7 +31,8 @@ public:
const \
KoColorSpace* dstColorSpace,
\
KoColorConversionTransformation::Intent renderingIntent,
\
KoColorConversionTransformation::ConversionFlags conversionFlags) \
const;
- virtual void addProfile(const QString &profile ) { Q_UNUSED(profile); }
+ virtual const KoColorProfile* addProfile(const QString &profile ) { \
Q_UNUSED(profile); return 0; } + virtual const KoColorProfile* addProfile(const \
QByteArray &data) { Q_UNUSED(data); return 0; }
virtual void removeProfile(const QString &profile ) { Q_UNUSED(profile); }
};
diff --git a/plugins/color/lcms2engine/IccColorSpaceEngine.cpp \
b/plugins/color/lcms2engine/IccColorSpaceEngine.cpp index 7fe0ed5..a562eed 100644
--- a/plugins/color/lcms2engine/IccColorSpaceEngine.cpp
+++ b/plugins/color/lcms2engine/IccColorSpaceEngine.cpp
@@ -187,7 +187,7 @@ IccColorSpaceEngine::~IccColorSpaceEngine()
delete d;
}
-void IccColorSpaceEngine::addProfile(const QString &filename)
+const KoColorProfile* IccColorSpaceEngine::addProfile(const QString &filename)
{
KoColorSpaceRegistry *registry = KoColorSpaceRegistry::instance();
@@ -205,13 +205,34 @@ void IccColorSpaceEngine::addProfile(const QString &filename)
}
if (profile->valid()) {
- qDebug() << "Valid profile : " << profile->fileName() << profile->name();
+ dbgPigment << "Valid profile : " << profile->fileName() << profile->name();
registry->addProfile(profile);
} else {
- qDebug() << "Invalid profile : " << profile->fileName() << profile->name();
+ dbgPigment << "Invalid profile : " << profile->fileName() << \
profile->name(); delete profile;
+ profile = 0;
}
+ return profile;
+}
+
+const KoColorProfile* IccColorSpaceEngine::addProfile(const QByteArray &data)
+{
+ KoColorSpaceRegistry *registry = KoColorSpaceRegistry::instance();
+
+ KoColorProfile *profile = new IccColorProfile(data);
+ Q_CHECK_PTR(profile);
+
+ if (profile->valid()) {
+ dbgPigment << "Valid profile : " << profile->fileName() << profile->name();
+ registry->addProfile(profile);
+ } else {
+ dbgPigment << "Invalid profile : " << profile->fileName() << \
profile->name(); + delete profile;
+ profile = 0;
+ }
+
+ return profile;
}
void IccColorSpaceEngine::removeProfile(const QString &filename)
diff --git a/plugins/color/lcms2engine/IccColorSpaceEngine.h \
b/plugins/color/lcms2engine/IccColorSpaceEngine.h index cc1654c..85c9c98 100644
--- a/plugins/color/lcms2engine/IccColorSpaceEngine.h
+++ b/plugins/color/lcms2engine/IccColorSpaceEngine.h
@@ -27,7 +27,8 @@ class IccColorSpaceEngine : public KoColorSpaceEngine
public:
IccColorSpaceEngine();
virtual ~IccColorSpaceEngine();
- void addProfile(const QString &filename);
+ const KoColorProfile *addProfile(const QString &filename);
+ const KoColorProfile *addProfile(const QByteArray &data);
void removeProfile(const QString &filename);
virtual KoColorConversionTransformation *createColorTransformation(const \
KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace,
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic