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