svx/source/inc/UnoGraphicExporter.hxx | 9 svx/source/unodraw/UnoGraphicExporter.cxx | 69 +++--- svx/source/unodraw/tableshape.cxx | 2 svx/source/xoutdev/_xoutbmp.cxx | 85 ++++---- sw/qa/extras/htmlexport/data/tdf161979_metafile.fodt | 200 +++++++++++++++++++ sw/qa/extras/htmlexport/htmlexport.cxx | 48 ++++ 6 files changed, 334 insertions(+), 79 deletions(-)
New commits: commit 37217909f2e7c042eab9a8b5eb1ab0a88cdda513 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Jul 10 12:26:37 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Jul 10 22:20:00 2024 +0200 tdf#161979: Render GDI metafile using drawinglayer in XOutBitmap After the changes related to EMF+ reworking, much of the code was removed from VCL, e.g. commit 217ad59a412ebab07a106b14c8976d20bddb9356 (tdf#111486 Removed not used EMF+ code, 2018-12-07). EMF+ code is now in drawinglayer (see EmfPlusHelperData::processEmfPlusData). Unfortunately, we can't make ImpGraphic::draw in VCL to use drawinglayer for rendering, because VCL is lower in dependency tree (it only can use drawinglayercore). Change-Id: I08f8c8ec66baf3dde1f35481144d5e1819bb5fc1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170311 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/svx/source/unodraw/UnoGraphicExporter.hxx b/svx/source/inc/UnoGraphicExporter.hxx similarity index 87% rename from svx/source/unodraw/UnoGraphicExporter.hxx rename to svx/source/inc/UnoGraphicExporter.hxx index ace0db252919..65014c4d7290 100644 --- a/svx/source/unodraw/UnoGraphicExporter.hxx +++ b/svx/source/inc/UnoGraphicExporter.hxx @@ -17,17 +17,18 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_SOURCE_UNODRAW_UNOGRAPHICEXPORTER_HXX -#define INCLUDED_SVX_SOURCE_UNODRAW_UNOGRAPHICEXPORTER_HXX +#pragma once #include <sal/config.h> +#include <vcl/bitmapex.hxx> #include <vcl/graph.hxx> +class Size; +class GDIMetaFile; class SdrObject; +BitmapEx GetBitmapFromMetaFile(const GDIMetaFile& rMtf, const Size* pSize); Graphic SvxGetGraphicForShape(SdrObject& rShape); -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/UnoGraphicExporter.cxx b/svx/source/unodraw/UnoGraphicExporter.cxx index 451b95b0e58b..72ae293ee4e2 100644 --- a/svx/source/unodraw/UnoGraphicExporter.cxx +++ b/svx/source/unodraw/UnoGraphicExporter.cxx @@ -66,7 +66,7 @@ #include <comphelper/sequenceashashmap.hxx> #include <comphelper/propertysequence.hxx> #include <comphelper/sequence.hxx> -#include "UnoGraphicExporter.hxx" +#include <UnoGraphicExporter.hxx> #include <memory> // #i102251# #include <editeng/editstat.hxx> @@ -171,37 +171,6 @@ namespace { SdrModel* mpDoc; }; - /** creates a bitmap that is optionally transparent from a metafile - */ - BitmapEx GetBitmapFromMetaFile( const GDIMetaFile& rMtf, const Size* pSize ) - { - // use new primitive conversion tooling - basegfx::B2DRange aRange(basegfx::B2DPoint(0.0, 0.0)); - sal_uInt32 nMaximumQuadraticPixels(500000); - - if(pSize) - { - // use 100th mm for primitive bitmap converter tool, input is pixel - // use a real OutDev to get the correct DPI, the static LogicToLogic assumes 72dpi which is wrong (!) - const Size aSize100th(Application::GetDefaultDevice()->PixelToLogic(*pSize, MapMode(MapUnit::Map100thMM))); - - aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); - - // when explicitly pixels are requested from the GraphicExporter, use a *very* high limit - // of 16gb (4096x4096 pixels), else use the default for the converters - nMaximumQuadraticPixels = std::min(sal_uInt32(4096 * 4096), sal_uInt32(pSize->Width() * pSize->Height())); - } - else - { - // use 100th mm for primitive bitmap converter tool - const Size aSize100th(OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM))); - - aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); - } - - return convertMetafileToBitmapEx(rMtf, aRange, nMaximumQuadraticPixels); - } - Size* CalcSize( sal_Int32 nWidth, sal_Int32 nHeight, const Size& aBoundSize, Size& aOutSize ) { if( (nWidth == 0) && (nHeight == 0) ) @@ -1289,6 +1258,42 @@ Sequence< OUString > SAL_CALL GraphicExporter::getSupportedMimeTypeNames( ) } +/** creates a bitmap that is optionally transparent from a metafile + */ +BitmapEx GetBitmapFromMetaFile(const GDIMetaFile& rMtf, const Size* pSize) +{ + // use new primitive conversion tooling + basegfx::B2DRange aRange(basegfx::B2DPoint(0.0, 0.0)); + sal_uInt32 nMaximumQuadraticPixels; + + if (pSize) + { + // use 100th mm for primitive bitmap converter tool, input is pixel + // use a real OutDev to get the correct DPI, the static LogicToLogic assumes 72dpi which is wrong (!) + const Size aSize100th( + Application::GetDefaultDevice()->PixelToLogic(*pSize, MapMode(MapUnit::Map100thMM))); + + aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); + + // when explicitly pixels are requested from the GraphicExporter, use a *very* high limit + // of 16gb (4096x4096 pixels) + nMaximumQuadraticPixels = 4096 * 4096; + } + else + { + // use 100th mm for primitive bitmap converter tool + const Size aSize100th(OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), + MapMode(MapUnit::Map100thMM))); + + aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); + + // limit to 2048x2048 pixels, as in ImpGraphic::getBitmap (vcl/source/gdi/impgraph.cxx): + nMaximumQuadraticPixels = 2048 * 2048; + } + + return convertMetafileToBitmapEx(rMtf, aRange, nMaximumQuadraticPixels); +} + Graphic SvxGetGraphicForShape( SdrObject& rShape ) { Graphic aGraphic; diff --git a/svx/source/unodraw/tableshape.cxx b/svx/source/unodraw/tableshape.cxx index c0df40ddc9f2..ebefa12fec3f 100644 --- a/svx/source/unodraw/tableshape.cxx +++ b/svx/source/unodraw/tableshape.cxx @@ -19,7 +19,7 @@ #include <sal/config.h> -#include "UnoGraphicExporter.hxx" +#include <UnoGraphicExporter.hxx> #include "shapeimpl.hxx" #include <svx/unodraw/SvxTableShape.hxx> #include <svx/unoshprp.hxx> diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx index db4ef7152089..f722dc394530 100644 --- a/svx/source/xoutdev/_xoutbmp.cxx +++ b/svx/source/xoutdev/_xoutbmp.cxx @@ -25,9 +25,15 @@ #include <tools/debug.hxx> #include <vcl/virdev.hxx> #include <sfx2/docfile.hxx> +#include <svx/svdpntv.hxx> #include <svx/xoutbmp.hxx> #include <vcl/graphicfilter.hxx> #include <vcl/cvtgrf.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/svapp.hxx> + +#include <UnoGraphicExporter.hxx> + #include <memory> #include <com/sun/star/beans/XPropertySet.hpp> @@ -271,63 +277,58 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName, Graphic aGraphic; OUString aExt = rFilter.GetExportFormatShortName( nFilter ).toAsciiLowerCase(); - if( bWriteTransGrf ) + if (bAnimated) + aGraphic = rGraphic; + else if (rGraphic.GetType() == GraphicType::GdiMetafile + && rGraphic.GetGDIMetaFile().GetActionSize()) { - if( bAnimated ) - aGraphic = rGraphic; - else + Size aSize; + const Size* pSize = nullptr; + if (pMtfSize_100TH_MM) { - if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GraphicType::Bitmap ) ) - { - ScopedVclPtrInstance< VirtualDevice > pVDev; - const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM))); - - if( pVDev->SetOutputSizePixel( aSize ) ) - { - const Wallpaper aWallpaper( pVDev->GetBackground() ); - const Point aPt; - - pVDev->SetBackground( Wallpaper( COL_BLACK ) ); - pVDev->Erase(); - rGraphic.Draw(*pVDev, aPt, aSize); - - const Bitmap aBitmap( pVDev->GetBitmap( aPt, aSize ) ); - - pVDev->SetBackground( aWallpaper ); - pVDev->Erase(); - rGraphic.Draw(*pVDev, aPt, aSize); - - pVDev->SetRasterOp( RasterOp::Xor ); - pVDev->DrawBitmap( aPt, aSize, aBitmap ); - aGraphic = BitmapEx( aBitmap, pVDev->GetBitmap( aPt, aSize ) ); - } - else - aGraphic = rGraphic.GetBitmapEx(); - } - else - aGraphic = rGraphic.GetBitmapEx(); + aSize = Application::GetDefaultDevice()->LogicToPixel(*pMtfSize_100TH_MM, + MapMode(MapUnit::Map100thMM)); + pSize = &aSize; } + aGraphic = GetBitmapFromMetaFile(rGraphic.GetGDIMetaFile(), pSize); } - else + else if (pMtfSize_100TH_MM && (rGraphic.GetType() != GraphicType::Bitmap)) { - if (bAnimated) - aGraphic = rGraphic; - else if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GraphicType::Bitmap ) ) + ScopedVclPtrInstance< VirtualDevice > pVDev; + const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM))); + + if( pVDev->SetOutputSizePixel( aSize ) ) { - ScopedVclPtrInstance< VirtualDevice > pVDev; - const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM))); + if (bWriteTransGrf) + { + const Wallpaper aWallpaper( pVDev->GetBackground() ); + const Point aPt; + + pVDev->SetBackground( Wallpaper( COL_BLACK ) ); + pVDev->Erase(); + rGraphic.Draw(*pVDev, aPt, aSize); + + const Bitmap aBitmap( pVDev->GetBitmap( aPt, aSize ) ); + + pVDev->SetBackground( aWallpaper ); + pVDev->Erase(); + rGraphic.Draw(*pVDev, aPt, aSize); - if( pVDev->SetOutputSizePixel( aSize ) ) + pVDev->SetRasterOp( RasterOp::Xor ); + pVDev->DrawBitmap( aPt, aSize, aBitmap ); + aGraphic = BitmapEx( aBitmap, pVDev->GetBitmap( aPt, aSize ) ); + } + else { rGraphic.Draw(*pVDev, Point(), aSize); aGraphic = BitmapEx(pVDev->GetBitmap(Point(), aSize)); } - else - aGraphic = rGraphic.GetBitmapEx(); } else aGraphic = rGraphic.GetBitmapEx(); } + else + aGraphic = rGraphic.GetBitmapEx(); // mirror? if( ( nFlags & XOutFlags::MirrorHorz ) || ( nFlags & XOutFlags::MirrorVert ) ) diff --git a/sw/qa/extras/htmlexport/data/tdf161979_metafile.fodt b/sw/qa/extras/htmlexport/data/tdf161979_metafile.fodt new file mode 100644 index 000000000000..f8fdcddb375f --- /dev/null +++ b/sw/qa/extras/htmlexport/data/tdf161979_metafile.fodt @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:automatic-styles> + <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics"> + <style:graphic-properties style:vertical-pos="top" style:vertical-rel="baseline" style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0in, 0in, 0in, 0in)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/> + </style:style> + </office:automatic-styles> + <office:body> + <office:text> + <text:p>Text</text:p> + <text:p><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="as-char" svg:width="0.4236in" svg:height="0.7043in" draw:z-index="0"><draw:image draw:mime-type="image/x-vclgraphic"> + <office:binary-data>VkNMTVRGAQAxAAAAAQAAAAEAGwAAAAcAAAAAAAAAAAABAAAA7AkAAAEAAADsCQAAADQEAAD9 + BgAADQAAAIQAAQAFAAAAAAAAAAGFAAEABQAAAP///wABjQABAAIAAAAAAI0AAQACAAAAAACE + AAEABQAAAAAAAAABhQABAAUAAAD///8AAYoAAQA4AAAABQAyAAAAAAAAAAAAAAAAAAAAAQAA + AAIAAwAAAAAAAAD/AwAAAAAAAAAAAP8DAAAAAAAAAAAAAACLAAEAAgAAAP//jQABAAIAAAAA + AIQAAQAFAAAAAAAAAAFtAAMAUwAAAAIAFAMAACABAAAxAAAA/QYAAAUAOgAAAAEAAAAAAAAA + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbQAD + AFMAAAACADQEAAAxAAAAUQEAAA4GAAAFADoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwAAQAAAAAA + </office:binary-data> + </draw:image> + </draw:frame></text:p> + <text:p/> + <text:p><draw:frame draw:style-name="fr1" draw:name="Image2" text:anchor-type="as-char" svg:width="2.4484in" svg:height="0.7453in" draw:z-index="1"><draw:image draw:mime-type="image/x-vclgraphic"> + <office:binary-data>VkNMTVRGAQAxAAAAAQAAAAEAGwAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAUsYAABl + BwAADgAAAIsAAQACAAAAIACNAAEAAgAAAAAAAAIBAFYAAAAUAEVNRl9QTFVTX0hFQURFUl9J + TkZPAAAAADgAAAAAAAAAAAAAAEoYAABkBwAAYRMAAGgbAADSAAAAKQEAAAAAgD8AAAAAAAAA + AAAAgD8AAAAAAAAAAAACAQAyAAAACABFTUZfUExVUwAAAAAgAAAAAUABABwAAAAQAAAAAhDA + 2wAAAABYAgAAWAIAAEYAAAAAAgEAwgIAAAgARU1GX1BMVVMAAAAAsAIAAB5ABQAMAAAAAAAA + AB9AAwAMAAAAAAAAADBAAgAQAAAABAAAAAAAgD8hQAcADAAAAAAAAAAiQAQADAAAAAAAAAAq + QAAAJAAAABgAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAArQAAADAAAAAAAAAAeQAYADAAA + AAAAAAAhQAUADAAAAAAAAAAeQAkADAAAAAAAAAAqQAAAJAAAABgAAAAAAIA/AAAAAAAAAAAA + AIA/AAAAAAAAAAAhQAcADAAAAAAAAAAqQAAAJAAAABgAAACwAiw6AAAAAAAAAACwAiw6AMBf + xAAQHsUrQAAADAAAAAAAAAAqQAAAJAAAABgAAACwAiw6AAAAAAAAAACwAiw6AMBfxAAQHsUr + QAAADAAAAAAAAAAqQAAAJAAAABgAAACwAiw6AAAAAAAAAACwAiw6AAAAQAAAN0MrQAAADAAA + AAAAAAAeQAYADAAAAAAAAAAhQAUADAAAAAAAAAAeQAkADAAAAAAAAAAqQAAAJAAAABgAAACw + Aiw6AAAAAAAAAACwAiw6AAAAQAAAN0MhQAcADAAAAAAAAAArQAAADAAAAAAAAAAqQAAAJAAA + ABgAAAAAAMhAAAAAAAAAAAAAAMhAAAAAQAAAN0MkQAQADAAAAAAAAAAIQAAFcAAAAGQAAAAC + EMDbAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAR0lGODlhEAAQAAAAACH5BAEAAAAALAAAAAAQ + ABAAoAEAADJoiQIdhB95y+nc3INGTmrtyrzyD4ZiAIyKF1Lqyrbu6xYAOwAACEABCCQAAAAY + AAAAAhDA2wEAAAADAAAAAAAAAAAAAAAAAAAAG0AAQDQAAAAoAAAAAQAAAAIAAAAAAAC/AAAA + vwAAgEEAAIBBAwAAAAAAAAAQAAAAAAAQACEAAAAAAgEAkgIAAAgARU1GX1BMVVMAAAAAgAIA + ACRAAAAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoAAABAAAA3QytAAAAM + AAAAAAAAAB5ABgAMAAAAAAAAACFABQAMAAAAAAAAAAhAAgQYAAAADAAAAAIQwNsAAAAAAwAA + EDRAAgAMAAAAAAAAAB5ACQAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoA + AABAAAA3QyFABwAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoAAABAAAA3 + QytAAAAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoAAMxCAICLQytAAAAM + AAAAAAAAAB5ABgAMAAAAAAAAACFABQAMAAAAAAAAAB5ACQAMAAAAAAAAACpAAAAkAAAAGAAA + ALACLDoAAAAAAAAAALACLDoAAMxCAICLQyFABwAMAAAAAAAAACtAAAAMAAAAAAAAACpAAAAk + AAAAGAAAAAAAyEAAAAAAAAAAAAAAyEAAAMxCAICLQyRABAAMAAAAAAAAAAhAAwWAAAAAdAAA + AAIQwNsBAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABHSUY4OWEQABAAEQAAIfkEAQAAAAAsAAAA + ABAAEAChAQAAMmiJ////AAAAAiaEj6nLEA8ZnBHRJ+a5OFcohGL4cWTlXN6TcGhLNcYrsXJ6 + 57pSAAA7AAAACEABCCQAAAAYAAAAAhDA2wEAAAADAAAAAAAAAAAAAAAAAAAAG0ADQDQAAAAo + AAAAAQAAAAIAAAAAAAC/AAAAvwAAgEEAAIBBAwAAAAAAAAAQAAAAAAAQABUAAAAAAgEAdgEA + AAgARU1GX1BMVVMAAAAAZAEAACRAAAAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAA + ALACLDoAAMxCAICLQytAAAAMAAAAAAAAAB5ABgAMAAAAAAAAACFABQAMAAAAAAAAADRAAgAM + AAAAAAAAAB5ACQAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoAAMxCAICL + QyFABwAMAAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLDoAAMxCAICLQytAAAAM + AAAAAAAAACpAAAAkAAAAGAAAALACLDoAAAAAAAAAALACLLoAAABAvZOkQwhABAI0AAAAKAAA + AAIQwNsAAAAAiAAAAAAAAAAA4A5GAgAAAAAAAAACEMDbAAAAAAAAAP8IQAUDLAAAACAAAAAC + EMDbAgAAAAAAAAAAAAAAAAAAAAA+X0jAGg9IAAEAABVABQAQAAAABAAAAAQAAAAkAAAAAAIB + AC4OAAAIAEVNRl9QTFVTAAAAABwOAAArQAAADAAAAAAAAAAqQAAAJAAAABgAAACwAiw6AAAA + AAAAAACwAiw6AAANRAAAAAArQAAADAAAAAAAAAAeQAYADAAAAAAAAAAhQAUADAAAAAAAAAAe + QAkADAAAAAAAAAAqQAAAJAAAABgAAACwAiw6AAAAAAAAAACwAiw6AAANRAAAAAAhQAcADAAA + AAAAAAArQAAADAAAAAAAAAAqQAAAJAAAABgAAABinmFAAAAAAAAAAABU82BAAAANRAAAAAAk + QAQADAAAAAAAAAAIQAYF9AwAAOgMAAACEMDbAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAiVBO + Rw0KGgoAAAANSUhEUgAAAQEAAABlCAYAAABN/lYFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA + B3RJTUUH4QMDEDQo1mBPxAAAAAd0RVh0QXV0aG9yAKmuzEgAAAAMdEVYdERlc2NyaXB0aW9u + ABMJISMAAAAKdEVYdENvcHlyaWdodACsD8w6AAAADnRFWHRDcmVhdGlvbiB0aW1lADX3DwkA + AAAJdEVYdFNvZnR3YXJlAF1w/zoAAAALdEVYdERpc2NsYWltZXIAt8C0jwAAAAh0RVh0V2Fy + bmluZwDAG+aHAAAAB3RFWHRTb3VyY2UA9f+D6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAABnRF + WHRUaXRsZQCo7tInAAALl0lEQVR4Xu2cv37bOBLH4durpPIst3Z3HyetXet5svc8l/dR7bSO + dzu5tX2l3e36CElUKGoAzAADECR/riJi/n4HGAKkootv3759GvyBAAjMlsA/beb//f59tgBS + E//P77+DXypEZX3URAZ01wT+/hubARm2U2kpv8/PNN4XFxcp4c5CV1qTWUBxJLlrAqE56Zq0 + qZPRZdcRq/eyL5ZUPz7bHH57mbSF302+zScUlxfYxAdDc3ri6YvSOzQBeoKGFk9ovI2knaxc + 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 + b3B5cmlnaHQArA/MOgAAAA50RVh0Q3JlYXRpb24gdGltZQA19w8JAAAACXRFWHRTb2Z0d2Fy + ZQBdcP86AAAAC3RFWHREaXNjbGFpbWVyALfAtI8AAAAIdEVYdFdhcm5pbmcAwBvmhwAAAAd0 + RVh0U291cmNlAPX/g+sAAAAIdEVYdENvbW1lbnQA9syWvwAAAAZ0RVh0VGl0bGUAqO7SJwAA + AvdQTFRFAAAADw8PHx8fAgICERERExMTCQkJCgoKDAwMDg4OHR0dDQ0NFBESFBERFRITEQ4P + AQEBCwsLDw0NEQ0OBgYGHBcYCAgIGBgYGhUWHBwcGxsbHh4eDQMGFwMJFwQJGAMJFQQJEhIS + FxcXGRkZAwMDFhYWFBQUBwcHNjY2ISEhIiIiIyMjPj4+Ly8vLS0tNTU1Nzc3JiYmJSUlNDQ0 + JycnPTw8KioqNjQ1MDAwNTM0PDs7KCgoJCQkKSkpPz8/MzMzXiAwSUlJWVlZTU1NV1dXTk5O + SEhIW1tbXV1dRkZGREREXl5eXFxcWlpaUlJST09PS0tLR0dHQEBASkpKX19fRUVFU1NTQUFB + Q0NDaiU4fCM7eiM7fCc+dnZ2YGBgYmJiaGhoenp6bW1tbGxsY2NjeXl5ZmZmampqcnJya2tr + YWFhdHR0e3t7fn5+dXV1c3NzZGRkb29vcHBwd3d3bm5uZ2dnaWlphxQzkRg5kBg4kRc4iSM/ + goKCnZ2diIiInJycn5+fh4eHjY2NgYGBj4+Pi4uLmpqamJiYhYWFm5ubg4ODhoaGkJCQjo6O + gICAlZWVnp6emZmZioqKlJSUl5eXk5OTkZGRlpaWhISEjIyMtgIztQAwtgAxtwAytQAvtgEy + twEztRpEtRtFvxRCvxJBuCVMtbW1rq6uvb29vLy8oqKisbGxpaWlsrKyra2tq6urpqamp6en + tLS0vr6+oaGhqKiosLCwqqqquLi4u7u7tra2urq6r6+vpKSkubm5oKCgs7Ozv7+/wBRDwsLC + 09PT0dHR2dnZ2NjYz8/P29vb0tLSx8fH3t7ezs7OxcXFzc3NysrK3NzcxsbGy8vL3d3d1dXV + zMzM1NTU1tbWwMDA0NDQw8PD39/f19fXwcHB9vb27e3t/v7+7Ozs/Pz8/f39+vr66+vr8PDw + 9fX1+fn57+/v6urq7u7u+/v74eHh9/f3+Pj44+Pj8vLy8fHx5OTk4uLi9PT05eXl4ODg5ubm + 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 + </office:binary-data> + </draw:image> + </draw:frame></text:p> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 02f0fd654620..b39d02a8ff86 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -3141,6 +3141,54 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_160867) .endsWith("foo/bar")); } +CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_161979) +{ + // Given a document with two embedded metafiles: + createSwDoc("tdf161979_metafile.fodt"); + ExportToHTML(); + xmlDocUniquePtr pDoc = parseXml(maTempFile); + CPPUNIT_ASSERT(pDoc); + // First image: it has no EMF+ actions, and didn't use canvas rendering before the fix; + // yet, it didn't export correctly. + OUString imgName = getXPath(pDoc, "/html/body/p[2]/img"_ostr, "src"_ostr); + CPPUNIT_ASSERT(imgName.endsWith(".gif")); + INetURLObject aUrl(maTempFile.GetURL()); + aUrl.setName(imgName); + Graphic graphic; + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, GraphicFilter().ImportGraphic(graphic, aUrl)); + + // Check that only ~4% of pixels are not transparent (before the fix, it was completely black) + BitmapEx bitmap = graphic.GetBitmapEx(); + Size size = bitmap.GetSizePixel(); + int numNonTransparent = 0; + for (tools::Long y = 0; y < size.Height(); ++y) + for (tools::Long x = 0; x < size.Width(); ++x) + if (bitmap.GetPixelColor(x, y) != COL_TRANSPARENT) + ++numNonTransparent; + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.04, numNonTransparent / double(size.Height() * size.Width()), + 0.01); + + // Second image: it consists of EMF+ records (no EMF fallback). It used canvas rendering + // before the fix; it also didn't export correctly. + imgName = getXPath(pDoc, "/html/body/p[4]/img"_ostr, "src"_ostr); + CPPUNIT_ASSERT(imgName.endsWith(".gif")); + aUrl.SetURL(maTempFile.GetURL()); + aUrl.setName(imgName); + graphic.Clear(); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, GraphicFilter().ImportGraphic(graphic, aUrl)); + + // Check that some pixels are transparent (before the fix, it was completely black) + bitmap = graphic.GetBitmapEx(); + size = bitmap.GetSizePixel(); + numNonTransparent = 0; + for (tools::Long y = 0; y < size.Height(); ++y) + for (tools::Long x = 0; x < size.Width(); ++x) + if (bitmap.GetPixelColor(x, y) != COL_TRANSPARENT) + ++numNonTransparent; + CPPUNIT_ASSERT(numNonTransparent > 0); + CPPUNIT_ASSERT(numNonTransparent < size.Height() * size.Width()); +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT();