/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: PresenterPaneBorderPainter.cxx,v $ * * $Revision: 1.6 $ * * 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 * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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& 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 GetFont ( const Reference& 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& rpTheme, const OUString& rsStyleName, const OUString& rsBitmapName); }; } class PresenterPaneBorderPainter::Renderer { public: Renderer ( const Reference& rxContext, const ::boost::shared_ptr& rpTheme); ~Renderer (void); void SetCanvas (const Reference& 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& 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 GetRendererPaneStyle (const OUString& rsResourceURL); void SetCalloutAnchor ( const awt::Point& rCalloutAnchor); private: ::boost::shared_ptr mpTheme; typedef ::std::map > RendererPaneStyleContainer; RendererPaneStyleContainer maRendererPaneStyles; Reference mxCanvas; Reference mxPresenterHelper; css::rendering::ViewState maViewState; Reference 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& 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& 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& 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 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& 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& 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 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 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(static_cast(this))); } } //===== PresenterPaneBorderPainter::Renderer ===================================== PresenterPaneBorderPainter::Renderer::Renderer ( const Reference& rxContext, const ::boost::shared_ptr& rpTheme) : mpTheme(rpTheme), maRendererPaneStyles(), mxCanvas(), mxPresenterHelper(), maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), mxViewStateClip(), mbHasCallout(false), maCalloutAnchor() { (void)rxContext; Reference xFactory (rxContext->getServiceManager()); if (xFactory.is()) { mxPresenterHelper = Reference( xFactory->createInstanceWithContext( OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"), rxContext), UNO_QUERY_THROW); } } PresenterPaneBorderPainter::Renderer::~Renderer (void) { } void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference& 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 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 xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is()) xSpriteCanvas->updateScreen(sal_False); } void PresenterPaneBorderPainter::Renderer::PaintTitle ( const OUString& rsTitle, const ::boost::shared_ptr& 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 xFont (rpStyle->GetFont(mxCanvas)); if ( ! xFont.is()) return; rendering::StringContext aContext ( rsTitle, 0, rsTitle.getLength()); Reference 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(4), rendering::CompositeOperation::SOURCE); if (bPaintBackground) { PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff)); Sequence > aPolygons(1); aPolygons[0] = Sequence(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 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 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 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(); } 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 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 xMaskedBitmap ( PresenterBitmapHelper::FillMaskedWithColor ( mxCanvas, Reference(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 xMask ( mxPresenterHelper->createMask( mxCanvas, rBitmap.mxMaskBitmap, nOutsideMaskColor, false)); xBitmap = mxPresenterHelper->applyBitmapMaskWithColor( mxCanvas, Reference(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(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 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 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& 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 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 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 RendererPaneStyle::GetFont ( const Reference& 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& 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