LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/basegfx/source/tools - unopolypolygon.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 9 183 4.9 %
Date: 2013-07-09 Functions: 2 21 9.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/geometry/AffineMatrix2D.hpp>
      21             : #include <com/sun/star/rendering/RenderState.hpp>
      22             : #include <com/sun/star/rendering/ViewState.hpp>
      23             : #include <com/sun/star/rendering/XCanvas.hpp>
      24             : #include <com/sun/star/rendering/CompositeOperation.hpp>
      25             : 
      26             : #include <basegfx/matrix/b2dhommatrix.hxx>
      27             : #include <basegfx/range/b2drange.hxx>
      28             : #include <basegfx/range/b2drectangle.hxx>
      29             : #include <basegfx/point/b2dpoint.hxx>
      30             : #include <basegfx/tools/canvastools.hxx>
      31             : #include <basegfx/polygon/b2dpolygon.hxx>
      32             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      33             : #include <basegfx/tools/unopolypolygon.hxx>
      34             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      35             : 
      36             : 
      37             : using namespace ::com::sun::star;
      38             : 
      39             : namespace basegfx
      40             : {
      41             : namespace unotools
      42             : {
      43          15 :     UnoPolyPolygon::UnoPolyPolygon( const B2DPolyPolygon& rPolyPoly ) :
      44             :         UnoPolyPolygonBase( m_aMutex ),
      45             :         maPolyPoly( rPolyPoly ),
      46          15 :         meFillRule( rendering::FillRule_EVEN_ODD )
      47             :     {
      48             :         // or else races will haunt us.
      49          15 :         maPolyPoly.makeUnique();
      50          15 :     }
      51             : 
      52           0 :     void SAL_CALL UnoPolyPolygon::addPolyPolygon(
      53             :         const geometry::RealPoint2D&                        position,
      54             :         const uno::Reference< rendering::XPolyPolygon2D >&  polyPolygon ) throw (lang::IllegalArgumentException,uno::RuntimeException)
      55             :     {
      56           0 :         osl::MutexGuard const guard( m_aMutex );
      57           0 :         modifying();
      58             : 
      59             :         // TODO(F1): Correctly fulfill the UNO API
      60             :         // specification. This will probably result in a vector of
      61             :         // poly-polygons to be stored in this object.
      62             : 
      63           0 :         const sal_Int32 nPolys( polyPolygon->getNumberOfPolygons() );
      64             : 
      65           0 :         if( !polyPolygon.is() || !nPolys )
      66             :         {
      67             :             // invalid or empty polygon - nothing to do.
      68           0 :             return;
      69             :         }
      70             : 
      71           0 :         B2DPolyPolygon        aSrcPoly;
      72           0 :         const UnoPolyPolygon* pSrc( dynamic_cast< UnoPolyPolygon* >(polyPolygon.get()) );
      73             : 
      74             :         // try to extract polygon data from interface. First,
      75             :         // check whether it's the same implementation object,
      76             :         // which we can tunnel then.
      77           0 :         if( pSrc )
      78             :         {
      79           0 :             aSrcPoly = pSrc->getPolyPolygon();
      80             :         }
      81             :         else
      82             :         {
      83             :             // not a known implementation object - try data source
      84             :             // interfaces
      85             :             uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
      86             :                 polyPolygon,
      87           0 :                 uno::UNO_QUERY );
      88             : 
      89           0 :             if( xBezierPoly.is() )
      90             :             {
      91           0 :                 aSrcPoly = unotools::polyPolygonFromBezier2DSequenceSequence(
      92           0 :                     xBezierPoly->getBezierSegments( 0,
      93             :                                                     nPolys,
      94             :                                                     0,
      95           0 :                                                     -1 ) );
      96             :             }
      97             :             else
      98             :             {
      99             :                 uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
     100             :                     polyPolygon,
     101           0 :                     uno::UNO_QUERY );
     102             : 
     103             :                 // no implementation class and no data provider
     104             :                 // found - contract violation.
     105           0 :                 if( !xLinePoly.is() )
     106             :                     throw lang::IllegalArgumentException(
     107             :                         "UnoPolyPolygon::addPolyPolygon(): Invalid input "
     108             :                         "poly-polygon, cannot retrieve vertex data",
     109           0 :                         static_cast<cppu::OWeakObject*>(this), 1);
     110             : 
     111           0 :                 aSrcPoly = unotools::polyPolygonFromPoint2DSequenceSequence(
     112           0 :                     xLinePoly->getPoints( 0,
     113             :                                           nPolys,
     114             :                                           0,
     115           0 :                                           -1 ) );
     116           0 :             }
     117             :         }
     118             : 
     119           0 :         const B2DRange  aBounds( tools::getRange( aSrcPoly ) );
     120           0 :         const B2DVector     aOffset( unotools::b2DPointFromRealPoint2D( position ) -
     121           0 :                                              aBounds.getMinimum() );
     122             : 
     123           0 :         if( !aOffset.equalZero() )
     124             :         {
     125           0 :             const B2DHomMatrix aTranslate(tools::createTranslateB2DHomMatrix(aOffset));
     126           0 :             aSrcPoly.transform( aTranslate );
     127             :         }
     128             : 
     129           0 :         maPolyPoly.append( aSrcPoly );
     130             :     }
     131             : 
     132           0 :     sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygons() throw (uno::RuntimeException)
     133             :     {
     134           0 :         osl::MutexGuard const guard( m_aMutex );
     135           0 :         return maPolyPoly.count();
     136             :     }
     137             : 
     138           0 :     sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygonPoints(
     139             :         sal_Int32 polygon ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     140             :     {
     141           0 :         osl::MutexGuard const guard( m_aMutex );
     142           0 :         checkIndex( polygon );
     143             : 
     144           0 :         return maPolyPoly.getB2DPolygon(polygon).count();
     145             :     }
     146             : 
     147           0 :     rendering::FillRule SAL_CALL UnoPolyPolygon::getFillRule() throw (uno::RuntimeException)
     148             :     {
     149           0 :         osl::MutexGuard const guard( m_aMutex );
     150           0 :         return meFillRule;
     151             :     }
     152             : 
     153           0 :     void SAL_CALL UnoPolyPolygon::setFillRule(
     154             :         rendering::FillRule fillRule ) throw (uno::RuntimeException)
     155             :     {
     156           0 :         osl::MutexGuard const guard( m_aMutex );
     157           0 :         modifying();
     158             : 
     159           0 :         meFillRule = fillRule;
     160           0 :     }
     161             : 
     162           0 :     sal_Bool SAL_CALL UnoPolyPolygon::isClosed(
     163             :         sal_Int32 index ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     164             :     {
     165           0 :         osl::MutexGuard const guard( m_aMutex );
     166           0 :         checkIndex( index );
     167             : 
     168           0 :         return maPolyPoly.getB2DPolygon(index).isClosed();
     169             :     }
     170             : 
     171           0 :     void SAL_CALL UnoPolyPolygon::setClosed(
     172             :         sal_Int32 index,
     173             :         sal_Bool closedState ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     174             :     {
     175           0 :         osl::MutexGuard const guard( m_aMutex );
     176           0 :         modifying();
     177             : 
     178           0 :         if( index == -1L )
     179             :         {
     180             :             // set all
     181           0 :             maPolyPoly.setClosed( closedState );
     182             :         }
     183             :         else
     184             :         {
     185           0 :             checkIndex( index );
     186             : 
     187             :             // fetch referenced polygon, change state
     188           0 :             B2DPolygon aTmp( maPolyPoly.getB2DPolygon(index) );
     189           0 :             aTmp.setClosed( closedState );
     190             : 
     191             :             // set back to container
     192           0 :             maPolyPoly.setB2DPolygon( index, aTmp );
     193           0 :         }
     194           0 :     }
     195             : 
     196           0 :     uno::Sequence< uno::Sequence< geometry::RealPoint2D > > SAL_CALL UnoPolyPolygon::getPoints(
     197             :         sal_Int32 nPolygonIndex,
     198             :         sal_Int32 nNumberOfPolygons,
     199             :         sal_Int32 nPointIndex,
     200             :         sal_Int32 nNumberOfPoints ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     201             :     {
     202           0 :         osl::MutexGuard const guard( m_aMutex );
     203             : 
     204             :         return unotools::pointSequenceSequenceFromB2DPolyPolygon(
     205             :             getSubsetPolyPolygon( nPolygonIndex,
     206             :                                   nNumberOfPolygons,
     207             :                                   nPointIndex,
     208           0 :                                   nNumberOfPoints ) );
     209             :     }
     210             : 
     211           0 :     void SAL_CALL UnoPolyPolygon::setPoints(
     212             :         const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points,
     213             :         sal_Int32 nPolygonIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     214             :     {
     215           0 :         osl::MutexGuard const guard( m_aMutex );
     216           0 :         modifying();
     217             : 
     218             :         const B2DPolyPolygon& rNewPolyPoly(
     219           0 :             unotools::polyPolygonFromPoint2DSequenceSequence( points ) );
     220             : 
     221           0 :         if( nPolygonIndex == -1 )
     222             :         {
     223           0 :             maPolyPoly = rNewPolyPoly;
     224             :         }
     225             :         else
     226             :         {
     227           0 :             checkIndex( nPolygonIndex );
     228             : 
     229           0 :             maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
     230           0 :         }
     231           0 :     }
     232             : 
     233           0 :     geometry::RealPoint2D SAL_CALL UnoPolyPolygon::getPoint(
     234             :         sal_Int32 nPolygonIndex,
     235             :         sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     236             :     {
     237           0 :         osl::MutexGuard const guard( m_aMutex );
     238           0 :         checkIndex( nPolygonIndex );
     239             : 
     240           0 :         const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
     241             : 
     242           0 :         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(rPoly.count()) )
     243           0 :             throw lang::IndexOutOfBoundsException();
     244             : 
     245           0 :         return unotools::point2DFromB2DPoint( rPoly.getB2DPoint( nPointIndex ) );
     246             :     }
     247             : 
     248           0 :     void SAL_CALL UnoPolyPolygon::setPoint(
     249             :         const geometry::RealPoint2D& point,
     250             :         sal_Int32 nPolygonIndex,
     251             :         sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
     252             :     {
     253           0 :         osl::MutexGuard const guard( m_aMutex );
     254           0 :         checkIndex( nPolygonIndex );
     255           0 :         modifying();
     256             : 
     257           0 :         B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
     258             : 
     259           0 :         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(aPoly.count()) )
     260           0 :             throw lang::IndexOutOfBoundsException();
     261             : 
     262             :         aPoly.setB2DPoint( nPointIndex,
     263           0 :                            unotools::b2DPointFromRealPoint2D( point ) );
     264           0 :         maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
     265           0 :     }
     266             : 
     267           0 :     uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > SAL_CALL UnoPolyPolygon::getBezierSegments(
     268             :         sal_Int32 nPolygonIndex,
     269             :         sal_Int32 nNumberOfPolygons,
     270             :         sal_Int32 nPointIndex,
     271             :         sal_Int32 nNumberOfPoints ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
     272             :     {
     273           0 :         osl::MutexGuard const guard( m_aMutex );
     274             :         return unotools::bezierSequenceSequenceFromB2DPolyPolygon(
     275             :             getSubsetPolyPolygon( nPolygonIndex,
     276             :                                   nNumberOfPolygons,
     277             :                                   nPointIndex,
     278           0 :                                   nNumberOfPoints ) );
     279             :     }
     280             : 
     281           0 :     void SAL_CALL UnoPolyPolygon::setBezierSegments(
     282             :         const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >&  points,
     283             :         sal_Int32                                                               nPolygonIndex ) throw (lang::IndexOutOfBoundsException,
     284             :                                                                                                        uno::RuntimeException)
     285             :     {
     286           0 :         osl::MutexGuard const guard( m_aMutex );
     287           0 :         modifying();
     288             :         const B2DPolyPolygon& rNewPolyPoly(
     289           0 :             unotools::polyPolygonFromBezier2DSequenceSequence( points ) );
     290             : 
     291           0 :         if( nPolygonIndex == -1 )
     292             :         {
     293           0 :             maPolyPoly = rNewPolyPoly;
     294             :         }
     295             :         else
     296             :         {
     297           0 :             checkIndex( nPolygonIndex );
     298             : 
     299           0 :             maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
     300           0 :         }
     301           0 :     }
     302             : 
     303           0 :     geometry::RealBezierSegment2D SAL_CALL UnoPolyPolygon::getBezierSegment( sal_Int32 nPolygonIndex,
     304             :                                                                              sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,
     305             :                                                                                                             uno::RuntimeException)
     306             :     {
     307           0 :         osl::MutexGuard const guard( m_aMutex );
     308           0 :         checkIndex( nPolygonIndex );
     309             : 
     310           0 :         const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
     311           0 :         const sal_uInt32  nPointCount(rPoly.count());
     312             : 
     313           0 :         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
     314           0 :             throw lang::IndexOutOfBoundsException();
     315             : 
     316           0 :         const B2DPoint& rPt( rPoly.getB2DPoint( nPointIndex ) );
     317           0 :         const B2DPoint& rCtrl0( rPoly.getNextControlPoint(nPointIndex) );
     318           0 :         const B2DPoint& rCtrl1( rPoly.getPrevControlPoint((nPointIndex + 1) % nPointCount) );
     319             : 
     320           0 :         return geometry::RealBezierSegment2D( rPt.getX(),
     321           0 :                                               rPt.getY(),
     322           0 :                                               rCtrl0.getX(),
     323           0 :                                               rCtrl0.getY(),
     324           0 :                                               rCtrl1.getX(),
     325           0 :                                               rCtrl1.getY() );
     326             :     }
     327             : 
     328           0 :     void SAL_CALL UnoPolyPolygon::setBezierSegment( const geometry::RealBezierSegment2D& segment,
     329             :                                                          sal_Int32                       nPolygonIndex,
     330             :                                                          sal_Int32                       nPointIndex ) throw (lang::IndexOutOfBoundsException,
     331             :                                                                                                               uno::RuntimeException)
     332             :     {
     333           0 :         osl::MutexGuard const guard( m_aMutex );
     334           0 :         checkIndex( nPolygonIndex );
     335           0 :         modifying();
     336             : 
     337           0 :         B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
     338           0 :         const sal_uInt32 nPointCount(aPoly.count());
     339             : 
     340           0 :         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
     341           0 :             throw lang::IndexOutOfBoundsException();
     342             : 
     343             :         aPoly.setB2DPoint( nPointIndex,
     344             :                            B2DPoint( segment.Px,
     345           0 :                                      segment.Py ) );
     346             :         aPoly.setNextControlPoint(nPointIndex,
     347           0 :                                   B2DPoint(segment.C1x, segment.C1y));
     348           0 :         aPoly.setPrevControlPoint((nPointIndex + 1) % nPointCount,
     349           0 :                                   B2DPoint(segment.C2x, segment.C2y));
     350             : 
     351           0 :         maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
     352           0 :     }
     353             : 
     354           0 :     B2DPolyPolygon UnoPolyPolygon::getSubsetPolyPolygon(
     355             :         sal_Int32 nPolygonIndex,
     356             :         sal_Int32 nNumberOfPolygons,
     357             :         sal_Int32 nPointIndex,
     358             :         sal_Int32 nNumberOfPoints ) const
     359             :     {
     360           0 :         osl::MutexGuard const guard( m_aMutex );
     361           0 :         checkIndex( nPolygonIndex );
     362             : 
     363           0 :         const sal_Int32 nPolyCount( maPolyPoly.count() );
     364             : 
     365             :         // check for "full polygon" case
     366           0 :         if( !nPolygonIndex &&
     367           0 :             !nPointIndex &&
     368           0 :             nNumberOfPolygons == nPolyCount &&
     369             :             nNumberOfPoints == -1 )
     370             :         {
     371           0 :             return maPolyPoly;
     372             :         }
     373             : 
     374           0 :         B2DPolyPolygon aSubsetPoly;
     375             : 
     376             :         // create temporary polygon (as an extract from maPoly,
     377             :         // which contains the requested subset)
     378           0 :         for( sal_Int32 i=nPolygonIndex; i<nNumberOfPolygons; ++i )
     379             :         {
     380           0 :             checkIndex(i);
     381             : 
     382           0 :             const B2DPolygon& rCurrPoly( maPolyPoly.getB2DPolygon(i) );
     383             : 
     384           0 :             sal_Int32 nFirstPoint(0);
     385           0 :             sal_Int32 nLastPoint(nPolyCount-1);
     386             : 
     387           0 :             if( nPointIndex && i==nPolygonIndex )
     388             :             {
     389             :                 // very first polygon - respect nPointIndex, if
     390             :                 // not zero
     391             : 
     392             :                 // empty polygon - impossible to specify _any_
     393             :                 // legal value except 0 here!
     394           0 :                 if( !nPolyCount && nPointIndex )
     395           0 :                     throw lang::IndexOutOfBoundsException();
     396             : 
     397           0 :                 nFirstPoint = nPointIndex;
     398             :             }
     399             : 
     400           0 :             if( i==nNumberOfPolygons-1 && nNumberOfPoints != -1 )
     401             :             {
     402             :                 // very last polygon - respect nNumberOfPoints
     403             : 
     404             :                 // empty polygon - impossible to specify _any_
     405             :                 // legal value except -1 here!
     406           0 :                 if( !nPolyCount )
     407           0 :                     throw lang::IndexOutOfBoundsException();
     408             : 
     409           0 :                 nLastPoint = nFirstPoint+nNumberOfPoints;
     410             :             }
     411             : 
     412           0 :             if( !nPolyCount )
     413             :             {
     414             :                 // empty polygon - index checks already performed
     415             :                 // above, now simply append empty polygon
     416           0 :                 aSubsetPoly.append( rCurrPoly );
     417             :             }
     418             :             else
     419             :             {
     420           0 :                 if( nFirstPoint < 0 || nFirstPoint >= nPolyCount )
     421           0 :                     throw lang::IndexOutOfBoundsException();
     422             : 
     423           0 :                 if( nLastPoint < 0 || nLastPoint >= nPolyCount )
     424           0 :                     throw lang::IndexOutOfBoundsException();
     425             : 
     426           0 :                 B2DPolygon aTmp;
     427           0 :                 for( sal_Int32 j=nFirstPoint; j<nLastPoint; ++j )
     428           0 :                     aTmp.append( rCurrPoly.getB2DPoint(j) );
     429             : 
     430           0 :                 aSubsetPoly.append( aTmp );
     431             :             }
     432           0 :         }
     433             : 
     434           0 :         return aSubsetPoly;
     435             :     }
     436             : 
     437             : #define IMPLEMENTATION_NAME "gfx::internal::UnoPolyPolygon"
     438             : #define SERVICE_NAME "com.sun.star.rendering.PolyPolygon2D"
     439           0 :     OUString SAL_CALL UnoPolyPolygon::getImplementationName() throw( uno::RuntimeException )
     440             :     {
     441           0 :         return OUString( IMPLEMENTATION_NAME );
     442             :     }
     443             : 
     444           0 :     sal_Bool SAL_CALL UnoPolyPolygon::supportsService( const OUString& ServiceName ) throw( uno::RuntimeException )
     445             :     {
     446           0 :         return ServiceName == SERVICE_NAME;
     447             :     }
     448             : 
     449           0 :     uno::Sequence< OUString > SAL_CALL UnoPolyPolygon::getSupportedServiceNames()  throw( uno::RuntimeException )
     450             :     {
     451           0 :         uno::Sequence< OUString > aRet(1);
     452           0 :         aRet[0] = SERVICE_NAME ;
     453             : 
     454           0 :         return aRet;
     455             :     }
     456             : 
     457          15 :     B2DPolyPolygon UnoPolyPolygon::getPolyPolygon() const
     458             :     {
     459          15 :         osl::MutexGuard const guard( m_aMutex );
     460             : 
     461             :         // detach result from us
     462          15 :         B2DPolyPolygon aRet( maPolyPoly );
     463          15 :         aRet.makeUnique();
     464          15 :         return aRet;
     465             :     }
     466             : 
     467             : }
     468             : }
     469             : 
     470             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10