[Libreoffice-commits] core.git: Branch 'feature/drawinglayercore' - 3 commits - vcl/inc vcl/qa vcl/source
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Sat May 2 12:47:43 UTC 2020
vcl/inc/graphic/DetectorTools.hxx | 63 +++++++++++++
vcl/qa/cppunit/GraphicFormatDetectorTest.cxx | 123 +++++++++++++++++++++++++++
vcl/qa/cppunit/data/TypeDetectionExample.eps | 82 ++++++++++++++++++
vcl/source/filter/GraphicFormatDetector.cxx | 52 +++--------
4 files changed, 286 insertions(+), 34 deletions(-)
New commits:
commit c4f2614a212f54e2edd903d6a73b3036a90be836
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sat May 2 14:46:37 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Sat May 2 14:46:37 2020 +0200
vcl: simplify graphic type detection for EPS files
Change-Id: Ia48560274c33aaa8e81a5ee6eb00f6470e92e0fd
diff --git a/vcl/source/filter/GraphicFormatDetector.cxx b/vcl/source/filter/GraphicFormatDetector.cxx
index 5682d78f8e3c..56f7a9f2d006 100644
--- a/vcl/source/filter/GraphicFormatDetector.cxx
+++ b/vcl/source/filter/GraphicFormatDetector.cxx
@@ -311,8 +311,7 @@ bool GraphicFormatDetector::checkEPS()
msDetectedFormat = "EPS";
return true;
}
- else if (matchArrayWithString(pFirstBytesAsCharArray, 10, "%!PS-Adobe")
- && matchArrayWithString(pFirstBytesAsCharArray + 15, 3, "EPS"))
+ else if (checkArrayForMatchingStrings(pFirstBytesAsCharArray, 30, { "%!PS-Adobe", " EPS" }))
{
msDetectedFormat = "EPS";
return true;
commit bcb2373d23e52d600809acb181c811dd08143830
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sat May 2 14:42:58 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Sat May 2 14:43:15 2020 +0200
vcl: add test case for EPS file detection
Change-Id: Ia6a4cedf5c570e5d9544887ae66da0ec1e491647
diff --git a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
index 155ff089811b..1ce516bf52b3 100644
--- a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
+++ b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
@@ -42,6 +42,7 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
void testDetectSVG();
void testDetectSVGZ();
void testDetectPDF();
+ void testDetectEPS();
void testMatchArray();
void testCheckArrayForMatchingStrings();
@@ -61,6 +62,7 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
CPPUNIT_TEST(testDetectSVG);
CPPUNIT_TEST(testDetectSVGZ);
CPPUNIT_TEST(testDetectPDF);
+ CPPUNIT_TEST(testDetectEPS);
CPPUNIT_TEST(testMatchArray);
CPPUNIT_TEST(testCheckArrayForMatchingStrings);
CPPUNIT_TEST_SUITE_END();
@@ -291,6 +293,21 @@ void GraphicFormatDetectorTest::testDetectPDF()
CPPUNIT_ASSERT_EQUAL(OUString("PDF"), rFormatExtension);
}
+void GraphicFormatDetectorTest::testDetectEPS()
+{
+ SvFileStream aFileStream(getFullUrl("TypeDetectionExample.eps"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "EPS");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkEPS());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(ImpPeekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("EPS"), rFormatExtension);
+}
+
void GraphicFormatDetectorTest::testMatchArray()
{
std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.eps b/vcl/qa/cppunit/data/TypeDetectionExample.eps
new file mode 100644
index 000000000000..7f0db47bc80c
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.eps
@@ -0,0 +1,82 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: cairo 1.16.0 (https://cairographics.org)
+%%CreationDate: Sat May 2 14:29:27 2020
+%%Pages: 1
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%BoundingBox: 0 1 7 8
+%%EndComments
+%%BeginProlog
+50 dict begin
+/q { gsave } bind def
+/Q { grestore } bind def
+/cm { 6 array astore concat } bind def
+/w { setlinewidth } bind def
+/J { setlinecap } bind def
+/j { setlinejoin } bind def
+/M { setmiterlimit } bind def
+/d { setdash } bind def
+/m { moveto } bind def
+/l { lineto } bind def
+/c { curveto } bind def
+/h { closepath } bind def
+/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
+ 0 exch rlineto 0 rlineto closepath } bind def
+/S { stroke } bind def
+/f { fill } bind def
+/f* { eofill } bind def
+/n { newpath } bind def
+/W { clip } bind def
+/W* { eoclip } bind def
+/BT { } bind def
+/ET { } bind def
+/BDC { mark 3 1 roll /BDC pdfmark } bind def
+/EMC { mark /EMC pdfmark } bind def
+/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
+/Tj { show currentpoint cairo_store_point } bind def
+/TJ {
+ {
+ dup
+ type /stringtype eq
+ { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
+ } forall
+ currentpoint cairo_store_point
+} bind def
+/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
+ cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
+/Tf { pop /cairo_font exch def /cairo_font_matrix where
+ { pop cairo_selectfont } if } bind def
+/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
+ /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
+ /cairo_font where { pop cairo_selectfont } if } bind def
+/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
+ cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
+/g { setgray } bind def
+/rg { setrgbcolor } bind def
+/d1 { setcachedevice } bind def
+/cairo_data_source {
+ CairoDataIndex CairoData length lt
+ { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }
+ { () } ifelse
+} def
+/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def
+/cairo_image { image cairo_flush_ascii85_file } def
+/cairo_imagemask { imagemask cairo_flush_ascii85_file } def
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%%Page: 1 1
+%%BeginPageSetup
+%%PageBoundingBox: 0 1 7 8
+%%EndPageSetup
+q 0 1 7 7 rectclip
+1 0 0 -1 0 8 cm q
+0.956863 0.831373 0.266667 rg
+3.75 0.75 m 5.41 0.75 6.75 2.09 6.75 3.75 c 6.75 5.41 5.41 6.75 3.75 6.75
+ c 2.09 6.75 0.75 5.41 0.75 3.75 c 0.75 2.09 2.09 0.75 3.75 0.75 c h
+3.75 0.75 m f
+Q Q
+showpage
+%%Trailer
+end
+%%EOF
commit 05f5c751bc1b4dceb8d6f788d963650c259697cd
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sat May 2 14:35:23 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Sat May 2 14:35:23 2020 +0200
vcl: add DetectorTools + tests, refactor array string matching
Add DetectorTools with byte array searching and matching to a
input string (or another byte array). This refactors the existing
function in GraphicFormatDetector. It needs to go into its own
header so that the function(s) can be tested easily. Replace
the previous searchEntry implementation with refactored one in
the source code.
Change-Id: I59d30b694e13f28d6366f1a99fe2ef2ea3c1a07d
diff --git a/vcl/inc/graphic/DetectorTools.hxx b/vcl/inc/graphic/DetectorTools.hxx
new file mode 100644
index 000000000000..b9163de135d9
--- /dev/null
+++ b/vcl/inc/graphic/DetectorTools.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+namespace vcl
+{
+const char* matchArray(const char* pSource, sal_Int32 nSourceSize, const char* pSearch,
+ sal_Int32 nSearchSize)
+{
+ for (sal_Int32 increment = 0; increment <= (nSourceSize - nSearchSize); ++increment)
+ {
+ bool bMatch = true;
+ // search both arrays if they match
+ for (sal_Int32 index = 0; index < nSearchSize && bMatch; ++index)
+ {
+ if (pSource[index] != pSearch[index])
+ bMatch = false;
+ }
+ // match has been found
+ if (bMatch)
+ return pSource;
+ pSource++;
+ }
+ return nullptr;
+}
+
+const char* matchArrayWithString(const char* pSource, sal_Int32 nSourceSize, OString const& rString)
+{
+ return matchArray(pSource, nSourceSize, rString.getStr(), rString.getLength());
+}
+
+bool checkArrayForMatchingStrings(const char* pSource, sal_Int32 nSourceSize,
+ std::vector<OString> const& rStrings)
+{
+ if (rStrings.empty())
+ return false;
+ if (rStrings.size() < 2)
+ return matchArrayWithString(pSource, nSourceSize, rStrings[0]) != nullptr;
+
+ const char* pBegin = pSource;
+ const char* pCurrent = pSource;
+ for (OString const& rString : rStrings)
+ {
+ sal_Int32 nCurrentSize = nSourceSize - sal_Int32(pCurrent - pBegin);
+ printf("Current size %d -> %d\n", nCurrentSize, nSourceSize);
+ pCurrent = matchArray(pCurrent, nCurrentSize, rString.getStr(), rString.getLength());
+ if (pCurrent == nullptr)
+ return false;
+ printf("%s\n", pCurrent);
+ }
+ return true;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
index 90183279dbc9..155ff089811b 100644
--- a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
+++ b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
@@ -12,6 +12,7 @@
#include <unotest/bootstrapfixturebase.hxx>
#include <graphic/GraphicFormatDetector.hxx>
+#include <graphic/DetectorTools.hxx>
#include <tools/stream.hxx>
@@ -41,6 +42,8 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
void testDetectSVG();
void testDetectSVGZ();
void testDetectPDF();
+ void testMatchArray();
+ void testCheckArrayForMatchingStrings();
CPPUNIT_TEST_SUITE(GraphicFormatDetectorTest);
CPPUNIT_TEST(testDetectMET);
@@ -58,6 +61,8 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
CPPUNIT_TEST(testDetectSVG);
CPPUNIT_TEST(testDetectSVGZ);
CPPUNIT_TEST(testDetectPDF);
+ CPPUNIT_TEST(testMatchArray);
+ CPPUNIT_TEST(testCheckArrayForMatchingStrings);
CPPUNIT_TEST_SUITE_END();
};
@@ -286,6 +291,107 @@ void GraphicFormatDetectorTest::testDetectPDF()
CPPUNIT_ASSERT_EQUAL(OUString("PDF"), rFormatExtension);
}
+void GraphicFormatDetectorTest::testMatchArray()
+{
+ std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
+ "<svg width=\"5cm\" height=\"4cm\" version=\"1.1\"\n"
+ "xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "</svg>");
+
+ const char* pCompleteStringPointer = aString.c_str();
+ const char* pMatchPointer;
+ int nCheckSize = aString.size();
+
+ // Check beginning of the input string
+ pMatchPointer = vcl::matchArrayWithString(pCompleteStringPointer, nCheckSize, "<?xml");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(0, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, OString(pMatchPointer).startsWith("<?xml"));
+
+ // Check middle of the input string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "version");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(6, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, OString(pMatchPointer).startsWith("version"));
+
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "<svg");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(38, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, OString(pMatchPointer).startsWith("<svg"));
+
+ // Check end of the input string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "/svg>");
+ CPPUNIT_ASSERT(pMatchPointer != nullptr);
+ CPPUNIT_ASSERT_EQUAL(119, int(pMatchPointer - pCompleteStringPointer));
+ CPPUNIT_ASSERT_EQUAL(true, OString(pMatchPointer).startsWith("/svg>"));
+
+ // Check that non-existing search string
+ pMatchPointer = vcl::matchArrayWithString(aString.c_str(), nCheckSize, "none");
+ CPPUNIT_ASSERT(pMatchPointer == nullptr);
+}
+
+void GraphicFormatDetectorTest::testCheckArrayForMatchingStrings()
+{
+ std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
+ "<svg width=\"5cm\" height=\"4cm\" version=\"1.1\"\n"
+ "xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "</svg>");
+ const char* pCompleteStringPointer = aString.c_str();
+ int nCheckSize = aString.size();
+ bool bResult;
+
+ // check beginning string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "<?xml" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check ending string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check middle string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "version" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check beginning and then ending string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check ending and then beginning string
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "/svg>", "<?xml" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check middle strings
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "version", "<svg" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check beginning, middle and ending strings
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "version", "<svg", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(true, bResult);
+
+ // check non-existing
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize, { "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing on the beginning
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "none", "version", "<svg", "/svg>" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing on the end
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "version", "<svg", "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+
+ // check non-existing after the end
+ bResult = vcl::checkArrayForMatchingStrings(pCompleteStringPointer, nCheckSize,
+ { "<?xml", "/svg>", "none" });
+ CPPUNIT_ASSERT_EQUAL(false, bResult);
+}
+
} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(GraphicFormatDetectorTest);
diff --git a/vcl/source/filter/GraphicFormatDetector.cxx b/vcl/source/filter/GraphicFormatDetector.cxx
index 56624074366e..5682d78f8e3c 100644
--- a/vcl/source/filter/GraphicFormatDetector.cxx
+++ b/vcl/source/filter/GraphicFormatDetector.cxx
@@ -22,6 +22,7 @@
#include <algorithm>
#include <graphic/GraphicFormatDetector.hxx>
+#include <graphic/DetectorTools.hxx>
#include <tools/solar.h>
#include <tools/zcodec.hxx>
@@ -67,23 +68,6 @@ bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
return false;
}
-sal_uInt8* searchEntry(sal_uInt8* pSource, const char* pDest, sal_uLong nComp, sal_uLong nSize)
-{
- while (nComp-- >= nSize)
- {
- sal_uLong i;
- for (i = 0; i < nSize; i++)
- {
- if ((pSource[i] & ~0x20) != (pDest[i] & ~0x20))
- break;
- }
- if (i == nSize)
- return pSource;
- pSource++;
- }
- return nullptr;
-}
-
} // end anonymous namespace
GraphicFormatDetector::GraphicFormatDetector(SvStream& rStream, OUString const& rFormatExtension)
@@ -320,13 +304,15 @@ bool GraphicFormatDetector::checkPSD()
bool GraphicFormatDetector::checkEPS()
{
+ const char* pFirstBytesAsCharArray = reinterpret_cast<char*>(maFirstBytes.data());
+
if (mnFirstLong == 0xC5D0D3C6)
{
msDetectedFormat = "EPS";
return true;
}
- else if (searchEntry(maFirstBytes.data(), "%!PS-Adobe", 10, 10)
- && searchEntry(&maFirstBytes[15], "EPS", 3, 3))
+ else if (matchArrayWithString(pFirstBytesAsCharArray, 10, "%!PS-Adobe")
+ && matchArrayWithString(pFirstBytesAsCharArray + 15, 3, "EPS"))
{
msDetectedFormat = "EPS";
return true;
@@ -419,7 +405,8 @@ bool GraphicFormatDetector::checkRAS()
bool GraphicFormatDetector::checkXPM()
{
- if (searchEntry(maFirstBytes.data(), "/* XPM */", 256, 9))
+ const char* pFirstBytesAsCharArray = reinterpret_cast<char*>(maFirstBytes.data());
+ if (matchArrayWithString(pFirstBytesAsCharArray, 256, "/* XPM */"))
{
msDetectedFormat = "XPM";
return true;
@@ -434,15 +421,13 @@ bool GraphicFormatDetector::checkXBM()
mrStream.Seek(mnStreamPosition);
mrStream.ReadBytes(pBuffer.get(), nSize);
- sal_uInt8* pPtr = searchEntry(pBuffer.get(), "#define", nSize, 7);
- if (pPtr)
+ const char* pBufferAsCharArray = reinterpret_cast<char*>(pBuffer.get());
+
+ if (checkArrayForMatchingStrings(pBufferAsCharArray, nSize, { "#define", "_width" }))
{
- if (searchEntry(pPtr, "_width", pBuffer.get() + nSize - pPtr, 6))
- {
- msDetectedFormat = "XBM";
- return true;
- }
+ msDetectedFormat = "XBM";
+ return true;
}
return false;
}
@@ -473,20 +458,20 @@ bool GraphicFormatDetector::checkSVG()
bool bIsSvg(false);
+ const char* pCheckArrayAsCharArray = reinterpret_cast<char*>(pCheckArray);
+
// check for XML
// #119176# SVG files which have no xml header at all have shown up this is optional
// check for "xml" then "version" then "DOCTYPE" and "svg" tags
- if (searchEntry(pCheckArray, "<?xml", nCheckSize, 5)
- && searchEntry(pCheckArray, "version", nCheckSize, 7)
- && searchEntry(pCheckArray, "DOCTYPE", nCheckSize, 7)
- && searchEntry(pCheckArray, "svg", nCheckSize, 3))
+ if (checkArrayForMatchingStrings(pCheckArrayAsCharArray, nCheckSize,
+ { "<?xml", "version", "DOCTYPE", "svg" }))
{
bIsSvg = true;
}
// check for svg element in 1st 256 bytes
// search for '<svg'
- if (!bIsSvg && searchEntry(pCheckArray, "<svg", nCheckSize, 4))
+ if (!bIsSvg && checkArrayForMatchingStrings(pCheckArrayAsCharArray, nCheckSize, { "<svg" }))
{
bIsSvg = true;
}
@@ -499,7 +484,7 @@ bool GraphicFormatDetector::checkSVG()
// with Svg files containing big comment headers or Svg as the host
// language
- pCheckArray = sExtendedOrDecompressedFirstBytes;
+ pCheckArrayAsCharArray = reinterpret_cast<char*>(sExtendedOrDecompressedFirstBytes);
if (bIsGZip)
{
@@ -513,7 +498,7 @@ bool GraphicFormatDetector::checkSVG()
}
// search for '<svg'
- if (searchEntry(pCheckArray, "<svg", nCheckSize, 4))
+ if (checkArrayForMatchingStrings(pCheckArrayAsCharArray, nCheckSize, { "<svg" }))
{
bIsSvg = true;
}
More information about the Libreoffice-commits
mailing list