include/vcl/gdimtf.hxx | 1 sw/source/core/view/vprint.cxx | 65 +++++++++++------------------------------ vcl/source/gdi/gdimtf.cxx | 7 +++- 3 files changed, 25 insertions(+), 48 deletions(-)
New commits: commit a225b4dbd46897903b217969da5f97f2660022c9 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Jun 30 14:44:21 2023 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Mon Jul 3 11:32:14 2023 +0200 tdf#152231 vcl,sw: PDF/UA export: fix comments in the margin If enabled, the comments mess up the structure elements, because the PageSyncData::mActions stores indexes into the GDIMetaFile::m_aList vector, and in PageSyncData::PlaySyncPageAct() the indexes don't match. This is because SwViewShell::PrintOrPDFExport() replaces the GDIMetaFile with a temporary one, then records the page content, then applies scaling to the temporary one and replays it, recording with the original one; somehow replaying a temporary GDIMetaFile with 270 actions to one that already has 4 actions results in 392 actions. It's not obvious how this can work with the temporary GDIMetaFile, so try to get rid of it; not sure if there any drawbacks to this but the GDIMetaFile is freshly created by the caller in any case. Change-Id: Ic297367ea307aa8eee8d609751d06abf417e9629 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153808 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/include/vcl/gdimtf.hxx b/include/vcl/gdimtf.hxx index d62cd899623b..63bde564dcfd 100644 --- a/include/vcl/gdimtf.hxx +++ b/include/vcl/gdimtf.hxx @@ -115,6 +115,7 @@ public: void Move( tools::Long nX, tools::Long nY ); // additional Move method getting specifics how to handle MapMode( MapUnit::MapPixel ) void Move( tools::Long nX, tools::Long nY, tools::Long nDPIX, tools::Long nDPIY ); + void ScaleActions(double fScaleX, double fScaleY); void Scale( double fScaleX, double fScaleY ); void Scale( const Fraction& rScaleX, const Fraction& rScaleY ); void Rotate( Degree10 nAngle10 ); diff --git a/sw/source/core/view/vprint.cxx b/sw/source/core/view/vprint.cxx index 0ad22ccf5357..3cd0c524007e 100644 --- a/sw/source/core/view/vprint.cxx +++ b/sw/source/core/view/vprint.cxx @@ -446,32 +446,12 @@ bool SwViewShell::PrintOrPDFExport( // output device is now provided by a call from outside the Writer) pOutDev->Push(); - // fdo#36815 for comments in margins print to a metafile - // and then scale that metafile down so that the comments - // will fit on the real page, and replay that scaled - // output to the real outputdevice - GDIMetaFile *pOrigRecorder(nullptr); - std::unique_ptr<GDIMetaFile> pMetaFile; SwPostItMode nPostItMode = rPrintData.GetPrintPostIts(); // tdf#91680 Reserve space in margin for comments only if there are comments const bool bHasPostItsToPrintInMargins = ( nPostItMode == SwPostItMode::InMargins ) && sw_GetPostIts( GetDoc()->getIDocumentFieldsAccess(), nullptr ); - - if ( bHasPostItsToPrintInMargins ) - { - //get and disable the existing recorder - pOrigRecorder = pOutDev->GetConnectMetaFile(); - pOutDev->SetConnectMetaFile(nullptr); - // turn off output to the device - pOutDev->EnableOutput(false); - // just record the rendering commands to the metafile - // instead - pMetaFile.reset(new GDIMetaFile); - pMetaFile->SetPrefSize(pOutDev->GetOutputSize()); - pMetaFile->SetPrefMapMode(pOutDev->GetMapMode()); - pMetaFile->Record(pOutDev); - } + ::std::optional<tools::Long> oOrigHeight; // Print/PDF export for (multi-)selection has already generated a // temporary document with the selected text. @@ -535,32 +515,7 @@ bool SwViewShell::PrintOrPDFExport( pPostItManager->CalcRects(); pPostItManager->LayoutPostIts(); pPostItManager->DrawNotesForPage(pOutDev, nPage-1); - - //Stop recording now - pMetaFile->Stop(); - pMetaFile->WindStart(); - //Enable output to the device again - pOutDev->EnableOutput(); - //Restore the original recorder - pOutDev->SetConnectMetaFile(pOrigRecorder); - - //Now scale the recorded page down so the notes - //will fit in the final page - double fScale = 0.75; - tools::Long nOrigHeight = pStPage->getFrameArea().Height(); - tools::Long nNewHeight = nOrigHeight*fScale; - tools::Long nShiftY = (nOrigHeight-nNewHeight)/2; - pMetaFile->Scale( fScale, fScale ); - pMetaFile->WindStart(); - //Move the scaled page down to center it - //the other variant of Move does not map pixels - //back to the logical units correctly - pMetaFile->Move(0, convertTwipToMm100(nShiftY), pOutDev->GetDPIX(), pOutDev->GetDPIY()); - pMetaFile->WindStart(); - - //play back the scaled page - pMetaFile->Play(*pOutDev); - pMetaFile.reset(); + oOrigHeight.emplace(pStPage->getFrameArea().Height()); } } @@ -570,6 +525,22 @@ bool SwViewShell::PrintOrPDFExport( // output device is now provided by a call from outside the Writer) pOutDev->Pop(); + // avoid a warning about unbalanced Push/Pop by doing this last: + if (oOrigHeight) + { + // fdo#36815 Now scale the recorded page down so the comments in + // margins will fit in the final page + double fScale = 0.75; + tools::Long nNewHeight = *oOrigHeight*fScale; + tools::Long nShiftY = (*oOrigHeight-nNewHeight)/2; + GDIMetaFile *const pMetaFile = pOutDev->GetConnectMetaFile(); + pMetaFile->ScaleActions(fScale, fScale); + //Move the scaled page down to center it + //the other variant of Move does not map pixels + //back to the logical units correctly + pMetaFile->Move(0, convertTwipToMm100(nShiftY), pOutDev->GetDPIX(), pOutDev->GetDPIY()); + } + return true; } diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx index e8bb8ba7e0bd..313d03811780 100644 --- a/vcl/source/gdi/gdimtf.cxx +++ b/vcl/source/gdi/gdimtf.cxx @@ -727,7 +727,7 @@ void GDIMetaFile::Move( tools::Long nX, tools::Long nY, tools::Long nDPIX, tools } } -void GDIMetaFile::Scale( double fScaleX, double fScaleY ) +void GDIMetaFile::ScaleActions(double const fScaleX, double const fScaleY) { for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() ) { @@ -743,6 +743,11 @@ void GDIMetaFile::Scale( double fScaleX, double fScaleY ) pModAct->Scale( fScaleX, fScaleY ); } +} + +void GDIMetaFile::Scale( double fScaleX, double fScaleY ) +{ + ScaleActions(fScaleX, fScaleY); m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) ); m_aPrefSize.setHeight( FRound( m_aPrefSize.Height() * fScaleY ) );