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);

Reply via email to