diff options
Diffstat (limited to 'sdext/source/presenter/PresenterPaneBorderPainter.cxx')
-rw-r--r-- | sdext/source/presenter/PresenterPaneBorderPainter.cxx | 1101 |
1 files changed, 1101 insertions, 0 deletions
diff --git a/sdext/source/presenter/PresenterPaneBorderPainter.cxx b/sdext/source/presenter/PresenterPaneBorderPainter.cxx new file mode 100644 index 000000000000..9e691954c806 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBorderPainter.cxx @@ -0,0 +1,1101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneBorderPainter.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/SimpleFontMetric.hpp> +#include <com/sun/star/awt/XFont.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/XGraphicRenderer.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/FillRule.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) + +namespace sdext { namespace presenter { + +namespace { + class BorderSize + { + public: + BorderSize (void); + BorderSize (const BorderSize& rBorderSize); + BorderSize& operator= (const BorderSize& rBoderSize); + sal_Int32 mnLeft; + sal_Int32 mnTop; + sal_Int32 mnRight; + sal_Int32 mnBottom; + }; + + class RendererPaneStyle + { + public: + RendererPaneStyle ( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName); + + awt::Rectangle AddBorder ( + const awt::Rectangle& rBox, + drawing::framework::BorderType eBorderType) const; + awt::Rectangle RemoveBorder ( + const awt::Rectangle& rBox, + drawing::framework::BorderType eBorderType) const; + const Reference<rendering::XCanvasFont> GetFont ( + const Reference<rendering::XCanvas>& rxCanvas) const; + + SharedBitmapDescriptor mpTopLeft; + SharedBitmapDescriptor mpTop; + SharedBitmapDescriptor mpTopRight; + SharedBitmapDescriptor mpLeft; + SharedBitmapDescriptor mpRight; + SharedBitmapDescriptor mpBottomLeft; + SharedBitmapDescriptor mpBottom; + SharedBitmapDescriptor mpBottomRight; + SharedBitmapDescriptor mpBottomCallout; + SharedBitmapDescriptor mpBackground; + SharedBitmapDescriptor mpEmpty; + PresenterTheme::SharedFontDescriptor mpFont; + sal_Int32 mnFontXOffset; + sal_Int32 mnFontYOffset; + enum Anchor { AnchorLeft, AnchorRight, AnchorCenter } meFontAnchor; + BorderSize maInnerBorderSize; + BorderSize maOuterBorderSize; + BorderSize maTotalBorderSize; + enum Side { Left, Top, Right, Bottom }; + private: + void UpdateBorderSizes (void); + SharedBitmapDescriptor GetBitmap( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName, + const OUString& rsBitmapName); + }; +} + + + +class PresenterPaneBorderPainter::Renderer +{ +public: + Renderer ( + const Reference<XComponentContext>& rxContext, + const ::boost::shared_ptr<PresenterTheme>& rpTheme); + ~Renderer (void); + + void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas); + void PaintBorder ( + const OUString& rsTitle, + const awt::Rectangle& rBBox, + const awt::Rectangle& rUpdateBox, + const OUString& rsPaneURL); + void PaintTitle ( + const OUString& rsTitle, + const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const awt::Rectangle& rInnerBox, + const bool bPaintBackground); + void SetupClipping ( + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const OUString& rsPaneStyleName); + ::boost::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL); + void SetCalloutAnchor ( + const awt::Point& rCalloutAnchor); + +private: + ::boost::shared_ptr<PresenterTheme> mpTheme; + typedef ::std::map<OUString, ::boost::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer; + RendererPaneStyleContainer maRendererPaneStyles; + Reference<rendering::XCanvas> mxCanvas; + Reference<drawing::XPresenterHelper> mxPresenterHelper; + css::rendering::ViewState maViewState; + Reference<rendering::XPolyPolygon2D> mxViewStateClip; + bool mbHasCallout; + awt::Point maCalloutAnchor; + + void PaintBitmap( + const awt::Rectangle& rBox, + const awt::Rectangle& rUpdateBox, + const sal_Int32 nXPosition, + const sal_Int32 nYPosition, + const sal_Int32 nStartOffset, + const sal_Int32 nEndOffset, + const bool bExpand, + const SharedBitmapDescriptor& rpBitmap, + const SharedBitmapDescriptor& rpBackgroundBitmap); +}; + + + + +// ===== PresenterPaneBorderPainter =========================================== + +PresenterPaneBorderPainter::PresenterPaneBorderPainter ( + const Reference<XComponentContext>& rxContext) + : PresenterPaneBorderPainterInterfaceBase(m_aMutex), + mxContext(rxContext), + mpTheme(), + mpRenderer() +{ +} + + + + +PresenterPaneBorderPainter::~PresenterPaneBorderPainter (void) +{ +} + + + + +//----- XPaneBorderPainter ---------------------------------------------------- + +awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + ProvideTheme(); + + return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType); +} + + + + +awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + ProvideTheme(); + + return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType); +} + + + + +void SAL_CALL PresenterPaneBorderPainter::paintBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + // Early reject paints completely outside the repaint area. + if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width + || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height + || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X + || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) + { + return; + } + ProvideTheme(rxCanvas); + + if (mpRenderer.get() != NULL) + { + mpRenderer->SetCanvas(rxCanvas); + mpRenderer->SetupClipping( + rRepaintArea, + rOuterBorderRectangle, + rsPaneBorderStyleName); + mpRenderer->PaintBorder( + rsTitle, + rOuterBorderRectangle, + rRepaintArea, + rsPaneBorderStyleName); + } +} + + + + +void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle, + const css::awt::Point& rCalloutAnchor) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + // Early reject paints completely outside the repaint area. + if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width + || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height + || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X + || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) + { + return; + } + ProvideTheme(rxCanvas); + + if (mpRenderer.get() != NULL) + { + mpRenderer->SetCanvas(rxCanvas); + mpRenderer->SetupClipping( + rRepaintArea, + rOuterBorderRectangle, + rsPaneBorderStyleName); + mpRenderer->SetCalloutAnchor(rCalloutAnchor); + mpRenderer->PaintBorder( + rsTitle, + rOuterBorderRectangle, + rRepaintArea, + rsPaneBorderStyleName); + } +} + + + + +awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset ( + const rtl::OUString& rsPaneBorderStyleName) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + ProvideTheme(); + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle( + mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName)); + if (pRendererPaneStyle.get() != NULL + && pRendererPaneStyle->mpBottomCallout.get() != NULL) + { + return awt::Point ( + 0, + pRendererPaneStyle->mpBottomCallout->mnHeight + - pRendererPaneStyle->mpBottomCallout->mnYHotSpot); + } + } + + return awt::Point(0,0); +} + + + + +//----------------------------------------------------------------------------- + +bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas) +{ + bool bModified (false); + + if ( ! mxContext.is()) + return false; + + if (mpTheme.get() != NULL) + { + // Check if the theme already has a canvas. + if ( ! mpTheme->HasCanvas()) + { + mpTheme->ProvideCanvas(rxCanvas); + bModified = true; + } + } + else + { + mpTheme.reset(new PresenterTheme(mxContext, OUString(), rxCanvas)); + bModified = true; + } + + if (mpTheme.get() != NULL && bModified) + { + if (mpRenderer.get() == NULL) + mpRenderer.reset(new Renderer(mxContext, mpTheme)); + else + mpRenderer->SetCanvas(rxCanvas); + } + + return bModified; +} + + + + +bool PresenterPaneBorderPainter::ProvideTheme (void) +{ + if (mpTheme.get() == NULL) + { + // Create a theme without bitmaps (no canvas => no bitmaps). + return ProvideTheme(NULL); + } + else + { + // When there already is a theme then without a canvas we can not + // add anything new. + return false; + } +} + + + + +bool PresenterPaneBorderPainter::HasTheme (void) const +{ + return mpTheme.get()!=NULL && mpRenderer.get()!=NULL; +} + + + + +void PresenterPaneBorderPainter::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme) +{ + mpTheme = rpTheme; + if (mpRenderer.get() == NULL) + mpRenderer.reset(new Renderer(mxContext, mpTheme)); +} + + + + +awt::Rectangle PresenterPaneBorderPainter::AddBorder ( + const ::rtl::OUString& rsPaneURL, + const awt::Rectangle& rInnerBox, + const css::drawing::framework::BorderType eBorderType) const +{ + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); + if (pRendererPaneStyle.get() != NULL) + return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType); + } + return rInnerBox; +} + + + + +awt::Rectangle PresenterPaneBorderPainter::RemoveBorder ( + const ::rtl::OUString& rsPaneURL, + const css::awt::Rectangle& rOuterBox, + const css::drawing::framework::BorderType eBorderType) const +{ + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); + if (pRendererPaneStyle.get() != NULL) + return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType); + } + return rOuterBox; +} + + + + +void PresenterPaneBorderPainter::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterPaneBorderPainter object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterPaneBorderPainter::Renderer ===================================== + + +PresenterPaneBorderPainter::Renderer::Renderer ( + const Reference<XComponentContext>& rxContext, + const ::boost::shared_ptr<PresenterTheme>& rpTheme) + : mpTheme(rpTheme), + maRendererPaneStyles(), + mxCanvas(), + mxPresenterHelper(), + maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), + mxViewStateClip(), + mbHasCallout(false), + maCalloutAnchor() +{ + (void)rxContext; + + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"), + rxContext), + UNO_QUERY_THROW); + } +} + + + + +PresenterPaneBorderPainter::Renderer::~Renderer (void) +{ +} + + + + +void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mxCanvas != rxCanvas) + { + mxCanvas = rxCanvas; + } +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintBorder ( + const OUString& rsTitle, + const awt::Rectangle& rBBox, + const awt::Rectangle& rUpdateBox, + const OUString& rsPaneURL) +{ + if ( ! mxCanvas.is()) + return; + + // Create the outer and inner border of the, ahm, border. + ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL)); + if (pStyle.get() == NULL) + return; + + awt::Rectangle aOuterBox (rBBox); + awt::Rectangle aCenterBox ( + pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER)); + awt::Rectangle aInnerBox ( + pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); + + // Prepare references for all used bitmaps. + SharedBitmapDescriptor pTop (pStyle->mpTop); + SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft); + SharedBitmapDescriptor pTopRight (pStyle->mpTopRight); + SharedBitmapDescriptor pLeft (pStyle->mpLeft); + SharedBitmapDescriptor pRight (pStyle->mpRight); + SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft); + SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight); + SharedBitmapDescriptor pBottom (pStyle->mpBottom); + SharedBitmapDescriptor pBackground (pStyle->mpBackground); + + // Paint the sides. + PaintBitmap(aCenterBox, rUpdateBox, 0,-1, + pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, -1,0, + pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,0, + pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight, pBackground); + if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is()) + { + const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth); + sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot + - (aCenterBox.X - aOuterBox.X)); + if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X) + nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X; + if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width) + nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width; + // Paint bottom callout. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout, pBackground); + // Paint regular bottom bitmap left and right. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom, pBackground); + } + else + { + // Stretch the bottom bitmap over the full width. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom, pBackground); + } + + // Paint the corners. + PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight, pBackground); + + // Paint the title. + PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox, false); + + // In a double buffering environment request to make the changes visible. + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintTitle ( + const OUString& rsTitle, + const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const awt::Rectangle& rInnerBox, + bool bPaintBackground) +{ + if ( ! mxCanvas.is()) + return; + + if (rsTitle.getLength() == 0) + return; + + Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas)); + if ( ! xFont.is()) + return; + + rendering::StringContext aContext ( + rsTitle, + 0, + rsTitle.getLength()); + Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + if ( ! xLayout.is()) + return; + + geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); + const double nTextHeight = aBox.Y2 - aBox.Y1; + const double nTextWidth = aBox.X2 - aBox.X1; + double nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; + const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1; + double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1; + if (nY >= rInnerBox.Y) + nY = rInnerBox.Y - 1; + switch (rpStyle->meFontAnchor) + { + default: + case RendererPaneStyle::AnchorLeft: + nX = rInnerBox.X; + break; + case RendererPaneStyle::AnchorRight: + nX = rInnerBox.X + rInnerBox.Width - nTextWidth; + break; + case RendererPaneStyle::AnchorCenter: + nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; + break; + } + nX += rpStyle->mnFontXOffset; + nY += rpStyle->mnFontYOffset; + + if (rUpdateBox.X >= nX+nTextWidth + || rUpdateBox.Y >= nY+nTextHeight + || rUpdateBox.X+rUpdateBox.Width <= nX + || rUpdateBox.Y+rUpdateBox.Height <= nY) + { + return; + } + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,nX, 0,1,nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + if (bPaintBackground) + { + PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff)); + Sequence<Sequence<geometry::RealPoint2D> > aPolygons(1); + aPolygons[0] = Sequence<geometry::RealPoint2D>(4); + aPolygons[0][0] = geometry::RealPoint2D(0, -nTextHeight); + aPolygons[0][1] = geometry::RealPoint2D(0, 0); + aPolygons[0][2] = geometry::RealPoint2D(nTextWidth, 0); + aPolygons[0][3] = geometry::RealPoint2D(nTextWidth, -nTextHeight); + Reference<rendering::XPolyPolygon2D> xPolygon ( + mxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPolygons), UNO_QUERY); + if (xPolygon.is()) + xPolygon->setClosed(0, sal_True); + mxCanvas->fillPolyPolygon( + xPolygon, + maViewState, + aRenderState); + } + else + { + PresenterCanvasHelper::SetDeviceColor( + aRenderState, + rpStyle->mpFont->mnColor); + + mxCanvas->drawText( + aContext, + xFont, + maViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + } +} + + + +::boost::shared_ptr<RendererPaneStyle> + PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL) +{ + OSL_ASSERT(mpTheme.get()!=NULL); + + RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL)); + if (iStyle == maRendererPaneStyles.end()) + { + OUString sPaneStyleName (OUString::createFromAscii("DefaultRendererPaneStyle")); + + // Get pane layout name for resource URL. + const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL)); + if (sStyleName.getLength() > 0) + sPaneStyleName = sStyleName; + + // Create a new pane style object and initialize it with bitmaps. + ::boost::shared_ptr<RendererPaneStyle> pStyle ( + new RendererPaneStyle(mpTheme,sPaneStyleName)); + iStyle = maRendererPaneStyles.insert( + RendererPaneStyleContainer::value_type(rsResourceURL, pStyle)).first; + } + if (iStyle != maRendererPaneStyles.end()) + return iStyle->second; + else + return ::boost::shared_ptr<RendererPaneStyle>(); +} + + + + +void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor ( + const awt::Point& rCalloutAnchor) +{ + mbHasCallout = true; + maCalloutAnchor = rCalloutAnchor; +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintBitmap( + const awt::Rectangle& rBox, + const awt::Rectangle& rUpdateBox, + const sal_Int32 nXPosition, + const sal_Int32 nYPosition, + const sal_Int32 nStartOffset, + const sal_Int32 nEndOffset, + const bool bExpand, + const SharedBitmapDescriptor& rpBitmap, + const SharedBitmapDescriptor& rpBackgroundBitmap) +{ + (void)rpBackgroundBitmap; + + bool bUseCanvas (mxCanvas.is()); + if ( ! bUseCanvas) + return; + + if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0) + return; + + Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY); + if ( ! xBitmap.is()) + return; + + // Calculate position, and for side bitmaps, the size. + sal_Int32 nX = 0; + sal_Int32 nY = 0; + sal_Int32 nW = rpBitmap->mnWidth; + sal_Int32 nH = rpBitmap->mnHeight; + if (nXPosition < 0) + { + nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset; + } + else if (nXPosition > 0) + { + nX = rBox.X + rBox.Width + rpBitmap->mnXOffset; + } + else + { + nX = rBox.X + nStartOffset; + if (bExpand) + nW = rBox.Width - nStartOffset + nEndOffset; + } + + if (nYPosition < 0) + { + nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset; + } + else if (nYPosition > 0) + { + nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset; + } + else + { + nY = rBox.Y + nStartOffset; + if (bExpand) + nH = rBox.Height - nStartOffset + nEndOffset; + } + + // Do not paint when bitmap area does not intersect with update box. + if (nX >= rUpdateBox.X + rUpdateBox.Width + || nX+nW <= rUpdateBox.X + || nY >= rUpdateBox.Y + rUpdateBox.Height + || nY+nH <= rUpdateBox.Y) + { + return; + } + + /* + Reference<rendering::XBitmap> xMaskedBitmap ( + PresenterBitmapHelper::FillMaskedWithColor ( + mxCanvas, + Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), + rBitmap.mxMaskBitmap, + 0x00ff0000, + rBackgroundBitmap.maReplacementColor)); + if (xMaskedBitmap.is()) + xBitmap = xMaskedBitmap; + else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is()) + { + const static sal_Int32 nOutsideMaskColor (0x00ff0000); + Reference<rendering::XIntegerBitmap> xMask ( + mxPresenterHelper->createMask( + mxCanvas, + rBitmap.mxMaskBitmap, + nOutsideMaskColor, + false)); + xBitmap = mxPresenterHelper->applyBitmapMaskWithColor( + mxCanvas, + Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), + xMask, + rBackgroundBitmap.maReplacementColor); + } + */ + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + double(nW)/rpBitmap->mnWidth, 0, nX, + 0, double(nH)/rpBitmap->mnHeight, nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::OVER); + + if (xBitmap.is()) + mxCanvas->drawBitmap( + xBitmap, + maViewState, + aRenderState); +} + + + + +void PresenterPaneBorderPainter::Renderer::SetupClipping ( + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const OUString& rsPaneStyleName) +{ + mxViewStateClip = NULL; + maViewState.Clip = NULL; + + if ( ! mxCanvas.is()) + return; + + ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName)); + if (pStyle.get() == NULL) + { + mxViewStateClip = PresenterGeometryHelper::CreatePolygon( + rUpdateBox, + mxCanvas->getDevice()); + } + else + { + awt::Rectangle aInnerBox ( + pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); + ::std::vector<awt::Rectangle> aRectangles; + aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox)); + aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox)); + mxViewStateClip = PresenterGeometryHelper::CreatePolygon( + aRectangles, + mxCanvas->getDevice()); + if (mxViewStateClip.is()) + mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD); + } + maViewState.Clip = mxViewStateClip; +} + + + +namespace { + +//===== BorderSize ============================================================ + +BorderSize::BorderSize (void) + : mnLeft(0), + mnTop(0), + mnRight(0), + mnBottom(0) +{ +} + + + + +BorderSize::BorderSize (const BorderSize& rBorderSize) + : mnLeft(rBorderSize.mnLeft), + mnTop(rBorderSize.mnTop), + mnRight(rBorderSize.mnRight), + mnBottom(rBorderSize.mnBottom) +{ +} + + + + +BorderSize& BorderSize::operator= (const BorderSize& rBorderSize) +{ + if (&rBorderSize != this) + { + mnLeft = rBorderSize.mnLeft; + mnTop = rBorderSize.mnTop; + mnRight = rBorderSize.mnRight; + mnBottom = rBorderSize.mnBottom; + } + return *this; +} + + + + +//===== RendererPaneStyle ============================================================ + +RendererPaneStyle::RendererPaneStyle ( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName) + : mpTopLeft(), + mpTop(), + mpTopRight(), + mpLeft(), + mpRight(), + mpBottomLeft(), + mpBottom(), + mpBottomRight(), + mpBottomCallout(), + mpBackground(), + mpEmpty(new PresenterBitmapDescriptor()), + mpFont(), + mnFontXOffset(0), + mnFontYOffset(0), + meFontAnchor(AnchorCenter), + maInnerBorderSize(), + maOuterBorderSize(), + maTotalBorderSize() +{ + if (rpTheme.get() != NULL) + { + mpTopLeft = GetBitmap(rpTheme, rsStyleName, A2S("TopLeft")); + mpTop = GetBitmap(rpTheme, rsStyleName, A2S("Top")); + mpTopRight = GetBitmap(rpTheme, rsStyleName, A2S("TopRight")); + mpLeft = GetBitmap(rpTheme, rsStyleName, A2S("Left")); + mpRight = GetBitmap(rpTheme, rsStyleName, A2S("Right")); + mpBottomLeft = GetBitmap(rpTheme, rsStyleName, A2S("BottomLeft")); + mpBottom = GetBitmap(rpTheme, rsStyleName, A2S("Bottom")); + mpBottomRight = GetBitmap(rpTheme, rsStyleName, A2S("BottomRight")); + mpBottomCallout = GetBitmap(rpTheme, rsStyleName, A2S("BottomCallout")); + mpBackground = GetBitmap(rpTheme, OUString(), A2S("Background")); + + // Get font description. + mpFont = rpTheme->GetFont(rsStyleName); + + OUString sAnchor (OUString::createFromAscii("Left")); + if (mpFont.get() != NULL) + { + sAnchor = mpFont->msAnchor; + mnFontXOffset = mpFont->mnXOffset; + mnFontYOffset = mpFont->mnYOffset; + } + + if (sAnchor == OUString::createFromAscii("Left")) + meFontAnchor = AnchorLeft; + else if (sAnchor == OUString::createFromAscii("Right")) + meFontAnchor = AnchorRight; + else if (sAnchor == OUString::createFromAscii("Center")) + meFontAnchor = AnchorCenter; + else + meFontAnchor = AnchorCenter; + + // Get border sizes. + try + { + ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false)); + OSL_ASSERT(aInnerBorder.size()==4); + maInnerBorderSize.mnLeft = aInnerBorder[0]; + maInnerBorderSize.mnTop = aInnerBorder[1]; + maInnerBorderSize.mnRight = aInnerBorder[2]; + maInnerBorderSize.mnBottom = aInnerBorder[3]; + + ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true)); + OSL_ASSERT(aOuterBorder.size()==4); + maOuterBorderSize.mnLeft = aOuterBorder[0]; + maOuterBorderSize.mnTop = aOuterBorder[1]; + maOuterBorderSize.mnRight = aOuterBorder[2]; + maOuterBorderSize.mnBottom = aOuterBorder[3]; + } + catch(beans::UnknownPropertyException&) + { + OSL_ASSERT(false); + } + + UpdateBorderSizes(); + } +} + + + + + +awt::Rectangle RendererPaneStyle::AddBorder ( + const awt::Rectangle& rBox, + const drawing::framework::BorderType eBorderType) const +{ + const BorderSize* pBorderSize = NULL; + switch (eBorderType) + { + case drawing::framework::BorderType_INNER_BORDER: + pBorderSize = &maInnerBorderSize; + break; + case drawing::framework::BorderType_OUTER_BORDER: + pBorderSize = &maOuterBorderSize; + break; + case drawing::framework::BorderType_TOTAL_BORDER: + pBorderSize = &maTotalBorderSize; + break; + default: + return rBox; + } + return awt::Rectangle ( + rBox.X - pBorderSize->mnLeft, + rBox.Y - pBorderSize->mnTop, + rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight, + rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom); +} + + + + +awt::Rectangle RendererPaneStyle::RemoveBorder ( + const awt::Rectangle& rBox, + const css::drawing::framework::BorderType eBorderType) const +{ + const BorderSize* pBorderSize = NULL; + switch (eBorderType) + { + case drawing::framework::BorderType_INNER_BORDER: + pBorderSize = &maInnerBorderSize; + break; + case drawing::framework::BorderType_OUTER_BORDER: + pBorderSize = &maOuterBorderSize; + break; + case drawing::framework::BorderType_TOTAL_BORDER: + pBorderSize = &maTotalBorderSize; + break; + default: + return rBox; + } + return awt::Rectangle ( + rBox.X + pBorderSize->mnLeft, + rBox.Y + pBorderSize->mnTop, + rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight, + rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom); +} + + + + +const Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont ( + const Reference<rendering::XCanvas>& rxCanvas) const +{ + if (mpFont.get() != NULL) + mpFont->PrepareFont(rxCanvas); + return mpFont->mxFont; +} + + + + +void RendererPaneStyle::UpdateBorderSizes (void) +{ + maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft; + maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop; + maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight; + maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom; +} + + + + +SharedBitmapDescriptor RendererPaneStyle::GetBitmap( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName, + const OUString& rsBitmapName) +{ + SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName)); + if (pDescriptor.get() != NULL) + return pDescriptor; + else + return mpEmpty; +} + + + +} // end of anonymous namespace + + +} } // end of namespace ::sd::presenter |