filter/source/pdf/pdfexport.cxx | 23 + filter/source/pdf/pdfexport.hxx | 2 filter/source/pdf/pdffilter.cxx | 36 ++ include/sfx2/sfxsids.hrc | 3 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 14 sd/uiconfig/sdraw/toolbar/redactionbar.xml | 2 sfx2/sdi/sfx.sdi | 3 sfx2/source/appl/appuno.cxx | 1 sfx2/source/doc/objserv.cxx | 175 +++++++++- sfx2/source/doc/objstor.cxx | 12 10 files changed, 266 insertions(+), 5 deletions(-)
New commits: commit 4471ee76533e3f3ac35f3b0e0c8f9981cc973930 Author: Muhammet Kara <muhammet.k...@collabora.com> AuthorDate: Thu Feb 7 22:07:09 2019 +0300 Commit: Muhammet Kara <muhammet.k...@collabora.com> CommitDate: Mon Jun 17 21:22:31 2019 +0200 Handle redaction finalization: Black Convert shapes on the document to black & opaque before sending it to the pdfexport filter. Convert them back to gray & transparent after the export operation. Change-Id: Iffe66e371710f16ef1c04f0da196fc5a561af344 Reviewed-on: https://gerrit.libreoffice.org/67517 Tested-by: Jenkins Reviewed-by: Muhammet Kara <muhammet.k...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/74202 Tested-by: Muhammet Kara <muhammet.k...@collabora.com> diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index c2162b6a473f..9488603e277c 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -119,6 +119,7 @@ #include <unotools/streamwrap.hxx> #include <svx/unoshape.hxx> +#include <com/sun/star/util/Color.hpp> using namespace ::com::sun::star; using namespace ::com::sun::star::lang; @@ -402,6 +403,23 @@ uno::Sequence< document::CmisVersion > SfxObjectShell::GetCmisVersions( ) return uno::Sequence< document::CmisVersion > ( ); } +namespace{ + +/// Checks to see if the request has a parameter of IsRedactMode:bool=true +bool isRedactMode(SfxRequest& rReq) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + if (pArgs) + { + const SfxBoolItem* pIsRedactMode = rReq.GetArg<SfxBoolItem>(SID_IS_REDACT_MODE); + if (pIsRedactMode && pIsRedactMode->GetValue()) + return true; + } + + return false; +} + +} void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) { @@ -675,8 +693,94 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case SID_EXPORTDOCASPDF: case SID_DIRECTEXPORTDOCASPDF: + { + uno::Reference< lang::XComponent > xComponent( GetCurrentComponent(), uno::UNO_QUERY ); + if (!xComponent.is()) + return; + + uno::Reference< lang::XServiceInfo > xServiceInfo( xComponent, uno::UNO_QUERY); + + // Redaction finalization takes place in Draw + if ( xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.DrawingDocument") + && isRedactMode(rReq) ) + { + // Access the draw pages + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(xComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); + + sal_Int32 nPageCount = xDrawPages->getCount(); + for (sal_Int32 nPageNum = 0; nPageNum < nPageCount; ++nPageNum) + { + // Get the page + uno::Reference< drawing::XDrawPage > xPage( xDrawPages->getByIndex( nPageNum ), uno::UNO_QUERY ); + + if (!xPage.is()) + continue; + + // Go through all shapes + sal_Int32 nShapeCount = xPage->getCount(); + for (sal_Int32 nShapeNum = 0; nShapeNum < nShapeCount; ++nShapeNum) + { + uno::Reference< drawing::XShape > xCurrShape(xPage->getByIndex(nShapeNum), uno::UNO_QUERY); + if (!xCurrShape.is()) + continue; + + uno::Reference< beans::XPropertySet > xPropSet(xCurrShape, uno::UNO_QUERY); + if (!xPropSet.is()) + continue; + + uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo(); + if (!xInfo.is()) + continue; + + // Rectangle redaction + if (xInfo->hasPropertyByName("FillTransparence") && xInfo->hasPropertyByName("FillColor")) + { + uno::Any aAnyTransp = xPropSet->getPropertyValue("FillTransparence"); + uno::Any aAnyColor = xPropSet->getPropertyValue("FillColor"); + + sal_Int16 nTransp = 0; + Color aColor; + const OUString sRectangleName("RectangleRedactionShape"); + + aAnyTransp >>= nTransp; + aAnyColor >>= aColor; + + if (nTransp == 50 && aColor == COL_GRAY7) + { + xPropSet->setPropertyValue("FillTransparence", css::uno::makeAny(static_cast<sal_Int16>(0))); + xPropSet->setPropertyValue("FillColor", css::uno::makeAny(COL_BLACK)); + xPropSet->setPropertyValue("Name", css::uno::makeAny(sRectangleName)); + } + } + //FIXME: Turn this into an else-if when we have the name-check + // Freeform redaction + if (xInfo->hasPropertyByName("LineTransparence") && xInfo->hasPropertyByName("LineColor")) + { + uno::Any aAnyTransp = xPropSet->getPropertyValue("LineTransparence"); + uno::Any aAnyColor = xPropSet->getPropertyValue("LineColor"); + + sal_Int16 nTransp = 0; + Color aColor; + const OUString sFreeformName("FreeformRedactionShape"); + + aAnyTransp >>= nTransp; + aAnyColor >>= aColor; + + if (nTransp == 50 && aColor == COL_GRAY7) + { + xPropSet->setPropertyValue("LineTransparence", css::uno::makeAny(static_cast<sal_Int16>(0))); + xPropSet->setPropertyValue("LineColor", css::uno::makeAny(COL_BLACK)); + xPropSet->setPropertyValue("Name", css::uno::makeAny(sFreeformName)); + } + } + } + } + } + } + [[fallthrough]]; + case SID_EXPORTDOCASPDF: bIsPDFExport = true; SAL_FALLTHROUGH; case SID_EXPORTDOCASEPUB: @@ -870,6 +974,75 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) ErrorHandler::HandleError(lErr, pDialogParent); } + if (nId == SID_DIRECTEXPORTDOCASPDF && + isRedactMode(rReq)) + { + // Return the finalized redaction shapes back to normal (gray & transparent) + uno::Reference< lang::XComponent > xComponent( GetCurrentComponent(), uno::UNO_QUERY ); + if (!xComponent.is()) + return; + + uno::Reference< lang::XServiceInfo > xServiceInfo( xComponent, uno::UNO_QUERY); + + // Redaction finalization takes place in Draw + if ( xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.DrawingDocument") ) + { + // Access the draw pages + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(xComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); + + sal_Int32 nPageCount = xDrawPages->getCount(); + for (sal_Int32 nPageNum = 0; nPageNum < nPageCount; ++nPageNum) + { + // Get the page + uno::Reference< drawing::XDrawPage > xPage( xDrawPages->getByIndex( nPageNum ), uno::UNO_QUERY ); + + if (!xPage.is()) + continue; + + // Go through all shapes + sal_Int32 nShapeCount = xPage->getCount(); + for (sal_Int32 nShapeNum = 0; nShapeNum < nShapeCount; ++nShapeNum) + { + uno::Reference< drawing::XShape > xCurrShape(xPage->getByIndex(nShapeNum), uno::UNO_QUERY); + if (!xCurrShape.is()) + continue; + + uno::Reference< beans::XPropertySet > xPropSet(xCurrShape, uno::UNO_QUERY); + if (!xPropSet.is()) + continue; + + uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo(); + if (!xInfo.is()) + continue; + + // Not a shape we converted? + if (!xInfo->hasPropertyByName("Name")) + continue; + + OUString sName; + uno::Any aAnyName = xPropSet->getPropertyValue("Name"); + aAnyName >>= sName; + + // Rectangle redaction + if (!sName.isEmpty() && sName == "RectangleRedactionShape") + { + xPropSet->setPropertyValue("FillTransparence", css::uno::makeAny(static_cast<sal_Int16>(50))); + xPropSet->setPropertyValue("FillColor", css::uno::makeAny(COL_GRAY7)); + } + // Freeform redaction + else if (!sName.isEmpty() && sName == "FreeformRedactionShape") + { + xPropSet->setPropertyValue("LineTransparence", css::uno::makeAny(static_cast<sal_Int16>(50))); + xPropSet->setPropertyValue("LineColor", css::uno::makeAny(COL_GRAY7)); + } + } + } + + + } + } + if ( nId == SID_EXPORTDOCASPDF ) { // This function is used by the SendMail function that needs information if a export commit 40e27c01c502269005395db06bfea39cf9c85ec3 Author: Muhammet Kara <muhammet.k...@collabora.com> AuthorDate: Tue Jan 29 23:02:22 2019 +0300 Commit: Muhammet Kara <muhammet.k...@collabora.com> CommitDate: Mon Jun 17 21:22:10 2019 +0200 Support bitmap PDF export for Redaction * Add a new parameter IsRedactMode (SID_IS_REDACT_MODE) to .uno:ExportDirectToPDF * Make sure the new param makes it into PDFExport as part of FilterData * Hijack the metafile before being sent to ImplExportPage(), convert to bitmap, and replace the original * Add a new entry to GenericCommands.xcu to make our button with param visible * Nitpick: For things to be included in the bitmap conversion, they need to be added to the metafile before the conversion in PDFExport::ExportSelection(). Things added after that point (inside ImplExportPage() for example) will not be bitmapped/pixelized Change-Id: Iec7020917da920a968ea969b98e53f17eadaa275 Reviewed-on: https://gerrit.libreoffice.org/67108 Tested-by: Jenkins Reviewed-by: Muhammet Kara <muhammet.k...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/74201 Tested-by: Muhammet Kara <muhammet.k...@collabora.com> diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx index 88f212fbb609..8e5b9eefdcc5 100644 --- a/filter/source/pdf/pdfexport.cxx +++ b/filter/source/pdf/pdfexport.cxx @@ -114,6 +114,8 @@ PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc, mnProgressValue ( 0 ), mbRemoveTransparencies ( false ), + mbIsRedactMode ( false ), + mbHideViewerToolbar ( false ), mbHideViewerMenubar ( false ), mbHideViewerWindowControls ( false ), @@ -226,6 +228,24 @@ bool PDFExport::ExportSelection( vcl::PDFWriter& rPDFWriter, if( aMtf.GetActionSize() && ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) ) { + // We convert the whole metafile into a bitmap to get rid of the + // text covered by redaction shapes + if (mbIsRedactMode) + { + try + { + Graphic aGraph(aMtf); + BitmapEx bmp = aGraph.GetBitmapEx(); + Graphic bgraph(bmp); + aMtf = bgraph.GetGDIMetaFile(); + } + catch(const Exception& e) + { + SAL_WARN("filter.pdf", "Something went wrong while converting metafile to bitmap. Exception: " + << e.Message); + } + } + ImplExportPage(rPDFWriter, rPDFExtOutDevData, aMtf); bRet = true; } @@ -556,6 +576,9 @@ bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData[ nData ].Value >>= mbExportPlaceholders; else if ( rFilterData[ nData ].Name == "UseReferenceXObject" ) rFilterData[ nData ].Value >>= mbUseReferenceXObject; + // Redaction & bitmap related stuff + else if ( rFilterData[ nData ].Name == "IsRedactMode" ) + rFilterData[ nData ].Value >>= mbIsRedactMode; } aContext.URL = aURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri); diff --git a/filter/source/pdf/pdfexport.hxx b/filter/source/pdf/pdfexport.hxx index 01befed55986..ac9362a01fb2 100644 --- a/filter/source/pdf/pdfexport.hxx +++ b/filter/source/pdf/pdfexport.hxx @@ -65,6 +65,8 @@ private: sal_Int32 mnProgressValue; bool mbRemoveTransparencies; + bool mbIsRedactMode; + OUString msWatermark; // these variable are here only to have a location in filter/pdf to set the default diff --git a/filter/source/pdf/pdffilter.cxx b/filter/source/pdf/pdffilter.cxx index 5bddb7e1f671..872c515e0543 100644 --- a/filter/source/pdf/pdffilter.cxx +++ b/filter/source/pdf/pdffilter.cxx @@ -46,11 +46,12 @@ bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor ) Sequence< PropertyValue > aFilterData; sal_Int32 nLength = rDescriptor.getLength(); const PropertyValue* pValue = rDescriptor.getConstArray(); + bool bIsRedactMode = false; bool bRet = false; Reference< task::XStatusIndicator > xStatusIndicator; Reference< task::XInteractionHandler > xIH; - for ( sal_Int32 i = 0 ; ( i < nLength ) && !xOStm.is(); ++i) + for (sal_Int32 i = 0 ; ( i < nLength ) && !xOStm.is(); ++i) { if ( pValue[ i ].Name == "OutputStream" ) pValue[ i ].Value >>= xOStm; @@ -62,6 +63,12 @@ bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor ) pValue[i].Value >>= xIH; } + for (sal_Int32 i = 0 ; i < nLength; ++i) + { + if ( pValue[i].Name == "IsRedactMode") + pValue[i].Value >>= bIsRedactMode; + } + /* we don't get FilterData if we are exporting directly to pdf, but we have to use the last user settings (especially for the CompressMode) */ if ( !aFilterData.getLength() ) @@ -109,9 +116,36 @@ bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor ) aCfgItem.ReadBool( "ExportBookmarks", true ); aCfgItem.ReadBool( "ExportHiddenSlides", false ); aCfgItem.ReadInt32( "OpenBookmarkLevels", -1 ); + + aCfgItem.ReadBool( "IsRedactMode", false); + aFilterData = aCfgItem.GetFilterData(); } + + if (bIsRedactMode) + { + bool bFound = false; + + for (int i = 0; i < aFilterData.getLength(); ++i) + { + if (aFilterData[i].Name == "IsRedactMode") + { + aFilterData[i].Value <<= bIsRedactMode; + bFound = true; + break; + } + } + + if (!bFound) + { + sal_Int32 nNewSize = aFilterData.getLength() + 1; + aFilterData.realloc( nNewSize ); + aFilterData[nNewSize - 1].Name = "IsRedactMode"; + aFilterData[nNewSize - 1].Value <<= bIsRedactMode; + } + } + if( mxSrcDoc.is() && xOStm.is() ) { PDFExport aExport( mxSrcDoc, xStatusIndicator, xIH, mxContext ); diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index badaedad4d26..811bfe59ce57 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -256,8 +256,9 @@ class SfxDocumentInfoItem; // Used to export a temporary file for preview in Mail Merge Wizard, where saving the data source is // not required for preview, but interferes with not-yet-saved embedded data source for main document. #define SID_NO_EMBEDDED_DS TypedWhichId<SfxBoolItem>(SID_SFX_START + 1731) +#define SID_IS_REDACT_MODE (SID_SFX_START + 1733) -// SID_SFX_free_START (SID_SFX_START + 1733) +// SID_SFX_free_START (SID_SFX_START + 1734) // SID_SFX_free_END (SID_SFX_START + 3999) #define SID_OPEN_NEW_VIEW (SID_SFX_START + 520) diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index ada4185dd477..1c829f842879 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -4991,6 +4991,20 @@ <value>1</value> </prop> </node> + <node oor:name=".uno:ExportDirectToPDF?IsRedactMode:bool=true" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Sanitized PDF</value> + </prop> + <prop oor:name="ContextLabel" oor:type="xs:string"> + <value xml:lang="en-US">Export Directly to PDF as Bitmap</value> + </prop> + <prop oor:name="TooltipLabel" oor:type="xs:string"> + <value xml:lang="en-US">Export Directly to PDF as Bitmap</value> + </prop> + <prop oor:name="Properties" oor:type="xs:int"> + <value>1</value> + </prop> + </node> <node oor:name=".uno:ExportToEPUB" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">EPUB</value> diff --git a/sd/uiconfig/sdraw/toolbar/redactionbar.xml b/sd/uiconfig/sdraw/toolbar/redactionbar.xml index 1a5b45b31634..a0fb06709377 100644 --- a/sd/uiconfig/sdraw/toolbar/redactionbar.xml +++ b/sd/uiconfig/sdraw/toolbar/redactionbar.xml @@ -21,5 +21,5 @@ <toolbar:toolbaritem xlink:href=".uno:Rect?FillTransparence:short=50&FillColor:string=COL_GRAY7&LineStyle:short=0&IsSticky:bool=true"/> <toolbar:toolbaritem xlink:href=".uno:Freeline_Unfilled?Transparence:short=50&Color:string=COL_GRAY7&Width:short=500&IsSticky:bool=true"/> <toolbar:toolbarseparator/> - <toolbar:toolbaritem xlink:href=".uno:ExportDirectToPDF"/> + <toolbar:toolbaritem xlink:href=".uno:ExportDirectToPDF?IsRedactMode:bool=true"/> </toolbar:toolbar> diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi index f8fbcd49d3b5..0f452114a71e 100644 --- a/sfx2/sdi/sfx.sdi +++ b/sfx2/sdi/sfx.sdi @@ -4764,7 +4764,8 @@ SfxVoidItem ExportToPDF SID_EXPORTDOCASPDF ] SfxVoidItem ExportDirectToPDF SID_DIRECTEXPORTDOCASPDF -(SfxStringItem URL SID_FILE_NAME, SfxStringItem FilterName SID_FILTER_NAME) +(SfxStringItem URL SID_FILE_NAME, SfxStringItem FilterName SID_FILTER_NAME, + SfxBoolItem IsRedactMode SID_IS_REDACT_MODE) [ AutoUpdate = FALSE, FastCall = FALSE, diff --git a/sfx2/source/appl/appuno.cxx b/sfx2/source/appl/appuno.cxx index 57bc154ad891..dec5c15a9896 100644 --- a/sfx2/source/appl/appuno.cxx +++ b/sfx2/source/appl/appuno.cxx @@ -109,6 +109,7 @@ SfxFormalArgument const aFormalArgs[] = { { reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoFileSync", SID_NO_FILE_SYNC }, { reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoThumbnail", SID_NO_THUMBNAIL }, { reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoEmbDataSet", SID_NO_EMBEDDED_DS }, + { reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "IsRedactMode", SID_IS_REDACT_MODE }, }; static sal_uInt16 nMediaArgsCount = SAL_N_ELEMENTS(aFormalArgs); diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index 1c6b6d5c13be..61e94cfc1c94 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -2367,6 +2367,7 @@ bool SfxObjectShell::ExportTo( SfxMedium& rMedium ) bool bHasStream = false; bool bHasBaseURL = false; bool bHasFilterName = false; + bool bIsRedactMode = false; sal_Int32 i; sal_Int32 nEnd = aOldArgs.getLength(); @@ -2385,6 +2386,10 @@ bool SfxObjectShell::ExportTo( SfxMedium& rMedium ) bHasFilterName = true; } + // FIXME: Handle this inside TransformItems() + if (pItems->GetItemState(SID_IS_REDACT_MODE) == SfxItemState::SET) + bIsRedactMode = true; + if ( !bHasOutputStream ) { aArgs.realloc ( ++nEnd ); @@ -2414,6 +2419,13 @@ bool SfxObjectShell::ExportTo( SfxMedium& rMedium ) aArgs[nEnd-1].Value <<= aFilterName; } + if (bIsRedactMode) + { + aArgs.realloc( ++nEnd ); + aArgs[nEnd-1].Name = "IsRedactMode"; + aArgs[nEnd-1].Value <<= bIsRedactMode; + } + return xFilter->filter( aArgs ); }catch(...) {} _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits