tdf#149880: handle url when it's inside the quotation marks

Change-Id: I053323f9b48c8856d520095da0a4768ac03b0176
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136847
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>

This commit also contains

svgio: make readLocalUrl standard-compliant

See https://bugs.documentfoundation.org/show_bug.cgi?id=149880#c12

Thanks to Mike Kaganski for the references

Change-Id: Idb06cf40ee992dd73120ce051d8ba4f61faaadfc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136877
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Tested-by: Jenkins
(cherry picked from commit e03cd0893eb2031d775764b4696b838dd09fb474)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136864
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136885
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index 49ac541..7fe6bad 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -71,6 +71,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools
    void testTdf94765();
    void testBehaviourWhenWidthAndHeightIsOrIsNotSet();
    void testTdf97663();
    void testTdf149880();

    Primitive2DSequence parseSvg(std::u16string_view aSource);

@@ -108,6 +109,7 @@ public:
    CPPUNIT_TEST(testTdf94765);
    CPPUNIT_TEST(testBehaviourWhenWidthAndHeightIsOrIsNotSet);
    CPPUNIT_TEST(testTdf97663);
    CPPUNIT_TEST(testTdf149880);
    CPPUNIT_TEST_SUITE_END();
};

@@ -850,6 +852,27 @@ void Test::testTdf97663()
    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "y", "236");
}

void Test::testTdf149880()
{
    Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf149880.svg");
    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));

    drawinglayer::Primitive2dXmlDump dumper;
    Primitive2DContainer container = comphelper::sequenceToContainer<Primitive2DContainer>(aSequence);
    xmlDocUniquePtr pDocument = dumper.dumpAndParse(container);

    CPPUNIT_ASSERT (pDocument);

    // Without the fix in place, this test would have failed with
    // - Expected: 1
    // - Actual  : 0
    // - In <>, XPath '/primitive2D/transform/mask/unhandled' number of nodes is incorrect
    assertXPath(pDocument,
            "/primitive2D/transform/mask/unhandled", "id", "PATTERNFILL");
    assertXPath(pDocument,
            "/primitive2D/transform/mask/unhandled/mask/transform/transform/bitmap", 28);
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

}
diff --git a/svgio/qa/cppunit/data/tdf149880.svg b/svgio/qa/cppunit/data/tdf149880.svg
new file mode 100644
index 0000000..08ba748
--- /dev/null
+++ b/svgio/qa/cppunit/data/tdf149880.svg
@@ -0,0 +1,11 @@
<?xml version="1.0" standalone="no"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <pattern id="Pattern" x=".05" y=".05" width=".25" height=".25">
      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
    </pattern>

  </defs>

  <rect fill='url("#Pattern")' stroke="black" x="0" y="0" width="200" height="200"/>
</svg>
diff --git a/svgio/source/svgreader/svgtools.cxx b/svgio/source/svgreader/svgtools.cxx
index cb2f1ab..82f1505 100644
--- a/svgio/source/svgreader/svgtools.cxx
+++ b/svgio/source/svgreader/svgtools.cxx
@@ -1059,16 +1059,33 @@ namespace svgio::svgreader

        bool readLocalUrl(const OUString& rCandidate, OUString& rURL)
        {
            static const char aStrUrl[] = "url";
            static const char aStrUrl[] = "url(";

            if(rCandidate.startsWith(aStrUrl))
            if(rCandidate.startsWithIgnoreAsciiCase(aStrUrl))
            {
                const sal_Int32 nLen(rCandidate.getLength());
                sal_Int32 nPos(strlen(aStrUrl));
                sal_Unicode aLimiter(')');

                skip_char(rCandidate, '(', '#', nPos, nLen);
                skip_char(rCandidate, ' ', nPos, nLen);

                if('"' == rCandidate[nPos])
                {
                    aLimiter = '"';
                    ++nPos;
                }
                else if('\'' == rCandidate[nPos])
                {
                    aLimiter = '\'';
                    ++nPos;
                }

                skip_char(rCandidate, ' ', nPos, nLen);
                skip_char(rCandidate, '#', nPos, nPos + 1);
                OUStringBuffer aTokenValue;
                copyToLimiter(rCandidate, ')', nPos, aTokenValue, nLen);

                copyToLimiter(rCandidate, aLimiter, nPos, aTokenValue, nLen);

                rURL = aTokenValue.makeStringAndClear();

                return true;