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

Generated by: LCOV version 1.10