sc/source/ui/view/output3.cxx | 54 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-)
New commits: commit 596c53b06cbb33d312d58572b61e966e913109f3 Author: Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de> AuthorDate: Thu Nov 30 15:33:07 2023 +0100 Commit: Armin Le Grand <armin.le.gr...@me.com> CommitDate: Thu Nov 30 19:52:41 2023 +0100 Make ScOutputData::DrawSelectiveObjects compatible The implementation was not aware of the used functionality in the used call to SdrPageView::DrawLayer: The given OutputDevice is *not* intended to hand over a new render target, it's used to allow the mechanism(s) to *identify* one of multiple possibe registered render targets (which are usually OutputDevice/SystemWindow). It is even the default to call these method(s) with a nullptr which means to repaint all registered OutputDevices/SystemWindows. This is no tooling intended to repaint parts of a View to 'any' OutputDevice. This is not very obvious and there are already other places in the office that do that wrong and never got cleaned-up, therefore also being fallbacks to not just let those cases fail, but at least paint something (and give you a warning). The caveat is that these fallbacks (e.g. in SdrPageView::DrawLayer) have to use temporary SdrPaintWindow/ SdrPageWindow instances to make the paint work. Especially when a temporary SdrPageWindow is used an evtl. existing VC/VOC/OC structure will not be used and with it also not the existing primitive decompositions. I thought about bigger changes in PageView/PaintView/ PageWindow/PaintWindow area to sort that out, but this is - despite being utterly necessary - too expensive for now, keep a note about this needed change for the future. For now I will just use an already (also for this purpose already existing) 'compromize' that will do it for now. Change-Id: I8c7ccee1deb0d69aad1d2145a7ac2039aca685b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160155 Tested-by: Jenkins Reviewed-by: Armin Le Grand <armin.le.gr...@me.com> diff --git a/sc/source/ui/view/output3.cxx b/sc/source/ui/view/output3.cxx index eec75c39664d..2fc317b85094 100644 --- a/sc/source/ui/view/output3.cxx +++ b/sc/source/ui/view/output3.cxx @@ -33,6 +33,8 @@ #include <tabvwsh.hxx> #include <svx/fmview.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/sdrpagewindow.hxx> // #i72502# Point ScOutputData::PrePrintDrawingLayer(tools::Long nLogStX, tools::Long nLogStY ) @@ -204,7 +206,57 @@ void ScOutputData::DrawSelectiveObjects(SdrLayerID nLayer) if(pPageView) { - pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); + if (nullptr != pPageView->FindPageWindow(*mpDev)) + { + // Target OutputDevice is registered for this view + // (as it should be), we can just render + pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); + } + else if (0 != pPageView->PageWindowCount()) + { + // We need to temporarily make the target OutputDevice being + // 'known/registered' in the paint mechanism so that + // SdrPageView::DrawLayer can find it. + // This situation can occur when someone interprets the + // OutputDevice parameter that gets handed over to DrawLayer + // (or other SdrPageView repaint methods) to be there to + // define a new render target. + // This is *not* the case: This parameter is used to + // *identify* an already registered target-OutputDevice. + // The default is even to call with a nullptr -> that triggers + // the repaint for *all* registered OutputDevices/Windows. + // Since this is a common and known misinterpretation it + // is good to offer workarounds in the code - there are some + // already. + // For now - use an already existing 'patch mechanism' and + // 'smuggle' the unknown/temporary OutputDevice as a + // temporary SdrPaintWindow to the SdrPageWindow, that is + // not very expensive. + // NOTE: Just using the 1st SdrPageWindow here will be OK + // in most cases, the splitting of a view is only used + // in calc nowadays and should have identical zoom. + // Still, trigger a warning... + OSL_ENSURE(1 == pPageView->PageWindowCount(), + "ScOutputData::DrawSelectiveObjects: More than one SdrPageView, still using 1st one (!)"); + SdrPageWindow* patchedPageWindow(pPageView->GetPageWindow(0)); + assert(nullptr != patchedPageWindow && "SdrPageWindow *must* exist when 0 != PageWindowCount()"); + SdrPaintWindow temporaryPaintWindow(*pDrawView, *mpDev); + SdrPaintWindow* previousPaintWindow(patchedPageWindow->patchPaintWindow(temporaryPaintWindow)); + pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); + patchedPageWindow->unpatchPaintWindow(previousPaintWindow); + } + else + { + // There does not even exist a SdrPageWindow. Still call the + // paint to get the paint done, but be aware that this will create + // temporary SdrPaintWindow and SdrPageWindow and - due to the + // former - will not be able to use the decomposition buffering + // in the VC/VOC/OC mechanism. For that reason this might be + // somewhat 'expensive'. + // You will also get a warning about it (see OSL_FAIL in + // SdrPageView::DrawLayer) + pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); + } } } }