diff options
-rw-r--r-- | include/svx/svdpntv.hxx | 6 | ||||
-rw-r--r-- | sd/qa/unit/tiledrendering/data/SlideRenderingTest.odp | bin | 29095 -> 26099 bytes | |||
-rw-r--r-- | sd/qa/unit/tiledrendering/tiledrendering.cxx | 66 | ||||
-rw-r--r-- | sd/source/ui/inc/SlideshowLayerRenderer.hxx | 21 | ||||
-rw-r--r-- | sd/source/ui/tools/SlideshowLayerRenderer.cxx | 159 | ||||
-rw-r--r-- | sd/source/ui/unoidl/unomodel.cxx | 2 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontactofmasterpagedescriptor.cxx | 7 | ||||
-rw-r--r-- | svx/source/svdraw/svdpntv.cxx | 1 |
8 files changed, 216 insertions, 46 deletions
diff --git a/include/svx/svdpntv.hxx b/include/svx/svdpntv.hxx index 8665262f0508..df3c95131590 100644 --- a/include/svx/svdpntv.hxx +++ b/include/svx/svdpntv.hxx @@ -207,7 +207,8 @@ protected: bool mbHideChart : 1; bool mbHideDraw : 1; // hide draw objects other than form controls bool mbHideFormControl : 1; // hide form controls only - bool mbPaintTextEdit : 1; // if should paint currently edited text + bool mbHideBackground : 1; // don't draw the (page's or matser page's) background + bool mbPaintTextEdit : 1; // if should paint currently edited text public: // Interface for BufferedOoutputAllowed flag @@ -473,10 +474,13 @@ public: bool getHideChart() const { return mbHideChart; } bool getHideDraw() const { return mbHideDraw; } bool getHideFormControl() const { return mbHideFormControl; } + bool getHideBackground() const { return mbHideBackground; } + void setHideOle(bool bNew) { if(bNew != mbHideOle) mbHideOle = bNew; } void setHideChart(bool bNew) { if(bNew != mbHideChart) mbHideChart = bNew; } void setHideDraw(bool bNew) { if(bNew != mbHideDraw) mbHideDraw = bNew; } void setHideFormControl(bool bNew) { if(bNew != mbHideFormControl) mbHideFormControl = bNew; } + void setHideBackground(bool bNew) { mbHideBackground = bNew; } void SetGridCoarse(const Size& rSiz) { maGridBig=rSiz; } void SetGridFine(const Size& rSiz) { diff --git a/sd/qa/unit/tiledrendering/data/SlideRenderingTest.odp b/sd/qa/unit/tiledrendering/data/SlideRenderingTest.odp Binary files differindex 4c7d4f101e32..8ffd7d38f051 100644 --- a/sd/qa/unit/tiledrendering/data/SlideRenderingTest.odp +++ b/sd/qa/unit/tiledrendering/data/SlideRenderingTest.odp diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index bb57cddf4bbc..604ec9047736 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -3177,8 +3177,9 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering) // The doucment has nothing set for the background, so it should be application color = white // On the master slide there is a (blue) rectangle on the right side - top-left should be transparent // On the main slide there is a (green) rectanlge on the top-left size - right side should be transparent - // enable layer output to PNG files - const bool bOutputPNG = false; + + const bool bOutputPNG = false; // Control layer output to PNG files + SdXImpressDocument* pXImpressDocument = createDoc("SlideRenderingTest.odp"); pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); @@ -3189,16 +3190,18 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering) sal_Int32 nViewHeight = 2000; CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(0, nViewWidth, nViewHeight, true, true)); CPPUNIT_ASSERT_EQUAL(2000, nViewWidth); - CPPUNIT_ASSERT_EQUAL(1125, nViewHeight); // adjusted to the slide aspect ratio - std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4); - bool bIsBitmapLayer = false; - OUString rJsonMsg; + CPPUNIT_ASSERT_EQUAL(1125, nViewHeight); - CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), bIsBitmapLayer, rJsonMsg)); - CPPUNIT_ASSERT(bIsBitmapLayer); - // TODO - check JSON content - // printf ("1 %s\n\n", rJsonMsg.toUtf8().getStr()); + const Color aTransparentColor(ColorAlpha, 0x00000000); { + std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4); + bool bIsBitmapLayer = false; + OUString rJsonMsg; + CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), bIsBitmapLayer, rJsonMsg)); + CPPUNIT_ASSERT(bIsBitmapLayer); + // TODO - check JSON content + // printf ("1 %s\n\n", rJsonMsg.toUtf8().getStr()); + BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true); if (bOutputPNG) { @@ -3207,14 +3210,49 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering) aPNGWriter.write(aBitmapEx); } + // top-left corner + CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 20)); + + // bottom-left corner + CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, nViewHeight - 20)); + + // bottom-right corner + CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd0, 0x40), aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20)); + } + + { + std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4); + bool bIsBitmapLayer = false; + OUString rJsonMsg; + CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), bIsBitmapLayer, rJsonMsg)); + CPPUNIT_ASSERT(bIsBitmapLayer); + // TODO - check JSON content + // printf ("2 %s\n\n", rJsonMsg.toUtf8().getStr()); + + BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true); + if (bOutputPNG) + { + SvFileStream aStream("/home/quikee/XXX_02.png", StreamMode::WRITE | StreamMode::TRUNC); + vcl::PngImageWriter aPNGWriter(aStream); + aPNGWriter.write(aBitmapEx); + } + + // top-left corner + CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x50, 0x90), aBitmapEx.GetPixelColor(20, 20)); + // bottom-left corner - CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0x00000000), aBitmapEx.GetPixelColor(20, nViewHeight - 20)); + CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, nViewHeight - 20)); // bottom-right corner - CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd5, 0x46), aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20)); + CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20)); + } + + { + std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4); + bool bIsBitmapLayer = false; + OUString rJsonMsg; + CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), bIsBitmapLayer, rJsonMsg)); } - // should return true - no more content - CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), bIsBitmapLayer, rJsonMsg)); pXImpressDocument->postSlideshowCleanup(); } diff --git a/sd/source/ui/inc/SlideshowLayerRenderer.hxx b/sd/source/ui/inc/SlideshowLayerRenderer.hxx index 28525839d579..33c2ca69d502 100644 --- a/sd/source/ui/inc/SlideshowLayerRenderer.hxx +++ b/sd/source/ui/inc/SlideshowLayerRenderer.hxx @@ -12,23 +12,36 @@ #include <sddllapi.h> #include <tools/gen.hxx> #include <rtl/string.hxx> +#include <deque> class SdrPage; -class BitmapEx; +class SdrModel; + class Size; namespace sd { +enum class SlideRenderStage +{ + Master, + Slide +}; + class SD_DLLPUBLIC SlideshowLayerRenderer { - SdrPage* mpPage; + SdrPage& mrPage; + SdrModel& mrModel; + Size maSlideSize; - bool bRenderDone = false; + + std::deque<SlideRenderStage> maRenderStages; public: - SlideshowLayerRenderer(SdrPage* pPage); + SlideshowLayerRenderer(SdrPage& rPage); Size calculateAndSetSizePixel(Size const& rDesiredSizePixel); bool render(unsigned char* pBuffer, OString& rJsonMsg); + bool renderMaster(unsigned char* pBuffer, OString& rJsonMsg); + bool renderSlide(unsigned char* pBuffer, OString& rJsonMsg); }; } // end of namespace sd diff --git a/sd/source/ui/tools/SlideshowLayerRenderer.cxx b/sd/source/ui/tools/SlideshowLayerRenderer.cxx index e618dd2fac33..5f6fe8d7eda1 100644 --- a/sd/source/ui/tools/SlideshowLayerRenderer.cxx +++ b/sd/source/ui/tools/SlideshowLayerRenderer.cxx @@ -14,7 +14,9 @@ #include <svx/unoapi.hxx> #include <svx/sdr/contact/viewobjectcontact.hxx> #include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/objectcontact.hxx> #include <svx/svdoutl.hxx> +#include <svx/svdpagv.hxx> #include <vcl/virdev.hxx> #include <tools/helpers.hxx> #include <tools/json_writer.hxx> @@ -23,9 +25,23 @@ namespace sd { namespace { -class SelectObjectRedirector : public sdr::contact::ViewObjectContactRedirector +struct RedirectorOptions { + bool mbSkipMainPageObjects = false; + bool mbSkipMasterPageObjects = false; +}; + +class ObjectRedirector : public sdr::contact::ViewObjectContactRedirector +{ +protected: + RedirectorOptions maOptions; + public: + ObjectRedirector(RedirectorOptions const& rOptions) + : maOptions(rOptions) + { + } + virtual void createRedirectedPrimitive2DSequence( const sdr::contact::ViewObjectContact& rOriginal, const sdr::contact::DisplayInfo& rDisplayInfo, @@ -37,12 +53,15 @@ public: if (pObject == nullptr || pPage == nullptr) { // Not a SdrObject or a object not connected to a page (object with no page) - - //sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence( - // rOriginal, rDisplayInfo, rVisitor); return; } + if (maOptions.mbSkipMasterPageObjects && pPage->IsMasterPage()) + return; + + if (maOptions.mbSkipMainPageObjects && !pPage->IsMasterPage()) + return; + const bool bDoCreateGeometry( pObject->getSdrPageFromSdrObject()->checkVisibility(rOriginal, rDisplayInfo, true)); @@ -60,43 +79,116 @@ public: rOriginal, rDisplayInfo, rVisitor); } }; + +bool hasEmptyMaster(SdrPage const& rPage) +{ + if (!rPage.TRG_HasMasterPage()) + return true; + + SdrPage& rMaster = rPage.TRG_GetMasterPage(); + for (size_t i = 0; i < rMaster.GetObjCount(); i++) + { + auto pObject = rMaster.GetObj(i); + if (!pObject->IsEmptyPresObj()) + return false; + } + return true; } -SlideshowLayerRenderer::SlideshowLayerRenderer(SdrPage* pPage) - : mpPage(pPage) +} // end anonymous namespace + +SlideshowLayerRenderer::SlideshowLayerRenderer(SdrPage& rPage) + : mrPage(rPage) + , mrModel(rPage.getSdrModelFromSdrPage()) { + if (!hasEmptyMaster(rPage)) + maRenderStages.emplace_back(SlideRenderStage::Master); + maRenderStages.emplace_back(SlideRenderStage::Slide); } Size SlideshowLayerRenderer::calculateAndSetSizePixel(Size const& rDesiredSizePixel) { - if (!mpPage) - return Size(); - - double fRatio = double(mpPage->GetHeight()) / mpPage->GetWidth(); + double fRatio = double(mrPage.GetHeight()) / mrPage.GetWidth(); Size aSize(rDesiredSizePixel.Width(), ::tools::Long(rDesiredSizePixel.Width() * fRatio)); maSlideSize = aSize; return maSlideSize; } -bool SlideshowLayerRenderer::render(unsigned char* pBuffer, OString& rJsonMsg) +bool SlideshowLayerRenderer::renderMaster(unsigned char* pBuffer, OString& rJsonMsg) { - if (bRenderDone) - return false; + SdrOutliner& rOutliner = mrModel.GetDrawOutliner(); + const EEControlBits nOldControlBits(rOutliner.GetControlWord()); + EEControlBits nControlBits = nOldControlBits & ~EEControlBits::ONLINESPELLING; + rOutliner.SetControlWord(nControlBits); - if (!mpPage) - return false; + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + + pDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(maSlideSize, Fraction(1.0), Point(), + pBuffer); + + Point aPoint; + Size aPageSize(mrPage.GetSize()); + + MapMode aMapMode(MapUnit::Map100thMM); + const Fraction aFracX(maSlideSize.Width(), pDevice->LogicToPixel(aPageSize, aMapMode).Width()); + aMapMode.SetScaleX(aFracX); + + const Fraction aFracY(maSlideSize.Height(), + pDevice->LogicToPixel(aPageSize, aMapMode).Height()); + aMapMode.SetScaleY(aFracY); + + pDevice->SetMapMode(aMapMode); - SdrModel& rModel = mpPage->getSdrModelFromSdrPage(); + SdrView aView(mrModel, pDevice); + + aView.SetPageVisible(false); + aView.SetPageShadowVisible(false); + aView.SetPageBorderVisible(false); + aView.SetBordVisible(false); + aView.SetGridVisible(false); + aView.SetHlplVisible(false); + aView.SetGlueVisible(false); + aView.setHideBackground(false); + aView.ShowSdrPage(&mrPage); + + vcl::Region aRegion(::tools::Rectangle(aPoint, aPageSize)); + ObjectRedirector aRedirector({ .mbSkipMainPageObjects = true }); + aView.CompleteRedraw(pDevice, aRegion, &aRedirector); + + ::tools::JsonWriter aJsonWriter; + aJsonWriter.put("group", "MasterPage"); + aJsonWriter.put("slideHash", GetInterfaceHash(GetXDrawPageForSdrPage(&mrPage))); + aJsonWriter.put("index", 0); + aJsonWriter.put("type", "bitmap"); + { + ::tools::ScopedJsonWriterNode aContentNode = aJsonWriter.startNode("content"); + aJsonWriter.put("type", "%IMAGETYPE%"); + aJsonWriter.put("checksum", "%IMAGECHECKSUM%"); + } + rJsonMsg = aJsonWriter.finishAndGetAsOString(); + + rOutliner.SetControlWord(nOldControlBits); + + return true; +} + +bool SlideshowLayerRenderer::renderSlide(unsigned char* pBuffer, OString& rJsonMsg) +{ + SdrOutliner& rOutliner = mrModel.GetDrawOutliner(); + const EEControlBits nOldControlBits(rOutliner.GetControlWord()); + EEControlBits nControlBits = nOldControlBits & ~EEControlBits::ONLINESPELLING; + rOutliner.SetControlWord(nControlBits); ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::WITHOUT_ALPHA); pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); - pDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(maSlideSize, Fraction(2.0), Point(), + pDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(maSlideSize, Fraction(1.0), Point(), pBuffer); Point aPoint; - Size aPageSize(mpPage->GetSize()); + Size aPageSize(mrPage.GetSize()); MapMode aMapMode(MapUnit::Map100thMM); const Fraction aFracX(maSlideSize.Width(), pDevice->LogicToPixel(aPageSize, aMapMode).Width()); @@ -108,7 +200,7 @@ bool SlideshowLayerRenderer::render(unsigned char* pBuffer, OString& rJsonMsg) pDevice->SetMapMode(aMapMode); - SdrView aView(rModel, pDevice); + SdrView aView(mrModel, pDevice); aView.SetPageVisible(false); aView.SetPageShadowVisible(false); @@ -117,16 +209,16 @@ bool SlideshowLayerRenderer::render(unsigned char* pBuffer, OString& rJsonMsg) aView.SetGridVisible(false); aView.SetHlplVisible(false); aView.SetGlueVisible(false); - - aView.ShowSdrPage(mpPage); + aView.setHideBackground(true); + aView.ShowSdrPage(&mrPage); vcl::Region aRegion(::tools::Rectangle(aPoint, aPageSize)); - SelectObjectRedirector aRedirector; + ObjectRedirector aRedirector({ .mbSkipMasterPageObjects = true }); aView.CompleteRedraw(pDevice, aRegion, &aRedirector); ::tools::JsonWriter aJsonWriter; aJsonWriter.put("group", "DrawPage"); - aJsonWriter.put("slideHash", GetInterfaceHash(GetXDrawPageForSdrPage(mpPage))); + aJsonWriter.put("slideHash", GetInterfaceHash(GetXDrawPageForSdrPage(&mrPage))); aJsonWriter.put("index", 0); aJsonWriter.put("type", "bitmap"); { @@ -136,7 +228,26 @@ bool SlideshowLayerRenderer::render(unsigned char* pBuffer, OString& rJsonMsg) } rJsonMsg = aJsonWriter.finishAndGetAsOString(); - bRenderDone = true; + rOutliner.SetControlWord(nOldControlBits); + + return true; +} + +bool SlideshowLayerRenderer::render(unsigned char* pBuffer, OString& rJsonMsg) +{ + if (maRenderStages.empty()) + return false; + + auto eRenderStage = maRenderStages.front(); + maRenderStages.pop_front(); + + switch (eRenderStage) + { + case SlideRenderStage::Master: + return renderMaster(pBuffer, rJsonMsg); + case SlideRenderStage::Slide: + return renderSlide(pBuffer, rJsonMsg); + }; return true; } diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index d388e6f80ee6..146a708f66d1 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -4419,7 +4419,7 @@ bool SdXImpressDocument::createSlideRenderer( if (!pPage) return false; - mpSlideshowLayerRenderer.reset(new SlideshowLayerRenderer(pPage)); + mpSlideshowLayerRenderer.reset(new SlideshowLayerRenderer(*pPage)); Size aDesiredSize(nViewWidth, nViewHeight); Size aCalculatedSize = mpSlideshowLayerRenderer->calculateAndSetSizePixel(aDesiredSize); nViewWidth = aCalculatedSize.Width(); diff --git a/svx/source/sdr/contact/viewobjectcontactofmasterpagedescriptor.cxx b/svx/source/sdr/contact/viewobjectcontactofmasterpagedescriptor.cxx index baa039b1bb0f..2cd4b64c2fe8 100644 --- a/svx/source/sdr/contact/viewobjectcontactofmasterpagedescriptor.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofmasterpagedescriptor.cxx @@ -23,6 +23,8 @@ #include <svx/sdr/contact/displayinfo.hxx> #include <svx/sdr/contact/objectcontact.hxx> #include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdview.hxx> #include <drawinglayer/primitive2d/maskprimitive2d.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/polygon/b2dpolygon.hxx> @@ -78,12 +80,13 @@ namespace sdr::contact aPreprocessedLayers &= rDescriptor.GetVisibleLayers(); rDisplayInfo.SetProcessLayers(aPreprocessedLayers); rDisplayInfo.SetSubContentActive(true); - + const SdrPageView* pSdrPageView = GetObjectContact().TryToGetSdrPageView(); + bool bHideBackground = pSdrPageView ? pSdrPageView->GetView().getHideBackground() : false; // check layer visibility (traditionally was member of layer 1) if(aPreprocessedLayers.IsSet(SdrLayerID(1))) { // hide PageBackground for special DrawModes; historical reasons - if(!GetObjectContact().isDrawModeGray() && !GetObjectContact().isDrawModeHighContrast()) + if (!bHideBackground && !GetObjectContact().isDrawModeGray() && !GetObjectContact().isDrawModeHighContrast()) { // if visible, create the default background primitive sequence static_cast< ViewContactOfMasterPageDescriptor& >(GetViewContact()).getViewIndependentPrimitive2DContainer(rVisitor); diff --git a/svx/source/svdraw/svdpntv.cxx b/svx/source/svdraw/svdpntv.cxx index 5fcea85745f5..1aa512072586 100644 --- a/svx/source/svdraw/svdpntv.cxx +++ b/svx/source/svdraw/svdpntv.cxx @@ -165,6 +165,7 @@ SdrPaintView::SdrPaintView(SdrModel& rSdrModel, OutputDevice* pOut) , mbHideChart(false) , mbHideDraw(false) , mbHideFormControl(false) + , mbHideBackground(false) , mbPaintTextEdit(true) , maGridColor(COL_BLACK) { |