bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / ui / tools / PreviewRenderer.cxx
blob9a355aa148e2fe46946cbce7162b3f252eb32e7b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "PreviewRenderer.hxx"
23 #include "DrawDocShell.hxx"
24 #include "drawdoc.hxx"
25 #include "drawview.hxx"
26 #include "sdpage.hxx"
27 #include "ViewShell.hxx"
28 #include <vcl/virdev.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/svdoutl.hxx>
31 #include <editeng/eeitem.hxx>
32 #include <editeng/editstat.hxx>
33 #include <vcl/svapp.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <svx/sdr/contact/viewobjectcontact.hxx>
36 #include <svx/sdr/contact/viewcontact.hxx>
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
42 namespace sd {
44 const int PreviewRenderer::snSubstitutionTextSize = 11;
45 const int PreviewRenderer::snFrameWidth = 1;
47 namespace {
48 /** This incarnation of the ViewObjectContactRedirector filters away all
49 PageObj objects, unconditionally.
51 class ViewRedirector : public ::sdr::contact::ViewObjectContactRedirector
53 public:
54 ViewRedirector (void);
55 virtual ~ViewRedirector (void);
56 virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence(
57 const sdr::contact::ViewObjectContact& rOriginal,
58 const sdr::contact::DisplayInfo& rDisplayInfo);
65 //===== PreviewRenderer =======================================================
67 PreviewRenderer::PreviewRenderer (
68 OutputDevice* pTemplate,
69 const bool bHasFrame)
70 : mpPreviewDevice (new VirtualDevice()),
71 mpView(NULL),
72 mpDocShellOfView(NULL),
73 maFrameColor (svtools::ColorConfig().GetColorValue(svtools::DOCBOUNDARIES).nColor),
74 mbHasFrame(bHasFrame)
76 if (pTemplate != NULL)
78 mpPreviewDevice->SetDigitLanguage (pTemplate->GetDigitLanguage());
79 mpPreviewDevice->SetBackground(pTemplate->GetBackground());
81 else
83 mpPreviewDevice->SetBackground(Wallpaper(
84 Application::GetSettings().GetStyleSettings().GetWindowColor()));
91 PreviewRenderer::~PreviewRenderer (void)
93 if (mpDocShellOfView != NULL)
94 EndListening (*mpDocShellOfView);
100 Image PreviewRenderer::RenderPage (
101 const SdPage* pPage,
102 const sal_Int32 nWidth,
103 const String& rSubstitutionText,
104 const bool bObeyHighContrastMode,
105 const bool bDisplayPresentationObjects)
107 if (pPage != NULL)
109 const Size aPageModelSize (pPage->GetSize());
110 const double nAspectRatio (
111 double(aPageModelSize.Width()) / double(aPageModelSize.Height()));
112 const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0);
113 const sal_Int32 nHeight (sal::static_int_cast<sal_Int32>(
114 (nWidth - 2*nFrameWidth) / nAspectRatio + 2*nFrameWidth + 0.5));
115 return RenderPage (
116 pPage,
117 Size(nWidth,nHeight),
118 rSubstitutionText,
119 bObeyHighContrastMode,
120 bDisplayPresentationObjects);
122 else
123 return Image();
129 Image PreviewRenderer::RenderPage (
130 const SdPage* pPage,
131 Size aPixelSize,
132 const String& rSubstitutionText,
133 const bool bObeyHighContrastMode,
134 const bool bDisplayPresentationObjects)
136 Image aPreview;
138 if (pPage != NULL)
142 if (Initialize(pPage, aPixelSize, bObeyHighContrastMode))
144 PaintPage(pPage, bDisplayPresentationObjects);
145 PaintSubstitutionText(rSubstitutionText);
146 PaintFrame();
148 Size aSize (mpPreviewDevice->GetOutputSizePixel());
149 aPreview = mpPreviewDevice->GetBitmap (
150 mpPreviewDevice->PixelToLogic(Point(0,0)),
151 mpPreviewDevice->PixelToLogic(aSize));
153 Cleanup();
156 catch (const com::sun::star::uno::Exception&)
158 DBG_UNHANDLED_EXCEPTION();
162 return aPreview;
168 Image PreviewRenderer::RenderSubstitution (
169 const Size& rPreviewPixelSize,
170 const String& rSubstitutionText)
172 Image aPreview;
176 // Set size.
177 mpPreviewDevice->SetOutputSizePixel(rPreviewPixelSize);
179 // Adjust contrast mode.
180 const bool bUseContrast (
181 Application::GetSettings().GetStyleSettings().GetHighContrastMode());
182 mpPreviewDevice->SetDrawMode (bUseContrast
183 ? ViewShell::OUTPUT_DRAWMODE_CONTRAST
184 : ViewShell::OUTPUT_DRAWMODE_COLOR);
186 // Set a map mode that makes a typical substitution text completely
187 // visible.
188 MapMode aMapMode (mpPreviewDevice->GetMapMode());
189 aMapMode.SetMapUnit(MAP_100TH_MM);
190 const double nFinalScale (25.0 * rPreviewPixelSize.Width() / 28000.0);
191 aMapMode.SetScaleX(nFinalScale);
192 aMapMode.SetScaleY(nFinalScale);
193 const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0);
194 aMapMode.SetOrigin(mpPreviewDevice->PixelToLogic(
195 Point(nFrameWidth,nFrameWidth),aMapMode));
196 mpPreviewDevice->SetMapMode (aMapMode);
198 // Clear the background.
199 const Rectangle aPaintRectangle (
200 Point(0,0),
201 mpPreviewDevice->GetOutputSizePixel());
202 mpPreviewDevice->EnableMapMode(sal_False);
203 mpPreviewDevice->SetLineColor();
204 svtools::ColorConfig aColorConfig;
205 mpPreviewDevice->SetFillColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
206 mpPreviewDevice->DrawRect (aPaintRectangle);
207 mpPreviewDevice->EnableMapMode(sal_True);
209 // Paint substitution text and a frame around it.
210 PaintSubstitutionText (rSubstitutionText);
211 PaintFrame();
213 const Size aSize (mpPreviewDevice->GetOutputSizePixel());
214 aPreview = mpPreviewDevice->GetBitmap (
215 mpPreviewDevice->PixelToLogic(Point(0,0)),
216 mpPreviewDevice->PixelToLogic(aSize));
218 catch (const com::sun::star::uno::Exception&)
220 DBG_UNHANDLED_EXCEPTION();
223 return aPreview;
229 bool PreviewRenderer::Initialize (
230 const SdPage* pPage,
231 const Size& rPixelSize,
232 const bool bObeyHighContrastMode)
234 if (pPage == NULL)
235 return false;
237 SdrModel* pModel = pPage->GetModel();
238 if (pModel == NULL)
239 return false;
241 SetupOutputSize(*pPage, rPixelSize);
243 SdDrawDocument* pDocument
244 = static_cast<SdDrawDocument*>(pPage->GetModel());
245 DrawDocShell* pDocShell = pDocument->GetDocSh();
247 // Create view
248 ProvideView (pDocShell);
249 if (mpView.get() == NULL)
250 return false;
252 // Adjust contrast mode.
253 bool bUseContrast (bObeyHighContrastMode
254 && Application::GetSettings().GetStyleSettings().GetHighContrastMode());
255 mpPreviewDevice->SetDrawMode (bUseContrast
256 ? ViewShell::OUTPUT_DRAWMODE_CONTRAST
257 : ViewShell::OUTPUT_DRAWMODE_COLOR);
258 mpPreviewDevice->SetSettings(Application::GetSettings());
260 // Tell the view to show the given page.
261 SdPage* pNonConstPage = const_cast<SdPage*>(pPage);
262 if (pPage->IsMasterPage())
264 mpView->ShowSdrPage(mpView->GetModel()->GetMasterPage(pPage->GetPageNum()));
266 else
268 mpView->ShowSdrPage(pNonConstPage);
271 // Make sure that a page view exists.
272 SdrPageView* pPageView = mpView->GetSdrPageView();
274 if (pPageView == NULL)
275 return false;
277 // Set background color of page view and outliner.
278 svtools::ColorConfig aColorConfig;
279 const Color aPageBackgroundColor(pPage->GetPageBackgroundColor(pPageView));
280 pPageView->SetApplicationBackgroundColor(aPageBackgroundColor);
281 SdrOutliner& rOutliner (pDocument->GetDrawOutliner(NULL));
282 rOutliner.SetBackgroundColor(aPageBackgroundColor);
283 rOutliner.SetDefaultLanguage(pDocument->GetLanguage(EE_CHAR_LANGUAGE));
284 mpView->SetApplicationBackgroundColor(
285 Color(aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor));
286 mpPreviewDevice->SetBackground(Wallpaper(aPageBackgroundColor));
287 mpPreviewDevice->Erase();
289 return true;
295 void PreviewRenderer::Cleanup (void)
297 mpView->HideSdrPage();
303 void PreviewRenderer::PaintPage (
304 const SdPage* pPage,
305 const bool bDisplayPresentationObjects)
307 // Paint the page.
308 Rectangle aPaintRectangle (Point(0,0), pPage->GetSize());
309 Region aRegion (aPaintRectangle);
311 // Turn off online spelling and redlining.
312 SdrOutliner* pOutliner = NULL;
313 sal_uLong nSavedControlWord (0);
314 if (mpDocShellOfView!=NULL && mpDocShellOfView->GetDoc()!=NULL)
316 pOutliner = &mpDocShellOfView->GetDoc()->GetDrawOutliner();
317 nSavedControlWord = pOutliner->GetControlWord();
318 pOutliner->SetControlWord((nSavedControlWord & ~EE_CNTRL_ONLINESPELLING));
321 // Use a special redirector to prevent PresObj shapes from being painted.
322 boost::scoped_ptr<ViewRedirector> pRedirector;
323 if ( ! bDisplayPresentationObjects)
324 pRedirector.reset(new ViewRedirector());
328 mpView->CompleteRedraw(mpPreviewDevice.get(), aRegion, pRedirector.get());
330 catch (const ::com::sun::star::uno::Exception&)
332 DBG_UNHANDLED_EXCEPTION();
335 // Restore the previous online spelling and redlining states.
336 if (pOutliner != NULL)
337 pOutliner->SetControlWord(nSavedControlWord);
343 void PreviewRenderer::PaintSubstitutionText (const String& rSubstitutionText)
345 if (rSubstitutionText.Len() > 0)
347 // Set the font size.
348 const Font& rOriginalFont (mpPreviewDevice->GetFont());
349 Font aFont (mpPreviewDevice->GetSettings().GetStyleSettings().GetAppFont());
350 sal_Int32 nHeight (mpPreviewDevice->PixelToLogic(Size(0,snSubstitutionTextSize)).Height());
351 aFont.SetHeight(nHeight);
352 mpPreviewDevice->SetFont (aFont);
354 // Paint the substitution text.
355 Rectangle aTextBox (
356 Point(0,0),
357 mpPreviewDevice->PixelToLogic(
358 mpPreviewDevice->GetOutputSizePixel()));
359 sal_uInt16 nTextStyle =
360 TEXT_DRAW_CENTER
361 | TEXT_DRAW_VCENTER
362 | TEXT_DRAW_MULTILINE
363 | TEXT_DRAW_WORDBREAK;
364 mpPreviewDevice->DrawText (aTextBox, rSubstitutionText, nTextStyle);
366 // Restore the font.
367 mpPreviewDevice->SetFont (rOriginalFont);
374 void PreviewRenderer::PaintFrame (void)
376 if (mbHasFrame)
378 // Paint a frame arround the preview.
379 Rectangle aPaintRectangle (
380 Point(0,0),
381 mpPreviewDevice->GetOutputSizePixel());
382 mpPreviewDevice->EnableMapMode(sal_False);
383 mpPreviewDevice->SetLineColor(maFrameColor);
384 mpPreviewDevice->SetFillColor();
385 mpPreviewDevice->DrawRect(aPaintRectangle);
386 mpPreviewDevice->EnableMapMode(sal_True);
393 void PreviewRenderer::SetupOutputSize (
394 const SdPage& rPage,
395 const Size& rFramePixelSize)
397 // First set the map mode to some arbitrary scale that is numerically
398 // stable.
399 MapMode aMapMode (mpPreviewDevice->GetMapMode());
400 aMapMode.SetMapUnit(MAP_PIXEL);
402 // Adapt it to the desired width.
403 const Size aPageModelSize (rPage.GetSize());
404 if (aPageModelSize.Width()>0 || aPageModelSize.Height()>0)
406 const sal_Int32 nFrameWidth (mbHasFrame ? snFrameWidth : 0);
407 aMapMode.SetScaleX(
408 Fraction(rFramePixelSize.Width()-2*nFrameWidth-1, aPageModelSize.Width()));
409 aMapMode.SetScaleY(
410 Fraction(rFramePixelSize.Height()-2*nFrameWidth-1, aPageModelSize.Height()));
411 aMapMode.SetOrigin(mpPreviewDevice->PixelToLogic(Point(nFrameWidth,nFrameWidth),aMapMode));
413 else
415 // We should never get here.
416 OSL_ASSERT(false);
417 aMapMode.SetScaleX(1.0);
418 aMapMode.SetScaleY(1.0);
420 mpPreviewDevice->SetMapMode (aMapMode);
421 mpPreviewDevice->SetOutputSizePixel(rFramePixelSize);
427 void PreviewRenderer::ProvideView (DrawDocShell* pDocShell)
429 if (pDocShell != mpDocShellOfView)
431 // Destroy the view that is connected to the current doc shell.
432 mpView.reset (NULL);
434 // Switch our attention, i.e. listening for DYING events, to
435 // the new doc shell.
436 if (mpDocShellOfView != NULL)
437 EndListening (*mpDocShellOfView);
438 mpDocShellOfView = pDocShell;
439 if (mpDocShellOfView != NULL)
440 StartListening (*mpDocShellOfView);
442 if (mpView.get() == NULL)
444 mpView.reset (new DrawView (pDocShell, mpPreviewDevice.get(), NULL));
446 mpView->SetPreviewRenderer(true);
447 #if 1
448 mpView->SetPageVisible(false);
449 mpView->SetPageBorderVisible(true);
450 mpView->SetBordVisible(false);
451 mpView->SetGridVisible(false);
452 mpView->SetHlplVisible(false);
453 mpView->SetGlueVisible(false);
455 #else
456 // This works in the slide sorter but prevents the master page
457 // background being painted in the list of current master pages in the
458 // task manager.
459 mpView->SetPagePaintingAllowed(false);
460 #endif
466 Image PreviewRenderer::ScaleBitmap (
467 const BitmapEx& rBitmapEx,
468 int nWidth)
470 Image aPreview;
474 // Adjust contrast mode.
475 bool bUseContrast = Application::GetSettings().GetStyleSettings().
476 GetHighContrastMode();
477 mpPreviewDevice->SetDrawMode (bUseContrast
478 ? ViewShell::OUTPUT_DRAWMODE_CONTRAST
479 : ViewShell::OUTPUT_DRAWMODE_COLOR);
481 // Set output size.
482 Size aSize (rBitmapEx.GetSizePixel());
483 if (aSize.Width() <= 0)
484 break;
485 Size aFrameSize (
486 nWidth,
487 (long)((nWidth*1.0 * aSize.Height()) / aSize.Width() + 0.5));
488 Size aPreviewSize (aFrameSize.Width()-2,aFrameSize.Height()-2);
489 MapMode aMapMode (mpPreviewDevice->GetMapMode());
490 aMapMode.SetMapUnit(MAP_PIXEL);
491 aMapMode.SetOrigin (Point());
492 aMapMode.SetScaleX (1.0);
493 aMapMode.SetScaleY (1.0);
494 mpPreviewDevice->SetMapMode (aMapMode);
495 mpPreviewDevice->SetOutputSize (aFrameSize);
497 // Paint a frame arround the preview.
498 mpPreviewDevice->SetLineColor (maFrameColor);
499 mpPreviewDevice->SetFillColor ();
500 mpPreviewDevice->DrawRect (Rectangle(Point(0,0), aFrameSize));
502 // Paint the bitmap scaled to the desired width.
503 BitmapEx aScaledBitmap (rBitmapEx.GetBitmap());
504 aScaledBitmap.Scale (aPreviewSize, BMP_SCALE_BESTQUALITY);
505 mpPreviewDevice->DrawBitmap (
506 Point(1,1),
507 aPreviewSize,
508 aScaledBitmap.GetBitmap());
510 // Get the resulting bitmap.
511 aPreview = mpPreviewDevice->GetBitmap (Point(0,0), aFrameSize);
513 while (false);
515 return aPreview;
521 void PreviewRenderer::Notify(SfxBroadcaster&, const SfxHint& rHint)
523 if (rHint.IsA(TYPE(SfxSimpleHint))
524 && mpDocShellOfView != NULL)
526 const SfxSimpleHint* pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
527 if (pSimpleHint != NULL
528 && pSimpleHint->GetId() == SFX_HINT_DYING)
530 // The doc shell is dying. Our view uses its item pool and
531 // has to be destroyed as well. The next call to
532 // ProvideView will create a new one (for another
533 // doc shell, of course.)
534 mpView.reset (NULL);
535 mpDocShellOfView = NULL;
543 //===== ViewRedirector ========================================================
545 namespace {
547 ViewRedirector::ViewRedirector (void)
554 ViewRedirector::~ViewRedirector (void)
561 drawinglayer::primitive2d::Primitive2DSequence ViewRedirector::createRedirectedPrimitive2DSequence(
562 const sdr::contact::ViewObjectContact& rOriginal,
563 const sdr::contact::DisplayInfo& rDisplayInfo)
565 SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
567 if (pObject==NULL || pObject->GetPage() == NULL)
569 // not a SdrObject visualisation (maybe e.g. page) or no page
570 return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(
571 rOriginal,
572 rDisplayInfo);
575 const bool bDoCreateGeometry (pObject->GetPage()->checkVisibility( rOriginal, rDisplayInfo, true));
577 if ( ! bDoCreateGeometry
578 && (pObject->GetObjInventor() != SdrInventor || pObject->GetObjIdentifier() != OBJ_PAGE))
580 return drawinglayer::primitive2d::Primitive2DSequence();
583 if (pObject->IsEmptyPresObj())
584 return drawinglayer::primitive2d::Primitive2DSequence();
586 return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(
587 rOriginal,
588 rDisplayInfo);
591 } // end of anonymous namespace
594 } // end of namespace ::sd
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */