1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
;
44 const int PreviewRenderer::snSubstitutionTextSize
= 11;
45 const int PreviewRenderer::snFrameWidth
= 1;
48 /** This incarnation of the ViewObjectContactRedirector filters away all
49 PageObj objects, unconditionally.
51 class ViewRedirector
: public ::sdr::contact::ViewObjectContactRedirector
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
,
70 : mpPreviewDevice (new VirtualDevice()),
72 mpDocShellOfView(NULL
),
73 maFrameColor (svtools::ColorConfig().GetColorValue(svtools::DOCBOUNDARIES
).nColor
),
76 if (pTemplate
!= NULL
)
78 mpPreviewDevice
->SetDigitLanguage (pTemplate
->GetDigitLanguage());
79 mpPreviewDevice
->SetBackground(pTemplate
->GetBackground());
83 mpPreviewDevice
->SetBackground(Wallpaper(
84 Application::GetSettings().GetStyleSettings().GetWindowColor()));
91 PreviewRenderer::~PreviewRenderer (void)
93 if (mpDocShellOfView
!= NULL
)
94 EndListening (*mpDocShellOfView
);
100 Image
PreviewRenderer::RenderPage (
102 const sal_Int32 nWidth
,
103 const String
& rSubstitutionText
,
104 const bool bObeyHighContrastMode
,
105 const bool bDisplayPresentationObjects
)
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));
117 Size(nWidth
,nHeight
),
119 bObeyHighContrastMode
,
120 bDisplayPresentationObjects
);
129 Image
PreviewRenderer::RenderPage (
132 const String
& rSubstitutionText
,
133 const bool bObeyHighContrastMode
,
134 const bool bDisplayPresentationObjects
)
142 if (Initialize(pPage
, aPixelSize
, bObeyHighContrastMode
))
144 PaintPage(pPage
, bDisplayPresentationObjects
);
145 PaintSubstitutionText(rSubstitutionText
);
148 Size
aSize (mpPreviewDevice
->GetOutputSizePixel());
149 aPreview
= mpPreviewDevice
->GetBitmap (
150 mpPreviewDevice
->PixelToLogic(Point(0,0)),
151 mpPreviewDevice
->PixelToLogic(aSize
));
156 catch (const com::sun::star::uno::Exception
&)
158 DBG_UNHANDLED_EXCEPTION();
168 Image
PreviewRenderer::RenderSubstitution (
169 const Size
& rPreviewPixelSize
,
170 const String
& rSubstitutionText
)
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
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 (
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
);
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();
229 bool PreviewRenderer::Initialize (
231 const Size
& rPixelSize
,
232 const bool bObeyHighContrastMode
)
237 SdrModel
* pModel
= pPage
->GetModel();
241 SetupOutputSize(*pPage
, rPixelSize
);
243 SdDrawDocument
* pDocument
244 = static_cast<SdDrawDocument
*>(pPage
->GetModel());
245 DrawDocShell
* pDocShell
= pDocument
->GetDocSh();
248 ProvideView (pDocShell
);
249 if (mpView
.get() == NULL
)
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()));
268 mpView
->ShowSdrPage(pNonConstPage
);
271 // Make sure that a page view exists.
272 SdrPageView
* pPageView
= mpView
->GetSdrPageView();
274 if (pPageView
== NULL
)
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();
295 void PreviewRenderer::Cleanup (void)
297 mpView
->HideSdrPage();
303 void PreviewRenderer::PaintPage (
305 const bool bDisplayPresentationObjects
)
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.
357 mpPreviewDevice
->PixelToLogic(
358 mpPreviewDevice
->GetOutputSizePixel()));
359 sal_uInt16 nTextStyle
=
362 | TEXT_DRAW_MULTILINE
363 | TEXT_DRAW_WORDBREAK
;
364 mpPreviewDevice
->DrawText (aTextBox
, rSubstitutionText
, nTextStyle
);
367 mpPreviewDevice
->SetFont (rOriginalFont
);
374 void PreviewRenderer::PaintFrame (void)
378 // Paint a frame arround the preview.
379 Rectangle
aPaintRectangle (
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 (
395 const Size
& rFramePixelSize
)
397 // First set the map mode to some arbitrary scale that is numerically
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);
408 Fraction(rFramePixelSize
.Width()-2*nFrameWidth
-1, aPageModelSize
.Width()));
410 Fraction(rFramePixelSize
.Height()-2*nFrameWidth
-1, aPageModelSize
.Height()));
411 aMapMode
.SetOrigin(mpPreviewDevice
->PixelToLogic(Point(nFrameWidth
,nFrameWidth
),aMapMode
));
415 // We should never get here.
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.
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);
448 mpView
->SetPageVisible(false);
449 mpView
->SetPageBorderVisible(true);
450 mpView
->SetBordVisible(false);
451 mpView
->SetGridVisible(false);
452 mpView
->SetHlplVisible(false);
453 mpView
->SetGlueVisible(false);
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
459 mpView
->SetPagePaintingAllowed(false);
466 Image
PreviewRenderer::ScaleBitmap (
467 const BitmapEx
& rBitmapEx
,
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
);
482 Size
aSize (rBitmapEx
.GetSizePixel());
483 if (aSize
.Width() <= 0)
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 (
508 aScaledBitmap
.GetBitmap());
510 // Get the resulting bitmap.
511 aPreview
= mpPreviewDevice
->GetBitmap (Point(0,0), aFrameSize
);
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.)
535 mpDocShellOfView
= NULL
;
543 //===== ViewRedirector ========================================================
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(
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(
591 } // end of anonymous namespace
594 } // end of namespace ::sd
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */