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);
+                }
             }
         }
     }

Reply via email to