| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svx.hxx" |
| |
| #include <svx/sdr/contact/viewobjectcontactofpageobj.hxx> |
| #include <svx/sdr/contact/viewcontactofpageobj.hxx> |
| #include <svx/svdopage.hxx> |
| #include <svx/sdr/contact/displayinfo.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> |
| #include <svx/sdr/contact/objectcontactofobjlistpainter.hxx> |
| #include <basegfx/matrix/b2dhommatrix.hxx> |
| #include <svx/svdpage.hxx> |
| #include <svx/unoapi.hxx> |
| #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| using namespace com::sun::star; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace sdr |
| { |
| namespace contact |
| { |
| class PagePrimitiveExtractor : public ObjectContactOfPagePainter, public Timer |
| { |
| private: |
| // the ViewObjectContactOfPageObj using this painter |
| ViewObjectContactOfPageObj& mrViewObjectContactOfPageObj; |
| |
| public: |
| // basic constructor/destructor |
| PagePrimitiveExtractor(ViewObjectContactOfPageObj& rVOC); |
| virtual ~PagePrimitiveExtractor(); |
| |
| // LazyInvalidate request. Supported here to not automatically |
| // invalidate the second interaction state all the time at the |
| // original OC |
| virtual void setLazyInvalidate(ViewObjectContact& rVOC); |
| |
| // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism |
| virtual void Timeout(); |
| |
| // get primitive visualization |
| drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequenceForPage(const DisplayInfo& rDisplayInfo); |
| |
| // Own reaction on changes which will be forwarded to the OC of the owner-VOC |
| virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const; |
| |
| // forward access to SdrPageView of ViewObjectContactOfPageObj |
| virtual bool isOutputToPrinter() const; |
| virtual bool isOutputToWindow() const; |
| virtual bool isOutputToVirtualDevice() const; |
| virtual bool isOutputToRecordingMetaFile() const; |
| virtual bool isOutputToPDFFile() const; |
| virtual bool isDrawModeGray() const; |
| virtual bool isDrawModeBlackWhite() const; |
| virtual bool isDrawModeHighContrast() const; |
| virtual SdrPageView* TryToGetSdrPageView() const; |
| virtual OutputDevice* TryToGetOutputDevice() const; |
| }; |
| |
| PagePrimitiveExtractor::PagePrimitiveExtractor( |
| ViewObjectContactOfPageObj& rVOC) |
| : ObjectContactOfPagePainter(0, rVOC.GetObjectContact()), |
| mrViewObjectContactOfPageObj(rVOC) |
| { |
| // make this renderer a preview renderer |
| setPreviewRenderer(true); |
| |
| // init timer |
| SetTimeout(1); |
| Stop(); |
| } |
| |
| PagePrimitiveExtractor::~PagePrimitiveExtractor() |
| { |
| // execute missing LazyInvalidates and stop timer |
| Timeout(); |
| } |
| |
| void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/) |
| { |
| // do NOT call parent, but remember that something is to do by |
| // starting the LazyInvalidateTimer |
| Start(); |
| } |
| |
| // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism |
| void PagePrimitiveExtractor::Timeout() |
| { |
| // stop the timer |
| Stop(); |
| |
| // invalidate all LazyInvalidate VOCs new situations |
| const sal_uInt32 nVOCCount(getViewObjectContactCount()); |
| |
| for(sal_uInt32 a(0); a < nVOCCount; a++) |
| { |
| ViewObjectContact* pCandidate = getViewObjectContact(a); |
| pCandidate->triggerLazyInvalidate(); |
| } |
| } |
| |
| drawinglayer::primitive2d::Primitive2DSequence PagePrimitiveExtractor::createPrimitive2DSequenceForPage(const DisplayInfo& /*rDisplayInfo*/) |
| { |
| drawinglayer::primitive2d::Primitive2DSequence xRetval; |
| const SdrPage* pStartPage = GetStartPage(); |
| |
| if(pStartPage) |
| { |
| // update own ViewInformation2D for visualized page |
| const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D(); |
| const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D( |
| rOriginalViewInformation.getObjectTransformation(), |
| rOriginalViewInformation.getViewTransformation(), |
| |
| // #i101075# use empty range for page content here to force |
| // the content not to be physically clipped in any way. This |
| // would be possible, but would require the internal transformation |
| // which maps between the page visualisation object and the page |
| // content, including the aspect ratios (for details see in |
| // PagePreviewPrimitive2D::create2DDecomposition) |
| basegfx::B2DRange(), |
| |
| GetXDrawPageForSdrPage(const_cast< SdrPage* >(pStartPage)), |
| 0.0, // no time; page previews are not animated |
| rOriginalViewInformation.getExtendedInformationSequence()); |
| updateViewInformation2D(aNewViewInformation2D); |
| |
| // create copy of DisplayInfo to set PagePainting |
| DisplayInfo aDisplayInfo; |
| |
| // get page's VOC |
| ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this); |
| |
| // get whole Primitive2DSequence |
| xRetval = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo); |
| } |
| |
| return xRetval; |
| } |
| |
| void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const |
| { |
| // an invalidate is called at this view, this needs to be translated to an invalidate |
| // for the using VOC. Coordinates are in page coordinate system. |
| const SdrPage* pStartPage = GetStartPage(); |
| |
| if(pStartPage && !rRange.isEmpty()) |
| { |
| const basegfx::B2DRange aPageRange(0.0, 0.0, (double)pStartPage->GetWdt(), (double)pStartPage->GetHgt()); |
| |
| if(rRange.overlaps(aPageRange)) |
| { |
| // if object on the page is inside or overlapping with page, create ActionChanged() for |
| // involved VOC |
| mrViewObjectContactOfPageObj.ActionChanged(); |
| } |
| } |
| } |
| |
| // forward access to SdrPageView to VOCOfPageObj |
| bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); } |
| bool PagePrimitiveExtractor::isOutputToWindow() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToWindow(); } |
| bool PagePrimitiveExtractor::isOutputToVirtualDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToVirtualDevice(); } |
| bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); } |
| bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); } |
| bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); } |
| bool PagePrimitiveExtractor::isDrawModeBlackWhite() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeBlackWhite(); } |
| bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); } |
| SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); } |
| OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); } |
| } // end of namespace contact |
| } // end of namespace sdr |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace sdr |
| { |
| namespace contact |
| { |
| drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const |
| { |
| drawinglayer::primitive2d::Primitive2DSequence xRetval; |
| const SdrPageObj& rPageObject((static_cast< ViewContactOfPageObj& >(GetViewContact())).GetPageObj()); |
| const SdrPage* pPage = rPageObject.GetReferencedPage(); |
| const svtools::ColorConfig aColorConfig; |
| |
| // get PageObject's geometry |
| basegfx::B2DHomMatrix aPageObjectTransform; |
| { |
| const Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect()); |
| const basegfx::B2DRange aPageObjectBound( |
| aPageObjectModelData.Left(), aPageObjectModelData.Top(), |
| aPageObjectModelData.Right(), aPageObjectModelData.Bottom()); |
| |
| aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth()); |
| aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight()); |
| aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX()); |
| aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY()); |
| } |
| |
| // #i102637# add gray frame also when printing and page exists (handout pages) |
| const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage); |
| |
| // get displayed page's content. This is the uscaled page content |
| if(mpExtractor && pPage) |
| { |
| // get displayed page's geometry |
| drawinglayer::primitive2d::Primitive2DSequence xPageContent; |
| const Size aPageSize(pPage->GetSize()); |
| const double fPageWidth(aPageSize.getWidth()); |
| const double fPageHeight(aPageSize.getHeight()); |
| |
| // The case that a PageObject contains another PageObject which visualizes the |
| // same page again would lead to a recursion. Limit that recursion depth to one |
| // by using a local static bool |
| static bool bInCreatePrimitive2D(false); |
| |
| if(bInCreatePrimitive2D) |
| { |
| // Recursion is possible. Create a replacement primitive |
| xPageContent.realloc(2); |
| const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); |
| const Color aBorderColor(aColorConfig.GetColorValue(svtools::DOCBOUNDARIES).nColor); |
| const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight); |
| const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aPageBound)); |
| |
| // add replacement fill |
| xPageContent[0L] = drawinglayer::primitive2d::Primitive2DReference( |
| new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aDocColor.getBColor())); |
| |
| // add replacement border |
| xPageContent[1L] = drawinglayer::primitive2d::Primitive2DReference( |
| new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aBorderColor.getBColor())); |
| } |
| else |
| { |
| // set recursion flag |
| bInCreatePrimitive2D = true; |
| |
| // init extractor, guarantee existance, set page there |
| mpExtractor->SetStartPage(pPage); |
| |
| // #i105548# also need to copy the VOCRedirector for sub-content creation |
| mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector()); |
| |
| // create page content |
| xPageContent = mpExtractor->createPrimitive2DSequenceForPage(rDisplayInfo); |
| |
| // #i105548# reset VOCRedirector to not accidentially have a pointer to a |
| // temporary class, so calls to it are avoided safely |
| mpExtractor->SetViewObjectContactRedirector(0); |
| |
| // reset recursion flag |
| bInCreatePrimitive2D = false; |
| } |
| |
| // prepare retval |
| if(xPageContent.hasElements()) |
| { |
| const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage))); |
| const drawinglayer::primitive2d::Primitive2DReference xPagePreview(new drawinglayer::primitive2d::PagePreviewPrimitive2D( |
| xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent, true)); |
| xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPagePreview, 1); |
| } |
| } |
| else if(bCreateGrayFrame) |
| { |
| // #i105146# no content, but frame display. To make hitting the page preview objects |
| // on the handout page more simple, add hidden fill geometry |
| const drawinglayer::primitive2d::Primitive2DReference xFrameHit( |
| drawinglayer::primitive2d::createHiddenGeometryPrimitives2D( |
| false, |
| aPageObjectTransform)); |
| xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xFrameHit, 1); |
| } |
| |
| // add a gray outline frame, except not when printing |
| if(bCreateGrayFrame) |
| { |
| const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor); |
| basegfx::B2DPolygon aOwnOutline(basegfx::tools::createUnitPolygon()); |
| aOwnOutline.transform(aPageObjectTransform); |
| |
| const drawinglayer::primitive2d::Primitive2DReference xGrayFrame( |
| new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor())); |
| |
| drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xGrayFrame); |
| } |
| |
| return xRetval; |
| } |
| |
| ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact) |
| : ViewObjectContactOfSdrObj(rObjectContact, rViewContact), |
| mpExtractor(new PagePrimitiveExtractor(*this)) |
| { |
| } |
| |
| ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj() |
| { |
| // delete the helper OC |
| if(mpExtractor) |
| { |
| // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence() |
| // would be called for any reason |
| PagePrimitiveExtractor* pCandidate = mpExtractor; |
| mpExtractor = 0; |
| |
| // also reset the StartPage to avoid ActionChanged() forwardings in the |
| // PagePrimitiveExtractor::InvalidatePartOfView() implementation |
| pCandidate->SetStartPage(0); |
| delete pCandidate; |
| } |
| } |
| } // end of namespace contact |
| } // end of namespace sdr |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // eof |