diff options
author | Vladimir Glazounov <vg@openoffice.org> | 2008-08-19 23:19:35 +0000 |
---|---|---|
committer | Vladimir Glazounov <vg@openoffice.org> | 2008-08-19 23:19:35 +0000 |
commit | 72986334357beb4d0138c2fc6279ec84f06faf91 (patch) | |
tree | 02d24ad6042144b317772ce9328acddccfb8ecb5 /sd/source | |
parent | a628c45deff70f16afc187c1f1cad575a9091e28 (diff) |
INTEGRATION: CWS aw033 (1.15.14); FILE MERGED
2008/07/10 12:56:27 aw 1.15.14.24: #i39532# XOutputDevice removed, PrepareDelete removed
2008/07/01 15:38:18 aw 1.15.14.23: #i39532# higher granularity for SDrPageObject primitives
2008/06/24 15:34:31 aw 1.15.14.22: #i39532# corrections
2008/05/27 15:18:03 aw 1.15.14.21: #i39532# changes DEV300 m12 resync corrections
2008/05/16 13:06:05 aw 1.15.14.20: adaptions after resync
2008/05/14 14:51:30 aw 1.15.14.19: RESYNC: (1.20-1.22); FILE MERGED
2008/04/16 05:03:51 aw 1.15.14.18: #i39532# corrected primitive creation callback
2008/03/14 14:02:06 cl 1.15.14.17: RESYNC: (1.19-1.20); FILE MERGED
2008/01/29 10:34:21 aw 1.15.14.16: updated refresh for ActionChanged(), diverse removals
2008/01/22 12:16:42 aw 1.15.14.15: adaptions and 1st stripping
2007/11/07 14:42:37 aw 1.15.14.14: #i39532# committing to have a base for HDU
2007/10/23 10:05:48 aw 1.15.14.13: #i39532# adapted frame around SlideNumber when excluded and shortened SlideName when space is to small
2007/10/22 10:26:50 aw 1.15.14.12: #i39523# joined #i82710# and adaptions to primitives
2007/10/16 15:49:46 aw 1.15.14.11: #i39532# Finetuning
2007/10/04 14:31:13 aw 1.15.14.10: #i39532# slightly changed to avoid zooming the preview bitmap
2007/08/09 15:27:14 aw 1.15.14.9: RESYNC: (1.18-1.19); FILE MERGED
2007/07/06 13:46:12 aw 1.15.14.8: #i39532# moved from Primitive2DReference to Primitive2DSequence where possible to avoid extra-group primitive creations and deeper hierarchies as necessary
2007/03/06 12:40:29 aw 1.15.14.7: #i39532#
2007/01/19 12:21:06 aw 1.15.14.6: RESYNC: (1.17-1.18); FILE MERGED
2006/11/28 16:56:18 aw 1.15.14.5: RESYNC: (1.16-1.17); FILE MERGED
2006/11/28 11:13:41 aw 1.15.14.4: #i39532#
2006/11/09 17:04:09 aw 1.15.14.3: #i39532# Prepared PageObjectViewObjectContact for primitive usage, see comments there.
2006/09/26 16:30:06 aw 1.15.14.2: RESYNC: (1.15-1.16); FILE MERGED
2006/05/16 14:56:15 aw 1.15.14.1: handish adaptions after resync
Diffstat (limited to 'sd/source')
-rw-r--r-- | sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx | 1316 |
1 files changed, 835 insertions, 481 deletions
diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx index 94813495acc9..482b6ead2e6b 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: SlsPageObjectViewObjectContact.cxx,v $ - * $Revision: 1.22 $ + * $Revision: 1.23 $ * * This file is part of OpenOffice.org. * @@ -37,7 +37,6 @@ #include "view/SlsPageObjectViewContact.hxx" #include "view/SlsPageObject.hxx" #include "view/SlsFontProvider.hxx" -#include "view/SlsPageNotificationObjectContact.hxx" #include "model/SlsPageDescriptor.hxx" #include "cache/SlsPageCache.hxx" #include "cache/SlsPageCacheManager.hxx" @@ -52,7 +51,6 @@ #include <svx/sdr/contact/displayinfo.hxx> #include <svx/sdr/contact/viewcontact.hxx> #include <svx/svdopage.hxx> -#include <svx/xoutx.hxx> #include <svx/svdpagv.hxx> #include <svx/xlndsit.hxx> #include <svx/xlnclit.hxx> @@ -88,13 +86,11 @@ PageObjectViewObjectContact::PageObjectViewObjectContact ( ViewContact& rViewContact, const ::boost::shared_ptr<cache::PageCache>& rpCache, const ::boost::shared_ptr<controller::Properties>& rpProperties) - : ViewObjectContact (rObjectContact, rViewContact), - mpPageDescriptor(GetPageDescriptor()), - mbIsValid(true), - mbInPrepareDelete(false), + : ViewObjectContactOfPageObj(rObjectContact, rViewContact), + mbInDestructor(false), mbIsBackgroundColorUpdatePending(true), + mxCurrentPageContents(), mpCache(rpCache), - mpNotifier(NULL), mpProperties(rpProperties), maBackgroundColor() { @@ -109,16 +105,18 @@ PageObjectViewObjectContact::PageObjectViewObjectContact ( PageObjectViewObjectContact::~PageObjectViewObjectContact (void) { + mbInDestructor = true; + + GetPageDescriptor()->SetViewObjectContact(NULL); + if (mpCache.get() != NULL) { - mpCache->ReleasePreviewBitmap(GetPage()); - } + const SdrPage* pPage = GetPage(); - if (mpNotifier.get() != NULL) - { - mbInPrepareDelete = true; - mpNotifier->PrepareDelete(); - mpNotifier.reset(); + if(pPage) + { + mpCache->ReleasePreviewBitmap(GetPage()); + } } } @@ -139,18 +137,27 @@ Rectangle PageObjectViewObjectContact::GetBoundingBox ( CoordinateSystem eCoordinateSystem) const { // Most of the bounding boxes are based on the bounding box of the preview. - Rectangle aBoundingBox (static_cast<PageObjectViewContact&>(GetViewContact() - ).GetPageObject().GetCurrentBoundRect()); + // SdrPageObj is a SdrObject, so use SdrObject::aOutRect as model data + const PageObjectViewContact& rPaObVOC(static_cast<PageObjectViewContact&>(GetViewContact())); + Rectangle aBoundingBox(rPaObVOC.GetPageObject().GetLastBoundRect()); CoordinateSystem eCurrentCoordinateSystem (ModelCoordinateSystem); switch(eType) { case PageObjectBoundingBox: - aBoundingBox = GetViewContact().GetPaintRectangle(); + { + const SvBorder aPageDescriptorBorder(GetPageDescriptor()->GetModelBorder()); + aBoundingBox.Left() -= aPageDescriptorBorder.Left(); + aBoundingBox.Top() -= aPageDescriptorBorder.Top(); + aBoundingBox.Right() += aPageDescriptorBorder.Right(); + aBoundingBox.Bottom() += aPageDescriptorBorder.Bottom(); break; + } case PreviewBoundingBox: + { // The aBoundingBox already has the right value. break; + } case MouseOverIndicatorBoundingBox: { const sal_Int32 nBorderWidth (mnMouseOverEffectOffset+mnMouseOverEffectThickness); @@ -225,376 +232,914 @@ Rectangle PageObjectViewObjectContact::GetBoundingBox ( return aBoundingBox; } +/////////////////////////////////////////////////////////////////////////////////////////////// +// example implementation for primitive usage for PageObjectViewObjectContact +} } } // end of namespace ::sd::slidesorter::view +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <sd_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <svx/sdr/contact/objectcontact.hxx> -BitmapEx PageObjectViewObjectContact::CreatePreview (OutputDevice& rDevice) const -{ - const SdPage* pPage = static_cast<const SdPage*>(GetPage()); - Rectangle aPreviewPixelBox (GetBoundingBox(rDevice,PreviewBoundingBox,PixelCoordinateSystem)); +namespace sd { namespace slidesorter { namespace view { - PreviewRenderer aRenderer(&rDevice); - Image aPreview (aRenderer.RenderPage( - pPage, - aPreviewPixelBox.GetSize(), - String())); +/////////////////////////////////////////////////////////////////////////////////////////////// +// All primitives for SdrPageObject visualisation are based on one range which describes +// the size of the inner rectangle for PagePreview visualisation. Use a common implementation +// class for all derived SdPageObjectPrimitives. The SdPageObjectBasePrimitive itself +// is pure virtual - return aPreview.GetBitmapEx(); -} +class SdPageObjectBasePrimitive : public drawinglayer::primitive2d::BasePrimitive2D +{ +private: + // the inner range of the SdPageObject visualisation + basegfx::B2DRange maRange; +public: + // constructor and destructor + SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange); + virtual ~SdPageObjectBasePrimitive(); + // data access + const basegfx::B2DRange& getPageObjectRange() const { return maRange; } + // compare operator + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const; +}; -BitmapEx PageObjectViewObjectContact::GetPreview ( - OutputDevice& rDevice, - const Rectangle& rNewSizePixel) +SdPageObjectBasePrimitive::SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange) +: drawinglayer::primitive2d::BasePrimitive2D(), + maRange(rRange) { - BitmapEx aBitmap; +} - try - { - if (mbIsValid) - { - if (mpCache != NULL) - { - aBitmap = mpCache->GetPreviewBitmap( - GetPage(), - rNewSizePixel.GetSize()); - mpCache->SetPreciousFlag(GetPage(), true); - } - else - aBitmap = CreatePreview(rDevice); - } - } - catch (const ::com::sun::star::uno::Exception&) +SdPageObjectBasePrimitive::~SdPageObjectBasePrimitive() +{ +} + +bool SdPageObjectBasePrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(drawinglayer::primitive2d::BasePrimitive2D::operator==(rPrimitive)) { - OSL_TRACE("PageObjectViewObjectContact::GetPreview: caught exception"); + const SdPageObjectBasePrimitive& rCompare = static_cast< const SdPageObjectBasePrimitive& >(rPrimitive); + return (getPageObjectRange() == rCompare.getPageObjectRange()); } - return aBitmap; + return false; } +/////////////////////////////////////////////////////////////////////////////////////////////// +// SdPageObjectPrimitive for selected visualisation + +class SdPageObjectPageBitmapPrimitive : public SdPageObjectBasePrimitive +{ +private: + // the bitmap containing the PagePreview + BitmapEx maBitmapEx; + +protected: + // method which is to be used to implement the local decomposition of a 2D primitive. + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; + +public: + // constructor and destructor + SdPageObjectPageBitmapPrimitive( + const basegfx::B2DRange& rRange, + const BitmapEx& rBitmapEx); + ~SdPageObjectPageBitmapPrimitive(); + // data access + const BitmapEx& getBitmapEx() const { return maBitmapEx; } + // compare operator + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const; -void PageObjectViewObjectContact::PaintObject (DisplayInfo& rDisplayInfo) + // provide unique ID + DeclPrimitrive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence SdPageObjectPageBitmapPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const { - try - { - // Make sure that our notification object contact exists... - if (mpNotifier.get() == NULL) - { - SdrPage* pPage = const_cast<SdrPage*>(GetPage()); - mpNotifier.reset(new PageNotificationObjectContact(*pPage, *this)); - } - // ...and that it has a valid contact object hierarchy. - mpNotifier->EnsureValidDrawHierarchy(rDisplayInfo); - - OutputDevice* pDevice = rDisplayInfo.GetOutputDevice(); - // Check if buffering can and shall be done. - if (pDevice != NULL - && !rDisplayInfo.OutputToPrinter() - && !rDisplayInfo.OutputToRecordingMetaFile() - && rDisplayInfo.IsBufferingAllowed() - && mbIsValid) - { - // Transform the page borders from pixel coordinates to model - // coordinates and tell the view contact object about them. It - // would be nice if we had to do this only once (better yet not at - // all). - GetViewContact().InvalidatePaintRectangle(); + // add bitmap primitive + // to avoid scaling, use the Bitmap pixel size as primitive size + basegfx::B2DHomMatrix aBitmapTransform; + const Size aBitmapSize(getBitmapEx().GetSizePixel()); + const basegfx::B2DVector aBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1)); + + // short form for scale and translate transformation + aBitmapTransform.set(0L, 0L, aBitmapSizeLogic.getX()); + aBitmapTransform.set(1L, 1L, aBitmapSizeLogic.getY()); + aBitmapTransform.set(0L, 2L, getPageObjectRange().getMinX()); + aBitmapTransform.set(1L, 2L, getPageObjectRange().getMinY()); + + // add a BitmapPrimitive2D to the result + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::BitmapPrimitive2D(getBitmapEx(), aBitmapTransform)); + return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); +} - // Set state flags. This overrides results from a contained - // call to PaintObject(..). - mbIsPainted = sal_True; +SdPageObjectPageBitmapPrimitive::SdPageObjectPageBitmapPrimitive( + const basegfx::B2DRange& rRange, + const BitmapEx& rBitmapEx) +: SdPageObjectBasePrimitive(rRange), + maBitmapEx(rBitmapEx) +{ +} - PaintContent(*pDevice); +SdPageObjectPageBitmapPrimitive::~SdPageObjectPageBitmapPrimitive() +{ +} - // set painted rectangle - maPaintedRectangle = GetViewContact().GetPaintRectangle(); - } - else - { - // paint normal, bitmap not available. Call parent. - ViewObjectContact::PaintObject(rDisplayInfo); - } - } - catch (const com::sun::star::uno::Exception&) +bool SdPageObjectPageBitmapPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(SdPageObjectBasePrimitive::operator==(rPrimitive)) { - OSL_TRACE("PageObjectViewObjectContact::PaintObject: caught exception"); - // Even though the object was not painted completely we set the - // state flags as if that has happened. We do this in order to - // avoid frequent repaints because when painting failed this time it - // may fail the next time, too. - mbIsPainted = sal_True; + const SdPageObjectPageBitmapPrimitive& rCompare = static_cast< const SdPageObjectPageBitmapPrimitive& >(rPrimitive); + return (getBitmapEx() == rCompare.getBitmapEx()); } -} + return false; +} +ImplPrimitrive2DIDBlock(SdPageObjectPageBitmapPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTPAGEBITMAPPRIMITIVE) +/////////////////////////////////////////////////////////////////////////////////////////////// +// SdPageObjectPrimitive for selected visualisation -void PageObjectViewObjectContact::PrepareDelete (void) +class SdPageObjectSelectPrimitive : public SdPageObjectBasePrimitive { - mbIsValid = false; - mbInPrepareDelete = true; +private: + /// Gap between border of page object and inside of selection rectangle. + static const sal_Int32 mnSelectionIndicatorOffset; - GetPageDescriptor()->SetViewObjectContact(NULL); + /// Thickness of the selection rectangle. + static const sal_Int32 mnSelectionIndicatorThickness; - if (mpCache != NULL) - mpCache->ReleasePreviewBitmap(GetPage()); +protected: + // method which is to be used to implement the local decomposition of a 2D primitive. + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; - ViewObjectContact::PrepareDelete(); +public: + // constructor and destructor + SdPageObjectSelectPrimitive(const basegfx::B2DRange& rRange); + ~SdPageObjectSelectPrimitive(); - mbInPrepareDelete = false; -} + // provide unique ID + DeclPrimitrive2DIDBlock() +}; +const sal_Int32 SdPageObjectSelectPrimitive::mnSelectionIndicatorOffset(1); +const sal_Int32 SdPageObjectSelectPrimitive::mnSelectionIndicatorThickness(3); +drawinglayer::primitive2d::Primitive2DSequence SdPageObjectSelectPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const +{ + drawinglayer::primitive2d::Primitive2DSequence xRetval(2); + + // since old Width/Height calculations always added a single pixel value, + // it is necessary to create a inner range which is one display unit less + // at the bottom right. + const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const basegfx::B2DRange aAdaptedInnerRange( + getPageObjectRange().getMinX(), getPageObjectRange().getMinY(), + getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY()); + + // PaintSelectionIndicator replacement. Grow by offset first + basegfx::B2DRange aDiscreteOuterRange(aAdaptedInnerRange); + aDiscreteOuterRange.grow(mnSelectionIndicatorOffset * aDiscretePixel.getX()); + + // remeber inner border. Make it one bigger in top left since polygons + // do not paint their lower-right corners. Since this is the inner polygon, + // the top-left corders are the ones to grow here + const basegfx::B2DRange aDiscreteInnerRange( + aDiscreteOuterRange.getMinimum() + aDiscretePixel, aDiscreteOuterRange.getMaximum()); + + // grow by line width + aDiscreteOuterRange.grow((mnSelectionIndicatorThickness - 1) * aDiscretePixel.getX()); + + // create a PolyPolygon from those ranges. For the outer polygon, round edges by + // giving a relative radius to the polygon creator (use mnSelectionIndicatorThickness here, too) + const double fPixelFactor(aDiscretePixel.getX() * (mnSelectionIndicatorThickness + 2.5)); + const double fRelativeRadiusX(fPixelFactor / ::std::max(aDiscreteOuterRange.getWidth(), 1.0)); + const double fRelativeRadiusY(fPixelFactor / ::std::max(aDiscreteOuterRange.getHeight(), 1.0)); + basegfx::B2DPolyPolygon aFramePolyPolygon; + const basegfx::B2DPolygon aRoundedOuterPolygon(basegfx::tools::createPolygonFromRect(aDiscreteOuterRange, fRelativeRadiusX, fRelativeRadiusY)); + + aFramePolyPolygon.append(aRoundedOuterPolygon); + aFramePolyPolygon.append(basegfx::tools::createPolygonFromRect(aDiscreteInnerRange)); + + // add colored PolyPolygon + const svtools::ColorConfig aColorConfig; + static bool bTestWithBrightColors(false); + const basegfx::BColor aFrameColor(bTestWithBrightColors ? basegfx::BColor(0,1,0) : Application::GetSettings().GetStyleSettings().GetMenuHighlightColor().getBColor()); + + xRetval[0] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(aFramePolyPolygon, aFrameColor)); + + // add aRoundedOuterPolygon again as non-filled line polygon to get the roundungs + // painted correctly + xRetval[1] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aRoundedOuterPolygon, aFrameColor)); + + return xRetval; +} +SdPageObjectSelectPrimitive::SdPageObjectSelectPrimitive(const basegfx::B2DRange& rRange) +: SdPageObjectBasePrimitive(rRange) +{ +} -const SdrPage* PageObjectViewObjectContact::GetPage (void) const +SdPageObjectSelectPrimitive::~SdPageObjectSelectPrimitive() { - return static_cast<PageObjectViewContact&>(GetViewContact()).GetPage(); } +ImplPrimitrive2DIDBlock(SdPageObjectSelectPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTSELECTPRIMITIVE) +/////////////////////////////////////////////////////////////////////////////////////////////// +// SdPageObjectPrimitive for border around bitmap visualisation +class SdPageObjectBorderPrimitive : public SdPageObjectBasePrimitive +{ +protected: + // method which is to be used to implement the local decomposition of a 2D primitive. + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; -void PageObjectViewObjectContact::ActionChanged (void) +public: + // constructor and destructor + SdPageObjectBorderPrimitive(const basegfx::B2DRange& rRange); + ~SdPageObjectBorderPrimitive(); + + // provide unique ID + DeclPrimitrive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence SdPageObjectBorderPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const { - // Even when we are called from PrepareDelete we still have to invalide - // the preview bitmap in the cache. - const SdrPage* pPage = GetPage(); - SdDrawDocument* pDocument = dynamic_cast<SdDrawDocument*>(pPage->GetModel()); - if (mpCache!=NULL && pPage!=NULL && pDocument!=NULL) - { - cache::PageCacheManager::Instance()->InvalidatePreviewBitmap( - pDocument->getUnoModel(), - GetPage()); - } + // since old Width/Height calculations always added a single pixel value, + // it is necessary to create a inner range which is one display unit less + // at the bottom right. + const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const basegfx::B2DRange aAdaptedInnerRange( + getPageObjectRange().getMinX(), getPageObjectRange().getMinY(), + getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY()); + + // Paint_Border replacement. (use aBorderColor) + static bool bTestWithBrightColors(false); + const svtools::ColorConfig aColorConfig; + const basegfx::BColor aBorderColor(bTestWithBrightColors ? basegfx::BColor(1,0,0) : Color(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor).getBColor()); + + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(basegfx::tools::createPolygonFromRect(aAdaptedInnerRange), aBorderColor)); + return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); +} - ViewObjectContact::ActionChanged(); +SdPageObjectBorderPrimitive::SdPageObjectBorderPrimitive(const basegfx::B2DRange& rRange) +: SdPageObjectBasePrimitive(rRange) +{ +} - mbIsBackgroundColorUpdatePending = true; +SdPageObjectBorderPrimitive::~SdPageObjectBorderPrimitive() +{ } +ImplPrimitrive2DIDBlock(SdPageObjectBorderPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTBORDERPRIMITIVE) +/////////////////////////////////////////////////////////////////////////////////////////////// +// SdPageObjectPrimitive for focus visualisation +class SdPageObjectFocusPrimitive : public SdPageObjectBasePrimitive +{ +private: + /// Gap between border of page object and inside of focus rectangle. + static const sal_Int32 mnFocusIndicatorOffset; -void PageObjectViewObjectContact::PaintContent (OutputDevice& rDevice) +protected: + // method which is to be used to implement the local decomposition of a 2D primitive. + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; + +public: + // constructor and destructor + SdPageObjectFocusPrimitive(const basegfx::B2DRange& rRange); + ~SdPageObjectFocusPrimitive(); + + // provide unique ID + DeclPrimitrive2DIDBlock() +}; + +const sal_Int32 SdPageObjectFocusPrimitive::mnFocusIndicatorOffset(2); + +drawinglayer::primitive2d::Primitive2DSequence SdPageObjectFocusPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const { - // Save (a part of) the state of the output device. - const ULONG nPreviousDrawMode (rDevice.GetDrawMode()); - const Color aOriginalFillColor (rDevice.GetFillColor()); - const Color aOriginalLineColor (rDevice.GetLineColor()); - const Font aOriginalFont (rDevice.GetFont()); + drawinglayer::primitive2d::Primitive2DSequence xRetval(2); - // Set default font. - rDevice.SetFont(*FontProvider::Instance().GetFont(rDevice)); + // since old Width/Height calculations always added a single pixel value, + // it is necessary to create a inner range which is one display unit less + // at the bottom right. + const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const basegfx::B2DRange aAdaptedInnerRange( + getPageObjectRange().getMinX(), getPageObjectRange().getMinY(), + getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY()); - // Do the actual painting. - PaintBackground(rDevice); - PaintPreview(rDevice); - PaintFrame(rDevice); - PaintFadeEffectIndicator(rDevice); - PaintPageName(rDevice); - PaintPageNumber(rDevice); + // Paint_FocusIndicator replacement. (black and white). + // imitate Paint_DottedRectangle: First paint a white rectangle and above it a black dotted one + basegfx::B2DRange aFocusIndicatorRange(aAdaptedInnerRange); + aFocusIndicatorRange.grow(mnFocusIndicatorOffset * aDiscretePixel.getX()); - // Restore old device state. - rDevice.SetFont(aOriginalFont); - rDevice.SetLineColor(aOriginalLineColor); - rDevice.SetFillColor(aOriginalFillColor); - rDevice.SetDrawMode(nPreviousDrawMode); + // create polygon + const basegfx::B2DPolygon aIndicatorPolygon(basegfx::tools::createPolygonFromRect(aFocusIndicatorRange)); + + // white rectangle + xRetval[0] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aIndicatorPolygon, Color(COL_WHITE).getBColor())); + + // dotted black rectangle with same geometry + ::std::vector< double > aDotDashArray; + + aDotDashArray.push_back(aDiscretePixel.getX()); + aDotDashArray.push_back(aDiscretePixel.getX()); + + // prepare line and stroke attributes + const drawinglayer::attribute::LineAttribute aLineAttribute(Color(COL_BLACK).getBColor()); + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDotDashArray, 2.0 * aDiscretePixel.getX()); + + xRetval[1] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D(aIndicatorPolygon, aLineAttribute, aStrokeAttribute)); + + return xRetval; } +SdPageObjectFocusPrimitive::SdPageObjectFocusPrimitive(const basegfx::B2DRange& rRange) +: SdPageObjectBasePrimitive(rRange) +{ +} + +SdPageObjectFocusPrimitive::~SdPageObjectFocusPrimitive() +{ +} +ImplPrimitrive2DIDBlock(SdPageObjectFocusPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTFOCUSPRIMITIVE) +/////////////////////////////////////////////////////////////////////////////////////////////// +// SdPageObjectPrimitive for fade effect visualisation -void PageObjectViewObjectContact::PaintBackground (OutputDevice& rDevice) const +class SdPageObjectFadeNameNumberPrimitive : public SdPageObjectBasePrimitive +{ +private: + /// Size of width and height of the fade effect indicator in pixels. + static const sal_Int32 mnFadeEffectIndicatorOffset; + + /// Gap between border of page object and number rectangle. + static const sal_Int32 mnPageNumberOffset; + + /// the FadeEffect bitmap. Static since it is usable outside this primitive + /// for size comparisons + static BitmapEx maFadeEffectIconBitmap; + + /// page name, number and needed infos + String maPageName; + sal_uInt32 mnPageNumber; + Font maPageNameFont; + Size maPageNumberAreaModelSize; + + // bitfield + unsigned mbShowFadeEffectIcon : 1; + unsigned mbExcluded : 1; + + // private helpers + const BitmapEx& getFadeEffectIconBitmap() const; + +protected: + // method which is to be used to implement the local decomposition of a 2D primitive. + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; + +public: + // constructor and destructor + SdPageObjectFadeNameNumberPrimitive( + const basegfx::B2DRange& rRange, + const String& rPageName, + sal_uInt32 nPageNumber, + const Font& rPageNameFont, + const Size& rPageNumberAreaModelSize, + bool bShowFadeEffectIcon, + bool bExcluded); + ~SdPageObjectFadeNameNumberPrimitive(); + + // data access + const String& getPageName() const { return maPageName; } + sal_uInt32 getPageNumber() const { return mnPageNumber; } + const Font& getPageNameFont() const { return maPageNameFont; } + const Size& getPageNumberAreaModelSize() const { return maPageNumberAreaModelSize; } + bool getShowFadeEffectIcon() const { return mbShowFadeEffectIcon; } + bool getExcluded() const { return mbExcluded; } + + // compare operator + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const; + + // provide unique ID + DeclPrimitrive2DIDBlock() +}; + +const sal_Int32 SdPageObjectFadeNameNumberPrimitive::mnFadeEffectIndicatorOffset(9); +const sal_Int32 SdPageObjectFadeNameNumberPrimitive::mnPageNumberOffset(9); +BitmapEx SdPageObjectFadeNameNumberPrimitive::maFadeEffectIconBitmap; + +const BitmapEx& SdPageObjectFadeNameNumberPrimitive::getFadeEffectIconBitmap() const { - if (mpProperties.get()!=NULL - && mpProperties->IsHighlightCurrentSlide() - && GetPageDescriptor()->IsCurrentPage()) + if(maFadeEffectIconBitmap.IsEmpty()) { - Rectangle aOuterBox (GetBoundingBox(rDevice,PageObjectBoundingBox,PixelCoordinateSystem)); - Rectangle aInnerBox (GetBoundingBox(rDevice,PreviewBoundingBox,PixelCoordinateSystem)); - - const Color aOldFillColor (rDevice.GetFillColor()); - const Color aOldLineColor (rDevice.GetLineColor()); - const sal_Bool bWasEnabled(rDevice.IsMapModeEnabled()); - - rDevice.SetLineColor(); - rDevice.SetFillColor(GetColor(rDevice, CS_BACKGROUND)); - rDevice.EnableMapMode(sal_False); - - // Paint the background without painting over the preview. - rDevice.DrawRect( - Rectangle(aOuterBox.Left(),aOuterBox.Top(),aInnerBox.Left(),aOuterBox.Bottom())); - rDevice.DrawRect( - Rectangle(aInnerBox.Left(),aOuterBox.Top(),aInnerBox.Right(),aInnerBox.Top())); - rDevice.DrawRect( - Rectangle(aInnerBox.Right(),aOuterBox.Top(),aOuterBox.Right(),aInnerBox.Bottom())); - rDevice.DrawRect( - Rectangle(aInnerBox.Left(),aInnerBox.Bottom(),aOuterBox.Right(),aOuterBox.Bottom())); - - // Draw the frame around the background. - rDevice.SetLineColor(GetColor(rDevice, CS_SELECTION)); - rDevice.SetFillColor(); - rDevice.DrawRect(aOuterBox); - - // Erase the corner pixel to have somewhat rounded corners. - const Color aCornerColor (GetColor(rDevice, CS_WINDOW)); - Point aCorner (aOuterBox.TopLeft()); - rDevice.DrawPixel (aCorner, aCornerColor); - aCorner = aOuterBox.TopRight(); - rDevice.DrawPixel (aCorner, aCornerColor); - aCorner = aOuterBox.BottomLeft(); - rDevice.DrawPixel (aCorner, aCornerColor); - aCorner = aOuterBox.BottomRight(); - rDevice.DrawPixel (aCorner, aCornerColor); - - rDevice.SetFillColor(aOldFillColor); - rDevice.SetLineColor(aOldLineColor); - rDevice.EnableMapMode(bWasEnabled); + // prepare FadeEffectIconBitmap on demand + const sal_uInt16 nIconId(Application::GetSettings().GetStyleSettings().GetHighContrastMode() + ? BMP_FADE_EFFECT_INDICATOR_H + : BMP_FADE_EFFECT_INDICATOR); + const BitmapEx aFadeEffectIconBitmap(IconCache::Instance().GetIcon(nIconId).GetBitmapEx()); + const_cast< SdPageObjectFadeNameNumberPrimitive* >(this)->maFadeEffectIconBitmap = aFadeEffectIconBitmap; } + + return maFadeEffectIconBitmap; } +drawinglayer::primitive2d::Primitive2DSequence SdPageObjectFadeNameNumberPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const +{ + const xub_StrLen nTextLength(getPageName().Len()); + const sal_uInt32 nCount( + (getShowFadeEffectIcon() ? 1 : 0) + // FadeEffect icon + (nTextLength ? 1 : 0) + // PageName + 1 + // PageNumber (always) + (getExcluded() ? 2 : 0) // PageNumber crossed out + ); + sal_uInt32 nInsert(0); + drawinglayer::primitive2d::Primitive2DSequence xRetval(nCount); + + // since old Width/Height calculations always added a single pixel value, + // it is necessary to create a inner range which is one display unit less + // at the bottom right. + const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const basegfx::B2DRange aAdaptedInnerRange( + getPageObjectRange().getMinX(), getPageObjectRange().getMinY(), + getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY()); + + // preapre TextLayouter + drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; + aTextLayouter.setFont(getPageNameFont()); + + // get font attributes + ::basegfx::B2DVector aTextSizeAttribute; + const drawinglayer::primitive2d::FontAttributes aFontAttributes(drawinglayer::primitive2d::getFontAttributesFromVclFont( + aTextSizeAttribute, + getPageNameFont(), + false, + false)); + + // prepare DXTextArray (can be empty one) + const ::std::vector< double > aDXArray; + + // prepare locale; this may need some more information in the future + const ::com::sun::star::lang::Locale aLocale; + + // prepare font color from System + const basegfx::BColor aFontColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor()); + + if(getShowFadeEffectIcon()) + { + // prepare fFadeEffect Sizes + const basegfx::B2DVector aFadeEffectBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector( + getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1, + getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1)); + + // Paint_FadeEffectIndicator replacement. + // create transformation. To avoid bitmap scaling, use bitmap size as size + basegfx::B2DHomMatrix aBitmapTransform; + + // short form for scale and translate transformation + aBitmapTransform.set(0L, 0L, aFadeEffectBitmapSizeLogic.getX()); + aBitmapTransform.set(1L, 1L, aFadeEffectBitmapSizeLogic.getY()); + aBitmapTransform.set(0L, 2L, aAdaptedInnerRange.getMinX()); + aBitmapTransform.set(1L, 2L, aAdaptedInnerRange.getMaxY() + ((mnFadeEffectIndicatorOffset + 1) * aDiscretePixel.getX())); + + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::BitmapPrimitive2D(getFadeEffectIconBitmap(), aBitmapTransform)); + } + + if(nTextLength) + { + // prepare fFadeEffect Sizes since it consumes from text size + const basegfx::B2DVector aFadeEffectBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector( + getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1, + getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1)); + + // Paint_PageName replacement. Get text size + const double fTextWidth(aTextLayouter.getTextWidth(getPageName(), 0, nTextLength)); + const double fTextHeight(getPageNameFont().GetHeight()); + const double fFadeEffectWidth(aFadeEffectBitmapSizeLogic.getX() * 2.0); + const double fFadeEffectTextGap(((mnFadeEffectIndicatorOffset + 2) * aDiscretePixel.getX())); + String aPageName(getPageName()); + + // calculate text start position + double fStartX( + aAdaptedInnerRange.getMaxX() + - fTextWidth + + (aDiscretePixel.getX() * 3.0)); + const double fStartY( + aAdaptedInnerRange.getMaxY() + + fTextHeight + + fFadeEffectTextGap); + const bool bNeedClipping(fStartX < aAdaptedInnerRange.getMinX() + fFadeEffectWidth); + + // if text is too big, clip it + if(bNeedClipping) + { + // new left start + fStartX = aAdaptedInnerRange.getMinX() + fFadeEffectWidth; + + // find out how many characters to use + const double fAvailableLength(aAdaptedInnerRange.getWidth() - fFadeEffectWidth); + static const String aThreePoints(String::CreateFromAscii("...")); + const double fWidthThreePoints(aTextLayouter.getTextWidth(aThreePoints, 0, aThreePoints.Len())); + xub_StrLen a(1); + for(; a < (xub_StrLen)nTextLength; a++) + { + const double fSnippetLength(aTextLayouter.getTextWidth(aPageName, 0, a)); + + if(fSnippetLength + fWidthThreePoints > fAvailableLength) + { + break; + } + } + + // build new string + aPageName = String(aPageName, 0, a - 1); + aPageName += aThreePoints; + } + // fill text matrix + ::basegfx::B2DHomMatrix aTextMatrix; -void PageObjectViewObjectContact::PaintPreview (OutputDevice& rDevice) + aTextMatrix.set(0L, 0L, aTextSizeAttribute.getX()); + aTextMatrix.set(1L, 1L, aTextSizeAttribute.getY()); + aTextMatrix.set(0L, 2L, fStartX); + aTextMatrix.set(1L, 2L, fStartY); + + // create Text primitive and add to target + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextMatrix, aPageName, 0, aPageName.Len(), aDXArray, aFontAttributes, aLocale, aFontColor)); + } + + { + // Paint_PageNumber replacement. Get the range where it shall be centered and prepare the string + const double fLeft(aAdaptedInnerRange.getMinX() - (mnPageNumberOffset * aDiscretePixel.getX()) - getPageNumberAreaModelSize().Width()); + const double fTop(aAdaptedInnerRange.getMinY()); + const basegfx::B2DRange aNumberRange(fLeft, fTop, + fLeft + getPageNumberAreaModelSize().Width(), fTop + getPageNumberAreaModelSize().Height()); + const String aPageNumber(String::CreateFromInt32(getPageNumber())); + const xub_StrLen nNumberLen(aPageNumber.Len()); + + // Get text size + const double fTextWidth(aTextLayouter.getTextWidth(aPageNumber, 0, nNumberLen)); + const double fTextHeight(getPageNameFont().GetHeight()); + + // get text start postion + const double fStartX(aNumberRange.getCenterX() - (fTextWidth / 2.0)); + const double fStartY(aNumberRange.getMinY() + fTextHeight + aDiscretePixel.getX()); + + // fill text matrix + ::basegfx::B2DHomMatrix aTextMatrix; + + aTextMatrix.set(0L, 0L, aTextSizeAttribute.getX()); + aTextMatrix.set(1L, 1L, aTextSizeAttribute.getY()); + aTextMatrix.set(0L, 2L, fStartX); + aTextMatrix.set(1L, 2L, fStartY); + + // create Text primitive + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextMatrix, aPageNumber, 0, nNumberLen, aDXArray, aFontAttributes, aLocale, aFontColor)); + + if(getExcluded()) + { + // create a box with strikethrough from top left to bottom right + const basegfx::BColor aActiveColor(Application::GetSettings().GetStyleSettings().GetActiveColor().getBColor()); + basegfx::B2DPolygon aStrikethrough; + + aStrikethrough.append(aNumberRange.getMinimum()); + aStrikethrough.append(aNumberRange.getMaximum()); + + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + basegfx::tools::createPolygonFromRect(aNumberRange), aActiveColor)); + + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aStrikethrough, aActiveColor)); + } + } + + return xRetval; +} + +SdPageObjectFadeNameNumberPrimitive::SdPageObjectFadeNameNumberPrimitive( + const basegfx::B2DRange& rRange, + const String& rPageName, + sal_uInt32 nPageNumber, + const Font& rPageNameFont, + const Size& rPageNumberAreaModelSize, + bool bShowFadeEffectIcon, + bool bExcluded) +: SdPageObjectBasePrimitive(rRange), + maPageName(rPageName), + mnPageNumber(nPageNumber), + maPageNameFont(rPageNameFont), + maPageNumberAreaModelSize(rPageNumberAreaModelSize), + mbShowFadeEffectIcon(bShowFadeEffectIcon), + mbExcluded(bExcluded) { - Rectangle aNewSizePixel (GetBoundingBox(rDevice,PreviewBoundingBox,PixelCoordinateSystem)); - BitmapEx aPreview (GetPreview(rDevice, aNewSizePixel)); +} - // Paint using cached bitmap. - const sal_Bool bWasEnabled(rDevice.IsMapModeEnabled()); - rDevice.EnableMapMode(sal_False); - rDevice.DrawBitmapEx(aNewSizePixel.TopLeft(), aPreview); - rDevice.EnableMapMode(bWasEnabled); +SdPageObjectFadeNameNumberPrimitive::~SdPageObjectFadeNameNumberPrimitive() +{ } +bool SdPageObjectFadeNameNumberPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(SdPageObjectBasePrimitive::operator==(rPrimitive)) + { + const SdPageObjectFadeNameNumberPrimitive& rCompare = static_cast< const SdPageObjectFadeNameNumberPrimitive& >(rPrimitive); + + return (getPageName() == rCompare.getPageName() + && getPageNumber() == rCompare.getPageNumber() + && getPageNameFont() == rCompare.getPageNameFont() + && getPageNumberAreaModelSize() == rCompare.getPageNumberAreaModelSize() + && getShowFadeEffectIcon() == rCompare.getShowFadeEffectIcon() + && getExcluded() == rCompare.getExcluded()); + } + return false; +} +ImplPrimitrive2DIDBlock(SdPageObjectFadeNameNumberPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTFADENAMENUMBERPRIMITIVE) -void PageObjectViewObjectContact::PaintFrame ( - OutputDevice& rDevice, - bool bShowMouseOverEffect) const +/////////////////////////////////////////////////////////////////////////////////////////////// +// createPrimitive2DSequence +// +// This method will replace the whole painting mechanism. Task is no longer to paint stuff to an OutDev, +// but to provide the necessary geometrical information using primitives. + +drawinglayer::primitive2d::Primitive2DSequence PageObjectViewObjectContact::createPrimitive2DSequence(const sdr::contact::DisplayInfo& rDisplayInfo) const { - PaintBorder (rDevice); - PaintSelectionIndicator (rDevice); - PaintMouseOverEffect (rDevice, bShowMouseOverEffect); - // else the mouse over effect is not visible when the selection - // indicator is painted already. - PaintFocusIndicator (rDevice, - GetPageDescriptor()->IsSelected() || ! bShowMouseOverEffect); -} + // OutputDevice* pDevice = rDisplayInfo.GetDIOutputDevice(); + OutputDevice* pDevice = GetObjectContact().TryToGetOutputDevice(); + + // get primitive vector from parent class. Do remember the contents for later use; this + // is done to create the page content renderer (see PagePrimitiveExtractor in svx) at the + // original object and to setup the draw hierarchy there so that changes to VCs of displayed + // objects will lead to InvalidatePartOfView-calls which will be forwarded from the helper-OC + // to this VOC in calling a ActionChanged(). + // + // This already produces the displayable page content as a primitive sequence, complete with + // embedding in the page visualizer, clipping if needed and object and aspect ratio + // preparations. It would thus be the base for creating the cached visualisation, too, + // by just painting extactly this primitive sequence. + // + // Currently, this slows down PagePane display heavily. Reason is that the current mechanism + // to react on a SdrObject change in an edit view is to react on the ModelChange and to completely + // reset the PagePane (delete SdrPageObjs, re-create and layout them). This works, but kicks + // the complete sequence of primitive creation at VOCs and VCs and their buffering out of + // memory each time. So there are two choices: + // + // 1, disable getting the sequence of primtives + // -> invalidate uses ModelChange + // -> cache repaint uses complete view creation and repainting + // + // 2, create and use the sequence of primitives + // -> invalidate would not need ModelChange, no destroy/recreate of SdrObjects, no rearrange, + // the invalidate and the following repaint would exactly update the SdrPages involved and + // use the DrawingLayer provided ActionChanged() invalidations over the VOCs and VCs + // -> cache repaint could use the here offered sequence of primitives to re-create the bitmap + // (just hand over the local member to the cache) + // + // For the moment i will use (1) and disable primitive creation for SdrPageObj contents here + + // const_cast< PageObjectViewObjectContact* >(this)->mxCurrentPageContents = ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo); + + // assert when this call is issued indirectly from the destructor of + // this instance. This is not allowed and needs to be looked at +#ifdef DBG_UTIL + if(mbInDestructor) + { + OSL_ENSURE(false, "Higher call inside PageObjectViewObjectContact in destructor (!)"); + } +#endif + + // Check if buffering can and shall be done. + if (pDevice != NULL + && !GetObjectContact().isOutputToPrinter() + && !GetObjectContact().isOutputToRecordingMetaFile() + && !mbInDestructor) + { + // get inner and outer logic rectangles. Use model data directly for creation. Do NOT use getBoundRect()/ + // getSnapRect() functionality; these will use the sequence of primitives in the long run itself. SdrPageObj + // is a SdrObject, so use SdrObject::aOutRect as model data. Access using GetLastBoundRect() to not execute anything + PageObjectViewContact& rPaObVOC(static_cast< PageObjectViewContact& >(GetViewContact())); + const Rectangle aInnerLogic(rPaObVOC.GetPageObject().GetLastBoundRect()); + + // get BitmapEx from cache. Do exactly the same as Paint_Preview() to avoid a repaint loop + // caused by slightly different pixel sizes of what the cache sees as pixel size and what is + // calculated here in discrete coordinates. This includes to not use LogicToPiyel on the Rectangle, + // but to do the same as the GetBoundingBox() implementation + const Rectangle aInnerPixel(Rectangle(pDevice->LogicToPixel(aInnerLogic.TopLeft()), pDevice->LogicToPixel(aInnerLogic.GetSize()))); + BitmapEx aBitmapEx(const_cast< PageObjectViewObjectContact* >(this)->GetPreview(rDisplayInfo, aInnerPixel)); + + // prepare inner range + const basegfx::B2DRange aInnerRange(aInnerLogic.Left(), aInnerLogic.Top(), aInnerLogic.Right(), aInnerLogic.Bottom()); + + // provide default parameters + String aPageName; + Font aPageNameFont; + sal_uInt32 nPageNumber(0); + Size aPageNumberAreaModelSize; + bool bShowFadeEffectIcon(false); + bool bExcluded(false); + + if(GetPage()) + { + const SdPage* pPage = static_cast<const SdPage*>(GetPage()); + + // decide if fade effect indicator will be painted + if(pPage->getTransitionType() > 0) + { + bShowFadeEffectIcon = true; + } + + // prepare PageName, PageNumber, font and AreaModelSize + aPageName = pPage->GetName(); + aPageNameFont = *FontProvider::Instance().GetFont(*pDevice); + nPageNumber = ((pPage->GetPageNum() - 1) / 2) + 1; + aPageNumberAreaModelSize = GetPageDescriptor()->GetPageNumberAreaModelSize(); + + if(!aPageName.Len()) + { + aPageName = String(SdResId(STR_PAGE)); + aPageName += String::CreateFromInt32(nPageNumber); + } + + // decide if page is excluded + bExcluded = pPage->IsExcluded(); + } + + // create specialized primitives for focus, select and PagePreview itself + const bool bCreateBitmap(!aBitmapEx.IsEmpty()); + const bool bCreateFocused(GetPageDescriptor()->IsFocused()); + const bool bCreateSelected(GetPageDescriptor()->IsSelected()); + + const sal_uInt32 nCount( + (bCreateBitmap ? 1 : 0) + // bitmap itself + 1 + // border around bitmap (always) + 1 + // FadeEffect, PageName and PageNumber visualisation (always) + (bCreateFocused ? 1 : 0) + // create focused + (bCreateSelected ? 1 : 0) // create selected + ); + sal_uInt32 nInsert(0); + drawinglayer::primitive2d::Primitive2DSequence xRetval(nCount); + + if(bCreateBitmap) + { + // add selection indicator if used + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new SdPageObjectPageBitmapPrimitive(aInnerRange, aBitmapEx)); + } + + if(true) + { + // add border (always) + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new SdPageObjectBorderPrimitive(aInnerRange)); + } + if(true) + { + // add fade effext, page name and number if used + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new SdPageObjectFadeNameNumberPrimitive( + aInnerRange, + aPageName, + nPageNumber, + aPageNameFont, + aPageNumberAreaModelSize, + bShowFadeEffectIcon, + bExcluded)); + } + if(bCreateSelected) + { + // add selection indicator if used + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new SdPageObjectSelectPrimitive(aInnerRange)); + } + if(bCreateFocused) + { + // add focus indicator if used + xRetval[nInsert++] = drawinglayer::primitive2d::Primitive2DReference(new SdPageObjectFocusPrimitive(aInnerRange)); + } -void PageObjectViewObjectContact::PaintBorder ( - OutputDevice& rDevice) const + return xRetval; + } + else + { + // Call parent. Output to printer or metafile will use vector data, not cached bitmaps + return ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo); + } +} + +BitmapEx PageObjectViewObjectContact::CreatePreview (const DisplayInfo& /*rDisplayInfo*/) { - Rectangle aFrameBox (GetBoundingBox(rDevice, PreviewBoundingBox, PixelCoordinateSystem)); - aFrameBox.Left() -= 1; - aFrameBox.Top() -= 1; - aFrameBox.Right() += 1; - aFrameBox.Bottom() += 1; - rDevice.EnableMapMode(FALSE); - rDevice.SetFillColor(); - svtools::ColorConfig aColorConfig; - Color aColor = aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor; - rDevice.SetLineColor(aColor); - rDevice.DrawRect(aFrameBox); - rDevice.EnableMapMode(TRUE); + const SdPage* pPage = static_cast<const SdPage*>(GetPage()); + OutputDevice* pDevice = GetObjectContact().TryToGetOutputDevice(); + + if(pDevice) + { + Rectangle aPreviewPixelBox (GetBoundingBox(*pDevice,PreviewBoundingBox,PixelCoordinateSystem)); + + PreviewRenderer aRenderer (pDevice); + Image aPreview (aRenderer.RenderPage( + pPage, + aPreviewPixelBox.GetSize(), + String())); + + return aPreview.GetBitmapEx(); + } + else + { + return BitmapEx(); + } } -void PageObjectViewObjectContact::PaintSelectionIndicator ( - OutputDevice& rDevice) const +BitmapEx PageObjectViewObjectContact::GetPreview ( + const DisplayInfo& rDisplayInfo, + const Rectangle& rNewSizePixel) { - if ( ! GetPageDescriptor()->IsSelected()) - return; + BitmapEx aBitmap; - if (mpProperties.get()!=NULL && ! mpProperties->IsShowSelection()) - return; + try + { + // assert when this call is issued indirectly from the destructor of + // this instance. This is not allowed and needs to be looked at + OSL_ENSURE(!mbInDestructor, "Higher call inside PageObjectViewObjectContact in destructor (!)"); - const Color aOldFillColor (rDevice.GetFillColor()); - const Color aOldLineColor (rDevice.GetLineColor()); + if (!mbInDestructor) + { + if (mpCache != NULL) + { + aBitmap = mpCache->GetPreviewBitmap( + GetPage(), + rNewSizePixel.GetSize()); + mpCache->SetPreciousFlag(GetPage(), true); + } + else + aBitmap = CreatePreview(rDisplayInfo); + } + } + catch (const ::com::sun::star::uno::Exception&) + { + OSL_TRACE("PageObjectViewObjectContact::GetPreview: caught exception"); + } - // Determine colors for the frame and the background and mix them to - // obtain a third color that is used for an antialiasing effect. - Color aFrameColor (GetColor(rDevice, CS_SELECTION)); - Color aBackgroundColor (GetColor(rDevice, CS_BACKGROUND)); - Color aCornerColor (aFrameColor); - aCornerColor.Merge (aBackgroundColor, 128); + return aBitmap; +} - // Set default draw mode to be able to correctly draw the selected - // (and only that) frame. - ULONG nPreviousDrawMode = rDevice.GetDrawMode(); - rDevice.SetDrawMode (DRAWMODE_DEFAULT); - Rectangle aInner (GetBoundingBox(rDevice,PreviewBoundingBox,PixelCoordinateSystem)); - rDevice.EnableMapMode (FALSE); - rDevice.SetFillColor(); - rDevice.SetLineColor(aFrameColor); - // Paint the frame. - for (int nOffset=mnSelectionIndicatorOffset; - nOffset<mnSelectionIndicatorOffset+mnSelectionIndicatorThickness; - nOffset++) +const SdrPage* PageObjectViewObjectContact::GetPage (void) const +{ + return static_cast<PageObjectViewContact&>(GetViewContact()).GetPage(); +} + + + + +void PageObjectViewObjectContact::ActionChanged (void) +{ + // Even when we are called from destructor we still have to invalide + // the preview bitmap in the cache. + const SdrPage* pPage = GetPage(); + SdDrawDocument* pDocument = dynamic_cast<SdDrawDocument*>(pPage->GetModel()); + if (mpCache!=NULL && pPage!=NULL && pDocument!=NULL) { - Rectangle aFrame (aInner); - aFrame.Left() -= nOffset; - aFrame.Top() -= nOffset; - aFrame.Right() += nOffset; - aFrame.Bottom() += nOffset; - rDevice.DrawRect (aFrame); + cache::PageCacheManager::Instance()->InvalidatePreviewBitmap( + pDocument->getUnoModel(), + GetPage()); } - // Paint the four corner pixels in backround color for a rounded - // effect. - int nFrameWidth (mnSelectionIndicatorOffset - + mnSelectionIndicatorThickness - 1); - Rectangle aOuter (aInner); - aOuter.Left() -= nFrameWidth; - aOuter.Top() -= nFrameWidth; - aOuter.Right() += nFrameWidth; - aOuter.Bottom() += nFrameWidth; - Point aCorner (aOuter.TopLeft()); - rDevice.DrawPixel (aCorner, aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()+1,aCorner.Y()),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()+1),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()+2,aCorner.Y()),aCornerColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()+2),aCornerColor); - aCorner = aOuter.TopRight(); - rDevice.DrawPixel (aCorner, aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()-1,aCorner.Y()),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()+1),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()-2,aCorner.Y()), aCornerColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()+2), aCornerColor); - aCorner = aOuter.BottomLeft(); - rDevice.DrawPixel (aCorner, aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()+1,aCorner.Y()),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()-1),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()+2,aCorner.Y()), aCornerColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()-2), aCornerColor); - aCorner = aOuter.BottomRight(); - rDevice.DrawPixel (aCorner, aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()-1,aCorner.Y()),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()-1),aBackgroundColor); - rDevice.DrawPixel (Point(aCorner.X()-2,aCorner.Y()), aCornerColor); - rDevice.DrawPixel (Point(aCorner.X(),aCorner.Y()-2), aCornerColor); - - rDevice.EnableMapMode (TRUE); + mbIsBackgroundColorUpdatePending = true; - // Restore old values. - rDevice.SetLineColor (aOldLineColor); - rDevice.SetFillColor (aOldFillColor); - rDevice.SetDrawMode (nPreviousDrawMode); + // call parent + ViewObjectContactOfPageObj::ActionChanged(); } @@ -661,133 +1206,6 @@ void PageObjectViewObjectContact::PaintMouseOverEffect ( -void PageObjectViewObjectContact::PaintFocusIndicator ( - OutputDevice& rDevice, - bool bEraseBackground) const -{ - (void)bEraseBackground; - - if (GetPageDescriptor()->IsSelected() - && mpProperties.get()!=NULL - && ! mpProperties->IsShowFocus()) - { - return; - } - - if (GetPageDescriptor()->IsFocused()) - { - Rectangle aPagePixelBBox (GetBoundingBox(rDevice,PreviewBoundingBox,PixelCoordinateSystem)); - - aPagePixelBBox.Left() -= mnFocusIndicatorOffset; - aPagePixelBBox.Top() -= mnFocusIndicatorOffset; - aPagePixelBBox.Right() += mnFocusIndicatorOffset; - aPagePixelBBox.Bottom() += mnFocusIndicatorOffset; - - PaintDottedRectangle(rDevice, aPagePixelBBox); - } -} - - - - -void PageObjectViewObjectContact::PaintFadeEffectIndicator (OutputDevice& rDevice) const -{ - if (GetPage() != NULL - && static_cast<const SdPage*>(GetPage())->getTransitionType() > 0) - { - Rectangle aIndicatorBox ( - GetBoundingBox(rDevice, FadeEffectIndicatorBoundingBox, ModelCoordinateSystem)); - - USHORT nIconId (BMP_FADE_EFFECT_INDICATOR); - if (rDevice.GetSettings().GetStyleSettings().GetHighContrastMode()!=0) - nIconId = BMP_FADE_EFFECT_INDICATOR_H; - - rDevice.DrawImage ( - aIndicatorBox.TopLeft(), - IconCache::Instance().GetIcon(nIconId)); - } -} - - - - -void PageObjectViewObjectContact::PaintPageName (OutputDevice& rDevice) const -{ - Rectangle aPageBox (GetBoundingBox(rDevice, PreviewBoundingBox, ModelCoordinateSystem)); - - Font aOriginalFont (rDevice.GetFont()); - rDevice.SetFont(*FontProvider::Instance().GetFont(rDevice)); - - const SdPage* pPage = static_cast<const SdPage*>(GetPage()); - int nPage = (pPage->GetPageNum()-1) / 2; - // Name der Seite - Point aPos = aPageBox.BottomLeft(); - const Size aSize (rDevice.PixelToLogic (Size (0, mnFadeEffectIndicatorOffset))); - const Rectangle aIndicatorBox ( - GetBoundingBox(rDevice, FadeEffectIndicatorBoundingBox, ModelCoordinateSystem)); - - aPos.Y() += aSize.Height(); - aPos.X() += 2 * aIndicatorBox.GetWidth(); - - Size aTextBoxSize (aPageBox.Right() - aPos.X(), rDevice.GetFont().GetSize().Height()); - - String sName (const_cast<SdPage*>(pPage)->GetName()); - if (sName.Len() == 0) - { - sName = String (SdResId(STR_PAGE)); - sName += String::CreateFromInt32 (nPage + 1); - } - - USHORT nTextStyle - = TEXT_DRAW_RIGHT - | TEXT_DRAW_NEWSELLIPSIS; - - rDevice.SetTextColor(GetColor(rDevice, CS_TEXT)); - rDevice.DrawText(Rectangle(aPos,aTextBoxSize), sName, nTextStyle); - - rDevice.SetFont(aOriginalFont); -} - - - - -void PageObjectViewObjectContact::PaintPageNumber (OutputDevice& rDevice) const -{ - const Rectangle aPageBox (GetBoundingBox(rDevice, PreviewBoundingBox, ModelCoordinateSystem)); - - const SdPage* pPage = static_cast<const SdPage*>(GetPage()); - const sal_Int32 nPageNumber (mpPageDescriptor->GetPageIndex() + 1); - const String sPageNumber (String::CreateFromInt32 (nPageNumber)); - Point aPos = aPageBox.TopLeft(); - Rectangle aBox (GetBoundingBox(rDevice, PageNumberBoundingBox, ModelCoordinateSystem)); - - // Paint the page number centered in its box. - // TODO: What when the page number is wider than the page number box? - const USHORT nTextStyle = TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER; - const Rectangle aTextBox (rDevice.GetTextRect (aBox, sPageNumber, nTextStyle)); - rDevice.SetFillColor(); - rDevice.SetTextColor(GetColor(rDevice, CS_TEXT)); - rDevice.DrawText(aTextBox, sPageNumber, nTextStyle); - - // Paint box arround the page number. Strike through when slide is - // excluded from the presentation - if (pPage->IsExcluded()) - { - // Make the box a little bit larger at the left so that the digits - // do not touch the border. - const Size aOffset (rDevice.PixelToLogic(Size(1,0))); - aBox.Left() -= aOffset.Width(); - - rDevice.SetLineColor( - rDevice.GetSettings().GetStyleSettings().GetActiveColor()); - rDevice.DrawRect(aBox); - rDevice.DrawLine(aBox.TopLeft(), aBox.BottomRight()); - } -} - - - - SvBorder PageObjectViewObjectContact::CalculatePageModelBorder ( OutputDevice* pDevice, int nPageCount) @@ -877,6 +1295,7 @@ model::SharedPageDescriptor + Color PageObjectViewObjectContact::GetColor ( const OutputDevice& rDevice, const ColorSpec eSpec, @@ -923,69 +1342,4 @@ Color PageObjectViewObjectContact::GetColor ( - -Color PageObjectViewObjectContact::GetBackgroundColor ( - const OutputDevice& rDevice) const -{ - Color aBackgroundColor (COL_AUTO); - bool bBackgroundColorSet (false); - - if ( ! bBackgroundColorSet) - { - aBackgroundColor = rDevice.GetSettings().GetStyleSettings().GetWindowColor(); - } - - aBackgroundColor.SetTransparency(0); - return aBackgroundColor; -} - - - - -void PageObjectViewObjectContact::PaintDottedRectangle ( - OutputDevice& rDevice, - const Rectangle& rRectangle, - const DashType eDashType) -{ - const Color aOriginalFillColor (rDevice.GetFillColor()); - const Color aOriginalLineColor (rDevice.GetLineColor()); - - // The dots or dashes are painted indepently of the zoom factor because - // selection or focus rectangles are not part of the model. - const bool bOriginalMapModeState(rDevice.IsMapModeEnabled()); - rDevice.EnableMapMode(FALSE); - - // Paint a solid rectangle first. - rDevice.SetFillColor(); - rDevice.SetLineColor(COL_WHITE); - rDevice.DrawRect(rRectangle); - - // Now paint the dots or dashes. - LineInfo aDottedStyle (LINE_DASH); - aDottedStyle.SetDashCount(0); - aDottedStyle.SetDotCount(1); - switch (eDashType) - { - case Dotted: - default: - aDottedStyle.SetDotLen(1); - aDottedStyle.SetDistance(1); - break; - - case Dashed: - aDottedStyle.SetDotLen(3); - aDottedStyle.SetDistance(3); - break; - } - - rDevice.SetLineColor(COL_BLACK); - rDevice.DrawPolyLine(Polygon(rRectangle), aDottedStyle); - - // Restore the original state. - rDevice.EnableMapMode(bOriginalMapModeState); - rDevice.SetFillColor(aOriginalFillColor); - rDevice.SetLineColor(aOriginalLineColor); -} - - } } } // end of namespace ::sd::slidesorter::view |