[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - 4 commits - filter/CppunitTest_filter_svg.mk filter/Module_filter.mk filter/qa filter/source include/svx sw/CppunitTest_sw_ww8import.mk sw/qa sw/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Wed May 13 07:38:12 UTC 2020
filter/CppunitTest_filter_svg.mk | 47 ++++++++
filter/Module_filter.mk | 1
filter/qa/unit/data/preserve-jpg.odt |binary
filter/qa/unit/svg.cxx | 124 +++++++++++++++++++++++
filter/source/svg/svgexport.cxx | 17 ++-
filter/source/svg/svgwriter.cxx | 81 +++++++++++++--
filter/source/svg/svgwriter.hxx | 2
include/svx/unoshape.hxx | 2
sw/CppunitTest_sw_ww8import.mk | 1
sw/qa/extras/ww8import/data/transparent-text.doc |binary
sw/qa/extras/ww8import/ww8import.cxx | 12 ++
sw/source/filter/ww8/ww8par6.cxx | 7 +
12 files changed, 277 insertions(+), 17 deletions(-)
New commits:
commit 48dd2e178f725304689cf760e816402dc2f14711
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Feb 27 09:34:30 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed May 13 09:28:57 2020 +0200
sw SVG export: try to reuse original bitmap data for JPG and PNG bitmaps
Writer shapes are implemented using SwXShape, Impress shapes use
SdrGrafObj. So switch to working with the XShape interface, which is
supported by both.
Also, don't work with the transformed graphic if it has the same
checksum as the original graphic: the transformed graphic is not linked
to the original JPG/PNG data.
Now selecting an image in Writer Online has the same speedup that
Impress Online already had.
(cherry picked from commit 8fc1b60f62c213a0476f3acc9f89cd5eccbf335d)
Change-Id: Iab2791c5f5c7a2754e3de0ebb2d6ea664f6c77e4
diff --git a/filter/CppunitTest_filter_svg.mk b/filter/CppunitTest_filter_svg.mk
new file mode 100644
index 000000000000..ec0841929f3f
--- /dev/null
+++ b/filter/CppunitTest_filter_svg.mk
@@ -0,0 +1,47 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_svg,\
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_svg, \
+ filter/qa/unit/svg \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_svg, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ test \
+ unotest \
+ utl \
+ tl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_svg))
+$(eval $(call gb_CppunitTest_use_vcl,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_svg,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,filter_svg,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_svg))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk
index 2d380fbd91ac..a01baa0b48a7 100644
--- a/filter/Module_filter.mk
+++ b/filter/Module_filter.mk
@@ -67,6 +67,7 @@ $(eval $(call gb_Module_add_check_targets,filter,\
CppunitTest_filter_ras_test \
CppunitTest_filter_tiff_test \
CppunitTest_filter_tga_test \
+ CppunitTest_filter_svg \
))
endif
diff --git a/filter/qa/unit/data/preserve-jpg.odt b/filter/qa/unit/data/preserve-jpg.odt
new file mode 100644
index 000000000000..83768bd47afb
Binary files /dev/null and b/filter/qa/unit/data/preserve-jpg.odt differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
new file mode 100644
index 000000000000..a8b177ed11bf
--- /dev/null
+++ b/filter/qa/unit/svg.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <unotools/streamwrap.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <tools/stream.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace ::com::sun::star;
+
+char const DATA_DIRECTORY[] = "/filter/qa/unit/data/";
+
+/// SVG filter tests.
+class SvgFilterTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+private:
+ uno::Reference<uno::XComponentContext> mxComponentContext;
+ uno::Reference<lang::XComponent> mxComponent;
+
+public:
+ void setUp() override;
+ void tearDown() override;
+ void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+ uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+ void load(const OUString& rURL);
+ void dispatchCommand(const uno::Reference<lang::XComponent>& xComponent,
+ const OUString& rCommand,
+ const uno::Sequence<beans::PropertyValue>& rPropertyValues);
+};
+
+void SvgFilterTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void SvgFilterTest::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
+void SvgFilterTest::load(const OUString& rFileName)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName;
+ mxComponent = loadFromDesktop(aURL);
+}
+
+void SvgFilterTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("svg"), BAD_CAST("http://www.w3.org/2000/svg"));
+}
+
+void SvgFilterTest::dispatchCommand(const uno::Reference<lang::XComponent>& xComponent,
+ const OUString& rCommand,
+ const uno::Sequence<beans::PropertyValue>& rPropertyValues)
+{
+ uno::Reference<frame::XController> xController
+ = uno::Reference<frame::XModel>(xComponent, uno::UNO_QUERY_THROW)->getCurrentController();
+ CPPUNIT_ASSERT(xController.is());
+ uno::Reference<frame::XDispatchProvider> xFrame(xController->getFrame(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xFrame.is());
+
+ uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference<frame::XDispatchHelper> xDispatchHelper(frame::DispatchHelper::create(xContext));
+ CPPUNIT_ASSERT(xDispatchHelper.is());
+
+ xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, rPropertyValues);
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testPreserveJpg)
+{
+#if !defined(MACOSX)
+ // Load a document with a jpeg image in it.
+ load("preserve-jpg.odt");
+
+ // Select the image.
+ dispatchCommand(getComponent(), ".uno:JumpToNextFrame", {});
+
+ // Export the selection to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_svg_Export");
+ aMediaDescriptor["SelectionOnly"] <<= true;
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Make sure the the original JPG data is reused and we don't perform a PNG re-compress.
+ xmlDocPtr pXmlDoc = parseXmlStream(&aStream);
+ OUString aAttributeValue = getXPath(pXmlDoc, "//svg:image", "href");
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expression: aAttributeValue.startsWith("data:image/jpeg")
+ // i.e. the SVG export result re-compressed the image as PNG, even if the original and the
+ // transformed image is the same, so there is no need for that.
+ CPPUNIT_ASSERT(aAttributeValue.startsWith("data:image/jpeg"));
+#endif
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 7913d3704e73..ab1ee9ce647b 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -689,13 +689,20 @@ bool SVGFilter::implExportWriterTextGraphic( const Reference< view::XSelectionSu
if (xSelection.is() && xSelection->supportsService("com.sun.star.text.TextGraphicObject"))
{
uno::Reference<beans::XPropertySet> xPropertySet(xSelection, uno::UNO_QUERY);
- uno::Reference<graphic::XGraphic> xGraphic;
- xPropertySet->getPropertyValue("TransformedGraphic") >>= xGraphic;
- if (!xGraphic.is())
- return false;
+ uno::Reference<graphic::XGraphic> xOriginalGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xOriginalGraphic;
+ const Graphic aOriginalGraphic(xOriginalGraphic);
+
+ uno::Reference<graphic::XGraphic> xTransformedGraphic;
+ xPropertySet->getPropertyValue("TransformedGraphic") >>= xTransformedGraphic;
- const Graphic aGraphic(xGraphic);
+ if (!xTransformedGraphic.is())
+ return false;
+ const Graphic aTransformedGraphic(xTransformedGraphic);
+ bool bChecksumMatches = aOriginalGraphic.GetChecksum() == aTransformedGraphic.GetChecksum();
+ const Graphic aGraphic = bChecksumMatches ? aOriginalGraphic : aTransformedGraphic;
+ uno::Reference<graphic::XGraphic> xGraphic = bChecksumMatches ? xOriginalGraphic : xTransformedGraphic;
// Calculate size from Graphic
Point aPos( OutputDevice::LogicToLogic(aGraphic.GetPrefMapMode().GetOrigin(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index cc3aa84d61e4..6f4c25c6f0f0 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2677,20 +2677,22 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
namespace
{
-SdrGrafObj* GetSdrGrafObjFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape)
+void GetGraphicFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape, Graphic& rGraphic)
{
if (!pShape)
{
- return nullptr;
+ return;
}
- auto pObject = dynamic_cast<SvxGraphicObject*>(pShape->get());
- if (!pObject)
+ uno::Reference<beans::XPropertySet> xPropertySet(*pShape, uno::UNO_QUERY);
+ if (!xPropertySet.is())
{
- return nullptr;
+ return;
}
- return dynamic_cast<SdrGrafObj*>(pObject->GetSdrObject());
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+ rGraphic= Graphic(xGraphic);
}
}
@@ -2713,34 +2715,30 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
SvMemoryStream aOStm( 65535, 65535 );
bool bCached = false;
- SdrGrafObj* pGrafObj = nullptr;
+ Graphic aGraphic;
bool bPNG = false;
bool bJPG = false;
if (pShape)
{
- pGrafObj = GetSdrGrafObjFromXShape(pShape);
- if (pGrafObj)
+ GetGraphicFromXShape(pShape, aGraphic);
+ if (aGraphic.GetType() == GraphicType::Bitmap)
{
- const Graphic& rGraphic = pGrafObj->GetGraphic();
- if (rGraphic.GetType() == GraphicType::Bitmap)
+ const BitmapEx& rGraphicBitmap = aGraphic.GetBitmapExRef();
+ if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
{
- const BitmapEx& rGraphicBitmap = rGraphic.GetBitmapExRef();
- if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
+ GfxLink aGfxLink = aGraphic.GetGfxLink();
+ if (aGfxLink.GetType() == GfxLinkType::NativePng)
{
- GfxLink aGfxLink = rGraphic.GetGfxLink();
- if (aGfxLink.GetType() == GfxLinkType::NativePng)
- {
- bPNG = true;
- }
- else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
- {
- bJPG = true;
- }
- if (bPNG || bJPG)
- {
- aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
- bCached = true;
- }
+ bPNG = true;
+ }
+ else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
+ {
+ bJPG = true;
+ }
+ if (bPNG || bJPG)
+ {
+ aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
+ bCached = true;
}
}
}
commit c5b3e28cc60e3e93564427424013d3cbe0531369
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Feb 25 11:28:44 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed May 13 09:17:04 2020 +0200
SVG export: try to reuse original bitmap data for JPG and PNG bitmaps
This has a number of benefits:
1) For a sample JPG photo, the SVG output is now 4,9MB, not 20MB.
2) Even the first export to SVG is fast, see commit
570be56b37e4ff105649e604ff4c8a6c368e2e79 (svx: cache PNG export of
graphic shapes, 2020-02-25) for exact numbers.
3) Allow using less memory as the SdrGrafObj doesn't have to store a PNG
result till the document is closed.
We still require matching checksums, so in case anything problematic
happens with the bitmap (grayscale filter applied, etc), then the
optimization is meant to not help, but still produces correct output.
(cherry picked from commit c7af36a6504a192f72fcd3a30712ca8c14e12fa5)
Change-Id: Id3bc359a8dcc4c4d12d3b66ffb512cfa71939a26
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index dfb203360b4e..cc3aa84d61e4 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2714,29 +2714,52 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
bool bCached = false;
SdrGrafObj* pGrafObj = nullptr;
+ bool bPNG = false;
+ bool bJPG = false;
if (pShape)
{
pGrafObj = GetSdrGrafObjFromXShape(pShape);
- if (pGrafObj && pGrafObj->GetPNGPreviewChecksum() == rBmpEx.GetChecksum())
+ if (pGrafObj)
{
- const std::vector<sal_Int8>& rPreviewData = pGrafObj->GetPNGPreviewData();
- aOStm.WriteBytes(rPreviewData.data(), rPreviewData.size());
- bCached = true;
+ const Graphic& rGraphic = pGrafObj->GetGraphic();
+ if (rGraphic.GetType() == GraphicType::Bitmap)
+ {
+ const BitmapEx& rGraphicBitmap = rGraphic.GetBitmapExRef();
+ if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
+ {
+ GfxLink aGfxLink = rGraphic.GetGfxLink();
+ if (aGfxLink.GetType() == GfxLinkType::NativePng)
+ {
+ bPNG = true;
+ }
+ else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
+ {
+ bJPG = true;
+ }
+ if (bPNG || bJPG)
+ {
+ aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
+ bCached = true;
+ }
+ }
+ }
}
}
if( bCached || GraphicConverter::Export( aOStm, rBmpEx, ConvertDataFormat::PNG ) == ERRCODE_NONE )
{
- if (!bCached && pGrafObj)
- {
- pGrafObj->SetPNGPreviewChecksum(rBmpEx.GetChecksum());
- pGrafObj->SetPNGPreviewData(aOStm);
- }
-
Point aPt;
Size aSz;
Sequence< sal_Int8 > aSeq( static_cast<sal_Int8 const *>(aOStm.GetData()), aOStm.Tell() );
- OUStringBuffer aBuffer( "data:image/png;base64," );
+ OUStringBuffer aBuffer;
+ if (bJPG)
+ {
+ aBuffer.append("data:image/jpeg;base64,");
+ }
+ else
+ {
+ aBuffer.append("data:image/png;base64,");
+ }
::comphelper::Base64::encode( aBuffer, aSeq );
ImplMap( rPt, aPt );
diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx
index 29e3a4364f9e..478eabb18dcf 100644
--- a/include/svx/svdograf.hxx
+++ b/include/svx/svdograf.hxx
@@ -29,7 +29,6 @@
#include <vcl/GraphicObject.hxx>
#include <svx/svxdllapi.h>
#include <o3tl/typed_flags_set.hxx>
-#include <tools/stream.hxx>
#include <memory>
#include <cstddef>
@@ -125,9 +124,6 @@ private:
void onGraphicChanged();
GDIMetaFile GetMetaFile(GraphicType &rGraphicType) const;
- BitmapChecksum mnPNGPreviewChecksum = 0;
- std::vector<sal_Int8> maPNGPreviewData;
-
protected:
// protected destructor
virtual ~SdrGrafObj() override;
@@ -303,11 +299,6 @@ public:
{
return mpQrCode.get();
};
-
- void SetPNGPreviewChecksum(BitmapChecksum nPNGPreviewChecksum);
- BitmapChecksum GetPNGPreviewChecksum() const;
- void SetPNGPreviewData(SvMemoryStream& rPNGPreviewData);
- const std::vector<sal_Int8>& GetPNGPreviewData() const;
};
#endif // INCLUDED_SVX_SVDOGRAF_HXX
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index c1e6fa8b6bb6..7e14a6d3bdd9 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -1278,26 +1278,4 @@ void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
}
-void SdrGrafObj::SetPNGPreviewChecksum(BitmapChecksum nPNGPreviewChecksum)
-{
- mnPNGPreviewChecksum = nPNGPreviewChecksum;
-}
-
-BitmapChecksum SdrGrafObj::GetPNGPreviewChecksum() const
-{
- return mnPNGPreviewChecksum;
-}
-
-void SdrGrafObj::SetPNGPreviewData(SvMemoryStream& rPNGPreviewData)
-{
- rPNGPreviewData.Seek(0);
- maPNGPreviewData.resize(rPNGPreviewData.remainingSize());
- rPNGPreviewData.ReadBytes(maPNGPreviewData.data(), maPNGPreviewData.size());
-}
-
-const std::vector<sal_Int8>& SdrGrafObj::GetPNGPreviewData() const
-{
- return maPNGPreviewData;
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4f1cf7a1205485ca7b011c5dd7c2031f498d5c7c
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Feb 25 09:04:10 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed May 13 09:16:33 2020 +0200
svx: cache PNG export of graphic shapes
One scenario where this is useful is: manipulate a JPEG photo in
Online's Impress, e.g. resize it multiple times. Each time we generate
an SVG preview of the shape, which includes the PNG export of the bitmap
itself.
This helps with a desktop CPU:
debug:9976:9974: SVGFilter::filter finished in 3422 ms
debug:9976:9974: SVGFilter::filter finished in 176 ms
But it is meant to help on mobile, too, where writing such a bitmap as
PNG takes 16-17 seconds without this.
(This works because SVG writes the original bitmap, even if it's scaled.
If that invariant will be broken in the future, we still emit correct
output, but then the cache will be less useful.)
(cherry picked from commit 570be56b37e4ff105649e604ff4c8a6c368e2e79)
Change-Id: I7204b04efeeb42c6eec67f04dfdb8a4ed50443a9
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 9253bbace5f3..dfb203360b4e 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -31,6 +31,8 @@
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <sax/tools/converter.hxx>
#include <i18nlangtag/languagetag.hxx>
+#include <svx/unoshape.hxx>
+#include <svx/svdograf.hxx>
#include <memory>
@@ -2673,10 +2675,29 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
}
}
+namespace
+{
+SdrGrafObj* GetSdrGrafObjFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape)
+{
+ if (!pShape)
+ {
+ return nullptr;
+ }
+
+ auto pObject = dynamic_cast<SvxGraphicObject*>(pShape->get());
+ if (!pObject)
+ {
+ return nullptr;
+ }
+
+ return dynamic_cast<SdrGrafObj*>(pObject->GetSdrObject());
+}
+}
void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
const Point& rPt, const Size& rSz,
- const Point& rSrcPt, const Size& rSrcSz )
+ const Point& rSrcPt, const Size& rSrcSz,
+ const css::uno::Reference<css::drawing::XShape>* pShape )
{
if( !!rBmpEx )
{
@@ -2691,8 +2712,27 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
{
SvMemoryStream aOStm( 65535, 65535 );
- if( GraphicConverter::Export( aOStm, rBmpEx, ConvertDataFormat::PNG ) == ERRCODE_NONE )
+ bool bCached = false;
+ SdrGrafObj* pGrafObj = nullptr;
+ if (pShape)
{
+ pGrafObj = GetSdrGrafObjFromXShape(pShape);
+ if (pGrafObj && pGrafObj->GetPNGPreviewChecksum() == rBmpEx.GetChecksum())
+ {
+ const std::vector<sal_Int8>& rPreviewData = pGrafObj->GetPNGPreviewData();
+ aOStm.WriteBytes(rPreviewData.data(), rPreviewData.size());
+ bCached = true;
+ }
+ }
+
+ if( bCached || GraphicConverter::Export( aOStm, rBmpEx, ConvertDataFormat::PNG ) == ERRCODE_NONE )
+ {
+ if (!bCached && pGrafObj)
+ {
+ pGrafObj->SetPNGPreviewChecksum(rBmpEx.GetChecksum());
+ pGrafObj->SetPNGPreviewData(aOStm);
+ }
+
Point aPt;
Size aSz;
Sequence< sal_Int8 > aSeq( static_cast<sal_Int8 const *>(aOStm.GetData()), aOStm.Tell() );
@@ -3036,7 +3076,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pSubstAct);
ImplWriteBmp( BitmapEx(pBmpScaleAction->GetBitmap()),
pA->GetPoint(), pA->GetSize(),
- Point(), pBmpScaleAction->GetBitmap().GetSizePixel() );
+ Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pxShape );
}
}
}
@@ -3419,7 +3459,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
ImplWriteBmp( BitmapEx(pA->GetBitmap()),
pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
- Point(), pA->GetBitmap().GetSizePixel() );
+ Point(), pA->GetBitmap().GetSizePixel(), pxShape );
}
}
break;
@@ -3439,7 +3479,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
ImplWriteBmp( BitmapEx(pA->GetBitmap()),
pA->GetPoint(), pA->GetSize(),
- Point(), pA->GetBitmap().GetSizePixel() );
+ Point(), pA->GetBitmap().GetSizePixel(), pxShape );
}
}
}
@@ -3453,7 +3493,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
ImplWriteBmp( BitmapEx(pA->GetBitmap()),
pA->GetDestPoint(), pA->GetDestSize(),
- pA->GetSrcPoint(), pA->GetSrcSize() );
+ pA->GetSrcPoint(), pA->GetSrcSize(), pxShape );
}
}
break;
@@ -3466,7 +3506,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
ImplWriteBmp( pA->GetBitmapEx(),
pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
- Point(), pA->GetBitmapEx().GetSizePixel() );
+ Point(), pA->GetBitmapEx().GetSizePixel(), pxShape );
}
}
break;
@@ -3486,7 +3526,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
ImplWriteBmp( pA->GetBitmapEx(),
pA->GetPoint(), pA->GetSize(),
- Point(), pA->GetBitmapEx().GetSizePixel() );
+ Point(), pA->GetBitmapEx().GetSizePixel(), pxShape );
}
}
}
@@ -3500,7 +3540,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
ImplWriteBmp( pA->GetBitmapEx(),
pA->GetDestPoint(), pA->GetDestSize(),
- pA->GetSrcPoint(), pA->GetSrcSize() );
+ pA->GetSrcPoint(), pA->GetSrcSize(), pxShape );
}
}
break;
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index f0271ed4090b..1418818b0c16 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -360,7 +360,7 @@ private:
void ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags );
void ImplWriteText( const Point& rPos, const OUString& rText, const long* pDXArray, long nWidth );
void ImplWriteText( const Point& rPos, const OUString& rText, const long* pDXArray, long nWidth, Color aTextColor );
- void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz );
+ void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const css::uno::Reference<css::drawing::XShape>* pShape);
void ImplWriteActions( const GDIMetaFile& rMtf,
sal_uInt32 nWriteFlags,
diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx
index 478eabb18dcf..29e3a4364f9e 100644
--- a/include/svx/svdograf.hxx
+++ b/include/svx/svdograf.hxx
@@ -29,6 +29,7 @@
#include <vcl/GraphicObject.hxx>
#include <svx/svxdllapi.h>
#include <o3tl/typed_flags_set.hxx>
+#include <tools/stream.hxx>
#include <memory>
#include <cstddef>
@@ -124,6 +125,9 @@ private:
void onGraphicChanged();
GDIMetaFile GetMetaFile(GraphicType &rGraphicType) const;
+ BitmapChecksum mnPNGPreviewChecksum = 0;
+ std::vector<sal_Int8> maPNGPreviewData;
+
protected:
// protected destructor
virtual ~SdrGrafObj() override;
@@ -299,6 +303,11 @@ public:
{
return mpQrCode.get();
};
+
+ void SetPNGPreviewChecksum(BitmapChecksum nPNGPreviewChecksum);
+ BitmapChecksum GetPNGPreviewChecksum() const;
+ void SetPNGPreviewData(SvMemoryStream& rPNGPreviewData);
+ const std::vector<sal_Int8>& GetPNGPreviewData() const;
};
#endif // INCLUDED_SVX_SVDOGRAF_HXX
diff --git a/include/svx/unoshape.hxx b/include/svx/unoshape.hxx
index 0b48d1e433d6..0e445c0e84f4 100644
--- a/include/svx/unoshape.hxx
+++ b/include/svx/unoshape.hxx
@@ -631,7 +631,7 @@ public:
* *
***********************************************************************/
-class SvxGraphicObject final : public SvxShapeText
+class SVX_DLLPUBLIC SvxGraphicObject final : public SvxShapeText
{
using SvxUnoTextRangeBase::setPropertyValue;
using SvxUnoTextRangeBase::getPropertyValue;
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index 7e14a6d3bdd9..c1e6fa8b6bb6 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -1278,4 +1278,26 @@ void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
}
+void SdrGrafObj::SetPNGPreviewChecksum(BitmapChecksum nPNGPreviewChecksum)
+{
+ mnPNGPreviewChecksum = nPNGPreviewChecksum;
+}
+
+BitmapChecksum SdrGrafObj::GetPNGPreviewChecksum() const
+{
+ return mnPNGPreviewChecksum;
+}
+
+void SdrGrafObj::SetPNGPreviewData(SvMemoryStream& rPNGPreviewData)
+{
+ rPNGPreviewData.Seek(0);
+ maPNGPreviewData.resize(rPNGPreviewData.remainingSize());
+ rPNGPreviewData.ReadBytes(maPNGPreviewData.data(), maPNGPreviewData.size());
+}
+
+const std::vector<sal_Int8>& SdrGrafObj::GetPNGPreviewData() const
+{
+ return maPNGPreviewData;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 39ddb0081def0d4635234f59de4e90adf06308e8
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Feb 24 09:44:36 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed May 13 09:09:24 2020 +0200
tdf#130812 DOC import: fix unexpected transparency of text
DOC can have black with transparency set to 0xff, and that is meant to
be just black. Allow COL_AUTO, though; the rendering will not consider
that as transparent anyway.
Other than that, DOC does not support text with transparency, it's a
DOCX-only feature.
(cherry picked from commit 634a9ba15d65b6fdc506326e6b49b4b957c5cfcb)
Change-Id: I33f61b54b8ebd7958845063ae61900182d6f5e80
diff --git a/sw/CppunitTest_sw_ww8import.mk b/sw/CppunitTest_sw_ww8import.mk
index 97061ef14ab8..6b248fb5f926 100644
--- a/sw/CppunitTest_sw_ww8import.mk
+++ b/sw/CppunitTest_sw_ww8import.mk
@@ -29,6 +29,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_ww8import, \
sfx \
svl \
sw \
+ tl \
utl \
))
diff --git a/sw/qa/extras/ww8import/data/transparent-text.doc b/sw/qa/extras/ww8import/data/transparent-text.doc
new file mode 100644
index 000000000000..b458db29cc09
Binary files /dev/null and b/sw/qa/extras/ww8import/data/transparent-text.doc differ
diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx
index 468cacfd0967..250a32832752 100644
--- a/sw/qa/extras/ww8import/ww8import.cxx
+++ b/sw/qa/extras/ww8import/ww8import.cxx
@@ -133,6 +133,18 @@ DECLARE_WW8IMPORT_TEST(testTdf106291, "tdf106291.doc")
CPPUNIT_ASSERT(cellHeight.toInt32() > 200); // height might depend on font size
}
+DECLARE_WW8IMPORT_TEST(testTransparentText, "transparent-text.doc")
+{
+ uno::Reference<text::XText> xHeaderText = getProperty<uno::Reference<text::XText>>(
+ getStyles("PageStyles")->getByName("Standard"), "HeaderText");
+ uno::Reference<text::XTextRange> xParagraph = getParagraphOfText(3, xHeaderText);
+ // Without the accompanying fix in place, this test would have failed: transparency was set to
+ // 100%, so the text was not readable.
+ sal_Int32 nExpected(COL_BLACK);
+ sal_Int32 nActual(getProperty<sal_Int16>(xParagraph, "CharTransparence"));
+ CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
+}
+
DECLARE_WW8IMPORT_TEST( testTdf105570, "tdf105570.doc" )
{
/*****
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 499fdc8e223e..634ac5131b0c 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -3594,6 +3594,13 @@ void SwWW8ImplReader::Read_TextForeColor(sal_uInt16, const sal_uInt8* pData, sho
else
{
Color aColor(msfilter::util::BGRToRGB(SVBT32ToUInt32(pData)));
+
+ // At least when transparency is 0xff and the color is black, Word renders that as black.
+ if (aColor.GetTransparency() && aColor != COL_AUTO)
+ {
+ aColor.SetTransparency(0);
+ }
+
NewAttr(SvxColorItem(aColor, RES_CHRATR_COLOR));
if (m_pCurrentColl && m_xStyles)
m_xStyles->mbTextColChanged = true;
More information about the Libreoffice-commits
mailing list