LCOV - code coverage report
Current view: top level - editeng/source/misc - txtrange.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 164 345 47.5 %
Date: 2012-08-25 Functions: 18 27 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 136 486 28.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <editeng/txtrange.hxx>
      31                 :            : #include <math.h>
      32                 :            : #include <tools/poly.hxx>
      33                 :            : #include <tools/debug.hxx>
      34                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      35                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      36                 :            : 
      37                 :            : #include <vector>
      38                 :            : 
      39                 :         16 : TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon,
      40                 :            :                         const basegfx::B2DPolyPolygon* pLinePolyPolygon,
      41                 :            :                         sal_uInt16 nCacheSz, sal_uInt16 nLft, sal_uInt16 nRght,
      42                 :            :                         sal_Bool bSimpl, sal_Bool bInnr, sal_Bool bVert ) :
      43                 :            :     pBound( NULL ),
      44                 :            :     nCacheSize( nCacheSz ),
      45                 :            :     nRight( nRght ),
      46                 :            :     nLeft( nLft ),
      47                 :            :     nUpper( 0 ),
      48                 :            :     nLower( 0 ),
      49                 :            :     nPointCount( 0 ),
      50                 :            :     bSimple( bSimpl ),
      51                 :            :     bInner( bInnr ),
      52                 :         16 :     bVertical( bVert )
      53                 :            : {
      54                 :            : #ifdef DBG_UTIL
      55                 :            :     bFlag3 = bFlag4 = bFlag5 = bFlag6 = bFlag7 = sal_False;
      56                 :            : #endif
      57         [ +  - ]:         16 :     sal_uInt32 nCount(rPolyPolygon.count());
      58 [ +  - ][ +  - ]:         16 :     mpPolyPolygon = new PolyPolygon( (sal_uInt16)nCount );
      59                 :            : 
      60         [ +  + ]:         32 :     for(sal_uInt32 i(0L); i < nCount; i++)
      61                 :            :     {
      62 [ +  - ][ +  - ]:         16 :         const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision());
                 [ +  - ]
      63         [ +  - ]:         16 :         nPointCount += aCandidate.count();
      64 [ +  - ][ +  - ]:         16 :         mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
                 [ +  - ]
      65         [ +  - ]:         16 :     }
      66                 :            : 
      67         [ -  + ]:         16 :     if( pLinePolyPolygon )
      68                 :            :     {
      69         [ #  # ]:          0 :         nCount = pLinePolyPolygon->count();
      70 [ #  # ][ #  # ]:          0 :         mpLinePolyPolygon = new PolyPolygon();
      71                 :            : 
      72         [ #  # ]:          0 :         for(sal_uInt32 i(0L); i < nCount; i++)
      73                 :            :         {
      74 [ #  # ][ #  # ]:          0 :             const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision());
                 [ #  # ]
      75         [ #  # ]:          0 :             nPointCount += aCandidate.count();
      76 [ #  # ][ #  # ]:          0 :             mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
                 [ #  # ]
      77         [ #  # ]:          0 :         }
      78                 :            :     }
      79                 :            :     else
      80                 :         16 :         mpLinePolyPolygon = NULL;
      81                 :         16 : }
      82                 :            : 
      83                 :            : 
      84                 :         16 : TextRanger::~TextRanger()
      85                 :            : {
      86                 :         16 :     mRangeCache.clear();
      87 [ +  - ][ +  - ]:         16 :     delete mpPolyPolygon;
      88 [ -  + ][ #  # ]:         16 :     delete mpLinePolyPolygon;
      89                 :         16 : }
      90                 :            : 
      91                 :            : /* TextRanger::SetVertical(..)
      92                 :            :    If there's is a change in the writing direction,
      93                 :            :    the cache has to be cleared.
      94                 :            : */
      95                 :          0 : void TextRanger::SetVertical( sal_Bool bNew )
      96                 :            : {
      97         [ #  # ]:          0 :     if( IsVertical() != bNew )
      98                 :            :     {
      99                 :          0 :         bVertical = bNew;
     100                 :          0 :         mRangeCache.clear();
     101                 :            :     }
     102                 :          0 : }
     103                 :            : 
     104                 :            : //! SvxBoundArgs is used to perform temporary calculations on a range array.
     105                 :            : //! Temporary instances are created in TextRanger::GetTextRanges()
     106                 :         16 : class SvxBoundArgs
     107                 :            : {
     108                 :            :     std::vector<bool> aBoolArr;
     109                 :            :     LongDqPtr pLongArr;
     110                 :            :     TextRanger *pTextRanger;
     111                 :            :     long nMin;
     112                 :            :     long nMax;
     113                 :            :     long nTop;
     114                 :            :     long nBottom;
     115                 :            :     long nUpDiff;
     116                 :            :     long nLowDiff;
     117                 :            :     long nUpper;
     118                 :            :     long nLower;
     119                 :            :     long nStart;
     120                 :            :     long nEnd;
     121                 :            :     sal_uInt16 nCut;
     122                 :            :     sal_uInt16 nLast;
     123                 :            :     sal_uInt16 nNext;
     124                 :            :     sal_uInt8 nAct;
     125                 :            :     sal_uInt8 nFirst;
     126                 :            :     sal_Bool bClosed : 1;
     127                 :            :     sal_Bool bInner : 1;
     128                 :            :     sal_Bool bMultiple : 1;
     129                 :            :     sal_Bool bConcat : 1;
     130                 :            :     sal_Bool bRotate : 1;
     131                 :            :     void NoteRange( bool bToggle );
     132                 :            :     long Cut( long nY, const Point& rPt1, const Point& rPt2 );
     133                 :            :     void Add();
     134                 :            :     void _NoteFarPoint( long nPx, long nPyDiff, long nDiff );
     135                 :          0 :     void NoteFarPoint( long nPx, long nPyDiff, long nDiff )
     136         [ #  # ]:          0 :         { if( nDiff ) _NoteFarPoint( nPx, nPyDiff, nDiff ); }
     137                 :            :     long CalcMax( const Point& rPt1, const Point& rPt2, long nRange, long nFar );
     138                 :            :     void CheckCut( const Point& rLst, const Point& rNxt );
     139         [ #  # ]:          0 :     inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); }
     140         [ -  + ]:         96 :     inline long B( const Point& rP ) const { return bRotate ? rP.X() : rP.Y(); }
     141                 :            : public:
     142                 :            :     SvxBoundArgs( TextRanger* pRanger, LongDqPtr pLong, const Range& rRange );
     143                 :         64 :     void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); }
     144                 :        111 :     void NoteMargin( const long nL, const long nR )
     145 [ +  + ][ -  + ]:        111 :         { if( nMin > nL ) nMin = nL; if( nMax < nR ) nMax = nR; }
     146                 :            :     sal_uInt16 Area( const Point& rPt );
     147                 :            :     void NoteUpLow( long nA, const sal_uInt8 nArea );
     148                 :            :     void Calc( const PolyPolygon& rPoly );
     149                 :            :     void Concat( const PolyPolygon* pPoly );
     150                 :            :     // inlines
     151         [ #  # ]:          0 :     void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); }
     152                 :         16 :     void SetClosed( const sal_Bool bNew ){ bClosed = bNew; }
     153                 :         16 :     sal_Bool IsClosed() const { return bClosed; }
     154                 :          0 :     void SetConcat( const sal_Bool bNew ){ bConcat = bNew; }
     155                 :         18 :     sal_Bool IsConcat() const { return bConcat; }
     156                 :            :     sal_uInt8 GetAct() const { return nAct; }
     157                 :            : };
     158                 :            : 
     159                 :         16 : SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, LongDqPtr pLong,
     160                 :            :     const Range& rRange )
     161                 :            :     : pLongArr( pLong ), pTextRanger( pRanger ),
     162                 :         16 :     nTop( rRange.Min() ), nBottom( rRange.Max() ),
     163                 :         32 :     bInner( pRanger->IsInner() ), bMultiple( bInner || !pRanger->IsSimple() ),
     164   [ +  -  +  + ]:         48 :     bConcat( sal_False ), bRotate( pRanger->IsVertical() )
     165                 :            : {
     166         [ -  + ]:         16 :     if( bRotate )
     167                 :            :     {
     168                 :          0 :         nStart = pRanger->GetUpper();
     169                 :          0 :         nEnd = pRanger->GetLower();
     170                 :          0 :         nLowDiff = pRanger->GetLeft();
     171                 :          0 :         nUpDiff = pRanger->GetRight();
     172                 :            :     }
     173                 :            :     else
     174                 :            :     {
     175                 :         16 :         nStart = pRanger->GetLeft();
     176                 :         16 :         nEnd = pRanger->GetRight();
     177                 :         16 :         nLowDiff = pRanger->GetUpper();
     178                 :         16 :         nUpDiff = pRanger->GetLower();
     179                 :            :     }
     180                 :         16 :     nUpper = nTop - nUpDiff;
     181                 :         16 :     nLower = nBottom + nLowDiff;
     182                 :         16 :     pLongArr->clear();
     183                 :         16 : }
     184                 :            : 
     185                 :          0 : long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2,
     186                 :            :     long nRange, long nFarRange )
     187                 :            : {
     188                 :          0 :     double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 );
     189                 :            :     double nB;
     190         [ #  # ]:          0 :     if( nDa < 0 )
     191                 :            :     {
     192                 :          0 :         nDa = -nDa;
     193                 :          0 :         nB = nEnd;
     194                 :            :     }
     195                 :            :     else
     196                 :          0 :         nB = nStart;
     197                 :          0 :     nB *= nB;
     198                 :          0 :     nB += nDa * nDa;
     199                 :          0 :     nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB );
     200                 :            : 
     201                 :            :     sal_Bool bNote;
     202         [ #  # ]:          0 :     if( nB < B(rPt2) )
     203                 :          0 :         bNote = nB > B(rPt1);
     204                 :            :     else
     205                 :          0 :         bNote = nB < B(rPt1);
     206         [ #  # ]:          0 :     if( bNote )
     207                 :          0 :         return( long( nB ) );
     208                 :          0 :     return 0;
     209                 :            : }
     210                 :            : 
     211                 :         62 : void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt )
     212                 :            : {
     213         [ +  + ]:         62 :     if( nCut & 1 )
     214                 :         32 :         NotePoint( Cut( nBottom, rLst, rNxt ) );
     215         [ +  + ]:         62 :     if( nCut & 2 )
     216                 :         32 :         NotePoint( Cut( nTop, rLst, rNxt ) );
     217 [ +  + ][ -  + ]:         62 :     if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() )
                 [ -  + ]
     218                 :            :     {
     219                 :            :         long nYps;
     220 [ #  # ][ #  # ]:          0 :         if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) )
         [ #  # ][ #  # ]
     221                 :            :         {
     222                 :          0 :             nYps = CalcMax( rLst, rNxt, nBottom, nLower );
     223         [ #  # ]:          0 :             if( nYps )
     224                 :          0 :                 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff );
     225                 :            :         }
     226 [ #  # ][ #  # ]:          0 :         if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) )
         [ #  # ][ #  # ]
     227                 :            :         {
     228                 :          0 :             nYps = CalcMax( rLst, rNxt, nTop, nUpper );
     229         [ #  # ]:          0 :             if( nYps )
     230                 :          0 :                 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff );
     231                 :            :         }
     232                 :            :     }
     233                 :         62 : }
     234                 :            : 
     235                 :          0 : void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff )
     236                 :            : {
     237                 :            :     long nTmpA;
     238                 :          0 :     double nQuot = 2 * nDiff - nPbDiff;
     239                 :          0 :     nQuot *= nPbDiff;
     240                 :          0 :     nQuot = sqrt( nQuot );
     241                 :          0 :     nQuot /= nDiff;
     242                 :          0 :     nTmpA = nPa - long( nStart * nQuot );
     243                 :          0 :     nPbDiff = nPa + long( nEnd * nQuot );
     244                 :          0 :     NoteMargin( nTmpA, nPbDiff );
     245                 :          0 : }
     246                 :            : 
     247                 :          2 : void SvxBoundArgs::NoteRange( bool bToggle )
     248                 :            : {
     249                 :            :     DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?");
     250         [ -  + ]:          2 :     if( nMax < nMin )
     251                 :          2 :         return;
     252         [ -  + ]:          2 :     if( !bClosed )
     253                 :          0 :         bToggle = sal_False;
     254                 :          2 :     sal_uInt16 nIdx = 0;
     255                 :          2 :     sal_uInt16 nCount = pLongArr->size();
     256                 :            :     DBG_ASSERT( nCount == 2 * aBoolArr.size(), "NoteRange: Incompatible Sizes" );
     257 [ +  + ][ -  + ]:          2 :     while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin )
                 [ -  + ]
     258                 :          0 :         ++nIdx;
     259                 :          2 :     sal_Bool bOdd = (nIdx % 2) ? sal_True : sal_False;
     260                 :            :     // No overlap with existing intervals?
     261 [ +  + ][ +  - ]:          2 :     if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) )
         [ +  - ][ +  - ]
     262                 :            :     {   // Then a new one is inserted ...
     263 [ +  - ][ +  - ]:          2 :         pLongArr->insert( pLongArr->begin() + nIdx, nMin );
     264 [ +  - ][ +  - ]:          2 :         pLongArr->insert( pLongArr->begin() + nIdx + 1, nMax );
                 [ +  - ]
     265         [ +  - ]:          2 :         aBoolArr.insert( aBoolArr.begin() + (nIdx/2), bToggle );
     266                 :            :     }
     267                 :            :     else
     268                 :            :     {   // expand an existing interval ...
     269                 :          0 :         sal_uInt16 nMaxIdx = nIdx;
     270                 :            :         // If we end up on a left interval boundary, it must be reduced to nMin.
     271         [ #  # ]:          0 :         if( bOdd )
     272                 :          0 :             --nIdx;
     273                 :            :         else
     274                 :          0 :             (*pLongArr)[ nIdx ] = nMin;
     275 [ #  # ][ #  # ]:          0 :         while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax )
                 [ #  # ]
     276                 :          0 :             ++nMaxIdx;
     277                 :            :         DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." );
     278         [ #  # ]:          0 :         if( nMaxIdx )
     279                 :          0 :             --nMaxIdx;
     280         [ #  # ]:          0 :         if( nMaxIdx < nIdx )
     281                 :          0 :             nMaxIdx = nIdx;
     282                 :            :         // If we end up on a right interval boundary, it must be raised to nMax.
     283         [ #  # ]:          0 :         if( nMaxIdx % 2 )
     284                 :          0 :             (*pLongArr)[ nMaxIdx-- ] = nMax;
     285                 :            :         // Possible merge of intervals.
     286                 :          0 :         sal_uInt16 nDiff = nMaxIdx - nIdx;
     287                 :          0 :         nMaxIdx = nIdx / 2; // From here on is nMaxIdx the Index in BoolArray.
     288         [ #  # ]:          0 :         if( nDiff )
     289                 :            :         {
     290 [ #  # ][ #  # ]:          0 :             pLongArr->erase( pLongArr->begin() + nIdx + 1, pLongArr->begin() + nIdx + 1 + nDiff );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     291                 :          0 :             nDiff /= 2;
     292                 :          0 :             sal_uInt16 nStop = nMaxIdx + nDiff;
     293         [ #  # ]:          0 :             for( sal_uInt16 i = nMaxIdx; i < nStop; ++i )
     294                 :          0 :                 bToggle ^= aBoolArr[ i ];
     295         [ #  # ]:          0 :             aBoolArr.erase( aBoolArr.begin() + nMaxIdx, aBoolArr.begin() + (nMaxIdx + nDiff) );
     296                 :            :         }
     297                 :            :         DBG_ASSERT( nMaxIdx < aBoolArr.size(), "NoteRange: Too much deleted" );
     298         [ #  # ]:          0 :         aBoolArr[ nMaxIdx ] = aBoolArr[ nMaxIdx ] ^ bToggle;
     299                 :            :     }
     300                 :            : }
     301                 :            : 
     302                 :         16 : void SvxBoundArgs::Calc( const PolyPolygon& rPoly )
     303                 :            : {
     304                 :            :     sal_uInt16 nCount;
     305                 :         16 :     nAct = 0;
     306         [ +  + ]:         32 :     for( sal_uInt16 i = 0; i < rPoly.Count(); ++i )
     307                 :            :     {
     308                 :         16 :         const Polygon& rPol = rPoly[ i ];
     309                 :         16 :         nCount = rPol.GetSize();
     310         [ +  - ]:         16 :         if( nCount )
     311                 :            :         {
     312                 :         16 :             const Point& rNull = rPol[ 0 ];
     313 [ +  - ][ +  - ]:         16 :             SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) );
     314                 :         16 :             nLast = Area( rNull );
     315         [ +  - ]:         16 :             if( nLast & 12 )
     316                 :            :             {
     317                 :         16 :                 nFirst = 3;
     318         [ +  + ]:         16 :                 if( bMultiple )
     319                 :          1 :                     nAct = 0;
     320                 :            :             }
     321                 :            :             else
     322                 :            :             {
     323                 :            :                 // The first point of the polygon is within the line.
     324         [ #  # ]:          0 :                 if( nLast )
     325                 :            :                 {
     326 [ #  # ][ #  # ]:          0 :                     if( bMultiple || !nAct )
     327                 :            :                     {
     328                 :          0 :                         nMin = USHRT_MAX;
     329                 :          0 :                         nMax = 0;
     330                 :            :                     }
     331         [ #  # ]:          0 :                     if( nLast & 1 )
     332                 :          0 :                         NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff );
     333                 :            :                     else
     334                 :          0 :                         NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff );
     335                 :            :                 }
     336                 :            :                 else
     337                 :            :                 {
     338 [ #  # ][ #  # ]:          0 :                     if( bMultiple || !nAct )
     339                 :            :                     {
     340                 :          0 :                         nMin = A(rNull);
     341                 :          0 :                         nMax = nMin + nEnd;
     342                 :          0 :                         nMin -= nStart;
     343                 :            :                     }
     344                 :            :                     else
     345                 :          0 :                         NotePoint( A(rNull) );
     346                 :            :                 }
     347                 :          0 :                 nFirst = 0; // leaving the line in which direction?
     348                 :          0 :                 nAct = 3;   // we are within the line at the moment.
     349                 :            :             }
     350         [ +  - ]:         16 :             if( nCount > 1 )
     351                 :            :             {
     352                 :         16 :                 sal_uInt16 nIdx = 1;
     353                 :         80 :                 while( sal_True )
     354                 :            :                 {
     355                 :         80 :                     const Point& rLast = rPol[ nIdx - 1 ];
     356         [ +  + ]:         80 :                     if( nIdx == nCount )
     357                 :         16 :                         nIdx = 0;
     358                 :         80 :                     const Point& rNext = rPol[ nIdx ];
     359                 :         80 :                     nNext = Area( rNext );
     360                 :         80 :                     nCut = nNext ^ nLast;
     361                 :         80 :                     sal_uInt16 nOldAct = nAct;
     362         [ +  + ]:         80 :                     if( nAct )
     363                 :         45 :                         CheckCut( rLast, rNext );
     364         [ +  + ]:         80 :                     if( nCut & 4 )
     365                 :            :                     {
     366                 :         32 :                         NoteUpLow( Cut( nLower, rLast, rNext ), 2 );
     367 [ +  + ][ +  - ]:         32 :                         if( nAct && nAct != nOldAct )
     368                 :            :                         {
     369                 :         17 :                             nOldAct = nAct;
     370                 :         17 :                             CheckCut( rLast, rNext );
     371                 :            :                         }
     372                 :            :                     }
     373         [ +  + ]:         80 :                     if( nCut & 8 )
     374                 :            :                     {
     375                 :         32 :                         NoteUpLow( Cut( nUpper, rLast, rNext ), 1 );
     376 [ -  + ][ +  + ]:         32 :                         if( nAct && nAct != nOldAct )
     377                 :          0 :                             CheckCut( rLast, rNext );
     378                 :            :                     }
     379         [ +  + ]:         80 :                     if( !nIdx )
     380                 :            :                     {
     381         [ -  + ]:         16 :                         if( !( nNext & 12 ) )
     382                 :          0 :                             NoteLast();
     383                 :         16 :                         break;
     384                 :            :                     }
     385         [ -  + ]:         64 :                     if( !( nNext & 12 ) )
     386                 :            :                     {
     387         [ #  # ]:          0 :                         if( !nNext )
     388                 :          0 :                             NotePoint( A(rNext) );
     389         [ #  # ]:          0 :                         else if( nNext & 1 )
     390                 :          0 :                             NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff );
     391                 :            :                         else
     392                 :          0 :                             NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff );
     393                 :            :                     }
     394                 :         64 :                     nLast = nNext;
     395 [ +  + ][ -  + ]:         64 :                     if( ++nIdx == nCount && !IsClosed() )
                 [ -  + ]
     396                 :            :                     {
     397         [ #  # ]:          0 :                         if( !( nNext & 12 ) )
     398                 :          0 :                             NoteLast();
     399                 :          0 :                         break;
     400                 :            :                     }
     401                 :            :                 }
     402                 :            :             }
     403 [ +  + ][ -  + ]:         16 :             if( bMultiple && IsConcat() )
                 [ -  + ]
     404                 :            :             {
     405                 :          0 :                 Add();
     406                 :          0 :                 nAct = 0;
     407                 :            :             }
     408                 :            :         }
     409                 :            :     }
     410         [ +  + ]:         16 :     if( !bMultiple )
     411                 :            :     {
     412                 :            :         DBG_ASSERT( pLongArr->empty(), "I said: Simple!" );
     413         [ +  - ]:         15 :         if( nAct )
     414                 :            :         {
     415         [ -  + ]:         15 :             if( bInner )
     416                 :            :             {
     417                 :          0 :                 long nTmpMin = nMin + 2 * nStart;
     418                 :          0 :                 long nTmpMax = nMax - 2 * nEnd;
     419         [ #  # ]:          0 :                 if( nTmpMin <= nTmpMax )
     420                 :            :                 {
     421         [ #  # ]:          0 :                     pLongArr->push_front(nTmpMax);
     422         [ #  # ]:          0 :                     pLongArr->push_front(nTmpMin);
     423                 :            :                 }
     424                 :            :             }
     425                 :            :             else
     426                 :            :             {
     427                 :         15 :                 pLongArr->push_front(nMax);
     428                 :         15 :                 pLongArr->push_front(nMin);
     429                 :            :             }
     430                 :            :         }
     431                 :            :     }
     432         [ +  - ]:          1 :     else if( !IsConcat() )
     433                 :          1 :         Add();
     434                 :         16 : }
     435                 :            : 
     436                 :          1 : void SvxBoundArgs::Add()
     437                 :            : {
     438                 :          1 :     size_t nCount = aBoolArr.size();
     439 [ -  + ][ #  # ]:          1 :     if( nCount && ( !bInner || !pTextRanger->IsSimple() ) )
         [ +  - ][ +  - ]
     440                 :            :     {
     441                 :          1 :         sal_Bool bDelete = aBoolArr.front();
     442         [ -  + ]:          1 :         if( bInner )
     443                 :          0 :             bDelete = !bDelete;
     444                 :          1 :         sal_uInt16 nLongIdx = 1;
     445         [ +  + ]:          2 :         for( size_t nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx )
     446                 :            :         {
     447         [ +  - ]:          1 :             if( bDelete )
     448                 :            :             {
     449                 :          1 :                 sal_uInt16 next = 2;
     450 [ +  - ][ +  - ]:          1 :                 while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] &&
         [ -  + ][ #  # ]
         [ #  # ][ +  - ]
           [ -  +  #  # ]
     451                 :          0 :                        (!bInner || nBoolIdx < nCount ) )
     452                 :          0 :                     next += 2;
     453 [ +  - ][ +  - ]:          1 :                 pLongArr->erase( pLongArr->begin() + nLongIdx, pLongArr->begin() + nLongIdx + next );
         [ +  - ][ +  - ]
     454                 :          1 :                 next /= 2;
     455                 :          1 :                 nBoolIdx = nBoolIdx - next;
     456                 :          1 :                 nCount = nCount - next;
     457         [ +  - ]:          1 :                 aBoolArr.erase( aBoolArr.begin() + nBoolIdx, aBoolArr.begin() + (nBoolIdx + next) );
     458         [ +  - ]:          1 :                 if( nBoolIdx )
     459                 :          1 :                     aBoolArr[ nBoolIdx - 1 ] = sal_False;
     460                 :            : #if OSL_DEBUG_LEVEL > 1
     461                 :            :                 else
     462                 :            :                     ++next;
     463                 :            : #endif
     464                 :            :             }
     465 [ -  + ][ #  # ]:          1 :             bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ];
         [ #  # ][ -  + ]
                 [ #  # ]
     466                 :          1 :             nLongIdx += 2;
     467                 :            :             DBG_ASSERT( nLongIdx == 2*nBoolIdx+1, "BoundArgs: Array-Idx Confusion" );
     468                 :            :             DBG_ASSERT( aBoolArr.size()*2 == pLongArr->size(),
     469                 :            :                         "BoundArgs: Array-Count: Confusion" );
     470                 :            :         }
     471                 :            :     }
     472         [ +  - ]:          1 :     if( 0 != ( nCount = pLongArr->size() ) )
     473                 :            :     {
     474         [ -  + ]:          1 :         if( bInner )
     475                 :            :         {
     476                 :          0 :             pLongArr->pop_front();
     477                 :          0 :             pLongArr->pop_back();
     478                 :            : 
     479                 :            :             // Here the line is held inside a large rectangle for "simple"
     480                 :            :             // contour wrap. Currently (April 1999) the EditEngine evaluates
     481                 :            :             // only the first rectangle. If it one day is able to output a line
     482                 :            :             // in several parts, it may be advisable to delete the following lines.
     483 [ #  # ][ #  # ]:          0 :             if( pTextRanger->IsSimple() && pLongArr->size() > 2 )
                 [ #  # ]
     484 [ #  # ][ #  # ]:          0 :                 pLongArr->erase( pLongArr->begin() + 1, pLongArr->end() - 1 );
                 [ #  # ]
     485                 :            : 
     486                 :            :         }
     487                 :            :     }
     488                 :          1 : }
     489                 :            : 
     490                 :          0 : void SvxBoundArgs::Concat( const PolyPolygon* pPoly )
     491                 :            : {
     492                 :          0 :     SetConcat( sal_True );
     493                 :            :     DBG_ASSERT( pPoly, "Nothing to do?" );
     494                 :          0 :     LongDqPtr pOld = pLongArr;
     495         [ #  # ]:          0 :     pLongArr = new std::deque<long>();
     496                 :          0 :     aBoolArr.clear();
     497                 :          0 :     bInner = sal_False;
     498                 :          0 :     Calc( *pPoly ); // Note that this updates pLongArr, which is why we swapped it out earlier.
     499                 :          0 :     sal_uInt16 nCount = pLongArr->size();
     500                 :          0 :     sal_uInt16 nIdx = 0;
     501                 :          0 :     sal_uInt16 i = 0;
     502                 :          0 :     sal_Bool bSubtract = pTextRanger->IsInner();
     503         [ #  # ]:          0 :     while( i < nCount )
     504                 :            :     {
     505                 :          0 :         sal_uLong nOldCount = pOld->size();
     506         [ #  # ]:          0 :         if( nIdx == nOldCount )
     507                 :            :         {   // Reached the end of the old Array...
     508         [ #  # ]:          0 :             if( !bSubtract )
     509 [ #  # ][ #  # ]:          0 :                 pOld->insert( pOld->begin() + nIdx, pLongArr->begin() + i, pLongArr->end() );
                 [ #  # ]
     510                 :          0 :             break;
     511                 :            :         }
     512                 :          0 :         long nLeft = (*pLongArr)[ i++ ];
     513                 :          0 :         long nRight = (*pLongArr)[ i++ ];
     514                 :          0 :         sal_uInt16 nLeftPos = nIdx + 1;
     515 [ #  # ][ #  # ]:          0 :         while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] )
                 [ #  # ]
     516                 :          0 :             nLeftPos += 2;
     517         [ #  # ]:          0 :         if( nLeftPos >= nOldCount )
     518                 :            :         {   // The current interval belongs to the end of the old array ...
     519         [ #  # ]:          0 :             if( !bSubtract )
     520 [ #  # ][ #  # ]:          0 :                 pOld->insert( pOld->begin() + nOldCount, pLongArr->begin() + i - 2, pLongArr->end() );
         [ #  # ][ #  # ]
     521                 :          0 :             break;
     522                 :            :         }
     523                 :          0 :         sal_uInt16 nRightPos = nLeftPos - 1;
     524 [ #  # ][ #  # ]:          0 :         while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] )
                 [ #  # ]
     525                 :          0 :             nRightPos += 2;
     526         [ #  # ]:          0 :         if( nRightPos < nLeftPos )
     527                 :            :         {   // The current interval belongs between two old intervals
     528         [ #  # ]:          0 :             if( !bSubtract )
     529 [ #  # ][ #  # ]:          0 :                 pOld->insert( pOld->begin() + nRightPos, pLongArr->begin() + i - 2, pLongArr->begin() + i );
         [ #  # ][ #  # ]
                 [ #  # ]
     530                 :          0 :             nIdx = nRightPos + 2;
     531                 :            :         }
     532         [ #  # ]:          0 :         else if( bSubtract ) // Subtract, if necessary separate
     533                 :            :         {
     534                 :            :             long nOld;
     535 [ #  # ][ #  # ]:          0 :             if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) )
     536                 :            :             {   // Now we split the left part...
     537         [ #  # ]:          0 :                 if( nLeft - 1 > nOld )
     538                 :            :                 {
     539 [ #  # ][ #  # ]:          0 :                     pOld->insert( pOld->begin() + nLeftPos - 1, nOld );
                 [ #  # ]
     540 [ #  # ][ #  # ]:          0 :                     pOld->insert( pOld->begin() + nLeftPos, nLeft - 1 );
     541                 :          0 :                     nLeftPos += 2;
     542                 :          0 :                     nRightPos += 2;
     543                 :            :                 }
     544                 :            :             }
     545         [ #  # ]:          0 :             if( nRightPos - nLeftPos > 1 )
     546 [ #  # ][ #  # ]:          0 :                 pOld->erase( pOld->begin() + nLeftPos, pOld->begin() + nRightPos - 1 );
         [ #  # ][ #  # ]
     547 [ #  # ][ #  # ]:          0 :             if( ++nRight >= ( nOld = (*pOld)[ nLeftPos ] ) )
     548 [ #  # ][ #  # ]:          0 :                 pOld->erase( pOld->begin() + nLeftPos - 1, pOld->begin() + nLeftPos + 1 );
         [ #  # ][ #  # ]
                 [ #  # ]
     549                 :            :             else
     550         [ #  # ]:          0 :                 (*pOld)[ nLeftPos - 1 ] = nRight;
     551                 :            :         }
     552                 :            :         else // Merge
     553                 :            :         {
     554         [ #  # ]:          0 :             if( nLeft < (*pOld)[ nLeftPos - 1 ] )
     555                 :          0 :                 (*pOld)[ nLeftPos - 1 ] = nLeft;
     556         [ #  # ]:          0 :             if( nRight > (*pOld)[ nRightPos - 1 ] )
     557                 :          0 :                 (*pOld)[ nRightPos - 1 ] = nRight;
     558         [ #  # ]:          0 :             if( nRightPos - nLeftPos > 1 )
     559 [ #  # ][ #  # ]:          0 :                 pOld->erase( pOld->begin() + nLeftPos, pOld->begin() + nRightPos - 1 );
         [ #  # ][ #  # ]
     560                 :            : 
     561                 :            :         }
     562                 :          0 :         nIdx = nLeftPos - 1;
     563                 :            :     }
     564         [ #  # ]:          0 :     delete pLongArr;
     565                 :          0 : }
     566                 :            : 
     567                 :            : /*************************************************************************
     568                 :            :  * SvxBoundArgs::Area returns the area in which the point is located.
     569                 :            :  * 0 = within the line
     570                 :            :  * 1 = below, but within the upper edge
     571                 :            :  * 2 = above, but within the lower edge
     572                 :            :  * 5 = below the upper edge
     573                 :            :  *10 = above the lower edge
     574                 :            :  *************************************************************************/
     575                 :            : 
     576                 :         96 : sal_uInt16 SvxBoundArgs::Area( const Point& rPt )
     577                 :            : {
     578                 :         96 :     long nB = B( rPt );
     579         [ +  + ]:         96 :     if( nB >= nBottom )
     580                 :            :     {
     581         [ +  - ]:         32 :         if( nB >= nLower )
     582                 :         32 :             return 5;
     583                 :          0 :         return 1;
     584                 :            :     }
     585         [ +  - ]:         64 :     if( nB <= nTop )
     586                 :            :     {
     587         [ +  - ]:         64 :         if( nB <= nUpper )
     588                 :         64 :             return 10;
     589                 :          0 :         return 2;
     590                 :            :     }
     591                 :         96 :     return 0;
     592                 :            : }
     593                 :            : 
     594                 :            : /*************************************************************************
     595                 :            :  * lcl_Cut calculates the X-Coordinate of the distance (Pt1-Pt2) at the
     596                 :            :  * Y-Coordinate nY.
     597                 :            :  * It is assumed that the one of the points are located above and the other
     598                 :            :  * one below the Y-Coordinate.
     599                 :            :  *************************************************************************/
     600                 :            : 
     601                 :        128 : long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 )
     602                 :            : {
     603         [ -  + ]:        128 :     if( pTextRanger->IsVertical() )
     604                 :            :     {
     605                 :          0 :         double nQuot = nB - rPt1.X();
     606                 :          0 :         nQuot /= ( rPt2.X() - rPt1.X() );
     607                 :          0 :         nQuot *= ( rPt2.Y() - rPt1.Y() );
     608                 :          0 :         return long( rPt1.Y() + nQuot );
     609                 :            :     }
     610                 :        128 :     double nQuot = nB - rPt1.Y();
     611                 :        128 :     nQuot /= ( rPt2.Y() - rPt1.Y() );
     612                 :        128 :     nQuot *= ( rPt2.X() - rPt1.X() );
     613                 :        128 :     return long( rPt1.X() + nQuot );
     614                 :            : }
     615                 :            : 
     616                 :         64 : void SvxBoundArgs::NoteUpLow( long nA, const sal_uInt8 nArea )
     617                 :            : {
     618         [ +  + ]:         64 :     if( nAct )
     619                 :            :     {
     620                 :         47 :         NoteMargin( nA, nA );
     621         [ +  + ]:         47 :         if( bMultiple )
     622                 :            :         {
     623                 :          2 :             NoteRange( nArea != nAct );
     624                 :          2 :             nAct = 0;
     625                 :            :         }
     626         [ -  + ]:         47 :         if( !nFirst )
     627                 :          0 :             nFirst = nArea;
     628                 :            :     }
     629                 :            :     else
     630                 :            :     {
     631                 :         17 :         nAct = nArea;
     632                 :         17 :         nMin = nA;
     633                 :         17 :         nMax = nA;
     634                 :            :     }
     635                 :         64 : }
     636                 :            : 
     637                 :         48 : LongDqPtr TextRanger::GetTextRanges( const Range& rRange )
     638                 :            : {
     639                 :            :     DBG_ASSERT( rRange.Min() || rRange.Max(), "Zero-Range not allowed, Bye Bye" );
     640                 :            :     //Can we find the result we need in the cache?
     641 [ #  # ][ +  - ]:         48 :     for (std::deque<RangeCache>::iterator it = mRangeCache.begin(); it != mRangeCache.end(); ++it)
                 [ +  + ]
     642                 :            :     {
     643 [ +  - ][ +  - ]:         32 :         if (it->range == rRange)
     644         [ +  - ]:         32 :             return &(it->results);
     645                 :            :     }
     646                 :            :     //Calculate a new result
     647         [ +  - ]:         16 :     RangeCache rngCache(rRange);
     648         [ +  - ]:         16 :     SvxBoundArgs aArg( this, &(rngCache.results), rRange );
     649         [ +  - ]:         16 :     aArg.Calc( *mpPolyPolygon );
     650         [ -  + ]:         16 :     if( mpLinePolyPolygon )
     651         [ #  # ]:          0 :         aArg.Concat( mpLinePolyPolygon );
     652                 :            :     //Add new result to the cache
     653         [ +  - ]:         16 :     mRangeCache.push_back(rngCache);
     654         [ -  + ]:         16 :     if (mRangeCache.size() > nCacheSize)
     655         [ #  # ]:          0 :         mRangeCache.pop_front();
     656         [ +  - ]:         48 :     return &(mRangeCache.back().results);
     657                 :            : }
     658                 :            : 
     659                 :          0 : const Rectangle& TextRanger::_GetBoundRect()
     660                 :            : {
     661                 :            :     DBG_ASSERT( 0 == pBound, "Don't call twice." );
     662         [ #  # ]:          0 :     pBound = new Rectangle( mpPolyPolygon->GetBoundRect() );
     663                 :          0 :     return *pBound;
     664                 :            : }
     665                 :            : 
     666                 :            : 
     667                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10