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: */

Reply via email to