diff options
author | Justin Luth <justin.luth@collabora.com> | 2024-02-07 17:25:50 -0500 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2024-02-26 08:48:41 +0100 |
commit | a1055563a0b72d470fa0e8ab6cd12d1e58932b40 (patch) | |
tree | 64ab369618ec25ea24ebbff772fc3c2aa317c96f | |
parent | 57244c2096782dbedfd55cea5629ae08433e204a (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.cxx | 48 | ||||
-rw-r--r-- | sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx | bin | 0 -> 10653 bytes | |||
-rw-r--r-- | sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx | bin | 0 -> 10553 bytes | |||
-rw-r--r-- | sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx | bin | 0 -> 9503 bytes | |||
-rw-r--r-- | sw/qa/extras/tiledrendering/tiledrendering.cxx | 97 |
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 Binary files differnew file mode 100644 index 000000000000..650f43055be5 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf159626_blackPatternFill.docx diff --git a/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx Binary files differnew file mode 100644 index 000000000000..9be8c27ad840 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx diff --git a/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx Binary files differnew file mode 100644 index 000000000000..f802513c447d --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFillB.docx 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: */ |