src/lib/VSDXMLParserBase.cpp | 25 ++++++++++ src/lib/VSDXMLParserBase.h | 1 src/lib/VSDXParser.cpp | 54 ++++++++++++++--------- src/test/Makefile.am | 5 +- src/test/data/tdf136564-WhiteTextBackground.vsdx |binary src/test/importtest.cpp | 20 ++++++++ 6 files changed, 83 insertions(+), 22 deletions(-)
New commits: commit 2849204df192331ea94c37414c9452acc9dda287 Author: Bartosz Kosiorek <gan...@poczta.onet.pl> AuthorDate: Sun Sep 29 11:16:18 2024 +0200 Commit: Bartosz Kosiorek <gan...@poczta.onet.pl> CommitDate: Tue Oct 1 20:14:47 2024 +0200 tdf136564 VSDX Add support for TextBackground from SheetStyle Previously the TextBackgroundColor was not supported when it was defined inside StyleSheet. This commit fixes that and allow for proper import of VSDX into LibreOffice. More information about TextBkgnd Cell: https://learn.microsoft.com/en-us/office/client-developer/visio/textbkgnd-cell-text-block-format-section Change-Id: Id8d1676d802916dc0776138041ea9f7928914f06 Reviewed-on: https://gerrit.libreoffice.org/c/libvisio/+/174173 Tested-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl> diff --git a/src/lib/VSDXMLParserBase.cpp b/src/lib/VSDXMLParserBase.cpp index bf1ab6a..8dadd5f 100644 --- a/src/lib/VSDXMLParserBase.cpp +++ b/src/lib/VSDXMLParserBase.cpp @@ -2221,6 +2221,31 @@ int libvisio::VSDXMLParserBase::readExtendedColourData(boost::optional<Colour> & return ret; } +/* Currently this method is used only for VSDX import, to avoid regression. + * TODO align usage with other file type importers (VSD), and cover it with test cases + */ +bool libvisio::VSDXMLParserBase::readColourOrColourIndex(Colour &value, long &idx, xmlTextReaderPtr reader) +{ + const shared_ptr<xmlChar> stringValue(readStringData(reader), xmlFree); + if (stringValue) + { + VSD_DEBUG_MSG(("VSDXMLParserBase::readExtendedColourData stringValue %s ", (const char *)stringValue.get())); + if (!xmlStrEqual(stringValue.get(), BAD_CAST("Themed"))) + { + try + { + value = xmlStringToColour(stringValue); + return true; + } + catch (const XmlParserException &) + { + idx = xmlStringToLong(stringValue); + } + } + } + return false; +} + int libvisio::VSDXMLParserBase::readExtendedColourData(Colour &value, xmlTextReaderPtr reader) { long idx = -1; diff --git a/src/lib/VSDXMLParserBase.h b/src/lib/VSDXMLParserBase.h index ab8521d..62ebb4b 100644 --- a/src/lib/VSDXMLParserBase.h +++ b/src/lib/VSDXMLParserBase.h @@ -79,6 +79,7 @@ protected: int readExtendedColourData(Colour &value, long &idx, xmlTextReaderPtr reader); int readExtendedColourData(Colour &value, xmlTextReaderPtr reader); int readExtendedColourData(boost::optional<Colour> &value, xmlTextReaderPtr reader); + bool readColourOrColourIndex(Colour &value, long &idx, xmlTextReaderPtr reader); int readNURBSData(boost::optional<NURBSData> &data, xmlTextReaderPtr reader); int readPolylineData(boost::optional<PolylineData> &data, xmlTextReaderPtr reader); int readStringData(VSDName &text, xmlTextReaderPtr reader); diff --git a/src/lib/VSDXParser.cpp b/src/lib/VSDXParser.cpp index 1167ccb..8ede9c7 100644 --- a/src/lib/VSDXParser.cpp +++ b/src/lib/VSDXParser.cpp @@ -737,8 +737,8 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) boost::optional<double> topMargin; boost::optional<double> bottomMargin; boost::optional<unsigned char> verticalAlign; - boost::optional<bool> bgClrId; - boost::optional<Colour> bgColour; + boost::optional<bool> isTextBkgndFilled; + boost::optional<Colour> textBkgndColour; boost::optional<double> defaultTabStop; boost::optional<unsigned char> textDirection; @@ -846,10 +846,35 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) ret = readByteData(verticalAlign, reader); break; case XML_TEXTBKGND: -#if 0 if (XML_READER_TYPE_ELEMENT == tokenType) - ret = readExtendedColourData(bgColour, bgClrId, reader); -#endif + { + long bgClrId = -1; + Colour tmpColour; + if (readColourOrColourIndex(tmpColour, bgClrId, reader)) + { + isTextBkgndFilled = true; + textBkgndColour = tmpColour; + break; + } + /* + The TextBkgnd cell can have any value from 0 through 24, or 255. + The values 0 and 255 (visTxtBlklOpaque) both indicate a transparent text background. + For custom color, is is using the RGB or HSL function plus one. + */ + if ((bgClrId < 1) || (bgClrId >= 255)) + { + isTextBkgndFilled = false; + break; + } + std::map<unsigned, Colour>::const_iterator iter = m_colours.find(bgClrId - 1); + if (iter != m_colours.end()) + { + textBkgndColour = iter->second; + isTextBkgndFilled = true; + break; + } + isTextBkgndFilled = false; + } break; case XML_DEFAULTTABSTOP: if (XML_READER_TYPE_ELEMENT == tokenType) @@ -893,19 +918,6 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) } while ((XML_STYLESHEET != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && (!m_watcher || !m_watcher->isError())); -#if 0 - if (bgClrId < 0) - bgClrId = 0; - if (bgClrId) - { - std::map<unsigned, Colour>::const_iterator iter = m_colours.find(bgClrId-1); - if (iter != m_colours.end()) - bgColour = iter->second; - else - bgColour = Colour(); - } -#endif - if (m_isInStyles) { m_collector->collectLineStyle(level, strokeWidth, strokeColour, linePattern, startMarker, endMarker, lineCap, @@ -914,7 +926,7 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) fillBGTransparency, shadowPattern, shadowColourFG, shadowOffsetX, shadowOffsetY, qsFillColour, qsShadowColour, qsFillMatrix); m_collector->collectTextBlockStyle(level, leftMargin, rightMargin, topMargin, bottomMargin, - verticalAlign, bgClrId, bgColour, defaultTabStop, textDirection); + verticalAlign, isTextBkgndFilled, textBkgndColour, defaultTabStop, textDirection); } else { @@ -923,8 +935,8 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) m_shape.m_fillStyle.override(VSDOptionalFillStyle(fillColourFG, fillColourBG, fillPattern, fillFGTransparency, fillBGTransparency, shadowColourFG, shadowPattern, shadowOffsetX, shadowOffsetY, qsFillColour, qsShadowColour, qsFillMatrix)); - m_shape.m_textBlockStyle.override(VSDOptionalTextBlockStyle(leftMargin, rightMargin, topMargin, bottomMargin, verticalAlign, !!bgClrId, bgColour, - defaultTabStop, textDirection)); + m_shape.m_textBlockStyle.override(VSDOptionalTextBlockStyle(leftMargin, rightMargin, topMargin, bottomMargin, verticalAlign, + isTextBkgndFilled, textBkgndColour, defaultTabStop, textDirection)); } } diff --git a/src/test/Makefile.am b/src/test/Makefile.am index a546396..224d14b 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -55,6 +55,7 @@ EXTRA_DIST = \ data/bgcolor.vsdx \ data/bitmaps.vsd \ data/bitmaps2.vsd \ + data/blue-box.vsdx \ data/color-boxes.vsdx \ data/dwg.vsd \ data/dwg.vsdx \ @@ -62,8 +63,10 @@ EXTRA_DIST = \ data/fdo86729-ms1252.vsd \ data/fdo86729-utf8.vsd \ data/no-bgcolor.vsd \ + data/qs-box.vsdx \ data/tdf76829-datetime-format.vsd \ - data/tdf76829-numeric-format.vsd + data/tdf76829-numeric-format.vsd \ + data/tdf136564-WhiteTextBackground.vsdx # ImportTest::testVsdMetadataTitleUtf8 checks formatted date string AM_TESTS_ENVIRONMENT = TZ=UTC; export TZ; diff --git a/src/test/data/tdf136564-WhiteTextBackground.vsdx b/src/test/data/tdf136564-WhiteTextBackground.vsdx new file mode 100644 index 0000000..59f4bca Binary files /dev/null and b/src/test/data/tdf136564-WhiteTextBackground.vsdx differ diff --git a/src/test/importtest.cpp b/src/test/importtest.cpp index 12e909a..c4fcf5c 100644 --- a/src/test/importtest.cpp +++ b/src/test/importtest.cpp @@ -210,6 +210,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testVsdxCharBgColor); #endif CPPUNIT_TEST(testVsdTextBlockWithoutBgColor); + CPPUNIT_TEST(testVsdxTextBkgndColorFromStylesheet); CPPUNIT_TEST(testVsdNumericFormat); CPPUNIT_TEST(testVsdDateTimeFormatting); CPPUNIT_TEST(testVsd11FormatLine); @@ -229,6 +230,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture void testVsdxImportBgColorFromTheme(); void testVsdxCharBgColor(); void testVsdTextBlockWithoutBgColor(); + void testVsdxTextBkgndColorFromStylesheet(); void testVsdNumericFormat(); void testVsd11FormatLine(); void testVsdDateTimeFormatting(); @@ -358,6 +360,24 @@ void ImportTest::testVsdTextBlockWithoutBgColor() assertXPathNoAttribute(m_doc, "/document/page/layer[5]/textObject/paragraph[1]/span", "background-color"); } +void ImportTest::testVsdxTextBkgndColorFromStylesheet() +{ + m_doc = parse("tdf136564-WhiteTextBackground.vsdx", m_buffer); + assertXPathNoAttribute(m_doc, "/document/page/layer[2]/textObject/paragraph/span", "background-color"); + assertXPathContent(m_doc, "/document/page/layer[2]/textObject/paragraph/span/insertText", "First triangle without background"); + + assertXPathNoAttribute(m_doc, "/document/page/layer[3]/textObject/paragraph/span", "background-color"); + assertXPathContent(m_doc, "/document/page/layer[3]/textObject/paragraph/span/insertText", "Second triangle without background"); + + // Without the accompanying fix in place, this test would have failed with: + // equality assertion failed + // - Expected: #ffffff + // - Actual : + assertXPath(m_doc, "/document/page/layer[4]/textObject/paragraph/span", "background-color", "#ffffff"); + assertXPath(m_doc, "/document/page/layer[4]/textObject/paragraph/span", "color", "#000000"); + assertXPathContent(m_doc, "/document/page/layer[4]/textObject/paragraph/span/insertText", "By default Text is with white Background"); +} + void ImportTest::testVsdNumericFormat() { m_doc = parse("tdf76829-numeric-format.vsd", m_buffer);