LCOV - code coverage report
Current view: top level - svx/source/dialog - framelinkarray.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 438 644 68.0 %
Date: 2014-11-03 Functions: 80 99 80.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <svx/framelinkarray.hxx>
      21             : 
      22             : #include <math.h>
      23             : #include <vector>
      24             : #include <algorithm>
      25             : #include <vcl/outdev.hxx>
      26             : 
      27             : namespace svx {
      28             : namespace frame {
      29             : 
      30             : struct Cell
      31             : {
      32             :     Style               maLeft;
      33             :     Style               maRight;
      34             :     Style               maTop;
      35             :     Style               maBottom;
      36             :     Style               maTLBR;
      37             :     Style               maBLTR;
      38             :     long                mnAddLeft;
      39             :     long                mnAddRight;
      40             :     long                mnAddTop;
      41             :     long                mnAddBottom;
      42             :     bool                mbMergeOrig;
      43             :     bool                mbOverlapX;
      44             :     bool                mbOverlapY;
      45             : 
      46             :     explicit            Cell();
      47             : 
      48     6764810 :     inline bool         IsMerged() const { return mbMergeOrig || mbOverlapX || mbOverlapY; }
      49             : 
      50             :     void                MirrorSelfX( bool bMirrorStyles, bool bSwapDiag );
      51             : };
      52             : 
      53             : typedef std::vector< long >     LongVec;
      54             : typedef std::vector< Cell >     CellVec;
      55             : 
      56     5531625 : Cell::Cell() :
      57             :     mnAddLeft( 0 ),
      58             :     mnAddRight( 0 ),
      59             :     mnAddTop( 0 ),
      60             :     mnAddBottom( 0 ),
      61             :     mbMergeOrig( false ),
      62             :     mbOverlapX( false ),
      63     5531625 :     mbOverlapY( false )
      64             : {
      65     5531625 : }
      66             : 
      67        1008 : void Cell::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
      68             : {
      69        1008 :     std::swap( maLeft, maRight );
      70        1008 :     std::swap( mnAddLeft, mnAddRight );
      71        1008 :     if( bMirrorStyles )
      72             :     {
      73        1008 :         maLeft.MirrorSelf();
      74        1008 :         maRight.MirrorSelf();
      75             :     }
      76        1008 :     if( bSwapDiag )
      77             :     {
      78           0 :         std::swap( maTLBR, maBLTR );
      79           0 :         if( bMirrorStyles )
      80             :         {
      81           0 :             maTLBR.MirrorSelf();
      82           0 :             maBLTR.MirrorSelf();
      83             :         }
      84             :     }
      85        1008 : }
      86             : 
      87             : 
      88             : 
      89             : 
      90        3104 : void lclRecalcCoordVec( LongVec& rCoords, const LongVec& rSizes )
      91             : {
      92             :     DBG_ASSERT( rCoords.size() == rSizes.size() + 1, "lclRecalcCoordVec - inconsistent vectors" );
      93        3104 :     LongVec::iterator aCIt = rCoords.begin();
      94        3104 :     LongVec::const_iterator aSIt = rSizes.begin(), aSEnd = rSizes.end();
      95       46912 :     for( ; aSIt != aSEnd; ++aCIt, ++aSIt )
      96       43808 :         *(aCIt + 1) = *aCIt + *aSIt;
      97        3104 : }
      98             : 
      99         572 : void lclSetMergedRange( CellVec& rCells, size_t nWidth, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     100             : {
     101        1686 :     for( size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     102             :     {
     103        4490 :         for( size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     104             :         {
     105        3376 :             Cell& rCell = rCells[ nRow * nWidth + nCol ];
     106        3376 :             rCell.mbMergeOrig = false;
     107        3376 :             rCell.mbOverlapX = nCol > nFirstCol;
     108        3376 :             rCell.mbOverlapY = nRow > nFirstRow;
     109             :         }
     110             :     }
     111         572 :     rCells[ nFirstRow * nWidth + nFirstCol ].mbMergeOrig = true;
     112         572 : }
     113             : 
     114             : 
     115             : 
     116         198 : static const Style OBJ_STYLE_NONE;
     117         198 : static const Cell OBJ_CELL_NONE;
     118             : 
     119             : const bool DIAG_DBL_CLIP_DEFAULT = false;
     120             : 
     121       32720 : struct ArrayImpl
     122             : {
     123             :     CellVec             maCells;
     124             :     LongVec             maWidths;
     125             :     LongVec             maHeights;
     126             :     mutable LongVec     maXCoords;
     127             :     mutable LongVec     maYCoords;
     128             :     size_t              mnWidth;
     129             :     size_t              mnHeight;
     130             :     size_t              mnFirstClipCol;
     131             :     size_t              mnFirstClipRow;
     132             :     size_t              mnLastClipCol;
     133             :     size_t              mnLastClipRow;
     134             :     mutable bool        mbXCoordsDirty;
     135             :     mutable bool        mbYCoordsDirty;
     136             :     bool                mbDiagDblClip;
     137             : 
     138             :     explicit            ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip );
     139             : 
     140    59953281 :     inline bool         IsValidPos( size_t nCol, size_t nRow ) const
     141    59953281 :                             { return (nCol < mnWidth) && (nRow < mnHeight); }
     142    58950213 :     inline size_t       GetIndex( size_t nCol, size_t nRow ) const
     143    58950213 :                             { return nRow * mnWidth + nCol; }
     144             : 
     145             :     const Cell&         GetCell( size_t nCol, size_t nRow ) const;
     146             :     Cell&               GetCellAcc( size_t nCol, size_t nRow );
     147             : 
     148             :     size_t              GetMergedFirstCol( size_t nCol, size_t nRow ) const;
     149             :     size_t              GetMergedFirstRow( size_t nCol, size_t nRow ) const;
     150             :     size_t              GetMergedLastCol( size_t nCol, size_t nRow ) const;
     151             :     size_t              GetMergedLastRow( size_t nCol, size_t nRow ) const;
     152             : 
     153             :     const Cell&         GetMergedOriginCell( size_t nCol, size_t nRow ) const;
     154             : 
     155             :     bool                IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const;
     156             :     bool                IsMergedOverlappedRight( size_t nCol, size_t nRow ) const;
     157             :     bool                IsMergedOverlappedTop( size_t nCol, size_t nRow ) const;
     158             :     bool                IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const;
     159             : 
     160             :     bool                IsInClipRange( size_t nCol, size_t nRow ) const;
     161             :     bool                IsColInClipRange( size_t nCol ) const;
     162             :     bool                IsRowInClipRange( size_t nRow ) const;
     163             : 
     164        1008 :     inline size_t       GetMirrorCol( size_t nCol ) const { return mnWidth - nCol - 1; }
     165             : 
     166             :     long                GetColPosition( size_t nCol ) const;
     167             :     long                GetRowPosition( size_t nRow ) const;
     168             : 
     169             :     long                GetColWidth( size_t nFirstCol, size_t nLastCol ) const;
     170             :     long                GetRowHeight( size_t nFirstRow, size_t nLastRow ) const;
     171             : 
     172             :     double              GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
     173             :     double              GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
     174             : };
     175             : 
     176       32720 : ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
     177             :     mnWidth( nWidth ),
     178             :     mnHeight( nHeight ),
     179             :     mnFirstClipCol( 0 ),
     180             :     mnFirstClipRow( 0 ),
     181       32720 :     mnLastClipCol( nWidth - 1 ),
     182       32720 :     mnLastClipRow( nHeight - 1 ),
     183             :     mbXCoordsDirty( false ),
     184             :     mbYCoordsDirty( false ),
     185       98160 :     mbDiagDblClip( bDiagDblClip )
     186             : {
     187             :     // default-construct all vectors
     188       32720 :     maCells.resize( mnWidth * mnHeight );
     189       32720 :     maWidths.resize( mnWidth, 0L );
     190       32720 :     maHeights.resize( mnHeight, 0L );
     191       32720 :     maXCoords.resize( mnWidth + 1, 0L );
     192       32720 :     maYCoords.resize( mnHeight + 1, 0L );
     193       32720 : }
     194             : 
     195    29620761 : const Cell& ArrayImpl::GetCell( size_t nCol, size_t nRow ) const
     196             : {
     197    29620761 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : OBJ_CELL_NONE;
     198             : }
     199             : 
     200    29329452 : Cell& ArrayImpl::GetCellAcc( size_t nCol, size_t nRow )
     201             : {
     202    29329452 :     static Cell aDummy;
     203    29329452 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : aDummy;
     204             : }
     205             : 
     206     6024776 : size_t ArrayImpl::GetMergedFirstCol( size_t nCol, size_t nRow ) const
     207             : {
     208     6024776 :     size_t nFirstCol = nCol;
     209     6024776 :     while( (nFirstCol > 0) && GetCell( nFirstCol, nRow ).mbOverlapX ) --nFirstCol;
     210     6024776 :     return nFirstCol;
     211             : }
     212             : 
     213     6024770 : size_t ArrayImpl::GetMergedFirstRow( size_t nCol, size_t nRow ) const
     214             : {
     215     6024770 :     size_t nFirstRow = nRow;
     216     6024770 :     while( (nFirstRow > 0) && GetCell( nCol, nFirstRow ).mbOverlapY ) --nFirstRow;
     217     6024770 :     return nFirstRow;
     218             : }
     219             : 
     220     1234039 : size_t ArrayImpl::GetMergedLastCol( size_t nCol, size_t nRow ) const
     221             : {
     222     1234039 :     size_t nLastCol = nCol + 1;
     223     1234039 :     while( (nLastCol < mnWidth) && GetCell( nLastCol, nRow ).mbOverlapX ) ++nLastCol;
     224     1234039 :     return nLastCol - 1;
     225             : }
     226             : 
     227     1234039 : size_t ArrayImpl::GetMergedLastRow( size_t nCol, size_t nRow ) const
     228             : {
     229     1234039 :     size_t nLastRow = nRow + 1;
     230     1234039 :     while( (nLastRow < mnHeight) && GetCell( nCol, nLastRow ).mbOverlapY ) ++nLastRow;
     231     1234039 :     return nLastRow - 1;
     232             : }
     233             : 
     234     3326812 : const Cell& ArrayImpl::GetMergedOriginCell( size_t nCol, size_t nRow ) const
     235             : {
     236     3326812 :     return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
     237             : }
     238             : 
     239      335631 : bool ArrayImpl::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     240             : {
     241      335631 :     const Cell& rCell = GetCell( nCol, nRow );
     242      335631 :     return rCell.mbOverlapX || (rCell.mnAddLeft > 0);
     243             : }
     244             : 
     245      492494 : bool ArrayImpl::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     246             : {
     247      492494 :     return GetCell( nCol + 1, nRow ).mbOverlapX || (GetCell( nCol, nRow ).mnAddRight > 0);
     248             : }
     249             : 
     250      327335 : bool ArrayImpl::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
     251             : {
     252      327335 :     const Cell& rCell = GetCell( nCol, nRow );
     253      327335 :     return rCell.mbOverlapY || (rCell.mnAddTop > 0);
     254             : }
     255             : 
     256      509146 : bool ArrayImpl::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
     257             : {
     258      509146 :     return GetCell( nCol, nRow + 1 ).mbOverlapY || (GetCell( nCol, nRow ).mnAddBottom > 0);
     259             : }
     260             : 
     261     3668254 : bool ArrayImpl::IsColInClipRange( size_t nCol ) const
     262             : {
     263     3668254 :     return (mnFirstClipCol <= nCol) && (nCol <= mnLastClipCol);
     264             : }
     265             : 
     266     3667860 : bool ArrayImpl::IsRowInClipRange( size_t nRow ) const
     267             : {
     268     3667860 :     return (mnFirstClipRow <= nRow) && (nRow <= mnLastClipRow);
     269             : }
     270             : 
     271     2003848 : bool ArrayImpl::IsInClipRange( size_t nCol, size_t nRow ) const
     272             : {
     273     2003848 :     return IsColInClipRange( nCol ) && IsRowInClipRange( nRow );
     274             : }
     275             : 
     276      762515 : long ArrayImpl::GetColPosition( size_t nCol ) const
     277             : {
     278      762515 :     if( mbXCoordsDirty )
     279             :     {
     280        1552 :         lclRecalcCoordVec( maXCoords, maWidths );
     281        1552 :         mbXCoordsDirty = false;
     282             :     }
     283      762515 :     return maXCoords[ nCol ];
     284             : }
     285             : 
     286      754443 : long ArrayImpl::GetRowPosition( size_t nRow ) const
     287             : {
     288      754443 :     if( mbYCoordsDirty )
     289             :     {
     290        1552 :         lclRecalcCoordVec( maYCoords, maHeights );
     291        1552 :         mbYCoordsDirty = false;
     292             :     }
     293      754443 :     return maYCoords[ nRow ];
     294             : }
     295             : 
     296         828 : long ArrayImpl::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     297             : {
     298         828 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     299             : }
     300             : 
     301         828 : long ArrayImpl::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     302             : {
     303         828 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     304             : }
     305             : 
     306     1001924 : double ArrayImpl::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     307             : {
     308     1001924 :     double fAngle = 0.0;
     309     1001924 :     if( IsValidPos( nCol, nRow ) )
     310             :     {
     311     1001924 :         if( bSimple || !GetCell( nCol, nRow ).IsMerged() )
     312             :         {
     313     1001096 :             fAngle = frame::GetHorDiagAngle( maWidths[ nCol ] + 1, maHeights[ nRow ] + 1 );
     314             :         }
     315             :         else
     316             :         {
     317             :             // return correct angle for each cell in the merged range
     318         828 :             size_t nFirstCol = GetMergedFirstCol( nCol, nRow );
     319         828 :             size_t nFirstRow = GetMergedFirstRow( nCol, nRow );
     320         828 :             const Cell& rCell = GetCell( nFirstCol, nFirstRow );
     321         828 :             long nWidth = GetColWidth( nFirstCol, GetMergedLastCol( nCol, nRow ) ) + rCell.mnAddLeft + rCell.mnAddRight;
     322         828 :             long nHeight = GetRowHeight( nFirstRow, GetMergedLastRow( nCol, nRow ) ) + rCell.mnAddTop + rCell.mnAddBottom;
     323         828 :             fAngle = frame::GetHorDiagAngle( nWidth + 1, nHeight + 1 );
     324             :         }
     325             :     }
     326     1001924 :     return fAngle;
     327             : }
     328             : 
     329      509278 : double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     330             : {
     331      509278 :     double fAngle = GetHorDiagAngle( nCol, nRow, bSimple );
     332      509278 :     return (fAngle > 0.0) ? (F_PI2 - fAngle) : 0.0;
     333             : }
     334             : 
     335             : 
     336             : 
     337             : class MergedCellIterator
     338             : {
     339             : public:
     340             :     explicit            MergedCellIterator( const Array& rArray, size_t nCol, size_t nRow );
     341             : 
     342         274 :     inline bool         Is() const { return (mnCol <= mnLastCol) && (mnRow <= mnLastRow); }
     343         216 :     inline size_t       Col() const { return mnCol; }
     344         216 :     inline size_t       Row() const { return mnRow; }
     345             : 
     346             :     MergedCellIterator& operator++();
     347             : 
     348             : private:
     349             :     size_t              mnFirstCol;
     350             :     size_t              mnFirstRow;
     351             :     size_t              mnLastCol;
     352             :     size_t              mnLastRow;
     353             :     size_t              mnCol;
     354             :     size_t              mnRow;
     355             : };
     356             : 
     357             : 
     358             : 
     359          58 : MergedCellIterator::MergedCellIterator( const Array& rArray, size_t nCol, size_t nRow )
     360             : {
     361             :     DBG_ASSERT( rArray.IsMerged( nCol, nRow ), "svx::frame::MergedCellIterator::MergedCellIterator - not in merged range" );
     362          58 :     rArray.GetMergedRange( mnFirstCol, mnFirstRow, mnLastCol, mnLastRow, nCol, nRow );
     363          58 :     mnCol = mnFirstCol;
     364          58 :     mnRow = mnFirstRow;
     365          58 : }
     366             : 
     367         216 : MergedCellIterator& MergedCellIterator::operator++()
     368             : {
     369             :     DBG_ASSERT( Is(), "svx::frame::MergedCellIterator::operator++() - already invalid" );
     370         216 :     if( ++mnCol > mnLastCol )
     371             :     {
     372         174 :         mnCol = mnFirstCol;
     373         174 :         ++mnRow;
     374             :     }
     375         216 :     return *this;
     376             : }
     377             : 
     378             : 
     379             : 
     380             : #define DBG_FRAME_CHECK( cond, funcname, error )        DBG_ASSERT( cond, "svx::frame::Array::" funcname " - " error )
     381             : #define DBG_FRAME_CHECK_COL( col, funcname )            DBG_FRAME_CHECK( (col) < GetColCount(), funcname, "invalid column index" )
     382             : #define DBG_FRAME_CHECK_ROW( row, funcname )            DBG_FRAME_CHECK( (row) < GetRowCount(), funcname, "invalid row index" )
     383             : #define DBG_FRAME_CHECK_COLROW( col, row, funcname )    DBG_FRAME_CHECK( ((col) < GetColCount()) && ((row) < GetRowCount()), funcname, "invalid cell index" )
     384             : #define DBG_FRAME_CHECK_COL_1( col, funcname )          DBG_FRAME_CHECK( (col) <= GetColCount(), funcname, "invalid column index" )
     385             : #define DBG_FRAME_CHECK_ROW_1( row, funcname )          DBG_FRAME_CHECK( (row) <= GetRowCount(), funcname, "invalid row index" )
     386             : 
     387             : 
     388             : 
     389             : #define CELL( col, row )        mxImpl->GetCell( col, row )
     390             : #define CELLACC( col, row )     mxImpl->GetCellAcc( col, row )
     391             : #define ORIGCELL( col, row )    mxImpl->GetMergedOriginCell( col, row )
     392             : 
     393             : 
     394             : 
     395       16360 : Array::Array()
     396             : {
     397       16360 :     Initialize( 0, 0 );
     398       16360 : }
     399             : 
     400       16360 : Array::~Array()
     401             : {
     402       16360 : }
     403             : 
     404             : // array size and column/row indexes
     405       32720 : void Array::Initialize( size_t nWidth, size_t nHeight )
     406             : {
     407       32720 :     bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
     408       32720 :     mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
     409       32720 : }
     410             : 
     411        1552 : size_t Array::GetColCount() const
     412             : {
     413        1552 :     return mxImpl->mnWidth;
     414             : }
     415             : 
     416        1552 : size_t Array::GetRowCount() const
     417             : {
     418        1552 :     return mxImpl->mnHeight;
     419             : }
     420             : 
     421           3 : size_t Array::GetCellCount() const
     422             : {
     423           3 :     return mxImpl->maCells.size();
     424             : }
     425             : 
     426           0 : size_t Array::GetCellIndex( size_t nCol, size_t nRow, bool bRTL ) const
     427             : {
     428             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetCellIndex" );
     429           0 :     if (bRTL)
     430           0 :         nCol = mxImpl->GetMirrorCol(nCol);
     431           0 :     return mxImpl->GetIndex( nCol, nRow );
     432             : }
     433             : 
     434             : // cell border styles
     435     4888206 : void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
     436             : {
     437             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
     438     4888206 :     CELLACC( nCol, nRow ).maLeft = rStyle;
     439     4888206 : }
     440             : 
     441     4888206 : void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
     442             : {
     443             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
     444     4888206 :     CELLACC( nCol, nRow ).maRight = rStyle;
     445     4888206 : }
     446             : 
     447     4888206 : void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
     448             : {
     449             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
     450     4888206 :     CELLACC( nCol, nRow ).maTop = rStyle;
     451     4888206 : }
     452             : 
     453     4888206 : void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
     454             : {
     455             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
     456     4888206 :     CELLACC( nCol, nRow ).maBottom = rStyle;
     457     4888206 : }
     458             : 
     459     4888206 : void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
     460             : {
     461             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
     462     4888206 :     CELLACC( nCol, nRow ).maTLBR = rStyle;
     463     4888206 : }
     464             : 
     465     4888206 : void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
     466             : {
     467             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
     468     4888206 :     CELLACC( nCol, nRow ).maBLTR = rStyle;
     469     4888206 : }
     470             : 
     471           0 : void Array::SetCellStyleDiag( size_t nCol, size_t nRow, const Style& rTLBR, const Style& rBLTR )
     472             : {
     473             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleDiag" );
     474           0 :     Cell& rCell = CELLACC( nCol, nRow );
     475           0 :     rCell.maTLBR = rTLBR;
     476           0 :     rCell.maBLTR = rBLTR;
     477           0 : }
     478             : 
     479           0 : void Array::SetColumnStyleLeft( size_t nCol, const Style& rStyle )
     480             : {
     481             :     DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleLeft" );
     482           0 :     for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     483           0 :         SetCellStyleLeft( nCol, nRow, rStyle );
     484           0 : }
     485             : 
     486           0 : void Array::SetColumnStyleRight( size_t nCol, const Style& rStyle )
     487             : {
     488             :     DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleRight" );
     489           0 :     for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     490           0 :         SetCellStyleRight( nCol, nRow, rStyle );
     491           0 : }
     492             : 
     493           0 : void Array::SetRowStyleTop( size_t nRow, const Style& rStyle )
     494             : {
     495             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleTop" );
     496           0 :     for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     497           0 :         SetCellStyleTop( nCol, nRow, rStyle );
     498           0 : }
     499             : 
     500           0 : void Array::SetRowStyleBottom( size_t nRow, const Style& rStyle )
     501             : {
     502             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleBottom" );
     503           0 :     for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     504           0 :         SetCellStyleBottom( nCol, nRow, rStyle );
     505           0 : }
     506             : 
     507      336047 : const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple ) const
     508             : {
     509             :     // simple: always return own left style
     510      336047 :     if( bSimple )
     511           0 :         return CELL( nCol, nRow ).maLeft;
     512             :     // outside clipping rows or overlapped in merged cells: invisible
     513      336047 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedLeft( nCol, nRow ) )
     514         528 :         return OBJ_STYLE_NONE;
     515             :     // left clipping border: always own left style
     516      335519 :     if( nCol == mxImpl->mnFirstClipCol )
     517         198 :         return ORIGCELL( nCol, nRow ).maLeft;
     518             :     // right clipping border: always right style of left neighbor cell
     519      335321 :     if( nCol == mxImpl->mnLastClipCol + 1 )
     520          66 :         return ORIGCELL( nCol - 1, nRow ).maRight;
     521             :     // outside clipping columns: invisible
     522      335255 :     if( !mxImpl->IsColInClipRange( nCol ) )
     523           0 :         return OBJ_STYLE_NONE;
     524             :     // inside clipping range: maximum of own left style and right style of left neighbor cell
     525      335255 :     return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
     526             : }
     527             : 
     528      492646 : const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple ) const
     529             : {
     530             :     // simple: always return own right style
     531      492646 :     if( bSimple )
     532           0 :         return CELL( nCol, nRow ).maRight;
     533             :     // outside clipping rows or overlapped in merged cells: invisible
     534      492646 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedRight( nCol, nRow ) )
     535         372 :         return OBJ_STYLE_NONE;
     536             :     // left clipping border: always left style of right neighbor cell
     537      492274 :     if( nCol + 1 == mxImpl->mnFirstClipCol )
     538           0 :         return ORIGCELL( nCol + 1, nRow ).maLeft;
     539             :     // right clipping border: always own right style
     540      492274 :     if( nCol == mxImpl->mnLastClipCol )
     541         132 :         return ORIGCELL( nCol, nRow ).maRight;
     542             :     // outside clipping columns: invisible
     543      492142 :     if( !mxImpl->IsColInClipRange( nCol ) )
     544           0 :         return OBJ_STYLE_NONE;
     545             :     // inside clipping range: maximum of own right style and left style of right neighbor cell
     546      492142 :     return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
     547             : }
     548             : 
     549      327731 : const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple ) const
     550             : {
     551             :     // simple: always return own top style
     552      327731 :     if( bSimple )
     553           0 :         return CELL( nCol, nRow ).maTop;
     554             :     // outside clipping columns or overlapped in merged cells: invisible
     555      327731 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedTop( nCol, nRow ) )
     556         562 :         return OBJ_STYLE_NONE;
     557             :     // top clipping border: always own top style
     558      327169 :     if( nRow == mxImpl->mnFirstClipRow )
     559         228 :         return ORIGCELL( nCol, nRow ).maTop;
     560             :     // bottom clipping border: always bottom style of top neighbor cell
     561      326941 :     if( nRow == mxImpl->mnLastClipRow + 1 )
     562          76 :         return ORIGCELL( nCol, nRow - 1 ).maBottom;
     563             :     // outside clipping rows: invisible
     564      326865 :     if( !mxImpl->IsRowInClipRange( nRow ) )
     565           0 :         return OBJ_STYLE_NONE;
     566             :     // inside clipping range: maximum of own top style and bottom style of top neighbor cell
     567      326865 :     return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
     568             : }
     569             : 
     570      509278 : const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple ) const
     571             : {
     572             :     // simple: always return own bottom style
     573      509278 :     if( bSimple )
     574           0 :         return CELL( nCol, nRow ).maBottom;
     575             :     // outside clipping columns or overlapped in merged cells: invisible
     576      509278 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedBottom( nCol, nRow ) )
     577         408 :         return OBJ_STYLE_NONE;
     578             :     // top clipping border: always top style of bottom neighbor cell
     579      508870 :     if( nRow + 1 == mxImpl->mnFirstClipRow )
     580           0 :         return ORIGCELL( nCol, nRow + 1 ).maTop;
     581             :     // bottom clipping border: always own bottom style
     582      508870 :     if( nRow == mxImpl->mnLastClipRow )
     583         152 :         return ORIGCELL( nCol, nRow ).maBottom;
     584             :     // outside clipping rows: invisible
     585      508718 :     if( !mxImpl->IsRowInClipRange( nRow ) )
     586           0 :         return OBJ_STYLE_NONE;
     587             :     // inside clipping range: maximum of own bottom style and top style of bottom neighbor cell
     588      508718 :     return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
     589             : }
     590             : 
     591      231468 : const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple ) const
     592             : {
     593      231468 :     return bSimple ? CELL( nCol, nRow ).maTLBR :
     594      462936 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maTLBR : OBJ_STYLE_NONE);
     595             : }
     596             : 
     597      231468 : const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple ) const
     598             : {
     599      231468 :     return bSimple ? CELL( nCol, nRow ).maBLTR :
     600      462936 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maBLTR : OBJ_STYLE_NONE);
     601             : }
     602             : 
     603      500962 : const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
     604             : {
     605             :     // not in clipping range: always invisible
     606      500962 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     607         142 :         return OBJ_STYLE_NONE;
     608             :     // return style only for top-left cell
     609      500820 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     610      500820 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     611      500610 :     return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
     612     1001286 :         CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
     613             : }
     614             : 
     615      500962 : const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
     616             : {
     617             :     // not in clipping range: always invisible
     618      500962 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     619         142 :         return OBJ_STYLE_NONE;
     620             :     // return style only for bottom-right cell
     621      500820 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     622      500820 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     623      500600 :     return ((nCol == nLastCol) && (nRow == nLastRow)) ?
     624     1001292 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
     625             : }
     626             : 
     627      500962 : const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
     628             : {
     629             :     // not in clipping range: always invisible
     630      500962 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     631         142 :         return OBJ_STYLE_NONE;
     632             :     // return style only for bottom-left cell
     633      500820 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     634      500820 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     635      500606 :     return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
     636     1001286 :         CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
     637             : }
     638             : 
     639      500962 : const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
     640             : {
     641             :     // not in clipping range: always invisible
     642      500962 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     643         142 :         return OBJ_STYLE_NONE;
     644             :     // return style only for top-right cell
     645      500820 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     646      500820 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     647      500604 :     return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
     648     1001292 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
     649             : }
     650             : 
     651             : // cell merging
     652         572 : void Array::SetMergedRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     653             : {
     654             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetMergedRange" );
     655             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetMergedRange" );
     656             : #if OSL_DEBUG_LEVEL >= 2
     657             :     {
     658             :         bool bFound = false;
     659             :         for( size_t nCurrCol = nFirstCol; !bFound && (nCurrCol <= nLastCol); ++nCurrCol )
     660             :             for( size_t nCurrRow = nFirstRow; !bFound && (nCurrRow <= nLastRow); ++nCurrRow )
     661             :                 bFound = CELL( nCurrCol, nCurrRow ).IsMerged();
     662             :         DBG_FRAME_CHECK( !bFound, "SetMergedRange", "overlapping merged ranges" );
     663             :     }
     664             : #endif
     665         572 :     if( mxImpl->IsValidPos( nFirstCol, nFirstRow ) && mxImpl->IsValidPos( nLastCol, nLastRow ) )
     666         572 :         lclSetMergedRange( mxImpl->maCells, mxImpl->mnWidth, nFirstCol, nFirstRow, nLastCol, nLastRow );
     667         572 : }
     668             : 
     669           0 : void Array::SetAddMergedLeftSize( size_t nCol, size_t nRow, long nAddSize )
     670             : {
     671             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedLeftSize" );
     672             :     DBG_FRAME_CHECK( mxImpl->GetMergedFirstCol( nCol, nRow ) == 0, "SetAddMergedLeftSize", "additional border inside array" );
     673           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     674           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddLeft = nAddSize;
     675           0 : }
     676             : 
     677          54 : void Array::SetAddMergedRightSize( size_t nCol, size_t nRow, long nAddSize )
     678             : {
     679             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedRightSize" );
     680             :     DBG_FRAME_CHECK( mxImpl->GetMergedLastCol( nCol, nRow ) + 1 == mxImpl->mnWidth, "SetAddMergedRightSize", "additional border inside array" );
     681         246 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     682         192 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddRight = nAddSize;
     683          54 : }
     684             : 
     685           4 : void Array::SetAddMergedTopSize( size_t nCol, size_t nRow, long nAddSize )
     686             : {
     687             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedTopSize" );
     688             :     DBG_FRAME_CHECK( mxImpl->GetMergedFirstRow( nCol, nRow ) == 0, "SetAddMergedTopSize", "additional border inside array" );
     689          28 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     690          24 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddTop = nAddSize;
     691           4 : }
     692             : 
     693           0 : void Array::SetAddMergedBottomSize( size_t nCol, size_t nRow, long nAddSize )
     694             : {
     695             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedBottomSize" );
     696             :     DBG_FRAME_CHECK( mxImpl->GetMergedLastRow( nCol, nRow ) + 1 == mxImpl->mnHeight, "SetAddMergedBottomSize", "additional border inside array" );
     697           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     698           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddBottom = nAddSize;
     699           0 : }
     700             : 
     701     5531373 : bool Array::IsMerged( size_t nCol, size_t nRow ) const
     702             : {
     703             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMerged" );
     704     5531373 :     return CELL( nCol, nRow ).IsMerged();
     705             : }
     706             : 
     707           0 : bool Array::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     708             : {
     709             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedLeft" );
     710           0 :     return mxImpl->IsMergedOverlappedLeft( nCol, nRow );
     711             : }
     712             : 
     713           0 : bool Array::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     714             : {
     715             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedRight" );
     716           0 :     return mxImpl->IsMergedOverlappedRight( nCol, nRow );
     717             : }
     718             : 
     719          58 : void Array::GetMergedOrigin( size_t& rnFirstCol, size_t& rnFirstRow, size_t nCol, size_t nRow ) const
     720             : {
     721             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetMergedOrigin" );
     722          58 :     rnFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     723          58 :     rnFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     724          58 : }
     725             : 
     726          58 : void Array::GetMergedRange( size_t& rnFirstCol, size_t& rnFirstRow,
     727             :         size_t& rnLastCol, size_t& rnLastRow, size_t nCol, size_t nRow ) const
     728             : {
     729          58 :     GetMergedOrigin( rnFirstCol, rnFirstRow, nCol, nRow );
     730          58 :     rnLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     731          58 :     rnLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     732          58 : }
     733             : 
     734             : // clipping
     735          66 : void Array::SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     736             : {
     737             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetClipRange" );
     738             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetClipRange" );
     739          66 :     mxImpl->mnFirstClipCol = nFirstCol;
     740          66 :     mxImpl->mnFirstClipRow = nFirstRow;
     741          66 :     mxImpl->mnLastClipCol = nLastCol;
     742          66 :     mxImpl->mnLastClipRow = nLastRow;
     743          66 : }
     744             : 
     745           0 : Rectangle Array::GetClipRangeRectangle() const
     746             : {
     747             :     return Rectangle(
     748           0 :         mxImpl->GetColPosition( mxImpl->mnFirstClipCol ),
     749           0 :         mxImpl->GetRowPosition( mxImpl->mnFirstClipRow ),
     750           0 :         mxImpl->GetColPosition( mxImpl->mnLastClipCol + 1 ),
     751           0 :         mxImpl->GetRowPosition( mxImpl->mnLastClipRow + 1 ) );
     752             : }
     753             : 
     754             : // cell coordinates
     755        1552 : void Array::SetXOffset( long nXOffset )
     756             : {
     757        1552 :     mxImpl->maXCoords[ 0 ] = nXOffset;
     758        1552 :     mxImpl->mbXCoordsDirty = true;
     759        1552 : }
     760             : 
     761        1552 : void Array::SetYOffset( long nYOffset )
     762             : {
     763        1552 :     mxImpl->maYCoords[ 0 ] = nYOffset;
     764        1552 :     mxImpl->mbYCoordsDirty = true;
     765        1552 : }
     766             : 
     767       17746 : void Array::SetColWidth( size_t nCol, long nWidth )
     768             : {
     769             :     DBG_FRAME_CHECK_COL( nCol, "SetColWidth" );
     770       17746 :     mxImpl->maWidths[ nCol ] = nWidth;
     771       17746 :     mxImpl->mbXCoordsDirty = true;
     772       17746 : }
     773             : 
     774       26062 : void Array::SetRowHeight( size_t nRow, long nHeight )
     775             : {
     776             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowHeight" );
     777       26062 :     mxImpl->maHeights[ nRow ] = nHeight;
     778       26062 :     mxImpl->mbYCoordsDirty = true;
     779       26062 : }
     780             : 
     781           0 : void Array::SetAllColWidths( long nWidth )
     782             : {
     783           0 :     std::fill( mxImpl->maWidths.begin(), mxImpl->maWidths.end(), nWidth );
     784           0 :     mxImpl->mbXCoordsDirty = true;
     785           0 : }
     786             : 
     787           0 : void Array::SetAllRowHeights( long nHeight )
     788             : {
     789           0 :     std::fill( mxImpl->maHeights.begin(), mxImpl->maHeights.end(), nHeight );
     790           0 :     mxImpl->mbYCoordsDirty = true;
     791           0 : }
     792             : 
     793      694539 : long Array::GetColPosition( size_t nCol ) const
     794             : {
     795             :     DBG_FRAME_CHECK_COL_1( nCol, "GetColPosition" );
     796      694539 :     return mxImpl->GetColPosition( nCol );
     797             : }
     798             : 
     799      694539 : long Array::GetRowPosition( size_t nRow ) const
     800             : {
     801             :     DBG_FRAME_CHECK_ROW_1( nRow, "GetRowPosition" );
     802      694539 :     return mxImpl->GetRowPosition( nRow );
     803             : }
     804             : 
     805      231513 : long Array::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     806             : {
     807             :     DBG_FRAME_CHECK_COL( nFirstCol, "GetColWidth" );
     808             :     DBG_FRAME_CHECK_COL( nLastCol, "GetColWidth" );
     809      231513 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     810             : }
     811             : 
     812      231513 : long Array::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     813             : {
     814             :     DBG_FRAME_CHECK_ROW( nFirstRow, "GetRowHeight" );
     815             :     DBG_FRAME_CHECK_ROW( nLastRow, "GetRowHeight" );
     816      231513 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     817             : }
     818             : 
     819           0 : long Array::GetWidth() const
     820             : {
     821           0 :     return GetColPosition( mxImpl->mnWidth ) - GetColPosition( 0 );
     822             : }
     823             : 
     824           0 : long Array::GetHeight() const
     825             : {
     826           0 :     return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
     827             : }
     828             : 
     829      231513 : Point Array::GetCellPosition( size_t nCol, size_t nRow, bool bSimple ) const
     830             : {
     831      231513 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     832      231513 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     833      231513 :     return Point( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     834             : }
     835             : 
     836      231513 : Size Array::GetCellSize( size_t nCol, size_t nRow, bool bSimple ) const
     837             : {
     838      231513 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     839      231513 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     840      231513 :     size_t nLastCol = bSimple ? nCol : mxImpl->GetMergedLastCol( nCol, nRow );
     841      231513 :     size_t nLastRow = bSimple ? nRow : mxImpl->GetMergedLastRow( nCol, nRow );
     842      231513 :     return Size( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     843             : }
     844             : 
     845      231513 : Rectangle Array::GetCellRect( size_t nCol, size_t nRow, bool bSimple ) const
     846             : {
     847      231513 :     Rectangle aRect( GetCellPosition( nCol, nRow, bSimple ), GetCellSize( nCol, nRow, bSimple ) );
     848             : 
     849             :     // adjust rectangle for partly visible merged cells
     850      231513 :     const Cell& rCell = CELL( nCol, nRow );
     851      231513 :     if( !bSimple && rCell.IsMerged() )
     852             :     {
     853          34 :         aRect.Left() -= rCell.mnAddLeft;
     854          34 :         aRect.Right() += rCell.mnAddRight;
     855          34 :         aRect.Top() -= rCell.mnAddTop;
     856          34 :         aRect.Bottom() += rCell.mnAddBottom;
     857             :     }
     858      231513 :     return aRect;
     859             : }
     860             : 
     861             : // diagonal frame borders
     862           0 : double Array::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     863             : {
     864             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetHorDiagAngle" );
     865           0 :     return mxImpl->GetHorDiagAngle( nCol, nRow, bSimple );
     866             : }
     867             : 
     868           0 : double Array::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     869             : {
     870             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetVerDiagAngle" );
     871           0 :     return mxImpl->GetVerDiagAngle( nCol, nRow, bSimple );
     872             : }
     873             : 
     874       16360 : void Array::SetUseDiagDoubleClipping( bool bSet )
     875             : {
     876       16360 :     mxImpl->mbDiagDblClip = bSet;
     877       16360 : }
     878             : 
     879             : // mirroring
     880           3 : void Array::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
     881             : {
     882           3 :     CellVec aNewCells;
     883           3 :     aNewCells.reserve( GetCellCount() );
     884             : 
     885             :     size_t nCol, nRow;
     886          87 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     887             :     {
     888        1092 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     889             :         {
     890        1008 :             aNewCells.push_back( CELL( mxImpl->GetMirrorCol( nCol ), nRow ) );
     891        1008 :             aNewCells.back().MirrorSelfX( bMirrorStyles, bSwapDiag );
     892             :         }
     893             :     }
     894          87 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     895             :     {
     896        1092 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     897             :         {
     898        1008 :             if( CELL( nCol, nRow ).mbMergeOrig )
     899             :             {
     900           0 :                 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     901           0 :                 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     902           0 :                 lclSetMergedRange( aNewCells, mxImpl->mnWidth,
     903             :                     mxImpl->GetMirrorCol( nLastCol ), nRow,
     904           0 :                     mxImpl->GetMirrorCol( nCol ), nLastRow );
     905             :             }
     906             :         }
     907             :     }
     908           3 :     mxImpl->maCells.swap( aNewCells );
     909             : 
     910           3 :     std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
     911           3 :     mxImpl->mbXCoordsDirty = true;
     912           3 : }
     913             : 
     914             : // drawing
     915        1552 : void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor,
     916             :         size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
     917             :         const Color* pForceColor ) const
     918             : {
     919             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
     920             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
     921             : 
     922             :     size_t nCol, nRow;
     923             : 
     924             :     // *** diagonal frame borders ***
     925       24510 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     926             :     {
     927      254639 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     928             :         {
     929      231681 :             const Cell& rCell = CELL( nCol, nRow );
     930      231681 :             bool bOverlapX = rCell.mbOverlapX;
     931      231681 :             bool bOverlapY = rCell.mbOverlapY;
     932      231681 :             bool bFirstCol = nCol == nFirstCol;
     933      231681 :             bool bFirstRow = nRow == nFirstRow;
     934      231853 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
     935         202 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
     936             :             {
     937      231513 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
     938      231513 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
     939             :                 {
     940      231468 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     941      231468 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     942             : 
     943      231468 :                     const Style aTlbrStyle = GetCellStyleTLBR( _nFirstCol, _nFirstRow, true );
     944      231468 :                     if ( aTlbrStyle.GetWidth( ) )
     945             :                         pProcessor->process( CreateClippedBorderPrimitives(
     946             :                                     aRect.TopLeft(), aRect.BottomRight(),
     947           0 :                                     aTlbrStyle, aRect ) );
     948             : 
     949      231468 :                     const Style aBltrStyle = GetCellStyleBLTR( _nFirstCol, _nFirstRow, true );
     950      231468 :                     if ( aBltrStyle.GetWidth( ) )
     951             :                         pProcessor->process( CreateClippedBorderPrimitives(
     952             :                                     aRect.BottomLeft(), aRect.TopRight(),
     953           0 :                                     aBltrStyle, aRect ) );
     954             :                 }
     955             :             }
     956             :         }
     957             :     }
     958             : 
     959             :     // *** horizontal frame borders ***
     960             : 
     961       26062 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
     962             :     {
     963       24510 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
     964       24510 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
     965             : 
     966             :         // *Start*** variables store the data of the left end of the cached frame border
     967       24510 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
     968       24510 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
     969       24510 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
     970       24510 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
     971       24510 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
     972       24510 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
     973       24510 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
     974             : 
     975             :         // *End*** variables store the data of the right end of the cached frame border
     976       24510 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
     977       24510 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
     978       24510 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
     979       24510 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
     980       24510 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
     981             : 
     982      246323 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
     983             :         {
     984      221813 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
     985      221813 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
     986             : 
     987      221813 :             const Style& rCurr = *pEndRFromR;
     988             : 
     989      221813 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
     990      221813 :             const Style& rLFromT = *pEndRFromT;
     991      221813 :             const Style& rLFromL = *pStart;
     992      221813 :             const Style& rLFromB = *pEndRFromB;
     993      221813 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
     994             : 
     995      221813 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
     996      221813 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
     997      221813 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
     998      221813 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
     999      221813 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1000             : 
    1001             :             // check if current frame border can be connected to cached frame border
    1002      221813 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1003      221813 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1004             :             {
    1005             :                 // draw previous frame border
    1006        1106 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1007        1106 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1008             :                    pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1009             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1010         777 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1011             : 
    1012             :                 // re-init "*Start***" variables
    1013        1106 :                 aStartPos = aEndPos;
    1014        1106 :                 pStart = &rCurr;
    1015        1106 :                 aStartLFromTR = aLFromTR;
    1016        1106 :                 pStartLFromT = &rLFromT;
    1017        1106 :                 pStartLFromL = &rLFromL;
    1018        1106 :                 pStartLFromB = &rLFromB;
    1019        1106 :                 aStartLFromBR = aLFromBR;
    1020             :             }
    1021             : 
    1022             :             // store current styles in "*End***" variables
    1023      221813 :             aEndRFromTL = aRFromTL;
    1024      221813 :             pEndRFromT = &rRFromT;
    1025      221813 :             pEndRFromR = &rRFromR;
    1026      221813 :             pEndRFromB = &rRFromB;
    1027      221813 :             aEndRFromBL = aRFromBL;
    1028             :         }
    1029             : 
    1030             :         // draw last frame border
    1031       24510 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1032       24510 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1033             :             pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1034             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1035        1530 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1036             :     }
    1037             : 
    1038             :     // *** vertical frame borders ***
    1039       17746 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1040             :     {
    1041       16194 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1042       16194 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1043             : 
    1044             :         // *Start*** variables store the data of the top end of the cached frame border
    1045       16194 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1046       16194 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1047       16194 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1048       16194 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1049       16194 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1050       16194 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1051       16194 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1052             : 
    1053             :         // *End*** variables store the data of the bottom end of the cached frame border
    1054       16194 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1055       16194 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1056       16194 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1057       16194 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1058       16194 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1059             : 
    1060      254639 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1061             :         {
    1062      238445 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1063      238445 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1064             : 
    1065      238445 :             const Style& rCurr = *pEndBFromB;
    1066             : 
    1067      238445 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1068      238445 :             const Style& rTFromL = *pEndBFromL;
    1069      238445 :             const Style& rTFromT = *pStart;
    1070      238445 :             const Style& rTFromR = *pEndBFromR;
    1071      238445 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1072             : 
    1073      238445 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1074      238445 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1075      238445 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1076      238445 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1077      238445 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1078             : 
    1079             :             // check if current frame border can be connected to cached frame border
    1080      238445 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1081      238445 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1082             :             {
    1083             :                 // draw previous frame border
    1084        1350 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1085        1350 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1086             :                     pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1087             :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1088         726 :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1089             : 
    1090             :                 // re-init "*Start***" variables
    1091        1350 :                 aStartPos = aEndPos;
    1092        1350 :                 pStart = &rCurr;
    1093        1350 :                 aStartTFromBL = aTFromBL;
    1094        1350 :                 pStartTFromL = &rTFromL;
    1095        1350 :                 pStartTFromT = &rTFromT;
    1096        1350 :                 pStartTFromR = &rTFromR;
    1097        1350 :                 aStartTFromBR = aTFromBR;
    1098             :             }
    1099             : 
    1100             :             // store current styles in "*End***" variables
    1101      238445 :             aEndBFromTL = aBFromTL;
    1102      238445 :             pEndBFromL = &rBFromL;
    1103      238445 :             pEndBFromB = &rBFromB;
    1104      238445 :             pEndBFromR = &rBFromR;
    1105      238445 :             aEndBFromTR = aBFromTR;
    1106             :         }
    1107             : 
    1108             :         // draw last frame border
    1109       16194 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1110       16194 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1111             :             pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1112             :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1113        1000 :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1114             :     }
    1115        1552 : }
    1116             : 
    1117           0 : void Array::DrawRange( OutputDevice& rDev,
    1118             :         size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
    1119             :         const Color* pForceColor ) const
    1120             : {
    1121             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
    1122             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
    1123             : 
    1124             :     size_t nCol, nRow;
    1125             : 
    1126             :     // *** diagonal frame borders ***
    1127             : 
    1128             :     // set clipping region to clip partly visible merged cells
    1129           0 :     rDev.Push( PushFlags::CLIPREGION );
    1130           0 :     rDev.IntersectClipRegion( GetClipRangeRectangle() );
    1131           0 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
    1132             :     {
    1133           0 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
    1134             :         {
    1135           0 :             const Cell& rCell = CELL( nCol, nRow );
    1136           0 :             bool bOverlapX = rCell.mbOverlapX;
    1137           0 :             bool bOverlapY = rCell.mbOverlapY;
    1138           0 :             bool bFirstCol = nCol == nFirstCol;
    1139           0 :             bool bFirstRow = nRow == nFirstRow;
    1140           0 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
    1141           0 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
    1142             :             {
    1143           0 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
    1144           0 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
    1145             :                 {
    1146           0 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
    1147           0 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
    1148           0 :                     size_t _nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
    1149           0 :                     size_t _nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
    1150             : 
    1151             :                     DrawDiagFrameBorders( rDev, aRect,
    1152           0 :                         GetCellStyleTLBR( _nFirstCol, _nFirstRow, true ), GetCellStyleBLTR( _nFirstCol, _nFirstRow, true ),
    1153           0 :                         GetCellStyleLeft( _nFirstCol, _nFirstRow ), GetCellStyleTop( _nFirstCol, _nFirstRow ),
    1154           0 :                         GetCellStyleRight( _nLastCol, _nLastRow ), GetCellStyleBottom( _nLastCol, _nLastRow ),
    1155           0 :                         GetCellStyleLeft( _nFirstCol, _nLastRow ), GetCellStyleBottom( _nFirstCol, _nLastRow ),
    1156           0 :                         GetCellStyleRight( _nLastCol, _nFirstRow ), GetCellStyleTop( _nLastCol, _nFirstRow ),
    1157           0 :                         pForceColor, mxImpl->mbDiagDblClip );
    1158             :                 }
    1159             :             }
    1160             :         }
    1161             :     }
    1162           0 :     rDev.Pop(); // clip region
    1163             : 
    1164             :     // *** horizontal frame borders ***
    1165             : 
    1166           0 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
    1167             :     {
    1168           0 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
    1169           0 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
    1170             : 
    1171             :         // *Start*** variables store the data of the left end of the cached frame border
    1172           0 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
    1173           0 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
    1174           0 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
    1175           0 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
    1176           0 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
    1177           0 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
    1178           0 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
    1179             : 
    1180             :         // *End*** variables store the data of the right end of the cached frame border
    1181           0 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
    1182           0 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
    1183           0 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
    1184           0 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
    1185           0 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
    1186             : 
    1187           0 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
    1188             :         {
    1189           0 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
    1190           0 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
    1191             : 
    1192           0 :             const Style& rCurr = *pEndRFromR;
    1193             : 
    1194           0 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
    1195           0 :             const Style& rLFromT = *pEndRFromT;
    1196           0 :             const Style& rLFromL = *pStart;
    1197           0 :             const Style& rLFromB = *pEndRFromB;
    1198           0 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1199             : 
    1200           0 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
    1201           0 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
    1202           0 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
    1203           0 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
    1204           0 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1205             : 
    1206             :             // check if current frame border can be connected to cached frame border
    1207           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1208           0 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1209             :             {
    1210             :                 // draw previous frame border
    1211           0 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1212           0 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1213             :                     DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1214             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1215           0 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
    1216             : 
    1217             :                 // re-init "*Start***" variables
    1218           0 :                 aStartPos = aEndPos;
    1219           0 :                 pStart = &rCurr;
    1220           0 :                 aStartLFromTR = aLFromTR;
    1221           0 :                 pStartLFromT = &rLFromT;
    1222           0 :                 pStartLFromL = &rLFromL;
    1223           0 :                 pStartLFromB = &rLFromB;
    1224           0 :                 aStartLFromBR = aLFromBR;
    1225             :             }
    1226             : 
    1227             :             // store current styles in "*End***" variables
    1228           0 :             aEndRFromTL = aRFromTL;
    1229           0 :             pEndRFromT = &rRFromT;
    1230           0 :             pEndRFromR = &rRFromR;
    1231           0 :             pEndRFromB = &rRFromB;
    1232           0 :             aEndRFromBL = aRFromBL;
    1233             :         }
    1234             : 
    1235             :         // draw last frame border
    1236           0 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1237           0 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1238             :             DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1239             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1240           0 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
    1241             :     }
    1242             : 
    1243             :     // *** vertical frame borders ***
    1244             : 
    1245           0 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1246             :     {
    1247           0 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1248           0 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1249             : 
    1250             :         // *Start*** variables store the data of the top end of the cached frame border
    1251           0 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1252           0 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1253           0 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1254           0 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1255           0 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1256           0 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1257           0 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1258             : 
    1259             :         // *End*** variables store the data of the bottom end of the cached frame border
    1260           0 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1261           0 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1262           0 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1263           0 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1264           0 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1265             : 
    1266           0 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1267             :         {
    1268           0 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1269           0 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1270             : 
    1271           0 :             const Style& rCurr = *pEndBFromB;
    1272             : 
    1273           0 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1274           0 :             const Style& rTFromL = *pEndBFromL;
    1275           0 :             const Style& rTFromT = *pStart;
    1276           0 :             const Style& rTFromR = *pEndBFromR;
    1277           0 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1278             : 
    1279           0 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1280           0 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1281           0 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1282           0 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1283           0 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1284             : 
    1285             :             // check if current frame border can be connected to cached frame border
    1286           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1287           0 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1288             :             {
    1289             :                 // draw previous frame border
    1290           0 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1291           0 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1292             :                     DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1293             :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
    1294           0 :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
    1295             : 
    1296             :                 // re-init "*Start***" variables
    1297           0 :                 aStartPos = aEndPos;
    1298           0 :                 pStart = &rCurr;
    1299           0 :                 aStartTFromBL = aTFromBL;
    1300           0 :                 pStartTFromL = &rTFromL;
    1301           0 :                 pStartTFromT = &rTFromT;
    1302           0 :                 pStartTFromR = &rTFromR;
    1303           0 :                 aStartTFromBR = aTFromBR;
    1304             :             }
    1305             : 
    1306             :             // store current styles in "*End***" variables
    1307           0 :             aEndBFromTL = aBFromTL;
    1308           0 :             pEndBFromL = &rBFromL;
    1309           0 :             pEndBFromB = &rBFromB;
    1310           0 :             pEndBFromR = &rBFromR;
    1311           0 :             aEndBFromTR = aBFromTR;
    1312             :         }
    1313             : 
    1314             :         // draw last frame border
    1315           0 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1316           0 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1317             :             DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1318             :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
    1319           0 :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
    1320             :     }
    1321           0 : }
    1322             : 
    1323           0 : void Array::DrawArray( OutputDevice& rDev, const Color* pForceColor ) const
    1324             : {
    1325           0 :     if( mxImpl->mnWidth && mxImpl->mnHeight )
    1326           0 :         DrawRange( rDev, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, pForceColor );
    1327           0 : }
    1328             : 
    1329             : 
    1330             : 
    1331             : #undef ORIGCELL
    1332             : #undef CELLACC
    1333             : #undef CELL
    1334             : 
    1335             : 
    1336             : 
    1337             : #undef DBG_FRAME_CHECK_ROW_1
    1338             : #undef DBG_FRAME_CHECK_COL_1
    1339             : #undef DBG_FRAME_CHECK_COLROW
    1340             : #undef DBG_FRAME_CHECK_ROW
    1341             : #undef DBG_FRAME_CHECK_COL
    1342             : #undef DBG_FRAME_CHECK
    1343             : 
    1344             : 
    1345             : 
    1346             : } // namespace frame
    1347         594 : } // namespace svx
    1348             : 
    1349             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10