summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Luth <justin.luth@collabora.com>2024-02-07 17:25:50 -0500
committerMiklos Vajna <vmiklos@collabora.com>2024-02-26 08:48:41 +0100
commita1055563a0b72d470fa0e8ab6cd12d1e58932b40 (patch)
tree64ab369618ec25ea24ebbff772fc3c2aa317c96f
parent57244c2096782dbedfd55cea5629ae08433e204a (diff)
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 <jluth@mail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163864 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--oox/source/vml/vmlformatting.cxx48
-rw-r--r--sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docxbin0 -> 10653 bytes
-rw-r--r--sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docxbin0 -> 10553 bytes
-rw-r--r--sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docxbin0 -> 9503 bytes
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx97
5 files changed, 145 insertions, 0 deletions
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
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx
Binary files 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
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx
Binary files 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
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx
Binary files 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: */