[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