diff options
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/frmfmt.hxx | 6 | ||||
-rw-r--r-- | sw/qa/extras/htmlexport/htmlexport.cxx | 67 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 8 | ||||
-rw-r--r-- | sw/source/filter/html/README | 42 | ||||
-rw-r--r-- | sw/source/filter/html/htmlflywriter.cxx | 7 | ||||
-rw-r--r-- | sw/source/filter/html/wrthtml.cxx | 8 | ||||
-rw-r--r-- | sw/source/filter/html/wrthtml.hxx | 3 |
7 files changed, 133 insertions, 8 deletions
diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx index d1146b8a736b..36333d4e8525 100644 --- a/sw/inc/frmfmt.hxx +++ b/sw/inc/frmfmt.hxx @@ -116,7 +116,7 @@ public: /// Creates the views. virtual void MakeFrames(); - virtual Graphic MakeGraphic( ImageMap* pMap = nullptr ); + virtual Graphic MakeGraphic( ImageMap* pMap = nullptr, const std::optional<Size>& rTargetDPI = std::nullopt ); /** @return the IMapObject defined at format (Fly) in the ImageMap at position Point. @@ -212,7 +212,7 @@ public: SwAnchoredObject* GetAnchoredObj() const; - virtual Graphic MakeGraphic( ImageMap* pMap = nullptr ) override; + virtual Graphic MakeGraphic( ImageMap* pMap = nullptr, const std::optional<Size>& rTargetDPI = std::nullopt ) override; virtual bool GetInfo( SfxPoolItem& rInfo ) const override; @@ -388,7 +388,7 @@ public: Reset delete marks. */ virtual void MakeFrames() override; - virtual Graphic MakeGraphic( ImageMap* pMap = nullptr ) override; + virtual Graphic MakeGraphic( ImageMap* pMap = nullptr, const std::optional<Size>& rTargetDPI = std::nullopt ) override; virtual SwFrameFormat::tLayoutDir GetLayoutDir() const override; virtual void SetLayoutDir( const SwFrameFormat::tLayoutDir _eLayoutDir ) override; diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 1f5182ac6e4c..8642b5baa4f5 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -40,6 +40,7 @@ #include <svtools/htmlcfg.hxx> #include <unotools/ucbstreamhelper.hxx> #include <comphelper/processfactory.hxx> +#include <vcl/graphicfilter.hxx> #include <swmodule.hxx> #include <swdll.hxx> @@ -270,6 +271,7 @@ class SwHtmlDomExportTest : public SwModelTestBase, public HtmlTestTools public: /// Get the .ole path, assuming maTempFile is an XHTML export result. OUString GetOlePath(); + OUString GetPngPath(); /// Parse the ole1 data out of an RTF fragment URL. void ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1); /// Export using the C++ HTML export filter, with xhtmlns=reqif-xhtml. @@ -292,6 +294,22 @@ OUString SwHtmlDomExportTest::GetOlePath() return aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE); } +OUString SwHtmlDomExportTest::GetPngPath() +{ + SvMemoryStream aStream; + HtmlExportTest::wrapFragment(maTempFile, aStream); + xmlDocUniquePtr pDoc = parseXmlStream(&aStream); + CPPUNIT_ASSERT(pDoc); + OUString aPngPath = getXPath( + pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data"); + OUString aPngSuffix(".png"); + CPPUNIT_ASSERT(aPngPath.endsWith(aPngSuffix)); + INetURLObject aUrl(maTempFile.GetURL()); + aUrl.setBase(aPngPath.subView(0, aPngPath.getLength() - aPngSuffix.getLength())); + aUrl.setExtension(u"png"); + return aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE); +} + void SwHtmlDomExportTest::ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1) { SvMemoryStream aRtf; @@ -1734,6 +1752,55 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNG) OUString::number(aPixelSize.getWidth())); } +CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNGCustomDPI) +{ + // Given a document with a shape: + loadURL("private:factory/swriter", nullptr); + uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape( + xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setSize(awt::Size(7145, 5240)); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + xDrawPageSupplier->getDrawPage()->add(xShape); + Size aSystemDPI( + Application::GetDefaultDevice()->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch))); + sal_Int32 nDPI = aSystemDPI.getWidth() * 2; + + // When exporting to XHTML: + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aStoreProperties = { + comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")), + comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")), + comphelper::makePropertyValue("ShapeDPI", nDPI), + }; + xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); + + // Then make sure the shape is embedded as a PNG: + SvMemoryStream aStream; + HtmlExportTest::wrapFragment(maTempFile, aStream); + xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "image/png"); + + // Then check the pixel size of the shape: + Size aPixelSize(Application::GetDefaultDevice()->LogicToPixel(Size(7145, 5240), + MapMode(MapUnit::Map100thMM))); + tools::Long nPNGWidth = aPixelSize.getWidth() * 2; + OUString aPngUrl = GetPngPath(); + SvFileStream aFileStream(aPngUrl, StreamMode::READ); + GraphicDescriptor aDescriptor(aFileStream, nullptr); + aDescriptor.Detect(/*bExtendedInfo=*/true); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 540 + // - Actual : 270 + // i.e. setting a double DPI didn't result in larger pixel width of the PNG. + CPPUNIT_ASSERT_EQUAL(nPNGWidth, aDescriptor.GetSizePixel().getWidth()); + + // Then make sure the shape's logic size (in CSS pixels) don't change: + assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "width", + OUString::number(aPixelSize.getWidth())); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index e74de064a9b6..4a9eb647bbd6 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -7441,12 +7441,12 @@ void SetOutDevAndWin( SwViewShell *pSh, OutputDevice *pO, pSh->mpOpt->SetZoom( nZoom ); } -Graphic SwFrameFormat::MakeGraphic( ImageMap* ) +Graphic SwFrameFormat::MakeGraphic( ImageMap*, const std::optional<Size>& /*rTargetDPI*/ ) { return Graphic(); } -Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap ) +Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap, const std::optional<Size>& /*rTargetDPI*/ ) { Graphic aRet; //search any Fly! @@ -7553,7 +7553,7 @@ Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap ) return aRet; } -Graphic SwDrawFrameFormat::MakeGraphic( ImageMap* ) +Graphic SwDrawFrameFormat::MakeGraphic( ImageMap*, const std::optional<Size>& rTargetDPI ) { Graphic aRet; SwDrawModel* pMod = getIDocumentDrawModelAccess().GetDrawModel(); @@ -7563,7 +7563,7 @@ Graphic SwDrawFrameFormat::MakeGraphic( ImageMap* ) SdrView aView( *pMod ); SdrPageView *pPgView = aView.ShowSdrPage(aView.GetModel()->GetPage(0)); aView.MarkObj( pObj, pPgView ); - aRet = aView.GetMarkedObjBitmapEx(); + aRet = aView.GetMarkedObjBitmapEx(/*bNoVDevIfOneBmpMarked=*/false, rTargetDPI); aView.HideSdrPage(); } return aRet; diff --git a/sw/source/filter/html/README b/sw/source/filter/html/README new file mode 100644 index 000000000000..7b16fb0838a3 --- /dev/null +++ b/sw/source/filter/html/README @@ -0,0 +1,42 @@ +This filter is used when the "HTML (StarWriter)" filter is invoked. + +Import options: + +- FilterOptions: string + + - xhtmlns=reqif-xhtml: actives the ReqIF mode + +- AllowedRTFOLEMimeTypes: sequence<string> + + In case an (UNO) client wants to limit the accepted set of MIME types for + OLE objects in ReqIF mode, that's possible via this parameter. + + Any MIME type is accepted by default. + +Export options: + +- FilterOptions: string + + - SkipImages: skips images + + - SkipHeaderFooter: skips the header and footer + + - EmbedImages: inlines images + + - XHTML: activates the XHTML mode + + - xhtmlns=reqif-xhtml: actives the ReqIF mode + +- RTFOLEMimeType: string + + Defines what MIME type to use for OLE objects in ReqIF mode, defaults to text/rtf. + +- ExportImagesAsOLE: boolean + + Defines if images should be exported as OLE objects or bitmaps, defaults to + false. + +- ShapeDPI: long (32bit signed int) + + Defines a custom DPI when converting vector shapes to bitmaps, defaults to + the system DPI (96 when not on HiDPI). diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx index 8f6608097f07..5dc8d69360c8 100644 --- a/sw/source/filter/html/htmlflywriter.cxx +++ b/sw/source/filter/html/htmlflywriter.cxx @@ -1804,7 +1804,12 @@ static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& r return rWrt; ImageMap aIMap; - Graphic aGraphic( const_cast<SwFrameFormat &>(rFrameFormat).MakeGraphic( &aIMap ) ); + std::optional<Size> aDPI; + if (rHTMLWrt.m_nShapeDPI.has_value()) + { + aDPI.emplace(*rHTMLWrt.m_nShapeDPI, *rHTMLWrt.m_nShapeDPI); + } + Graphic aGraphic( const_cast<SwFrameFormat &>(rFrameFormat).MakeGraphic( &aIMap, aDPI ) ); if (rHTMLWrt.mbReqIF) { diff --git a/sw/source/filter/html/wrthtml.cxx b/sw/source/filter/html/wrthtml.cxx index dfd03a5360f2..d6880d407842 100644 --- a/sw/source/filter/html/wrthtml.cxx +++ b/sw/source/filter/html/wrthtml.cxx @@ -208,6 +208,14 @@ void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium) { it->second >>= m_bExportImagesAsOLE; } + + it = aStoreMap.find("ShapeDPI"); + if (it != aStoreMap.end()) + { + sal_Int32 nVal{}; + it->second >>= nVal; + m_nShapeDPI.emplace(nVal); + } } void SwHTMLWriter::SetupFilterOptions(const OUString& rFilterOptions) diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx index cc84b39f1e65..340c1a0a81dc 100644 --- a/sw/source/filter/html/wrthtml.hxx +++ b/sw/source/filter/html/wrthtml.hxx @@ -414,6 +414,9 @@ public: /// ReqIF mode: export images as OLE objects. bool m_bExportImagesAsOLE = false; + /// DPI used when exporting a vector shape as a bitmap. + std::optional<sal_Int32> m_nShapeDPI; + /// Construct an instance of SwHTMLWriter and optionally give it /// the filter options directly, which can also be set via SetupFilterOptions(). explicit SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOptions = "" ); |