/************************************************************** * * 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 #include #include #include #include #include #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////////////////// 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 existence, 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