src/lib/VSDStyles.h   |    2 
 src/lib/VSDXTheme.cpp |  138 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/lib/VSDXTheme.h   |   13 ++++
 3 files changed, 152 insertions(+), 1 deletion(-)

New commits:
commit 6f6165796d4de297fa7b65a5bc18002ff03bfcad
Author:     Balazs Varga <[email protected]>
AuthorDate: Thu Sep 18 19:54:16 2025 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Sep 19 16:51:27 2025 +0200

    Related tdf#168475 libvisio: vsdx Import variationStyleSchemeLst
    
    elements such as variationStyleScheme and varStyle attributes and apply
    their referenced styles with VariationStyleIndex, if necessary.
    
    Follow-up of: 0f28b4dbdb951bd95381bbe0a5caa0d4a2d47d29
    
    Change-Id: I2dae12e89a7b2caa7c32edee516c857ca2547907
    Reviewed-on: https://gerrit.libreoffice.org/c/libvisio/+/191170
    Tested-by: Miklos Vajna <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/src/lib/VSDStyles.h b/src/lib/VSDStyles.h
index cff97d4..31f7e9d 100644
--- a/src/lib/VSDStyles.h
+++ b/src/lib/VSDStyles.h
@@ -194,6 +194,8 @@ struct VSDFillStyle
       ASSIGN_OPTIONAL(theme->getThemeColour(qsShadowColour, 
variationColorIndex), shadowFgColour);
       if (!!style.qsFillMatrix && style.qsFillMatrix.value() >= 0)
         ASSIGN_OPTIONAL(theme->getFillStyleColour(style.qsFillMatrix.value()), 
fgColour);
+      // Check fill style color from variationStyleScheme --> varStyle --> 
fillIdx
+      ASSIGN_OPTIONAL(theme->getStyleColour(qsFillColour, 
variationStyleIndex), fgColour);
     }
     ASSIGN_OPTIONAL(style.fgColour, fgColour);
     ASSIGN_OPTIONAL(style.bgColour, bgColour);
diff --git a/src/lib/VSDXTheme.cpp b/src/lib/VSDXTheme.cpp
index 3890afe..69fd4ec 100644
--- a/src/lib/VSDXTheme.cpp
+++ b/src/lib/VSDXTheme.cpp
@@ -61,10 +61,16 @@ libvisio::VSDXFontScheme::VSDXFontScheme()
 {
 }
 
+libvisio::VSDXVariationStyleScheme::VSDXVariationStyleScheme()
+  : m_varStyles()
+{
+}
+
 libvisio::VSDXTheme::VSDXTheme()
   : m_clrScheme(),
     m_fontScheme(),
-    m_fillStyleLst(std::vector<std::optional<libvisio::Colour>>(6))
+    m_fillStyleLst(std::vector<std::optional<libvisio::Colour>>(6)),
+    m_variationStyleSchemeLst()
 {
 }
 
@@ -106,6 +112,9 @@ bool libvisio::VSDXTheme::parse(librevenge::RVNGInputStream 
*input)
       case XML_A_FMTSCHEME:
         readFmtScheme(reader.get());
         break;
+      case XML_VT_VARIATIONSTYLESCHEMELST:
+        readVariationStyleSchemeLst(reader.get());
+        break;
       default:
         break;
       }
@@ -499,6 +508,133 @@ std::optional<libvisio::Colour> 
libvisio::VSDXTheme::getThemeColour(unsigned val
   return std::optional<libvisio::Colour>();
 }
 
+void libvisio::VSDXTheme::readVariationStyleSchemeLst(xmlTextReaderPtr reader)
+{
+  VSD_DEBUG_MSG(("VSDXTheme::readVariationStyleSchemeLst
"));
+  int ret = 1;
+  int tokenId = XML_TOKEN_INVALID;
+  int tokenType = -1;
+  m_variationStyleSchemeLst.clear();
+  do
+  {
+    ret = xmlTextReaderRead(reader);
+    tokenId = getElementToken(reader);
+    if (XML_TOKEN_INVALID == tokenId)
+    {
+      VSD_DEBUG_MSG(("VSDXTheme::readVariationStyleSchemeLst: unknown token %s
", xmlTextReaderConstName(reader)));
+    }
+    tokenType = xmlTextReaderNodeType(reader);
+    switch (tokenId)
+    {
+    case XML_VT_VARIATIONSTYLESCHEME:
+    {
+      VSDXVariationStyleScheme vaStyleSch;
+      readVariationStyleScheme(reader, tokenId, vaStyleSch);
+      m_variationStyleSchemeLst.push_back(vaStyleSch);
+      break;
+    }
+    default:
+      break;
+    }
+  }
+  while ((XML_VT_VARIATIONCLRSCHEMELST != tokenId || 
XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret);
+}
+
+void libvisio::VSDXTheme::readVariationStyleScheme(xmlTextReaderPtr reader, 
int idToken, VSDXVariationStyleScheme &vaStyleSch)
+{
+  int ret = 1;
+  int tokenId = XML_TOKEN_INVALID;
+  int tokenType = -1;
+  size_t iVNum = 0;
+  do
+  {
+    ret = xmlTextReaderRead(reader);
+    tokenId = getElementToken(reader);
+    if (XML_TOKEN_INVALID == tokenId)
+    {
+      VSD_DEBUG_MSG(("VSDXTheme::readVariationStyleScheme: unknown token %s
", xmlTextReaderConstName(reader)));
+    }
+    tokenType = xmlTextReaderNodeType(reader);
+    switch (tokenId)
+    {
+      case XML_VT_VARSTYLE:
+      {
+        if (vaStyleSch.m_varStyles.size() > iVNum)
+        {
+          readVarIdx(reader, vaStyleSch.m_varStyles[iVNum++]);
+        }
+        else
+        {
+          VSD_DEBUG_MSG(("Only four XML_VT_VARSTYLE can exists.
"));
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  while ((idToken != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 
== ret);
+}
+
+void libvisio::VSDXTheme::readVarIdx(xmlTextReaderPtr reader, 
std::array<unsigned, 4>& varStyle)
+{
+  if (XML_VT_VARSTYLE == getElementToken(reader))
+  {
+    // 
https://learn.microsoft.com/en-us/openspecs/sharepoint_protocols/ms-vsdx/07c6a18a-16ec-4c36-942b-8c611dd3d140
+    const shared_ptr<xmlChar> valFillIdx(xmlTextReaderGetAttribute(reader, 
BAD_CAST("fillIdx")), xmlFree);
+    varStyle[0] = valFillIdx ? (unsigned)xmlStringToLong(valFillIdx) : 
MINUS_ONE;
+
+    const shared_ptr<xmlChar> valLineIdx(xmlTextReaderGetAttribute(reader, 
BAD_CAST("lineIdx")), xmlFree);
+    varStyle[1] = valLineIdx ? (unsigned)xmlStringToLong(valLineIdx) : 
MINUS_ONE;
+
+    const shared_ptr<xmlChar> valEffIdx(xmlTextReaderGetAttribute(reader, 
BAD_CAST("effectIdx")), xmlFree);
+    varStyle[2] = valEffIdx ? (unsigned)xmlStringToLong(valEffIdx) : MINUS_ONE;
+
+    const shared_ptr<xmlChar> valFontIdx(xmlTextReaderGetAttribute(reader, 
BAD_CAST("fontIdx")), xmlFree);
+    varStyle[3] = valFontIdx ? (unsigned)xmlStringToLong(valFontIdx) : 
MINUS_ONE;
+  }
+}
+
+std::optional<libvisio::Colour> libvisio::VSDXTheme::getStyleColour(unsigned 
value, unsigned variationIndex) const
+{
+  if (!m_variationStyleSchemeLst.empty())
+  {
+    // 
https://learn.microsoft.com/en-us/openspecs/sharepoint_protocols/ms-vsdx/25689058-b1e7-4d3c-a833-0a4c7180f5f2
+    if (variationIndex >= m_variationStyleSchemeLst.size())
+      variationIndex = 0;
+    switch (value)
+    {
+    case 100:
+    case 200:
+    {
+      std::array<unsigned, 4> varStyle = 
m_variationStyleSchemeLst[variationIndex].m_varStyles[0];
+      return getFillStyleColour(varStyle[0]);
+    }
+    case 101:
+    case 201:
+    {
+      std::array<unsigned, 4> varStyle = 
m_variationStyleSchemeLst[variationIndex].m_varStyles[1];
+      return getFillStyleColour(varStyle[0]);
+    }
+    case 102:
+    case 202:
+    {
+      std::array<unsigned, 4> varStyle = 
m_variationStyleSchemeLst[variationIndex].m_varStyles[2];
+      return getFillStyleColour(varStyle[0]);
+    }
+    case 103:
+    case 203:
+    {
+      std::array<unsigned, 4> varStyle = 
m_variationStyleSchemeLst[variationIndex].m_varStyles[3];
+      return getFillStyleColour(varStyle[0]);
+    }
+    default:
+      break;
+    }
+  }
+  return std::optional<libvisio::Colour>();
+}
+
 void libvisio::VSDXTheme::readFmtScheme(xmlTextReaderPtr reader)
 {
   VSD_DEBUG_MSG(("VSDXTheme::readFmtScheme
"));
diff --git a/src/lib/VSDXTheme.h b/src/lib/VSDXTheme.h
index 7e4c414..728d1fb 100644
--- a/src/lib/VSDXTheme.h
+++ b/src/lib/VSDXTheme.h
@@ -13,6 +13,7 @@
 #include <vector>
 #include <map>
 #include <optional>
+#include <array>
 #include <librevenge-stream/librevenge-stream.h>
 #include "VSDXMLHelper.h"
 
@@ -73,6 +74,13 @@ struct VSDXFontScheme
   VSDXFontScheme();
 };
 
+struct VSDXVariationStyleScheme
+{
+  std::array<std::array<unsigned, 4>, 4> m_varStyles;
+
+  VSDXVariationStyleScheme();
+};
+
 class VSDXTheme
 {
 public:
@@ -80,6 +88,7 @@ public:
   ~VSDXTheme();
   bool parse(librevenge::RVNGInputStream *input);
   std::optional<Colour> getThemeColour(unsigned value, unsigned variationIndex 
= 0) const;
+  std::optional<Colour> getStyleColour(unsigned value, unsigned variationIndex 
= 0) const;
   std::optional<Colour> getFillStyleColour(unsigned value) const;
 
 private:
@@ -93,6 +102,9 @@ private:
   bool readThemeColour(xmlTextReaderPtr reader, int idToken, Colour &clr);
   void readVariationClrSchemeLst(xmlTextReaderPtr reader);
   void readVariationClrScheme(xmlTextReaderPtr reader, VSDXVariationClrScheme 
&varClrSch);
+  void readVariationStyleSchemeLst(xmlTextReaderPtr reader);
+  void readVariationStyleScheme(xmlTextReaderPtr reader, int idToken, 
VSDXVariationStyleScheme &vaStyleSch);
+  void readVarIdx(xmlTextReaderPtr reader, std::array<unsigned, 4>& varStyle);
   void readFontScheme(xmlTextReaderPtr reader);
   void readFont(xmlTextReaderPtr reader, int idToken, VSDXFont &font);
   bool readTypeFace(xmlTextReaderPtr reader, librevenge::RVNGString &typeFace);
@@ -106,6 +118,7 @@ private:
   VSDXClrScheme m_clrScheme;
   VSDXFontScheme m_fontScheme;
   std::vector<std::optional<Colour>> m_fillStyleLst;
+  std::vector<VSDXVariationStyleScheme> m_variationStyleSchemeLst;
 };
 
 } // namespace libvisio

Reply via email to