oox/source/vml/vmlformatting.cxx                                   |   48 ++++
 sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx   |binary
 sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx  |binary
 sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx |binary
 sw/qa/extras/tiledrendering/tiledrendering.cxx                     |   97 
++++++++++
 5 files changed, 145 insertions(+)

New commits:
commit a1055563a0b72d470fa0e8ab6cd12d1e58932b40
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Wed Feb 7 17:25:50 2024 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Feb 26 08:48:41 2024 +0100

    tdf#159626 vml pattern import: add color, fix back/foreground
    
    This depends on tdf#126533 which imports page style v:fill,
    BUT ONLY IN ORDER TO support the unit tests.
    The patch itself can stand alone
    and fixes vml import into textboxes/shapes etc.
    i.e. backporting could be possible by dropping the unit tests.
    
    The pattern that VML uses to indicate foreground
    and background is very different from what LO needs.
    [Fortunately LO does not use the _guess_ from
    vcl::bitmap::isHistorical8x8 to determine which
    color is the background. Instead it always uses the first pixel.]
    
    Documentation says that unspecified XML_fillcolor
    and XML_color should be white, but observation
    says it should be 25% gray (Word 2003).
    25% gray == C0C0C0 == fillcolor="silver" == COL_LIGHTGRAY
    
    Currently, we simply export as a colored, tiled image,
    and not as a B&W type="pattern"
    so no corresponding export changes need to be made to export.
    
    Existing unit test documents that are affected:
    -chart2export's PieChartDataLabels.docx (page background)
    -ooxmlexport5's fdo77725.docx (minimized PieChartDataLabels.docx)
     * both foreground and background are set to white => solid white
    -sw/qa/core/data/ooxml/pass/fdo79131.docx (shape "inline")
    
    make CppunitTest_sw_tiledrendering \
        CPPUNIT_TEST_NAME=testTdf159626_yellowPatternFill
    make CppunitTest_sw_tiledrendering \
        CPPUNIT_TEST_NAME=testTdf159626_yellowPatternFillB
    make CppunitTest_sw_tiledrendering \
        CPPUNIT_TEST_NAME=testTdf159626_blackPatternFill
    
    Change-Id: I9533ac4a7489081ffc62a10e900f5526abb906db
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163106
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163864
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx
index 029d5429d921..6182950973ee 100644
--- a/oox/source/vml/vmlformatting.cxx
+++ b/oox/source/vml/vmlformatting.cxx
@@ -29,6 +29,7 @@
 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
 #include <com/sun/star/table/ShadowFormat.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
+
 #include <o3tl/float_int_conversion.hxx>
 #include <o3tl/unit_conversion.hxx>
 #include <rtl/strbuf.hxx>
@@ -46,6 +47,8 @@
 #include <svx/svdtrans.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <o3tl/string_view.hxx>
+#include <svx/xbitmap.hxx>
+#include <vcl/BitmapTools.hxx>
 #include <vcl/virdev.hxx>
 
 namespace oox::vml {
@@ -843,6 +846,51 @@ void FillModel::pushToPropMap( ShapePropertyMap& rPropMap, 
const GraphicHelper&
                     aFillProps.maBlipProps.mxFillGraphic = 
rGraphicHelper.importEmbeddedGraphic(moBitmapPath.value());
                     if (aFillProps.maBlipProps.mxFillGraphic.is())
                     {
+                        if (nFillType == XML_pattern)
+                        {
+                            // VML provides an 8x8 black(background) and 
white(foreground) pattern
+                            // along with specified background(color2) and 
foreground(color) colors,
+                            // while LO needs the color applied directly to 
the pattern.
+                            const Graphic 
aGraphic(aFillProps.maBlipProps.mxFillGraphic);
+                            ::Color nBackColor;
+                            ::Color nPixelColor;
+                            bool bIs8x8 = 
vcl::bitmap::isHistorical8x8(aGraphic.GetBitmapEx(),
+                                                                       
nBackColor, nPixelColor);
+                            if (bIs8x8)
+                            {
+                                nBackColor
+                                    = 
ConversionHelper::decodeColor(rGraphicHelper, moColor2,
+                                                                    
moOpacity2, API_RGB_WHITE)
+                                          .getColor(rGraphicHelper);
+                                // Documentation says undefined == white; 
observation says lightgray
+                                nPixelColor
+                                    = 
ConversionHelper::decodeColor(rGraphicHelper, moColor,
+                                                                    moOpacity, 
COL_LIGHTGRAY)
+                                          .getColor(rGraphicHelper);
+
+                                XOBitmap aXOB(aGraphic.GetBitmapEx());
+                                aXOB.Bitmap2Array();
+                                // LO uses the first pixel's color to 
represent background pixels
+                                if (aXOB.GetBackgroundColor() == COL_WHITE)
+                                {
+                                    // White always represents the foreground 
in VML => swap
+                                    aXOB.SetPixelColor(nBackColor);
+                                    aXOB.SetBackgroundColor(nPixelColor);
+                                }
+                                else
+                                {
+                                    assert(aXOB.GetBackgroundColor() == 
COL_BLACK);
+                                    aXOB.SetPixelColor(nPixelColor);
+                                    aXOB.SetBackgroundColor(nBackColor);
+                                }
+                                aXOB.Array2Bitmap();
+
+                                Graphic aLOPattern(aXOB.GetBitmap());
+                                
aLOPattern.setOriginURL(aGraphic.getOriginURL());
+                                aFillProps.maBlipProps.mxFillGraphic = 
aLOPattern.GetXGraphic();
+                            }
+                        }
+
                         aFillProps.moFillType = XML_blipFill;
                         aFillProps.maBlipProps.moBitmapMode = (nFillType == 
XML_frame) ? XML_stretch : XML_tile;
                         break;  // do not break if bitmap is missing, but run 
to XML_solid instead
diff --git a/sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx 
b/sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx
new file mode 100644
index 000000000000..650f43055be5
Binary files /dev/null and 
b/sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx differ
diff --git a/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx 
b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx
new file mode 100644
index 000000000000..9be8c27ad840
Binary files /dev/null and 
b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx differ
diff --git a/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx 
b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx
new file mode 100644
index 000000000000..f802513c447d
Binary files /dev/null and 
b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 94b203ef3d48..dddf4f9503b5 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -4229,6 +4229,103 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testStatusBarPageNumber)
     CPPUNIT_ASSERT_EQUAL(".uno:StatePageNumber=Page 2 of 2"_ostr, 
aView2.m_aStateChanges[0]);
 }
 
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTdf159626_yellowPatternFill)
+{
+    SwXTextDocument* pXTextDocument = 
createDoc("tdf159626_yellowPatternFill.docx");
+    CPPUNIT_ASSERT(pXTextDocument);
+
+    SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
+    SwView* pView = pDoc->GetDocShell()->GetView();
+    uno::Reference<frame::XFrame> xFrame = 
pView->GetViewFrame().GetFrame().GetFrameInterface();
+
+    Bitmap aBitmap(getTile(pXTextDocument));
+    Size aSize = aBitmap.GetSizePixel();
+
+    int nPureYellowPixels = 0;
+    int nEdgePlusGrayPlusAntialiasPixels = 0;
+    BitmapScopedReadAccess pAccess(aBitmap);
+    for (tools::Long x = 0; x < aSize.Width(); ++x)
+    {
+        for (tools::Long y = 0; y < aSize.Height(); ++y)
+        {
+            Color aActualColor(pAccess->GetPixel(y, x));
+            if (aActualColor == COL_YELLOW)
+                ++nPureYellowPixels;
+            else
+                ++nEdgePlusGrayPlusAntialiasPixels;
+        }
+    }
+    // The page background pattern is 62 yellow/2 gray pixels - first pixel is 
gray(foreground)
+    // Without the patch, the document was primarily gray.
+    CPPUNIT_ASSERT(nPureYellowPixels > 0);
+    CPPUNIT_ASSERT(nPureYellowPixels / 2 > nEdgePlusGrayPlusAntialiasPixels);
+}
+
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTdf159626_yellowPatternFillB)
+{
+    SwXTextDocument* pXTextDocument = 
createDoc("tdf159626_yellowPatternFillB.docx");
+    CPPUNIT_ASSERT(pXTextDocument);
+
+    SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
+    SwView* pView = pDoc->GetDocShell()->GetView();
+    uno::Reference<frame::XFrame> xFrame = 
pView->GetViewFrame().GetFrame().GetFrameInterface();
+
+    Bitmap aBitmap(getTile(pXTextDocument));
+    Size aSize = aBitmap.GetSizePixel();
+
+    int nPureYellowPixels = 0;
+    int nEdgePlusGrayPlusAntialiasPixels = 0;
+    BitmapScopedReadAccess pAccess(aBitmap);
+    for (tools::Long x = 0; x < aSize.Width(); ++x)
+    {
+        for (tools::Long y = 0; y < aSize.Height(); ++y)
+        {
+            Color aActualColor(pAccess->GetPixel(y, x));
+            if (aActualColor == COL_YELLOW)
+                ++nPureYellowPixels;
+            else
+                ++nEdgePlusGrayPlusAntialiasPixels;
+        }
+    }
+    // The page background pattern is 62 yellow/2 gray pixels - first pixel is 
yellow(background)
+    // LO already imported this correctly, as primarily yellow - ensure it 
stays that way.
+    CPPUNIT_ASSERT(nPureYellowPixels > 0);
+    CPPUNIT_ASSERT(nPureYellowPixels / 2 > nEdgePlusGrayPlusAntialiasPixels);
+}
+
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTdf159626_blackPatternFill)
+{
+    SwXTextDocument* pXTextDocument = 
createDoc("tdf159626_blackPatternFill.docx");
+    CPPUNIT_ASSERT(pXTextDocument);
+
+    SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
+    SwView* pView = pDoc->GetDocShell()->GetView();
+    uno::Reference<frame::XFrame> xFrame = 
pView->GetViewFrame().GetFrame().GetFrameInterface();
+
+    Bitmap aBitmap(getTile(pXTextDocument));
+    Size aSize = aBitmap.GetSizePixel();
+
+    int nPureBlackPixels = 0;
+    int nEdgePlusWhitePlusAntialiasPixels = 0;
+    BitmapScopedReadAccess pAccess(aBitmap);
+    for (tools::Long x = 0; x < aSize.Width(); ++x)
+    {
+        for (tools::Long y = 0; y < aSize.Height(); ++y)
+        {
+            Color aActualColor(pAccess->GetPixel(y, x));
+            if (aActualColor == COL_BLACK)
+                ++nPureBlackPixels;
+            else
+                ++nEdgePlusWhitePlusAntialiasPixels;
+        }
+    }
+    // Both the foreground and background are defined as black, represented by 
a pattern with
+    // 48 white/16 black pixels.
+    // The document should be entirely black (except for text margin markings).
+    CPPUNIT_ASSERT(nEdgePlusWhitePlusAntialiasPixels > 0);
+    CPPUNIT_ASSERT(nPureBlackPixels / 10 > nEdgePlusWhitePlusAntialiasPixels);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to