| /************************************************************** |
| * |
| * 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_sd.hxx" |
| |
| #include "PreviewRenderer.hxx" |
| |
| #include "DrawDocShell.hxx" |
| #include "drawdoc.hxx" |
| #include "drawview.hxx" |
| #include "sdpage.hxx" |
| #include "ViewShell.hxx" |
| #include <vcl/virdev.hxx> |
| #include <svx/svdpagv.hxx> |
| #include <svx/svdoutl.hxx> |
| #include <editeng/eeitem.hxx> |
| #include <editeng/editstat.hxx> |
| #include <tools/link.hxx> |
| #include <vcl/svapp.hxx> |
| #include <tools/diagnose_ex.h> |
| #include <svx/sdr/contact/viewobjectcontact.hxx> |
| #include <svx/sdr/contact/viewcontact.hxx> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| |
| |
| namespace sd { |
| |
| const int PreviewRenderer::snSubstitutionTextSize = 11; |
| const int PreviewRenderer::snFrameWidth = 1; |
| |
| namespace { |
| /** This incarnation of the ViewObjectContactRedirector filters away all |
| PageObj objects, unconditionally. |
| */ |
| class ViewRedirector : public ::sdr::contact::ViewObjectContactRedirector |
| { |
| public: |
| ViewRedirector (void); |
| virtual ~ViewRedirector (void); |
| virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence( |
| const sdr::contact::ViewObjectContact& rOriginal, |
| const sdr::contact::DisplayInfo& rDisplayInfo); |
| }; |
| } |
| |
| |
| |
| |
| //===== PreviewRenderer ======================================================= |
| |
| PreviewRenderer::PreviewRenderer ( |
| OutputDevice* pTemplate, |
| const bool bHasFrame) |
| : mpPreviewDevice (new VirtualDevice()), |
| mpView(NULL), |
| mpDocShellOfView(NULL), |
| mnWidthOfView(0), |
| maFrameColor (svtools::ColorConfig().GetColorValue(svtools::DOCBOUNDARIES).nColor), |
| mbHasFrame(bHasFrame) |
| { |
| if (pTemplate != NULL) |
| { |
| mpPreviewDevice->SetDigitLanguage (pTemplate->GetDigitLanguage()); |
| mpPreviewDevice->SetBackground(pTemplate->GetBackground()); |
| } |
| else |
| { |
| mpPreviewDevice->SetBackground(Wallpaper( |
| Application::GetSettings().GetStyleSettings().GetWindowColor())); |
| } |
| } |
| |
| |
| |
| |
| PreviewRenderer::~PreviewRenderer (void) |
| { |
| if (mpDocShellOfView != NULL) |
| EndListening (*mpDocShellOfView); |
| } |
| |
| |
| |
| |
| Image PreviewRenderer::RenderPage ( |
| const SdPage* pPage, |
| const sal_Int32 nWidth, |
| const String& rSubstitutionText, |
| const bool bObeyHighContrastMode, |
| const bool bDisplayPresentationObjects) |
| { |
| if (pPage != NULL) |
| { |
| const Size aPageModelSize (pPage->GetSize()); |
| const double nAspectRatio ( |
| double(aPageModelSize.Width()) / double(aPageModelSize.Height())); |
| const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0); |
| const sal_Int32 nHeight (sal::static_int_cast<sal_Int32>( |
| (nWidth - 2*nFrameWidth) / nAspectRatio + 2*nFrameWidth + 0.5)); |
| return RenderPage ( |
| pPage, |
| Size(nWidth,nHeight), |
| rSubstitutionText, |
| bObeyHighContrastMode, |
| bDisplayPresentationObjects); |
| } |
| else |
| return Image(); |
| } |
| |
| |
| |
| |
| Image PreviewRenderer::RenderPage ( |
| const SdPage* pPage, |
| Size aPixelSize, |
| const String& rSubstitutionText, |
| const bool bObeyHighContrastMode, |
| const bool bDisplayPresentationObjects) |
| { |
| Image aPreview; |
| |
| if (pPage != NULL) |
| { |
| try |
| { |
| if (Initialize(pPage, aPixelSize, bObeyHighContrastMode)) |
| { |
| PaintPage(pPage, bDisplayPresentationObjects); |
| PaintSubstitutionText(rSubstitutionText); |
| PaintFrame(); |
| |
| Size aSize (mpPreviewDevice->GetOutputSizePixel()); |
| aPreview = mpPreviewDevice->GetBitmap ( |
| mpPreviewDevice->PixelToLogic(Point(0,0)), |
| mpPreviewDevice->PixelToLogic(aSize)); |
| |
| Cleanup(); |
| } |
| } |
| catch (const com::sun::star::uno::Exception&) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| |
| return aPreview; |
| } |
| |
| |
| |
| |
| Image PreviewRenderer::RenderSubstitution ( |
| const Size& rPreviewPixelSize, |
| const String& rSubstitutionText) |
| { |
| Image aPreview; |
| |
| try |
| { |
| // Set size. |
| mpPreviewDevice->SetOutputSizePixel(rPreviewPixelSize); |
| |
| // Adjust contrast mode. |
| const bool bUseContrast ( |
| Application::GetSettings().GetStyleSettings().GetHighContrastMode()); |
| mpPreviewDevice->SetDrawMode (bUseContrast |
| ? ViewShell::OUTPUT_DRAWMODE_CONTRAST |
| : ViewShell::OUTPUT_DRAWMODE_COLOR); |
| |
| // Set a map mode that makes a typical substitution text completely |
| // visible. |
| MapMode aMapMode (mpPreviewDevice->GetMapMode()); |
| aMapMode.SetMapUnit(MAP_100TH_MM); |
| const double nFinalScale (25.0 * rPreviewPixelSize.Width() / 28000.0); |
| aMapMode.SetScaleX(nFinalScale); |
| aMapMode.SetScaleY(nFinalScale); |
| const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0); |
| aMapMode.SetOrigin(mpPreviewDevice->PixelToLogic( |
| Point(nFrameWidth,nFrameWidth),aMapMode)); |
| mpPreviewDevice->SetMapMode (aMapMode); |
| |
| // Clear the background. |
| const Rectangle aPaintRectangle ( |
| Point(0,0), |
| mpPreviewDevice->GetOutputSizePixel()); |
| mpPreviewDevice->EnableMapMode(sal_False); |
| mpPreviewDevice->SetLineColor(); |
| svtools::ColorConfig aColorConfig; |
| mpPreviewDevice->SetFillColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); |
| mpPreviewDevice->DrawRect (aPaintRectangle); |
| mpPreviewDevice->EnableMapMode(sal_True); |
| |
| // Paint substitution text and a frame around it. |
| PaintSubstitutionText (rSubstitutionText); |
| PaintFrame(); |
| |
| const Size aSize (mpPreviewDevice->GetOutputSizePixel()); |
| aPreview = mpPreviewDevice->GetBitmap ( |
| mpPreviewDevice->PixelToLogic(Point(0,0)), |
| mpPreviewDevice->PixelToLogic(aSize)); |
| } |
| catch (const com::sun::star::uno::Exception&) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| |
| return aPreview; |
| } |
| |
| |
| |
| |
| bool PreviewRenderer::Initialize ( |
| const SdPage* pPage, |
| const Size& rPixelSize, |
| const bool bObeyHighContrastMode) |
| { |
| bool bSuccess = false; |
| do |
| { |
| if (pPage == NULL) |
| break; |
| |
| SdrModel* pModel = pPage->GetModel(); |
| if (pModel == NULL) |
| break; |
| |
| SetupOutputSize(*pPage, rPixelSize); |
| |
| SdDrawDocument* pDocument |
| = static_cast<SdDrawDocument*>(pPage->GetModel()); |
| DrawDocShell* pDocShell = pDocument->GetDocSh(); |
| |
| // Create view |
| ProvideView (pDocShell); |
| if (mpView.get() == NULL) |
| break; |
| |
| // Adjust contrast mode. |
| bool bUseContrast (bObeyHighContrastMode |
| && Application::GetSettings().GetStyleSettings().GetHighContrastMode()); |
| mpPreviewDevice->SetDrawMode (bUseContrast |
| ? ViewShell::OUTPUT_DRAWMODE_CONTRAST |
| : ViewShell::OUTPUT_DRAWMODE_COLOR); |
| mpPreviewDevice->SetSettings(Application::GetSettings()); |
| |
| // Tell the view to show the given page. |
| SdPage* pNonConstPage = const_cast<SdPage*>(pPage); |
| if (pPage->IsMasterPage()) |
| { |
| mpView->ShowSdrPage(mpView->GetModel()->GetMasterPage(pPage->GetPageNum())); |
| } |
| else |
| { |
| mpView->ShowSdrPage(pNonConstPage); |
| } |
| |
| // Make sure that a page view exists. |
| SdrPageView* pPageView = mpView->GetSdrPageView(); |
| if (pPageView == NULL) |
| break; |
| |
| // #121224# No need to set SetApplicationBackgroundColor (which is the color |
| // of the area 'behind' the page (formally called 'Wiese') since the page previews |
| // produced exactly cover the page's area, so it would never be visible. What |
| // needs to be set is the ApplicationDocumentColor which is derived from |
| // svtools::DOCCOLOR normally |
| svtools::ColorConfig aColorConfig; |
| Color aApplicationDocumentColor; |
| |
| if(!pPageView || pPageView->GetApplicationDocumentColor() == COL_AUTO) |
| { |
| svtools::ColorConfig aColorConfig; |
| aApplicationDocumentColor = aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor; |
| } |
| else |
| { |
| aApplicationDocumentColor = pPageView->GetApplicationDocumentColor(); |
| } |
| |
| pPageView->SetApplicationDocumentColor(aApplicationDocumentColor); |
| SdrOutliner& rOutliner(pDocument->GetDrawOutliner(NULL)); |
| rOutliner.SetBackgroundColor(aApplicationDocumentColor); |
| rOutliner.SetDefaultLanguage(pDocument->GetLanguage(EE_CHAR_LANGUAGE)); |
| mpPreviewDevice->SetBackground(Wallpaper(aApplicationDocumentColor)); |
| mpPreviewDevice->Erase(); |
| |
| bSuccess = true; |
| } |
| while (false); |
| |
| return bSuccess; |
| } |
| |
| |
| |
| |
| void PreviewRenderer::Cleanup (void) |
| { |
| mpView->HideSdrPage(); |
| } |
| |
| |
| |
| |
| void PreviewRenderer::PaintPage ( |
| const SdPage* pPage, |
| const bool bDisplayPresentationObjects) |
| { |
| // Paint the page. |
| Rectangle aPaintRectangle (Point(0,0), pPage->GetSize()); |
| Region aRegion (aPaintRectangle); |
| |
| // Turn off online spelling and redlining. |
| SdrOutliner* pOutliner = NULL; |
| sal_uLong nSavedControlWord (0); |
| if (mpDocShellOfView!=NULL && mpDocShellOfView->GetDoc()!=NULL) |
| { |
| pOutliner = &mpDocShellOfView->GetDoc()->GetDrawOutliner(); |
| nSavedControlWord = pOutliner->GetControlWord(); |
| pOutliner->SetControlWord((nSavedControlWord & ~EE_CNTRL_ONLINESPELLING)); |
| } |
| |
| // Use a special redirector to prevent PresObj shapes from being painted. |
| boost::scoped_ptr<ViewRedirector> pRedirector; |
| if ( ! bDisplayPresentationObjects) |
| pRedirector.reset(new ViewRedirector()); |
| |
| try |
| { |
| mpView->CompleteRedraw(mpPreviewDevice.get(), aRegion, pRedirector.get()); |
| } |
| catch (const ::com::sun::star::uno::Exception&) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| |
| // Restore the previous online spelling and redlining states. |
| if (pOutliner != NULL) |
| pOutliner->SetControlWord(nSavedControlWord); |
| } |
| |
| |
| |
| |
| void PreviewRenderer::PaintSubstitutionText (const String& rSubstitutionText) |
| { |
| if (rSubstitutionText.Len() > 0) |
| { |
| // Set the font size. |
| const Font& rOriginalFont (mpPreviewDevice->GetFont()); |
| Font aFont (mpPreviewDevice->GetSettings().GetStyleSettings().GetAppFont()); |
| sal_Int32 nHeight (mpPreviewDevice->PixelToLogic(Size(0,snSubstitutionTextSize)).Height()); |
| aFont.SetHeight(nHeight); |
| mpPreviewDevice->SetFont (aFont); |
| |
| // Paint the substitution text. |
| Rectangle aTextBox ( |
| Point(0,0), |
| mpPreviewDevice->PixelToLogic( |
| mpPreviewDevice->GetOutputSizePixel())); |
| sal_uInt16 nTextStyle = |
| TEXT_DRAW_CENTER |
| | TEXT_DRAW_VCENTER |
| | TEXT_DRAW_MULTILINE |
| | TEXT_DRAW_WORDBREAK; |
| mpPreviewDevice->DrawText (aTextBox, rSubstitutionText, nTextStyle); |
| |
| // Restore the font. |
| mpPreviewDevice->SetFont (rOriginalFont); |
| } |
| } |
| |
| |
| |
| |
| void PreviewRenderer::PaintFrame (void) |
| { |
| if (mbHasFrame) |
| { |
| // Paint a frame around the preview. |
| Rectangle aPaintRectangle ( |
| Point(0,0), |
| mpPreviewDevice->GetOutputSizePixel()); |
| mpPreviewDevice->EnableMapMode(sal_False); |
| mpPreviewDevice->SetLineColor(maFrameColor); |
| mpPreviewDevice->SetFillColor(); |
| mpPreviewDevice->DrawRect(aPaintRectangle); |
| mpPreviewDevice->EnableMapMode(sal_True); |
| } |
| } |
| |
| |
| |
| |
| void PreviewRenderer::SetupOutputSize ( |
| const SdPage& rPage, |
| const Size& rFramePixelSize) |
| { |
| // First set the map mode to some arbitrary scale that is numerically |
| // stable. |
| MapMode aMapMode (mpPreviewDevice->GetMapMode()); |
| aMapMode.SetMapUnit(MAP_PIXEL); |
| |
| // Adapt it to the desired width. |
| const Size aPageModelSize (rPage.GetSize()); |
| if (aPageModelSize.Width()>0 || aPageModelSize.Height()>0) |
| { |
| const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0); |
| aMapMode.SetScaleX( |
| Fraction(rFramePixelSize.Width()-2*nFrameWidth-1, aPageModelSize.Width())); |
| aMapMode.SetScaleY( |
| Fraction(rFramePixelSize.Height()-2*nFrameWidth-1, aPageModelSize.Height())); |
| aMapMode.SetOrigin(mpPreviewDevice->PixelToLogic(Point(nFrameWidth,nFrameWidth),aMapMode)); |
| } |
| else |
| { |
| // We should never get here. |
| OSL_ASSERT(false); |
| aMapMode.SetScaleX(1.0); |
| aMapMode.SetScaleY(1.0); |
| } |
| mpPreviewDevice->SetMapMode (aMapMode); |
| mpPreviewDevice->SetOutputSizePixel(rFramePixelSize); |
| } |
| |
| |
| |
| |
| void PreviewRenderer::ProvideView (DrawDocShell* pDocShell) |
| { |
| if (pDocShell != mpDocShellOfView) |
| { |
| // Destroy the view that is connected to the current doc shell. |
| mpView.reset(); |
| |
| // Switch our attention, i.e. listening for DYING events, to |
| // the new doc shell. |
| if (mpDocShellOfView != NULL) |
| EndListening (*mpDocShellOfView); |
| mpDocShellOfView = pDocShell; |
| if (mpDocShellOfView != NULL) |
| StartListening (*mpDocShellOfView); |
| } |
| if (mpView.get() == NULL) |
| { |
| mpView.reset (new DrawView (pDocShell, mpPreviewDevice.get(), NULL)); |
| } |
| mpView->SetPreviewRenderer(true); |
| #if 1 |
| mpView->SetPageVisible(false); |
| mpView->SetPageBorderVisible(true); |
| mpView->SetBordVisible(false); |
| #else |
| // This works in the slide sorter but prevents the master page |
| // background being painted in the list of current master pages in the |
| // task manager. |
| mpView->SetPagePaintingAllowed(false); |
| #endif |
| } |
| |
| |
| |
| |
| Image PreviewRenderer::ScaleBitmap ( |
| const BitmapEx& rBitmapEx, |
| int nWidth) |
| { |
| Image aPreview; |
| |
| do |
| { |
| // Adjust contrast mode. |
| bool bUseContrast = Application::GetSettings().GetStyleSettings(). |
| GetHighContrastMode(); |
| mpPreviewDevice->SetDrawMode (bUseContrast |
| ? ViewShell::OUTPUT_DRAWMODE_CONTRAST |
| : ViewShell::OUTPUT_DRAWMODE_COLOR); |
| |
| // Set output size. |
| Size aSize (rBitmapEx.GetSizePixel()); |
| if (aSize.Width() <= 0) |
| break; |
| Size aFrameSize ( |
| nWidth, |
| (long)((nWidth*1.0 * aSize.Height()) / aSize.Width() + 0.5)); |
| Size aPreviewSize (aFrameSize.Width()-2,aFrameSize.Height()-2); |
| MapMode aMapMode (mpPreviewDevice->GetMapMode()); |
| aMapMode.SetMapUnit(MAP_PIXEL); |
| aMapMode.SetOrigin (Point()); |
| aMapMode.SetScaleX (1.0); |
| aMapMode.SetScaleY (1.0); |
| mpPreviewDevice->SetMapMode (aMapMode); |
| mpPreviewDevice->SetOutputSize (aFrameSize); |
| |
| // Paint a frame around the preview. |
| mpPreviewDevice->SetLineColor (maFrameColor); |
| mpPreviewDevice->SetFillColor (); |
| mpPreviewDevice->DrawRect (Rectangle(Point(0,0), aFrameSize)); |
| |
| // Paint the bitmap scaled to the desired width. |
| BitmapEx aScaledBitmap (rBitmapEx.GetBitmap()); |
| aScaledBitmap.Scale (aPreviewSize, BMP_SCALE_INTERPOLATE); |
| mpPreviewDevice->DrawBitmap ( |
| Point(1,1), |
| aPreviewSize, |
| aScaledBitmap.GetBitmap()); |
| |
| // Get the resulting bitmap. |
| aPreview = mpPreviewDevice->GetBitmap (Point(0,0), aFrameSize); |
| } |
| while (false); |
| |
| return aPreview; |
| } |
| |
| |
| |
| |
| void PreviewRenderer::Notify(SfxBroadcaster&, const SfxHint& rHint) |
| { |
| if (rHint.IsA(TYPE(SfxSimpleHint)) |
| && mpDocShellOfView != NULL) |
| { |
| const SfxSimpleHint* pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint); |
| if (pSimpleHint != NULL |
| && pSimpleHint->GetId() == SFX_HINT_DYING) |
| { |
| // The doc shell is dying. Our view uses its item pool and |
| // has to be destroyed as well. The next call to |
| // ProvideView will create a new one (for another |
| // doc shell, of course.) |
| mpView.reset(); |
| mpDocShellOfView = NULL; |
| } |
| } |
| } |
| |
| |
| |
| |
| //===== ViewRedirector ======================================================== |
| |
| namespace { |
| |
| ViewRedirector::ViewRedirector (void) |
| { |
| } |
| |
| |
| |
| |
| ViewRedirector::~ViewRedirector (void) |
| { |
| } |
| |
| |
| |
| |
| drawinglayer::primitive2d::Primitive2DSequence ViewRedirector::createRedirectedPrimitive2DSequence( |
| const sdr::contact::ViewObjectContact& rOriginal, |
| const sdr::contact::DisplayInfo& rDisplayInfo) |
| { |
| SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject(); |
| |
| if (pObject==NULL || pObject->GetPage() == NULL) |
| { |
| // not a SdrObject visualisation (maybe e.g. page) or no page |
| return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence( |
| rOriginal, |
| rDisplayInfo); |
| } |
| |
| const bool bDoCreateGeometry (pObject->GetPage()->checkVisibility( rOriginal, rDisplayInfo, true)); |
| |
| if ( ! bDoCreateGeometry |
| && (pObject->GetObjInventor() != SdrInventor || pObject->GetObjIdentifier() != OBJ_PAGE)) |
| { |
| return drawinglayer::primitive2d::Primitive2DSequence(); |
| } |
| |
| if (pObject->IsEmptyPresObj()) |
| return drawinglayer::primitive2d::Primitive2DSequence(); |
| |
| return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence( |
| rOriginal, |
| rDisplayInfo); |
| } |
| |
| } // end of anonymous namespace |
| |
| |
| } // end of namespace ::sd |