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

Generated by: LCOV version 1.10