LCOV - code coverage report
Current view: top level - svx/source/dialog - framelinkarray.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 438 644 68.0 %
Date: 2014-04-11 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     3803235 :     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     2898020 : Cell::Cell() :
      57             :     mnAddLeft( 0 ),
      58             :     mnAddRight( 0 ),
      59             :     mnAddTop( 0 ),
      60             :     mnAddBottom( 0 ),
      61             :     mbMergeOrig( false ),
      62             :     mbOverlapX( false ),
      63     2898020 :     mbOverlapY( false )
      64             : {
      65     2898020 : }
      66             : 
      67         696 : void Cell::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
      68             : {
      69         696 :     std::swap( maLeft, maRight );
      70         696 :     std::swap( mnAddLeft, mnAddRight );
      71         696 :     if( bMirrorStyles )
      72             :     {
      73         696 :         maLeft.MirrorSelf();
      74         696 :         maRight.MirrorSelf();
      75             :     }
      76         696 :     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         696 : }
      86             : 
      87             : 
      88             : 
      89             : 
      90        3234 : void lclRecalcCoordVec( LongVec& rCoords, const LongVec& rSizes )
      91             : {
      92             :     DBG_ASSERT( rCoords.size() == rSizes.size() + 1, "lclRecalcCoordVec - inconsistent vectors" );
      93        3234 :     LongVec::iterator aCIt = rCoords.begin();
      94        3234 :     LongVec::const_iterator aSIt = rSizes.begin(), aSEnd = rSizes.end();
      95       41551 :     for( ; aSIt != aSEnd; ++aCIt, ++aSIt )
      96       38317 :         *(aCIt + 1) = *aCIt + *aSIt;
      97        3234 : }
      98             : 
      99         291 : void lclSetMergedRange( CellVec& rCells, size_t nWidth, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     100             : {
     101         859 :     for( size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     102             :     {
     103        2292 :         for( size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     104             :         {
     105        1724 :             Cell& rCell = rCells[ nRow * nWidth + nCol ];
     106        1724 :             rCell.mbMergeOrig = false;
     107        1724 :             rCell.mbOverlapX = nCol > nFirstCol;
     108        1724 :             rCell.mbOverlapY = nRow > nFirstRow;
     109             :         }
     110             :     }
     111         291 :     rCells[ nFirstRow * nWidth + nFirstCol ].mbMergeOrig = true;
     112         291 : }
     113             : 
     114             : 
     115             : 
     116          85 : static const Style OBJ_STYLE_NONE;
     117          85 : static const Cell OBJ_CELL_NONE;
     118             : 
     119             : const bool DIAG_DBL_CLIP_DEFAULT = false;
     120             : 
     121       17970 : 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    36799257 :     inline bool         IsValidPos( size_t nCol, size_t nRow ) const
     141    36799257 :                             { return (nCol < mnWidth) && (nRow < mnHeight); }
     142    36061585 :     inline size_t       GetIndex( size_t nCol, size_t nRow ) const
     143    36061585 :                             { 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         696 :     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       17970 : ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
     177             :     mnWidth( nWidth ),
     178             :     mnHeight( nHeight ),
     179             :     mnFirstClipCol( 0 ),
     180             :     mnFirstClipRow( 0 ),
     181       17970 :     mnLastClipCol( nWidth - 1 ),
     182       17970 :     mnLastClipRow( nHeight - 1 ),
     183             :     mbXCoordsDirty( false ),
     184             :     mbYCoordsDirty( false ),
     185       53910 :     mbDiagDblClip( bDiagDblClip )
     186             : {
     187             :     // default-construct all vectors
     188       17970 :     maCells.resize( mnWidth * mnHeight );
     189       17970 :     maWidths.resize( mnWidth, 0L );
     190       17970 :     maHeights.resize( mnHeight, 0L );
     191       17970 :     maXCoords.resize( mnWidth + 1, 0L );
     192       17970 :     maYCoords.resize( mnHeight + 1, 0L );
     193       17970 : }
     194             : 
     195    20695699 : const Cell& ArrayImpl::GetCell( size_t nCol, size_t nRow ) const
     196             : {
     197    20695699 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : OBJ_CELL_NONE;
     198             : }
     199             : 
     200    15365886 : Cell& ArrayImpl::GetCellAcc( size_t nCol, size_t nRow )
     201             : {
     202    15365886 :     static Cell aDummy;
     203    15365886 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : aDummy;
     204             : }
     205             : 
     206     4468091 : size_t ArrayImpl::GetMergedFirstCol( size_t nCol, size_t nRow ) const
     207             : {
     208     4468091 :     size_t nFirstCol = nCol;
     209     4468091 :     while( (nFirstCol > 0) && GetCell( nFirstCol, nRow ).mbOverlapX ) --nFirstCol;
     210     4468091 :     return nFirstCol;
     211             : }
     212             : 
     213     4468087 : size_t ArrayImpl::GetMergedFirstRow( size_t nCol, size_t nRow ) const
     214             : {
     215     4468087 :     size_t nFirstRow = nRow;
     216     4468087 :     while( (nFirstRow > 0) && GetCell( nCol, nFirstRow ).mbOverlapY ) --nFirstRow;
     217     4468087 :     return nFirstRow;
     218             : }
     219             : 
     220      905763 : size_t ArrayImpl::GetMergedLastCol( size_t nCol, size_t nRow ) const
     221             : {
     222      905763 :     size_t nLastCol = nCol + 1;
     223      905763 :     while( (nLastCol < mnWidth) && GetCell( nLastCol, nRow ).mbOverlapX ) ++nLastCol;
     224      905763 :     return nLastCol - 1;
     225             : }
     226             : 
     227      905763 : size_t ArrayImpl::GetMergedLastRow( size_t nCol, size_t nRow ) const
     228             : {
     229      905763 :     size_t nLastRow = nRow + 1;
     230      905763 :     while( (nLastRow < mnHeight) && GetCell( nCol, nLastRow ).mbOverlapY ) ++nLastRow;
     231      905763 :     return nLastRow - 1;
     232             : }
     233             : 
     234     2489372 : const Cell& ArrayImpl::GetMergedOriginCell( size_t nCol, size_t nRow ) const
     235             : {
     236     2489372 :     return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
     237             : }
     238             : 
     239      255649 : bool ArrayImpl::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     240             : {
     241      255649 :     const Cell& rCell = GetCell( nCol, nRow );
     242      255649 :     return rCell.mbOverlapX || (rCell.mnAddLeft > 0);
     243             : }
     244             : 
     245      365632 : bool ArrayImpl::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     246             : {
     247      365632 :     return GetCell( nCol + 1, nRow ).mbOverlapX || (GetCell( nCol, nRow ).mnAddRight > 0);
     248             : }
     249             : 
     250      252822 : bool ArrayImpl::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
     251             : {
     252      252822 :     const Cell& rCell = GetCell( nCol, nRow );
     253      252822 :     return rCell.mbOverlapY || (rCell.mnAddTop > 0);
     254             : }
     255             : 
     256      371316 : bool ArrayImpl::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
     257             : {
     258      371316 :     return GetCell( nCol, nRow + 1 ).mbOverlapY || (GetCell( nCol, nRow ).mnAddBottom > 0);
     259             : }
     260             : 
     261     2719439 : bool ArrayImpl::IsColInClipRange( size_t nCol ) const
     262             : {
     263     2719439 :     return (mnFirstClipCol <= nCol) && (nCol <= mnLastClipCol);
     264             : }
     265             : 
     266     2719229 : bool ArrayImpl::IsRowInClipRange( size_t nRow ) const
     267             : {
     268     2719229 :     return (mnFirstClipRow <= nRow) && (nRow <= mnLastClipRow);
     269             : }
     270             : 
     271     1474180 : bool ArrayImpl::IsInClipRange( size_t nCol, size_t nRow ) const
     272             : {
     273     1474180 :     return IsColInClipRange( nCol ) && IsRowInClipRange( nRow );
     274             : }
     275             : 
     276      560511 : long ArrayImpl::GetColPosition( size_t nCol ) const
     277             : {
     278      560511 :     if( mbXCoordsDirty )
     279             :     {
     280        1617 :         lclRecalcCoordVec( maXCoords, maWidths );
     281        1617 :         mbXCoordsDirty = false;
     282             :     }
     283      560511 :     return maXCoords[ nCol ];
     284             : }
     285             : 
     286      557805 : long ArrayImpl::GetRowPosition( size_t nRow ) const
     287             : {
     288      557805 :     if( mbYCoordsDirty )
     289             :     {
     290        1617 :         lclRecalcCoordVec( maYCoords, maHeights );
     291        1617 :         mbYCoordsDirty = false;
     292             :     }
     293      557805 :     return maYCoords[ nRow ];
     294             : }
     295             : 
     296         549 : long ArrayImpl::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     297             : {
     298         549 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     299             : }
     300             : 
     301         549 : long ArrayImpl::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     302             : {
     303         549 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     304             : }
     305             : 
     306      737090 : double ArrayImpl::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     307             : {
     308      737090 :     double fAngle = 0.0;
     309      737090 :     if( IsValidPos( nCol, nRow ) )
     310             :     {
     311      737090 :         if( bSimple || !GetCell( nCol, nRow ).IsMerged() )
     312             :         {
     313      736541 :             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         549 :             size_t nFirstCol = GetMergedFirstCol( nCol, nRow );
     319         549 :             size_t nFirstRow = GetMergedFirstRow( nCol, nRow );
     320         549 :             const Cell& rCell = GetCell( nFirstCol, nFirstRow );
     321         549 :             long nWidth = GetColWidth( nFirstCol, GetMergedLastCol( nCol, nRow ) ) + rCell.mnAddLeft + rCell.mnAddRight;
     322         549 :             long nHeight = GetRowHeight( nFirstRow, GetMergedLastRow( nCol, nRow ) ) + rCell.mnAddTop + rCell.mnAddBottom;
     323         549 :             fAngle = frame::GetHorDiagAngle( nWidth + 1, nHeight + 1 );
     324             :         }
     325             :     }
     326      737090 :     return fAngle;
     327             : }
     328             : 
     329      371382 : double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     330             : {
     331      371382 :     double fAngle = GetHorDiagAngle( nCol, nRow, bSimple );
     332      371382 :     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         144 :     inline bool         Is() const { return (mnCol <= mnLastCol) && (mnRow <= mnLastRow); }
     343         114 :     inline size_t       Col() const { return mnCol; }
     344         114 :     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          30 : 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          30 :     rArray.GetMergedRange( mnFirstCol, mnFirstRow, mnLastCol, mnLastRow, nCol, nRow );
     363          30 :     mnCol = mnFirstCol;
     364          30 :     mnRow = mnFirstRow;
     365          30 : }
     366             : 
     367         114 : MergedCellIterator& MergedCellIterator::operator++()
     368             : {
     369             :     DBG_ASSERT( Is(), "svx::frame::MergedCellIterator::operator++() - already invalid" );
     370         114 :     if( ++mnCol > mnLastCol )
     371             :     {
     372          90 :         mnCol = mnFirstCol;
     373          90 :         ++mnRow;
     374             :     }
     375         114 :     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        8985 : Array::Array()
     396             : {
     397        8985 :     Initialize( 0, 0 );
     398        8985 : }
     399             : 
     400        8985 : Array::~Array()
     401             : {
     402        8985 : }
     403             : 
     404             : // array size and column/row indexes ------------------------------------------
     405             : 
     406       17970 : void Array::Initialize( size_t nWidth, size_t nHeight )
     407             : {
     408       17970 :     bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
     409       17970 :     mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
     410       17970 : }
     411             : 
     412        1617 : size_t Array::GetColCount() const
     413             : {
     414        1617 :     return mxImpl->mnWidth;
     415             : }
     416             : 
     417        1617 : size_t Array::GetRowCount() const
     418             : {
     419        1617 :     return mxImpl->mnHeight;
     420             : }
     421             : 
     422           2 : size_t Array::GetCellCount() const
     423             : {
     424           2 :     return mxImpl->maCells.size();
     425             : }
     426             : 
     427           0 : size_t Array::GetCellIndex( size_t nCol, size_t nRow, bool bRTL ) const
     428             : {
     429             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetCellIndex" );
     430           0 :     if (bRTL)
     431           0 :         nCol = mxImpl->GetMirrorCol(nCol);
     432           0 :     return mxImpl->GetIndex( nCol, nRow );
     433             : }
     434             : 
     435             : // cell border styles ---------------------------------------------------------
     436             : 
     437     2560962 : void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
     438             : {
     439             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
     440     2560962 :     CELLACC( nCol, nRow ).maLeft = rStyle;
     441     2560962 : }
     442             : 
     443     2560962 : void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
     444             : {
     445             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
     446     2560962 :     CELLACC( nCol, nRow ).maRight = rStyle;
     447     2560962 : }
     448             : 
     449     2560962 : void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
     450             : {
     451             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
     452     2560962 :     CELLACC( nCol, nRow ).maTop = rStyle;
     453     2560962 : }
     454             : 
     455     2560962 : void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
     456             : {
     457             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
     458     2560962 :     CELLACC( nCol, nRow ).maBottom = rStyle;
     459     2560962 : }
     460             : 
     461     2560962 : void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
     462             : {
     463             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
     464     2560962 :     CELLACC( nCol, nRow ).maTLBR = rStyle;
     465     2560962 : }
     466             : 
     467     2560962 : void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
     468             : {
     469             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
     470     2560962 :     CELLACC( nCol, nRow ).maBLTR = rStyle;
     471     2560962 : }
     472             : 
     473           0 : void Array::SetCellStyleDiag( size_t nCol, size_t nRow, const Style& rTLBR, const Style& rBLTR )
     474             : {
     475             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleDiag" );
     476           0 :     Cell& rCell = CELLACC( nCol, nRow );
     477           0 :     rCell.maTLBR = rTLBR;
     478           0 :     rCell.maBLTR = rBLTR;
     479           0 : }
     480             : 
     481           0 : void Array::SetColumnStyleLeft( size_t nCol, const Style& rStyle )
     482             : {
     483             :     DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleLeft" );
     484           0 :     for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     485           0 :         SetCellStyleLeft( nCol, nRow, rStyle );
     486           0 : }
     487             : 
     488           0 : void Array::SetColumnStyleRight( size_t nCol, const Style& rStyle )
     489             : {
     490             :     DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleRight" );
     491           0 :     for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     492           0 :         SetCellStyleRight( nCol, nRow, rStyle );
     493           0 : }
     494             : 
     495           0 : void Array::SetRowStyleTop( size_t nRow, const Style& rStyle )
     496             : {
     497             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleTop" );
     498           0 :     for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     499           0 :         SetCellStyleTop( nCol, nRow, rStyle );
     500           0 : }
     501             : 
     502           0 : void Array::SetRowStyleBottom( size_t nRow, const Style& rStyle )
     503             : {
     504             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleBottom" );
     505           0 :     for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     506           0 :         SetCellStyleBottom( nCol, nRow, rStyle );
     507           0 : }
     508             : 
     509      255857 : const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple ) const
     510             : {
     511             :     // simple: always return own left style
     512      255857 :     if( bSimple )
     513           0 :         return CELL( nCol, nRow ).maLeft;
     514             :     // outside clipping rows or overlapped in merged cells: invisible
     515      255857 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedLeft( nCol, nRow ) )
     516         284 :         return OBJ_STYLE_NONE;
     517             :     // left clipping border: always own left style
     518      255573 :     if( nCol == mxImpl->mnFirstClipCol )
     519          99 :         return ORIGCELL( nCol, nRow ).maLeft;
     520             :     // right clipping border: always right style of left neighbor cell
     521      255474 :     if( nCol == mxImpl->mnLastClipCol + 1 )
     522          33 :         return ORIGCELL( nCol - 1, nRow ).maRight;
     523             :     // outside clipping columns: invisible
     524      255441 :     if( !mxImpl->IsColInClipRange( nCol ) )
     525           0 :         return OBJ_STYLE_NONE;
     526             :     // inside clipping range: maximum of own left style and right style of left neighbor cell
     527      255441 :     return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
     528             : }
     529             : 
     530      365708 : const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple ) const
     531             : {
     532             :     // simple: always return own right style
     533      365708 :     if( bSimple )
     534           0 :         return CELL( nCol, nRow ).maRight;
     535             :     // outside clipping rows or overlapped in merged cells: invisible
     536      365708 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedRight( nCol, nRow ) )
     537         226 :         return OBJ_STYLE_NONE;
     538             :     // left clipping border: always left style of right neighbor cell
     539      365482 :     if( nCol + 1 == mxImpl->mnFirstClipCol )
     540           0 :         return ORIGCELL( nCol + 1, nRow ).maLeft;
     541             :     // right clipping border: always own right style
     542      365482 :     if( nCol == mxImpl->mnLastClipCol )
     543          66 :         return ORIGCELL( nCol, nRow ).maRight;
     544             :     // outside clipping columns: invisible
     545      365416 :     if( !mxImpl->IsColInClipRange( nCol ) )
     546           0 :         return OBJ_STYLE_NONE;
     547             :     // inside clipping range: maximum of own right style and left style of right neighbor cell
     548      365416 :     return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
     549             : }
     550             : 
     551      253020 : const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple ) const
     552             : {
     553             :     // simple: always return own top style
     554      253020 :     if( bSimple )
     555           0 :         return CELL( nCol, nRow ).maTop;
     556             :     // outside clipping columns or overlapped in merged cells: invisible
     557      253020 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedTop( nCol, nRow ) )
     558         306 :         return OBJ_STYLE_NONE;
     559             :     // top clipping border: always own top style
     560      252714 :     if( nRow == mxImpl->mnFirstClipRow )
     561         114 :         return ORIGCELL( nCol, nRow ).maTop;
     562             :     // bottom clipping border: always bottom style of top neighbor cell
     563      252600 :     if( nRow == mxImpl->mnLastClipRow + 1 )
     564          38 :         return ORIGCELL( nCol, nRow - 1 ).maBottom;
     565             :     // outside clipping rows: invisible
     566      252562 :     if( !mxImpl->IsRowInClipRange( nRow ) )
     567           0 :         return OBJ_STYLE_NONE;
     568             :     // inside clipping range: maximum of own top style and bottom style of top neighbor cell
     569      252562 :     return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
     570             : }
     571             : 
     572      371382 : const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple ) const
     573             : {
     574             :     // simple: always return own bottom style
     575      371382 :     if( bSimple )
     576           0 :         return CELL( nCol, nRow ).maBottom;
     577             :     // outside clipping columns or overlapped in merged cells: invisible
     578      371382 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedBottom( nCol, nRow ) )
     579         252 :         return OBJ_STYLE_NONE;
     580             :     // top clipping border: always top style of bottom neighbor cell
     581      371130 :     if( nRow + 1 == mxImpl->mnFirstClipRow )
     582           0 :         return ORIGCELL( nCol, nRow + 1 ).maTop;
     583             :     // bottom clipping border: always own bottom style
     584      371130 :     if( nRow == mxImpl->mnLastClipRow )
     585          76 :         return ORIGCELL( nCol, nRow ).maBottom;
     586             :     // outside clipping rows: invisible
     587      371054 :     if( !mxImpl->IsRowInClipRange( nRow ) )
     588           0 :         return OBJ_STYLE_NONE;
     589             :     // inside clipping range: maximum of own bottom style and top style of bottom neighbor cell
     590      371054 :     return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
     591             : }
     592             : 
     593      168236 : const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple ) const
     594             : {
     595      168236 :     return bSimple ? CELL( nCol, nRow ).maTLBR :
     596      336472 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maTLBR : OBJ_STYLE_NONE);
     597             : }
     598             : 
     599      168236 : const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple ) const
     600             : {
     601      168236 :     return bSimple ? CELL( nCol, nRow ).maBLTR :
     602      336472 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maBLTR : OBJ_STYLE_NONE);
     603             : }
     604             : 
     605      368545 : const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
     606             : {
     607             :     // not in clipping range: always invisible
     608      368545 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     609          71 :         return OBJ_STYLE_NONE;
     610             :     // return style only for top-left cell
     611      368474 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     612      368474 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     613      368332 :     return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
     614      736712 :         CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
     615             : }
     616             : 
     617      368545 : const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
     618             : {
     619             :     // not in clipping range: always invisible
     620      368545 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     621          71 :         return OBJ_STYLE_NONE;
     622             :     // return style only for bottom-right cell
     623      368474 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     624      368474 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     625      368324 :     return ((nCol == nLastCol) && (nRow == nLastRow)) ?
     626      736716 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
     627             : }
     628             : 
     629      368545 : const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
     630             : {
     631             :     // not in clipping range: always invisible
     632      368545 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     633          71 :         return OBJ_STYLE_NONE;
     634             :     // return style only for bottom-left cell
     635      368474 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     636      368474 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     637      368330 :     return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
     638      736712 :         CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
     639             : }
     640             : 
     641      368545 : const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
     642             : {
     643             :     // not in clipping range: always invisible
     644      368545 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     645          71 :         return OBJ_STYLE_NONE;
     646             :     // return style only for top-right cell
     647      368474 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     648      368474 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     649      368326 :     return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
     650      736716 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
     651             : }
     652             : 
     653             : // cell merging ---------------------------------------------------------------
     654             : 
     655         291 : void Array::SetMergedRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     656             : {
     657             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetMergedRange" );
     658             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetMergedRange" );
     659             : #if OSL_DEBUG_LEVEL >= 2
     660             :     {
     661             :         bool bFound = false;
     662             :         for( size_t nCurrCol = nFirstCol; !bFound && (nCurrCol <= nLastCol); ++nCurrCol )
     663             :             for( size_t nCurrRow = nFirstRow; !bFound && (nCurrRow <= nLastRow); ++nCurrRow )
     664             :                 bFound = CELL( nCurrCol, nCurrRow ).IsMerged();
     665             :         DBG_FRAME_CHECK( !bFound, "SetMergedRange", "overlapping merged ranges" );
     666             :     }
     667             : #endif
     668         291 :     if( mxImpl->IsValidPos( nFirstCol, nFirstRow ) && mxImpl->IsValidPos( nLastCol, nLastRow ) )
     669         291 :         lclSetMergedRange( mxImpl->maCells, mxImpl->mnWidth, nFirstCol, nFirstRow, nLastCol, nLastRow );
     670         291 : }
     671             : 
     672           0 : void Array::SetAddMergedLeftSize( size_t nCol, size_t nRow, long nAddSize )
     673             : {
     674             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedLeftSize" );
     675             :     DBG_FRAME_CHECK( mxImpl->GetMergedFirstCol( nCol, nRow ) == 0, "SetAddMergedLeftSize", "additional border inside array" );
     676           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     677           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddLeft = nAddSize;
     678           0 : }
     679             : 
     680          28 : void Array::SetAddMergedRightSize( size_t nCol, size_t nRow, long nAddSize )
     681             : {
     682             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedRightSize" );
     683             :     DBG_FRAME_CHECK( mxImpl->GetMergedLastCol( nCol, nRow ) + 1 == mxImpl->mnWidth, "SetAddMergedRightSize", "additional border inside array" );
     684         130 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     685         102 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddRight = nAddSize;
     686          28 : }
     687             : 
     688           2 : void Array::SetAddMergedTopSize( size_t nCol, size_t nRow, long nAddSize )
     689             : {
     690             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedTopSize" );
     691             :     DBG_FRAME_CHECK( mxImpl->GetMergedFirstRow( nCol, nRow ) == 0, "SetAddMergedTopSize", "additional border inside array" );
     692          14 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     693          12 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddTop = nAddSize;
     694           2 : }
     695             : 
     696           0 : void Array::SetAddMergedBottomSize( size_t nCol, size_t nRow, long nAddSize )
     697             : {
     698             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedBottomSize" );
     699             :     DBG_FRAME_CHECK( mxImpl->GetMergedLastRow( nCol, nRow ) + 1 == mxImpl->mnHeight, "SetAddMergedBottomSize", "additional border inside array" );
     700           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     701           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddBottom = nAddSize;
     702           0 : }
     703             : 
     704     2897909 : bool Array::IsMerged( size_t nCol, size_t nRow ) const
     705             : {
     706             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMerged" );
     707     2897909 :     return CELL( nCol, nRow ).IsMerged();
     708             : }
     709             : 
     710           0 : bool Array::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     711             : {
     712             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedLeft" );
     713           0 :     return mxImpl->IsMergedOverlappedLeft( nCol, nRow );
     714             : }
     715             : 
     716           0 : bool Array::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     717             : {
     718             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedRight" );
     719           0 :     return mxImpl->IsMergedOverlappedRight( nCol, nRow );
     720             : }
     721             : 
     722          30 : void Array::GetMergedOrigin( size_t& rnFirstCol, size_t& rnFirstRow, size_t nCol, size_t nRow ) const
     723             : {
     724             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetMergedOrigin" );
     725          30 :     rnFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     726          30 :     rnFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     727          30 : }
     728             : 
     729          30 : void Array::GetMergedRange( size_t& rnFirstCol, size_t& rnFirstRow,
     730             :         size_t& rnLastCol, size_t& rnLastRow, size_t nCol, size_t nRow ) const
     731             : {
     732          30 :     GetMergedOrigin( rnFirstCol, rnFirstRow, nCol, nRow );
     733          30 :     rnLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     734          30 :     rnLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     735          30 : }
     736             : 
     737             : // clipping -------------------------------------------------------------------
     738             : 
     739          33 : void Array::SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     740             : {
     741             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetClipRange" );
     742             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetClipRange" );
     743          33 :     mxImpl->mnFirstClipCol = nFirstCol;
     744          33 :     mxImpl->mnFirstClipRow = nFirstRow;
     745          33 :     mxImpl->mnLastClipCol = nLastCol;
     746          33 :     mxImpl->mnLastClipRow = nLastRow;
     747          33 : }
     748             : 
     749           0 : Rectangle Array::GetClipRangeRectangle() const
     750             : {
     751             :     return Rectangle(
     752           0 :         mxImpl->GetColPosition( mxImpl->mnFirstClipCol ),
     753           0 :         mxImpl->GetRowPosition( mxImpl->mnFirstClipRow ),
     754           0 :         mxImpl->GetColPosition( mxImpl->mnLastClipCol + 1 ),
     755           0 :         mxImpl->GetRowPosition( mxImpl->mnLastClipRow + 1 ) );
     756             : }
     757             : 
     758             : // cell coordinates -----------------------------------------------------------
     759             : 
     760        1617 : void Array::SetXOffset( long nXOffset )
     761             : {
     762        1617 :     mxImpl->maXCoords[ 0 ] = nXOffset;
     763        1617 :     mxImpl->mbXCoordsDirty = true;
     764        1617 : }
     765             : 
     766        1617 : void Array::SetYOffset( long nYOffset )
     767             : {
     768        1617 :     mxImpl->maYCoords[ 0 ] = nYOffset;
     769        1617 :     mxImpl->mbYCoordsDirty = true;
     770        1617 : }
     771             : 
     772       17740 : void Array::SetColWidth( size_t nCol, long nWidth )
     773             : {
     774             :     DBG_FRAME_CHECK_COL( nCol, "SetColWidth" );
     775       17740 :     mxImpl->maWidths[ nCol ] = nWidth;
     776       17740 :     mxImpl->mbXCoordsDirty = true;
     777       17740 : }
     778             : 
     779       20577 : void Array::SetRowHeight( size_t nRow, long nHeight )
     780             : {
     781             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowHeight" );
     782       20577 :     mxImpl->maHeights[ nRow ] = nHeight;
     783       20577 :     mxImpl->mbYCoordsDirty = true;
     784       20577 : }
     785             : 
     786           0 : void Array::SetAllColWidths( long nWidth )
     787             : {
     788           0 :     std::fill( mxImpl->maWidths.begin(), mxImpl->maWidths.end(), nWidth );
     789           0 :     mxImpl->mbXCoordsDirty = true;
     790           0 : }
     791             : 
     792           0 : void Array::SetAllRowHeights( long nHeight )
     793             : {
     794           0 :     std::fill( mxImpl->maHeights.begin(), mxImpl->maHeights.end(), nHeight );
     795           0 :     mxImpl->mbYCoordsDirty = true;
     796           0 : }
     797             : 
     798      504708 : long Array::GetColPosition( size_t nCol ) const
     799             : {
     800             :     DBG_FRAME_CHECK_COL_1( nCol, "GetColPosition" );
     801      504708 :     return mxImpl->GetColPosition( nCol );
     802             : }
     803             : 
     804      504708 : long Array::GetRowPosition( size_t nRow ) const
     805             : {
     806             :     DBG_FRAME_CHECK_ROW_1( nRow, "GetRowPosition" );
     807      504708 :     return mxImpl->GetRowPosition( nRow );
     808             : }
     809             : 
     810      168236 : long Array::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     811             : {
     812             :     DBG_FRAME_CHECK_COL( nFirstCol, "GetColWidth" );
     813             :     DBG_FRAME_CHECK_COL( nLastCol, "GetColWidth" );
     814      168236 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     815             : }
     816             : 
     817      168236 : long Array::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     818             : {
     819             :     DBG_FRAME_CHECK_ROW( nFirstRow, "GetRowHeight" );
     820             :     DBG_FRAME_CHECK_ROW( nLastRow, "GetRowHeight" );
     821      168236 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     822             : }
     823             : 
     824           0 : long Array::GetWidth() const
     825             : {
     826           0 :     return GetColPosition( mxImpl->mnWidth ) - GetColPosition( 0 );
     827             : }
     828             : 
     829           0 : long Array::GetHeight() const
     830             : {
     831           0 :     return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
     832             : }
     833             : 
     834      168236 : Point Array::GetCellPosition( size_t nCol, size_t nRow, bool bSimple ) const
     835             : {
     836      168236 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     837      168236 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     838      168236 :     return Point( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     839             : }
     840             : 
     841      168236 : Size Array::GetCellSize( size_t nCol, size_t nRow, bool bSimple ) const
     842             : {
     843      168236 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     844      168236 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     845      168236 :     size_t nLastCol = bSimple ? nCol : mxImpl->GetMergedLastCol( nCol, nRow );
     846      168236 :     size_t nLastRow = bSimple ? nRow : mxImpl->GetMergedLastRow( nCol, nRow );
     847      168236 :     return Size( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     848             : }
     849             : 
     850      168236 : Rectangle Array::GetCellRect( size_t nCol, size_t nRow, bool bSimple ) const
     851             : {
     852      168236 :     Rectangle aRect( GetCellPosition( nCol, nRow, bSimple ), GetCellSize( nCol, nRow, bSimple ) );
     853             : 
     854             :     // adjust rectangle for partly visible merged cells
     855      168236 :     const Cell& rCell = CELL( nCol, nRow );
     856      168236 :     if( !bSimple && rCell.IsMerged() )
     857             :     {
     858          22 :         aRect.Left() -= rCell.mnAddLeft;
     859          22 :         aRect.Right() += rCell.mnAddRight;
     860          22 :         aRect.Top() -= rCell.mnAddTop;
     861          22 :         aRect.Bottom() += rCell.mnAddBottom;
     862             :     }
     863      168236 :     return aRect;
     864             : }
     865             : 
     866             : // diagonal frame borders -----------------------------------------------------
     867             : 
     868           0 : double Array::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     869             : {
     870             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetHorDiagAngle" );
     871           0 :     return mxImpl->GetHorDiagAngle( nCol, nRow, bSimple );
     872             : }
     873             : 
     874           0 : double Array::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     875             : {
     876             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetVerDiagAngle" );
     877           0 :     return mxImpl->GetVerDiagAngle( nCol, nRow, bSimple );
     878             : }
     879             : 
     880        8985 : void Array::SetUseDiagDoubleClipping( bool bSet )
     881             : {
     882        8985 :     mxImpl->mbDiagDblClip = bSet;
     883        8985 : }
     884             : 
     885             : // mirroring ------------------------------------------------------------------
     886             : 
     887           2 : void Array::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
     888             : {
     889           2 :     CellVec aNewCells;
     890           2 :     aNewCells.reserve( GetCellCount() );
     891             : 
     892             :     size_t nCol, nRow;
     893          60 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     894             :     {
     895         754 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     896             :         {
     897         696 :             aNewCells.push_back( CELL( mxImpl->GetMirrorCol( nCol ), nRow ) );
     898         696 :             aNewCells.back().MirrorSelfX( bMirrorStyles, bSwapDiag );
     899             :         }
     900             :     }
     901          60 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     902             :     {
     903         754 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     904             :         {
     905         696 :             if( CELL( nCol, nRow ).mbMergeOrig )
     906             :             {
     907           0 :                 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     908           0 :                 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     909           0 :                 lclSetMergedRange( aNewCells, mxImpl->mnWidth,
     910             :                     mxImpl->GetMirrorCol( nLastCol ), nRow,
     911           0 :                     mxImpl->GetMirrorCol( nCol ), nLastRow );
     912             :             }
     913             :         }
     914             :     }
     915           2 :     mxImpl->maCells.swap( aNewCells );
     916             : 
     917           2 :     std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
     918           2 :     mxImpl->mbXCoordsDirty = true;
     919           2 : }
     920             : 
     921             : // drawing --------------------------------------------------------------------
     922             : 
     923        1617 : void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor,
     924             :         size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
     925             :         const Color* pForceColor ) const
     926             : {
     927             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
     928             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
     929             : 
     930             :     size_t nCol, nRow;
     931             : 
     932             :     // *** diagonal frame borders ***
     933       18960 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     934             :     {
     935      185691 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     936             :         {
     937      168348 :             const Cell& rCell = CELL( nCol, nRow );
     938      168348 :             bool bOverlapX = rCell.mbOverlapX;
     939      168348 :             bool bOverlapY = rCell.mbOverlapY;
     940      168348 :             bool bFirstCol = nCol == nFirstCol;
     941      168348 :             bool bFirstRow = nRow == nFirstRow;
     942      168462 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
     943         134 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
     944             :             {
     945      168236 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
     946      168236 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
     947             :                 {
     948      168236 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     949      168236 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     950             : 
     951      168236 :                     const Style aTlbrStyle = GetCellStyleTLBR( _nFirstCol, _nFirstRow, true );
     952      168236 :                     if ( aTlbrStyle.GetWidth( ) )
     953             :                         pProcessor->process( CreateClippedBorderPrimitives(
     954             :                                     aRect.TopLeft(), aRect.BottomRight(),
     955           0 :                                     aTlbrStyle, aRect ) );
     956             : 
     957      168236 :                     const Style aBltrStyle = GetCellStyleBLTR( _nFirstCol, _nFirstRow, true );
     958      168236 :                     if ( aBltrStyle.GetWidth( ) )
     959             :                         pProcessor->process( CreateClippedBorderPrimitives(
     960             :                                     aRect.BottomLeft(), aRect.TopRight(),
     961           0 :                                     aBltrStyle, aRect ) );
     962             :                 }
     963             :             }
     964             :         }
     965             :     }
     966             : 
     967             :     // *** horizontal frame borders ***
     968             : 
     969       20577 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
     970             :     {
     971       18960 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
     972       18960 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
     973             : 
     974             :         // *Start*** variables store the data of the left end of the cached frame border
     975       18960 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
     976       18960 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
     977       18960 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
     978       18960 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
     979       18960 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
     980       18960 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
     981       18960 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
     982             : 
     983             :         // *End*** variables store the data of the right end of the cached frame border
     984       18960 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
     985       18960 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
     986       18960 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
     987       18960 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
     988       18960 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
     989             : 
     990      182854 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
     991             :         {
     992      163894 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
     993      163894 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
     994             : 
     995      163894 :             const Style& rCurr = *pEndRFromR;
     996             : 
     997      163894 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
     998      163894 :             const Style& rLFromT = *pEndRFromT;
     999      163894 :             const Style& rLFromL = *pStart;
    1000      163894 :             const Style& rLFromB = *pEndRFromB;
    1001      163894 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1002             : 
    1003      163894 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
    1004      163894 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
    1005      163894 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
    1006      163894 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
    1007      163894 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1008             : 
    1009             :             // check if current frame border can be connected to cached frame border
    1010      163894 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1011      163894 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1012             :             {
    1013             :                 // draw previous frame border
    1014         662 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1015         662 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1016             :                    pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1017             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1018         458 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1019             : 
    1020             :                 // re-init "*Start***" variables
    1021         662 :                 aStartPos = aEndPos;
    1022         662 :                 pStart = &rCurr;
    1023         662 :                 aStartLFromTR = aLFromTR;
    1024         662 :                 pStartLFromT = &rLFromT;
    1025         662 :                 pStartLFromL = &rLFromL;
    1026         662 :                 pStartLFromB = &rLFromB;
    1027         662 :                 aStartLFromBR = aLFromBR;
    1028             :             }
    1029             : 
    1030             :             // store current styles in "*End***" variables
    1031      163894 :             aEndRFromTL = aRFromTL;
    1032      163894 :             pEndRFromT = &rRFromT;
    1033      163894 :             pEndRFromR = &rRFromR;
    1034      163894 :             pEndRFromB = &rRFromB;
    1035      163894 :             aEndRFromBL = aRFromBL;
    1036             :         }
    1037             : 
    1038             :         // draw last frame border
    1039       18960 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1040       18960 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1041             :             pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1042             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1043        1006 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1044             :     }
    1045             : 
    1046             :     // *** vertical frame borders ***
    1047       17740 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1048             :     {
    1049       16123 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1050       16123 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1051             : 
    1052             :         // *Start*** variables store the data of the top end of the cached frame border
    1053       16123 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1054       16123 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1055       16123 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1056       16123 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1057       16123 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1058       16123 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1059       16123 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1060             : 
    1061             :         // *End*** variables store the data of the bottom end of the cached frame border
    1062       16123 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1063       16123 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1064       16123 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1065       16123 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1066       16123 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1067             : 
    1068      185691 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1069             :         {
    1070      169568 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1071      169568 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1072             : 
    1073      169568 :             const Style& rCurr = *pEndBFromB;
    1074             : 
    1075      169568 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1076      169568 :             const Style& rTFromL = *pEndBFromL;
    1077      169568 :             const Style& rTFromT = *pStart;
    1078      169568 :             const Style& rTFromR = *pEndBFromR;
    1079      169568 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1080             : 
    1081      169568 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1082      169568 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1083      169568 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1084      169568 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1085      169568 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1086             : 
    1087             :             // check if current frame border can be connected to cached frame border
    1088      169568 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1089      169568 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1090             :             {
    1091             :                 // draw previous frame border
    1092         793 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1093         793 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1094             :                     pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1095             :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1096         437 :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1097             : 
    1098             :                 // re-init "*Start***" variables
    1099         793 :                 aStartPos = aEndPos;
    1100         793 :                 pStart = &rCurr;
    1101         793 :                 aStartTFromBL = aTFromBL;
    1102         793 :                 pStartTFromL = &rTFromL;
    1103         793 :                 pStartTFromT = &rTFromT;
    1104         793 :                 pStartTFromR = &rTFromR;
    1105         793 :                 aStartTFromBR = aTFromBR;
    1106             :             }
    1107             : 
    1108             :             // store current styles in "*End***" variables
    1109      169568 :             aEndBFromTL = aBFromTL;
    1110      169568 :             pEndBFromL = &rBFromL;
    1111      169568 :             pEndBFromB = &rBFromB;
    1112      169568 :             pEndBFromR = &rBFromR;
    1113      169568 :             aEndBFromTR = aBFromTR;
    1114             :         }
    1115             : 
    1116             :         // draw last frame border
    1117       16123 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1118       16123 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1119             :             pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1120             :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1121         707 :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1122             :     }
    1123        1617 : }
    1124             : 
    1125           0 : void Array::DrawRange( OutputDevice& rDev,
    1126             :         size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
    1127             :         const Color* pForceColor ) const
    1128             : {
    1129             :     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
    1130             :     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
    1131             : 
    1132             :     size_t nCol, nRow;
    1133             : 
    1134             :     // *** diagonal frame borders ***
    1135             : 
    1136             :     // set clipping region to clip partly visible merged cells
    1137           0 :     rDev.Push( PUSH_CLIPREGION );
    1138           0 :     rDev.IntersectClipRegion( GetClipRangeRectangle() );
    1139           0 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
    1140             :     {
    1141           0 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
    1142             :         {
    1143           0 :             const Cell& rCell = CELL( nCol, nRow );
    1144           0 :             bool bOverlapX = rCell.mbOverlapX;
    1145           0 :             bool bOverlapY = rCell.mbOverlapY;
    1146           0 :             bool bFirstCol = nCol == nFirstCol;
    1147           0 :             bool bFirstRow = nRow == nFirstRow;
    1148           0 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
    1149           0 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
    1150             :             {
    1151           0 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
    1152           0 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
    1153             :                 {
    1154           0 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
    1155           0 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
    1156           0 :                     size_t _nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
    1157           0 :                     size_t _nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
    1158             : 
    1159             :                     DrawDiagFrameBorders( rDev, aRect,
    1160           0 :                         GetCellStyleTLBR( _nFirstCol, _nFirstRow, true ), GetCellStyleBLTR( _nFirstCol, _nFirstRow, true ),
    1161           0 :                         GetCellStyleLeft( _nFirstCol, _nFirstRow ), GetCellStyleTop( _nFirstCol, _nFirstRow ),
    1162           0 :                         GetCellStyleRight( _nLastCol, _nLastRow ), GetCellStyleBottom( _nLastCol, _nLastRow ),
    1163           0 :                         GetCellStyleLeft( _nFirstCol, _nLastRow ), GetCellStyleBottom( _nFirstCol, _nLastRow ),
    1164           0 :                         GetCellStyleRight( _nLastCol, _nFirstRow ), GetCellStyleTop( _nLastCol, _nFirstRow ),
    1165           0 :                         pForceColor, mxImpl->mbDiagDblClip );
    1166             :                 }
    1167             :             }
    1168             :         }
    1169             :     }
    1170           0 :     rDev.Pop(); // clip region
    1171             : 
    1172             :     // *** horizontal frame borders ***
    1173             : 
    1174           0 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
    1175             :     {
    1176           0 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
    1177           0 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
    1178             : 
    1179             :         // *Start*** variables store the data of the left end of the cached frame border
    1180           0 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
    1181           0 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
    1182           0 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
    1183           0 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
    1184           0 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
    1185           0 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
    1186           0 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
    1187             : 
    1188             :         // *End*** variables store the data of the right end of the cached frame border
    1189           0 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
    1190           0 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
    1191           0 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
    1192           0 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
    1193           0 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
    1194             : 
    1195           0 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
    1196             :         {
    1197           0 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
    1198           0 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
    1199             : 
    1200           0 :             const Style& rCurr = *pEndRFromR;
    1201             : 
    1202           0 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
    1203           0 :             const Style& rLFromT = *pEndRFromT;
    1204           0 :             const Style& rLFromL = *pStart;
    1205           0 :             const Style& rLFromB = *pEndRFromB;
    1206           0 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1207             : 
    1208           0 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
    1209           0 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
    1210           0 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
    1211           0 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
    1212           0 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1213             : 
    1214             :             // check if current frame border can be connected to cached frame border
    1215           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1216           0 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1217             :             {
    1218             :                 // draw previous frame border
    1219           0 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1220           0 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1221             :                     DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1222             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1223           0 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
    1224             : 
    1225             :                 // re-init "*Start***" variables
    1226           0 :                 aStartPos = aEndPos;
    1227           0 :                 pStart = &rCurr;
    1228           0 :                 aStartLFromTR = aLFromTR;
    1229           0 :                 pStartLFromT = &rLFromT;
    1230           0 :                 pStartLFromL = &rLFromL;
    1231           0 :                 pStartLFromB = &rLFromB;
    1232           0 :                 aStartLFromBR = aLFromBR;
    1233             :             }
    1234             : 
    1235             :             // store current styles in "*End***" variables
    1236           0 :             aEndRFromTL = aRFromTL;
    1237           0 :             pEndRFromT = &rRFromT;
    1238           0 :             pEndRFromR = &rRFromR;
    1239           0 :             pEndRFromB = &rRFromB;
    1240           0 :             aEndRFromBL = aRFromBL;
    1241             :         }
    1242             : 
    1243             :         // draw last frame border
    1244           0 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1245           0 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1246             :             DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1247             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1248           0 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
    1249             :     }
    1250             : 
    1251             :     // *** vertical frame borders ***
    1252             : 
    1253           0 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1254             :     {
    1255           0 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1256           0 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1257             : 
    1258             :         // *Start*** variables store the data of the top end of the cached frame border
    1259           0 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1260           0 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1261           0 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1262           0 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1263           0 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1264           0 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1265           0 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1266             : 
    1267             :         // *End*** variables store the data of the bottom end of the cached frame border
    1268           0 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1269           0 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1270           0 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1271           0 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1272           0 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1273             : 
    1274           0 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1275             :         {
    1276           0 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1277           0 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1278             : 
    1279           0 :             const Style& rCurr = *pEndBFromB;
    1280             : 
    1281           0 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1282           0 :             const Style& rTFromL = *pEndBFromL;
    1283           0 :             const Style& rTFromT = *pStart;
    1284           0 :             const Style& rTFromR = *pEndBFromR;
    1285           0 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1286             : 
    1287           0 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1288           0 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1289           0 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1290           0 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1291           0 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1292             : 
    1293             :             // check if current frame border can be connected to cached frame border
    1294           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1295           0 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1296             :             {
    1297             :                 // draw previous frame border
    1298           0 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1299           0 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1300             :                     DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1301             :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
    1302           0 :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
    1303             : 
    1304             :                 // re-init "*Start***" variables
    1305           0 :                 aStartPos = aEndPos;
    1306           0 :                 pStart = &rCurr;
    1307           0 :                 aStartTFromBL = aTFromBL;
    1308           0 :                 pStartTFromL = &rTFromL;
    1309           0 :                 pStartTFromT = &rTFromT;
    1310           0 :                 pStartTFromR = &rTFromR;
    1311           0 :                 aStartTFromBR = aTFromBR;
    1312             :             }
    1313             : 
    1314             :             // store current styles in "*End***" variables
    1315           0 :             aEndBFromTL = aBFromTL;
    1316           0 :             pEndBFromL = &rBFromL;
    1317           0 :             pEndBFromB = &rBFromB;
    1318           0 :             pEndBFromR = &rBFromR;
    1319           0 :             aEndBFromTR = aBFromTR;
    1320             :         }
    1321             : 
    1322             :         // draw last frame border
    1323           0 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1324           0 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1325             :             DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
    1326             :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
    1327           0 :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
    1328             :     }
    1329           0 : }
    1330             : 
    1331           0 : void Array::DrawArray( OutputDevice& rDev, const Color* pForceColor ) const
    1332             : {
    1333           0 :     if( mxImpl->mnWidth && mxImpl->mnHeight )
    1334           0 :         DrawRange( rDev, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, pForceColor );
    1335           0 : }
    1336             : 
    1337             : 
    1338             : 
    1339             : #undef ORIGCELL
    1340             : #undef CELLACC
    1341             : #undef CELL
    1342             : 
    1343             : 
    1344             : 
    1345             : #undef DBG_FRAME_CHECK_ROW_1
    1346             : #undef DBG_FRAME_CHECK_COL_1
    1347             : #undef DBG_FRAME_CHECK_COLROW
    1348             : #undef DBG_FRAME_CHECK_ROW
    1349             : #undef DBG_FRAME_CHECK_COL
    1350             : #undef DBG_FRAME_CHECK
    1351             : 
    1352             : 
    1353             : 
    1354             : } // namespace frame
    1355         255 : } // namespace svx
    1356             : 
    1357             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10