src/lib/VSDStyles.h | 19 +++----- src/lib/VSDXTheme.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++++- src/lib/VSDXTheme.h | 7 ++- src/test/data/qs-box.vsdx |binary src/test/importtest.cpp | 12 +++++ 5 files changed, 128 insertions(+), 14 deletions(-)
New commits: commit aac02f9141fcaf0acc1bce2ff6a5c2e9618f9235 Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Mon Feb 19 09:07:42 2024 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Mar 19 14:01:56 2024 +0100 read and use simple solid fill styles Implemented the reading of simple solid fills from the fill styles list in a theme. And it's use with the quick style fill matrix value. Change-Id: I658340f73ced475bbc8999b4d09c4666fd50dea5 Reviewed-on: https://gerrit.libreoffice.org/c/libvisio/+/163580 Tested-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/src/lib/VSDStyles.h b/src/lib/VSDStyles.h index 93eff0e..ba13805 100644 --- a/src/lib/VSDStyles.h +++ b/src/lib/VSDStyles.h @@ -129,9 +129,7 @@ struct VSDOptionalFillStyle ASSIGN_OPTIONAL(style.qsFillColour, qsFillColour); ASSIGN_OPTIONAL(style.qsShadowColour, qsShadowColour); ASSIGN_OPTIONAL(style.qsFillMatrix, qsFillMatrix); - // Colour 'Blue, Variant 1' is special. It is the default, - // and it is not saved explicitely in the VSDX file. - ASSIGN_OPTIONAL(style.fgColour, fgColour);else fgColour = Colour(0x5b, 0x9b, 0xd5, 0); + ASSIGN_OPTIONAL(style.fgColour, fgColour); ASSIGN_OPTIONAL(style.bgColour, bgColour); ASSIGN_OPTIONAL(style.shadowFgColour, shadowFgColour); } @@ -179,14 +177,13 @@ struct VSDFillStyle ASSIGN_OPTIONAL(style.qsFillMatrix, qsFillMatrix); if (theme) { - if (!!style.qsFillColour && style.qsFillColour.get() >= 0) - ASSIGN_OPTIONAL(theme->getThemeColour(style.qsFillColour.get()), fgColour); - - if (!!style.qsFillColour && style.qsFillColour.get() >= 0) - ASSIGN_OPTIONAL(theme->getThemeColour(style.qsFillColour.get()), bgColour); - - if (!!style.qsShadowColour && style.qsShadowColour.get() >= 0) - ASSIGN_OPTIONAL(theme->getThemeColour(style.qsShadowColour.get()), shadowFgColour); + // Quick Style Colour 100 is special. It is the default, + // and it is not saved explicitely in the VSDX file. + ASSIGN_OPTIONAL(theme->getThemeColour(style.qsFillColour.value_or(100)), fgColour); + ASSIGN_OPTIONAL(theme->getThemeColour(style.qsFillColour.value_or(100)), bgColour); + ASSIGN_OPTIONAL(theme->getThemeColour(style.qsShadowColour.value_or(100)), shadowFgColour); + if (!!style.qsFillMatrix && style.qsFillMatrix.get() >= 0) + ASSIGN_OPTIONAL(theme->getFillStyleColour(style.qsFillMatrix.get()), fgColour); } ASSIGN_OPTIONAL(style.fgColour, fgColour); ASSIGN_OPTIONAL(style.bgColour, bgColour); diff --git a/src/lib/VSDXTheme.cpp b/src/lib/VSDXTheme.cpp index 59044b5..537e2ad 100644 --- a/src/lib/VSDXTheme.cpp +++ b/src/lib/VSDXTheme.cpp @@ -63,7 +63,8 @@ libvisio::VSDXFontScheme::VSDXFontScheme() libvisio::VSDXTheme::VSDXTheme() : m_clrScheme(), - m_fontScheme() + m_fontScheme(), + m_fillStyleLst(std::vector<boost::optional<libvisio::Colour>>(6)) { } @@ -102,6 +103,9 @@ bool libvisio::VSDXTheme::parse(librevenge::RVNGInputStream *input) case XML_A_FONTSCHEME: readFontScheme(reader.get()); break; + case XML_A_FMTSCHEME: + readFmtScheme(reader.get()); + break; default: break; } @@ -320,7 +324,7 @@ void libvisio::VSDXTheme::readClrScheme(xmlTextReaderPtr reader) while ((XML_A_CLRSCHEME != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); } -void libvisio::VSDXTheme::readThemeColour(xmlTextReaderPtr reader, int idToken, Colour &clr) +bool libvisio::VSDXTheme::readThemeColour(xmlTextReaderPtr reader, int idToken, Colour &clr) { int ret = 1; int tokenId = XML_TOKEN_INVALID; @@ -350,7 +354,11 @@ void libvisio::VSDXTheme::readThemeColour(xmlTextReaderPtr reader, int idToken, while ((idToken != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); if (colour) + { clr = *colour; + return true; + } + return false; } void libvisio::VSDXTheme::readVariationClrSchemeLst(xmlTextReaderPtr reader) @@ -491,4 +499,96 @@ boost::optional<libvisio::Colour> libvisio::VSDXTheme::getThemeColour(unsigned v return boost::optional<libvisio::Colour>(); } +void libvisio::VSDXTheme::readFmtScheme(xmlTextReaderPtr reader) +{ + VSD_DEBUG_MSG(("VSDXTheme::readFmtScheme ")); + int ret = 1; + int tokenId = XML_TOKEN_INVALID; + int tokenType = -1; + do + { + ret = xmlTextReaderRead(reader); + tokenId = getElementToken(reader); + if (XML_TOKEN_INVALID == tokenId) + { + VSD_DEBUG_MSG(("VSDXTheme::readFmtScheme: unknown token %s ", xmlTextReaderConstName(reader))); + } + tokenType = xmlTextReaderNodeType(reader); + switch (tokenId) + { + case XML_A_FILLSTYLELST: + { + readFillStyleLst(reader); + break; + } + default: + // Other style lists not implemented + break; + } + } while ((XML_A_FMTSCHEME != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); +} + +void libvisio::VSDXTheme::skipUnimplemented(xmlTextReaderPtr reader, int idToken) +{ + int ret = 1; + int tokenId = XML_TOKEN_INVALID; + int tokenType = -1; + do + { + ret = xmlTextReaderRead(reader); + tokenId = getElementToken(reader); + if (XML_TOKEN_INVALID == tokenId) + { + VSD_DEBUG_MSG(("VSDXTheme::skipUnimplemented: unknown token %s ", xmlTextReaderConstName(reader))); + } + tokenType = xmlTextReaderNodeType(reader); + } while ((idToken != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); +} + +void libvisio::VSDXTheme::readFillStyleLst(xmlTextReaderPtr reader) +{ + VSD_DEBUG_MSG(("VSDXTheme::readFillStyleLst ")); + int ret = xmlTextReaderRead(reader); + int tokenId = getElementToken(reader); + if (XML_TOKEN_INVALID == tokenId) + { + VSD_DEBUG_MSG(("VSDXTheme::readFillStyleLst: unknown token %s ", xmlTextReaderConstName(reader))); + } + int tokenType = xmlTextReaderNodeType(reader); + int i = 0; + while ((XML_A_FILLSTYLELST != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret) + { + switch (tokenId) + { + case XML_A_SOLIDFILL: + { + Colour colour; + if (readThemeColour(reader, tokenId, colour)) + { + m_fillStyleLst[i] = colour; + } + break; + } + default: + // Skip unimplemented fill type + skipUnimplemented(reader, tokenId); + break; + } + ret = xmlTextReaderRead(reader); + tokenId = getElementToken(reader); + if (XML_TOKEN_INVALID == tokenId) + { + VSD_DEBUG_MSG(("VSDXTheme::readFillStyleLst: unknown token %s ", xmlTextReaderConstName(reader))); + } + tokenType = xmlTextReaderNodeType(reader); + } +} + +boost::optional<libvisio::Colour> libvisio::VSDXTheme::getFillStyleColour(unsigned value) const +{ + if (value == 0 || value > m_fillStyleLst.size()) + return boost::optional<libvisio::Colour>(); + return m_fillStyleLst[value - 1]; +} + /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ diff --git a/src/lib/VSDXTheme.h b/src/lib/VSDXTheme.h index f600c96..2451ca8 100644 --- a/src/lib/VSDXTheme.h +++ b/src/lib/VSDXTheme.h @@ -80,6 +80,7 @@ public: ~VSDXTheme(); bool parse(librevenge::RVNGInputStream *input); boost::optional<Colour> getThemeColour(unsigned value, unsigned variationIndex = 0) const; + boost::optional<Colour> getFillStyleColour(unsigned value) const; private: VSDXTheme(const VSDXTheme &); @@ -89,18 +90,22 @@ private: boost::optional<Colour> readSysClr(xmlTextReaderPtr reader); void readClrScheme(xmlTextReaderPtr reader); - void readThemeColour(xmlTextReaderPtr reader, int idToken, Colour &clr); + bool readThemeColour(xmlTextReaderPtr reader, int idToken, Colour &clr); void readVariationClrSchemeLst(xmlTextReaderPtr reader); void readVariationClrScheme(xmlTextReaderPtr reader, VSDXVariationClrScheme &varClrSch); void readFontScheme(xmlTextReaderPtr reader); void readFont(xmlTextReaderPtr reader, int idToken, VSDXFont &font); bool readTypeFace(xmlTextReaderPtr reader, librevenge::RVNGString &typeFace); bool readTypeFace(xmlTextReaderPtr reader, int &script, librevenge::RVNGString &typeFace); + void readFmtScheme(xmlTextReaderPtr reader); + void readFillStyleLst(xmlTextReaderPtr reader); int getElementToken(xmlTextReaderPtr reader); + void skipUnimplemented(xmlTextReaderPtr reader, int idToken); VSDXClrScheme m_clrScheme; VSDXFontScheme m_fontScheme; + std::vector<boost::optional<Colour>> m_fillStyleLst; }; } // namespace libvisio diff --git a/src/test/data/qs-box.vsdx b/src/test/data/qs-box.vsdx new file mode 100644 index 0000000..59be43c Binary files /dev/null and b/src/test/data/qs-box.vsdx differ diff --git a/src/test/importtest.cpp b/src/test/importtest.cpp index 89e497f..12e909a 100644 --- a/src/test/importtest.cpp +++ b/src/test/importtest.cpp @@ -218,6 +218,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testBmpFileHeader); CPPUNIT_TEST(testBmpFileHeader2); CPPUNIT_TEST(testVsdxImportDefaultFillColour); + CPPUNIT_TEST(testVsdxQickStyleFillStyle); CPPUNIT_TEST_SUITE_END(); void testVsdxMetadataTitle(); @@ -236,6 +237,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture void testBmpFileHeader(); void testBmpFileHeader2(); void testVsdxImportDefaultFillColour(); + void testVsdxQickStyleFillStyle(); xmlBufferPtr m_buffer; xmlDocPtr m_doc; @@ -533,6 +535,16 @@ void ImportTest::testVsdxImportDefaultFillColour() assertXPath(m_doc, "/document/page/layer[1]//setStyle[2]", "fill-color", "#5b9bd5"); } +void ImportTest::testVsdxQickStyleFillStyle() +{ + // Without the accompanying fix in place, this test would have failed with: + // equality assertion failed + // - Expected: #ffffff + // - Actual : #fec000 + m_doc = parse("qs-box.vsdx", m_buffer); + assertXPath(m_doc, "/document/page/layer[1]//setStyle[2]", "fill-color", "#ffffff"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ImportTest); /* vim:set shiftwidth=2 softtabstop=2 expandtab: */