LCOV - code coverage report
Current view: top level - svx/source/dialog - framelinkarray.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 438 644 68.0 %
Date: 2015-06-13 12:38:46 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     3853315 :     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     2729571 : Cell::Cell() :
      57             :     mnAddLeft( 0 ),
      58             :     mnAddRight( 0 ),
      59             :     mnAddTop( 0 ),
      60             :     mnAddBottom( 0 ),
      61             :     mbMergeOrig( false ),
      62             :     mbOverlapX( false ),
      63     2729571 :     mbOverlapY( false )
      64             : {
      65     2729571 : }
      66             : 
      67         616 : void Cell::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
      68             : {
      69         616 :     std::swap( maLeft, maRight );
      70         616 :     std::swap( mnAddLeft, mnAddRight );
      71         616 :     if( bMirrorStyles )
      72             :     {
      73         616 :         maLeft.MirrorSelf();
      74         616 :         maRight.MirrorSelf();
      75             :     }
      76         616 :     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         616 : }
      86             : 
      87             : 
      88             : 
      89             : 
      90        5982 : void lclRecalcCoordVec( LongVec& rCoords, const LongVec& rSizes )
      91             : {
      92             :     DBG_ASSERT( rCoords.size() == rSizes.size() + 1, "lclRecalcCoordVec - inconsistent vectors" );
      93        5982 :     LongVec::iterator aCIt = rCoords.begin();
      94        5982 :     LongVec::const_iterator aSIt = rSizes.begin(), aSEnd = rSizes.end();
      95       63478 :     for( ; aSIt != aSEnd; ++aCIt, ++aSIt )
      96       57496 :         *(aCIt + 1) = *aCIt + *aSIt;
      97        5982 : }
      98             : 
      99         274 : void lclSetMergedRange( CellVec& rCells, size_t nWidth, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     100             : {
     101         832 :     for( size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     102             :     {
     103        2243 :         for( size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     104             :         {
     105        1685 :             Cell& rCell = rCells[ nRow * nWidth + nCol ];
     106        1685 :             rCell.mbMergeOrig = false;
     107        1685 :             rCell.mbOverlapX = nCol > nFirstCol;
     108        1685 :             rCell.mbOverlapY = nRow > nFirstRow;
     109             :         }
     110             :     }
     111         274 :     rCells[ nFirstRow * nWidth + nFirstCol ].mbMergeOrig = true;
     112         274 : }
     113             : 
     114             : 
     115             : 
     116         130 : static const Style OBJ_STYLE_NONE;
     117         130 : static const Cell OBJ_CELL_NONE;
     118             : 
     119             : const bool DIAG_DBL_CLIP_DEFAULT = false;
     120             : 
     121       20966 : 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    40300714 :     inline bool         IsValidPos( size_t nCol, size_t nRow ) const
     141    40300714 :                             { return (nCol < mnWidth) && (nRow < mnHeight); }
     142    39382710 :     inline size_t       GetIndex( size_t nCol, size_t nRow ) const
     143    39382710 :                             { 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         616 :     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       20966 : ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
     177             :     mnWidth( nWidth ),
     178             :     mnHeight( nHeight ),
     179             :     mnFirstClipCol( 0 ),
     180             :     mnFirstClipRow( 0 ),
     181       20966 :     mnLastClipCol( nWidth - 1 ),
     182       20966 :     mnLastClipRow( nHeight - 1 ),
     183             :     mbXCoordsDirty( false ),
     184             :     mbYCoordsDirty( false ),
     185       62898 :     mbDiagDblClip( bDiagDblClip )
     186             : {
     187             :     // default-construct all vectors
     188       20966 :     maCells.resize( mnWidth * mnHeight );
     189       20966 :     maWidths.resize( mnWidth, 0L );
     190       20966 :     maHeights.resize( mnHeight, 0L );
     191       20966 :     maXCoords.resize( mnWidth + 1, 0L );
     192       20966 :     maYCoords.resize( mnHeight + 1, 0L );
     193       20966 : }
     194             : 
     195    25001295 : const Cell& ArrayImpl::GetCell( size_t nCol, size_t nRow ) const
     196             : {
     197    25001295 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : OBJ_CELL_NONE;
     198             : }
     199             : 
     200    14381415 : Cell& ArrayImpl::GetCellAcc( size_t nCol, size_t nRow )
     201             : {
     202    14381415 :     static Cell aDummy;
     203    14381415 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : aDummy;
     204             : }
     205             : 
     206     5616326 : size_t ArrayImpl::GetMergedFirstCol( size_t nCol, size_t nRow ) const
     207             : {
     208     5616326 :     size_t nFirstCol = nCol;
     209     5616326 :     while( (nFirstCol > 0) && GetCell( nFirstCol, nRow ).mbOverlapX ) --nFirstCol;
     210     5616326 :     return nFirstCol;
     211             : }
     212             : 
     213     5616320 : size_t ArrayImpl::GetMergedFirstRow( size_t nCol, size_t nRow ) const
     214             : {
     215     5616320 :     size_t nFirstRow = nRow;
     216     5616320 :     while( (nFirstRow > 0) && GetCell( nCol, nFirstRow ).mbOverlapY ) --nFirstRow;
     217     5616320 :     return nFirstRow;
     218             : }
     219             : 
     220     1124514 : size_t ArrayImpl::GetMergedLastCol( size_t nCol, size_t nRow ) const
     221             : {
     222     1124514 :     size_t nLastCol = nCol + 1;
     223     1124514 :     while( (nLastCol < mnWidth) && GetCell( nLastCol, nRow ).mbOverlapX ) ++nLastCol;
     224     1124514 :     return nLastCol - 1;
     225             : }
     226             : 
     227     1124514 : size_t ArrayImpl::GetMergedLastRow( size_t nCol, size_t nRow ) const
     228             : {
     229     1124514 :     size_t nLastRow = nRow + 1;
     230     1124514 :     while( (nLastRow < mnHeight) && GetCell( nCol, nLastRow ).mbOverlapY ) ++nLastRow;
     231     1124514 :     return nLastRow - 1;
     232             : }
     233             : 
     234     3162140 : const Cell& ArrayImpl::GetMergedOriginCell( size_t nCol, size_t nRow ) const
     235             : {
     236     3162140 :     return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
     237             : }
     238             : 
     239      332593 : bool ArrayImpl::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     240             : {
     241      332593 :     const Cell& rCell = GetCell( nCol, nRow );
     242      332593 :     return rCell.mbOverlapX || (rCell.mnAddLeft > 0);
     243             : }
     244             : 
     245      457994 : bool ArrayImpl::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     246             : {
     247      457994 :     return GetCell( nCol + 1, nRow ).mbOverlapX || (GetCell( nCol, nRow ).mnAddRight > 0);
     248             : }
     249             : 
     250      331919 : bool ArrayImpl::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
     251             : {
     252      331919 :     const Cell& rCell = GetCell( nCol, nRow );
     253      331919 :     return rCell.mbOverlapY || (rCell.mnAddTop > 0);
     254             : }
     255             : 
     256      459366 : bool ArrayImpl::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
     257             : {
     258      459366 :     return GetCell( nCol, nRow + 1 ).mbOverlapY || (GetCell( nCol, nRow ).mnAddBottom > 0);
     259             : }
     260             : 
     261     3416527 : bool ArrayImpl::IsColInClipRange( size_t nCol ) const
     262             : {
     263     3416527 :     return (mnFirstClipCol <= nCol) && (nCol <= mnLastClipCol);
     264             : }
     265             : 
     266     3416375 : bool ArrayImpl::IsRowInClipRange( size_t nRow ) const
     267             : {
     268     3416375 :     return (mnFirstClipRow <= nRow) && (nRow <= mnLastClipRow);
     269             : }
     270             : 
     271     1834912 : bool ArrayImpl::IsInClipRange( size_t nCol, size_t nRow ) const
     272             : {
     273     1834912 :     return IsColInClipRange( nCol ) && IsRowInClipRange( nRow );
     274             : }
     275             : 
     276      699174 : long ArrayImpl::GetColPosition( size_t nCol ) const
     277             : {
     278      699174 :     if( mbXCoordsDirty )
     279             :     {
     280        2991 :         lclRecalcCoordVec( maXCoords, maWidths );
     281        2991 :         mbXCoordsDirty = false;
     282             :     }
     283      699174 :     return maXCoords[ nCol ];
     284             : }
     285             : 
     286      698621 : long ArrayImpl::GetRowPosition( size_t nRow ) const
     287             : {
     288      698621 :     if( mbYCoordsDirty )
     289             :     {
     290        2991 :         lclRecalcCoordVec( maYCoords, maHeights );
     291        2991 :         mbYCoordsDirty = false;
     292             :     }
     293      698621 :     return maYCoords[ nRow ];
     294             : }
     295             : 
     296         693 : long ArrayImpl::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     297             : {
     298         693 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     299             : }
     300             : 
     301         693 : long ArrayImpl::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     302             : {
     303         693 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     304             : }
     305             : 
     306      917456 : double ArrayImpl::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     307             : {
     308      917456 :     double fAngle = 0.0;
     309      917456 :     if( IsValidPos( nCol, nRow ) )
     310             :     {
     311      917456 :         if( bSimple || !GetCell( nCol, nRow ).IsMerged() )
     312             :         {
     313      916763 :             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         693 :             size_t nFirstCol = GetMergedFirstCol( nCol, nRow );
     319         693 :             size_t nFirstRow = GetMergedFirstRow( nCol, nRow );
     320         693 :             const Cell& rCell = GetCell( nFirstCol, nFirstRow );
     321         693 :             long nWidth = GetColWidth( nFirstCol, GetMergedLastCol( nCol, nRow ) ) + rCell.mnAddLeft + rCell.mnAddRight;
     322         693 :             long nHeight = GetRowHeight( nFirstRow, GetMergedLastRow( nCol, nRow ) ) + rCell.mnAddTop + rCell.mnAddBottom;
     323         693 :             fAngle = frame::GetHorDiagAngle( nWidth + 1, nHeight + 1 );
     324             :         }
     325             :     }
     326      917456 :     return fAngle;
     327             : }
     328             : 
     329      459410 : double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     330             : {
     331      459410 :     double fAngle = GetHorDiagAngle( nCol, nRow, bSimple );
     332      459410 :     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          42 :     inline bool         Is() const { return (mnCol <= mnLastCol) && (mnRow <= mnLastRow); }
     343          33 :     inline size_t       Col() const { return mnCol; }
     344          33 :     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           9 : 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           9 :     rArray.GetMergedRange( mnFirstCol, mnFirstRow, mnLastCol, mnLastRow, nCol, nRow );
     363           9 :     mnCol = mnFirstCol;
     364           9 :     mnRow = mnFirstRow;
     365           9 : }
     366             : 
     367          33 : MergedCellIterator& MergedCellIterator::operator++()
     368             : {
     369             :     DBG_ASSERT( Is(), "svx::frame::MergedCellIterator::operator++() - already invalid" );
     370          33 :     if( ++mnCol > mnLastCol )
     371             :     {
     372          27 :         mnCol = mnFirstCol;
     373          27 :         ++mnRow;
     374             :     }
     375          33 :     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       10483 : Array::Array()
     396             : {
     397       10483 :     Initialize( 0, 0 );
     398       10483 : }
     399             : 
     400       10483 : Array::~Array()
     401             : {
     402       10483 : }
     403             : 
     404             : // array size and column/row indexes
     405       20966 : void Array::Initialize( size_t nWidth, size_t nHeight )
     406             : {
     407       20966 :     bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
     408       20966 :     mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
     409       20966 : }
     410             : 
     411        2991 : size_t Array::GetColCount() const
     412             : {
     413        2991 :     return mxImpl->mnWidth;
     414             : }
     415             : 
     416        2991 : size_t Array::GetRowCount() const
     417             : {
     418        2991 :     return mxImpl->mnHeight;
     419             : }
     420             : 
     421           2 : size_t Array::GetCellCount() const
     422             : {
     423           2 :     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     2396897 : void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
     436             : {
     437             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
     438     2396897 :     CELLACC( nCol, nRow ).maLeft = rStyle;
     439     2396897 : }
     440             : 
     441     2396897 : void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
     442             : {
     443             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
     444     2396897 :     CELLACC( nCol, nRow ).maRight = rStyle;
     445     2396897 : }
     446             : 
     447     2396897 : void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
     448             : {
     449             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
     450     2396897 :     CELLACC( nCol, nRow ).maTop = rStyle;
     451     2396897 : }
     452             : 
     453     2396897 : void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
     454             : {
     455             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
     456     2396897 :     CELLACC( nCol, nRow ).maBottom = rStyle;
     457     2396897 : }
     458             : 
     459     2396897 : void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
     460             : {
     461             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
     462     2396897 :     CELLACC( nCol, nRow ).maTLBR = rStyle;
     463     2396897 : }
     464             : 
     465     2396897 : void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
     466             : {
     467             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
     468     2396897 :     CELLACC( nCol, nRow ).maBLTR = rStyle;
     469     2396897 : }
     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      332733 : const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple ) const
     508             : {
     509             :     // simple: always return own left style
     510      332733 :     if( bSimple )
     511           0 :         return CELL( nCol, nRow ).maLeft;
     512             :     // outside clipping rows or overlapped in merged cells: invisible
     513      332733 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedLeft( nCol, nRow ) )
     514         241 :         return OBJ_STYLE_NONE;
     515             :     // left clipping border: always own left style
     516      332492 :     if( nCol == mxImpl->mnFirstClipCol )
     517          66 :         return ORIGCELL( nCol, nRow ).maLeft;
     518             :     // right clipping border: always right style of left neighbor cell
     519      332426 :     if( nCol == mxImpl->mnLastClipCol + 1 )
     520          22 :         return ORIGCELL( nCol - 1, nRow ).maRight;
     521             :     // outside clipping columns: invisible
     522      332404 :     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      332404 :     return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
     526             : }
     527             : 
     528      458046 : const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple ) const
     529             : {
     530             :     // simple: always return own right style
     531      458046 :     if( bSimple )
     532           0 :         return CELL( nCol, nRow ).maRight;
     533             :     // outside clipping rows or overlapped in merged cells: invisible
     534      458046 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedRight( nCol, nRow ) )
     535         252 :         return OBJ_STYLE_NONE;
     536             :     // left clipping border: always left style of right neighbor cell
     537      457794 :     if( nCol + 1 == mxImpl->mnFirstClipCol )
     538           0 :         return ORIGCELL( nCol + 1, nRow ).maLeft;
     539             :     // right clipping border: always own right style
     540      457794 :     if( nCol == mxImpl->mnLastClipCol )
     541          44 :         return ORIGCELL( nCol, nRow ).maRight;
     542             :     // outside clipping columns: invisible
     543      457750 :     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      457750 :     return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
     547             : }
     548             : 
     549      332051 : const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple ) const
     550             : {
     551             :     // simple: always return own top style
     552      332051 :     if( bSimple )
     553           0 :         return CELL( nCol, nRow ).maTop;
     554             :     // outside clipping columns or overlapped in merged cells: invisible
     555      332051 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedTop( nCol, nRow ) )
     556         261 :         return OBJ_STYLE_NONE;
     557             :     // top clipping border: always own top style
     558      331790 :     if( nRow == mxImpl->mnFirstClipRow )
     559          78 :         return ORIGCELL( nCol, nRow ).maTop;
     560             :     // bottom clipping border: always bottom style of top neighbor cell
     561      331712 :     if( nRow == mxImpl->mnLastClipRow + 1 )
     562          26 :         return ORIGCELL( nCol, nRow - 1 ).maBottom;
     563             :     // outside clipping rows: invisible
     564      331686 :     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      331686 :     return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
     568             : }
     569             : 
     570      459410 : const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple ) const
     571             : {
     572             :     // simple: always return own bottom style
     573      459410 :     if( bSimple )
     574           0 :         return CELL( nCol, nRow ).maBottom;
     575             :     // outside clipping columns or overlapped in merged cells: invisible
     576      459410 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedBottom( nCol, nRow ) )
     577         272 :         return OBJ_STYLE_NONE;
     578             :     // top clipping border: always top style of bottom neighbor cell
     579      459138 :     if( nRow + 1 == mxImpl->mnFirstClipRow )
     580           0 :         return ORIGCELL( nCol, nRow + 1 ).maTop;
     581             :     // bottom clipping border: always own bottom style
     582      459138 :     if( nRow == mxImpl->mnLastClipRow )
     583          52 :         return ORIGCELL( nCol, nRow ).maBottom;
     584             :     // outside clipping rows: invisible
     585      459086 :     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      459086 :     return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
     589             : }
     590             : 
     591      206452 : const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple ) const
     592             : {
     593      206452 :     return bSimple ? CELL( nCol, nRow ).maTLBR :
     594      412904 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maTLBR : OBJ_STYLE_NONE);
     595             : }
     596             : 
     597      206452 : const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple ) const
     598             : {
     599      206452 :     return bSimple ? CELL( nCol, nRow ).maBLTR :
     600      412904 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maBLTR : OBJ_STYLE_NONE);
     601             : }
     602             : 
     603      458728 : const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
     604             : {
     605             :     // not in clipping range: always invisible
     606      458728 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     607          48 :         return OBJ_STYLE_NONE;
     608             :     // return style only for top-left cell
     609      458680 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     610      458680 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     611      458482 :     return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
     612      917058 :         CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
     613             : }
     614             : 
     615      458728 : const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
     616             : {
     617             :     // not in clipping range: always invisible
     618      458728 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     619          48 :         return OBJ_STYLE_NONE;
     620             :     // return style only for bottom-right cell
     621      458680 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     622      458680 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     623      458480 :     return ((nCol == nLastCol) && (nRow == nLastRow)) ?
     624      917064 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
     625             : }
     626             : 
     627      458728 : const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
     628             : {
     629             :     // not in clipping range: always invisible
     630      458728 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     631          48 :         return OBJ_STYLE_NONE;
     632             :     // return style only for bottom-left cell
     633      458680 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     634      458680 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     635      458480 :     return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
     636      917058 :         CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
     637             : }
     638             : 
     639      458728 : const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
     640             : {
     641             :     // not in clipping range: always invisible
     642      458728 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     643          48 :         return OBJ_STYLE_NONE;
     644             :     // return style only for top-right cell
     645      458680 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     646      458680 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     647      458482 :     return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
     648      917064 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
     649             : }
     650             : 
     651             : // cell merging
     652         274 : 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         274 :     if( mxImpl->IsValidPos( nFirstCol, nFirstRow ) && mxImpl->IsValidPos( nLastCol, nLastRow ) )
     666         274 :         lclSetMergedRange( mxImpl->maCells, mxImpl->mnWidth, nFirstCol, nFirstRow, nLastCol, nLastRow );
     667         274 : }
     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           7 : 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          28 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     682          21 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddRight = nAddSize;
     683           7 : }
     684             : 
     685           2 : 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          14 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     690          12 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddTop = nAddSize;
     691           2 : }
     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     2729407 : bool Array::IsMerged( size_t nCol, size_t nRow ) const
     702             : {
     703             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMerged" );
     704     2729407 :     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           9 : 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           9 :     rnFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     723           9 :     rnFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     724           9 : }
     725             : 
     726           9 : 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           9 :     GetMergedOrigin( rnFirstCol, rnFirstRow, nCol, nRow );
     730           9 :     rnLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     731           9 :     rnLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     732           9 : }
     733             : 
     734             : // clipping
     735          22 : 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          22 :     mxImpl->mnFirstClipCol = nFirstCol;
     740          22 :     mxImpl->mnFirstClipRow = nFirstRow;
     741          22 :     mxImpl->mnLastClipCol = nLastCol;
     742          22 :     mxImpl->mnLastClipRow = nLastRow;
     743          22 : }
     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        2991 : void Array::SetXOffset( long nXOffset )
     756             : {
     757        2991 :     mxImpl->maXCoords[ 0 ] = nXOffset;
     758        2991 :     mxImpl->mbXCoordsDirty = true;
     759        2991 : }
     760             : 
     761        2991 : void Array::SetYOffset( long nYOffset )
     762             : {
     763        2991 :     mxImpl->maYCoords[ 0 ] = nYOffset;
     764        2991 :     mxImpl->mbYCoordsDirty = true;
     765        2991 : }
     766             : 
     767       28407 : void Array::SetColWidth( size_t nCol, long nWidth )
     768             : {
     769             :     DBG_FRAME_CHECK_COL( nCol, "SetColWidth" );
     770       28407 :     mxImpl->maWidths[ nCol ] = nWidth;
     771       28407 :     mxImpl->mbXCoordsDirty = true;
     772       28407 : }
     773             : 
     774       29089 : void Array::SetRowHeight( size_t nRow, long nHeight )
     775             : {
     776             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowHeight" );
     777       29089 :     mxImpl->maHeights[ nRow ] = nHeight;
     778       29089 :     mxImpl->mbYCoordsDirty = true;
     779       29089 : }
     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      619356 : long Array::GetColPosition( size_t nCol ) const
     794             : {
     795             :     DBG_FRAME_CHECK_COL_1( nCol, "GetColPosition" );
     796      619356 :     return mxImpl->GetColPosition( nCol );
     797             : }
     798             : 
     799      619356 : long Array::GetRowPosition( size_t nRow ) const
     800             : {
     801             :     DBG_FRAME_CHECK_ROW_1( nRow, "GetRowPosition" );
     802      619356 :     return mxImpl->GetRowPosition( nRow );
     803             : }
     804             : 
     805      206452 : 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      206452 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     810             : }
     811             : 
     812      206452 : 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      206452 :     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      206452 : Point Array::GetCellPosition( size_t nCol, size_t nRow, bool bSimple ) const
     830             : {
     831      206452 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     832      206452 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     833      206452 :     return Point( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     834             : }
     835             : 
     836      206452 : Size Array::GetCellSize( size_t nCol, size_t nRow, bool bSimple ) const
     837             : {
     838      206452 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     839      206452 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     840      206452 :     size_t nLastCol = bSimple ? nCol : mxImpl->GetMergedLastCol( nCol, nRow );
     841      206452 :     size_t nLastRow = bSimple ? nRow : mxImpl->GetMergedLastRow( nCol, nRow );
     842      206452 :     return Size( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     843             : }
     844             : 
     845      206452 : Rectangle Array::GetCellRect( size_t nCol, size_t nRow, bool bSimple ) const
     846             : {
     847      206452 :     Rectangle aRect( GetCellPosition( nCol, nRow, bSimple ), GetCellSize( nCol, nRow, bSimple ) );
     848             : 
     849             :     // adjust rectangle for partly visible merged cells
     850      206452 :     const Cell& rCell = CELL( nCol, nRow );
     851      206452 :     if( !bSimple && rCell.IsMerged() )
     852             :     {
     853          24 :         aRect.Left() -= rCell.mnAddLeft;
     854          24 :         aRect.Right() += rCell.mnAddRight;
     855          24 :         aRect.Top() -= rCell.mnAddTop;
     856          24 :         aRect.Bottom() += rCell.mnAddBottom;
     857             :     }
     858      206452 :     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       10483 : void Array::SetUseDiagDoubleClipping( bool bSet )
     875             : {
     876       10483 :     mxImpl->mbDiagDblClip = bSet;
     877       10483 : }
     878             : 
     879             : // mirroring
     880           2 : void Array::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
     881             : {
     882           2 :     CellVec aNewCells;
     883           2 :     aNewCells.reserve( GetCellCount() );
     884             : 
     885             :     size_t nCol, nRow;
     886          58 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     887             :     {
     888         672 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     889             :         {
     890         616 :             aNewCells.push_back( CELL( mxImpl->GetMirrorCol( nCol ), nRow ) );
     891         616 :             aNewCells.back().MirrorSelfX( bMirrorStyles, bSwapDiag );
     892             :         }
     893             :     }
     894          58 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     895             :     {
     896         672 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     897             :         {
     898         616 :             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           2 :     mxImpl->maCells.swap( aNewCells );
     909             : 
     910           2 :     std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
     911           2 :     mxImpl->mbXCoordsDirty = true;
     912           2 : }
     913             : 
     914             : // drawing
     915        2991 : 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       26098 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     926             :     {
     927      229705 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     928             :         {
     929      206598 :             const Cell& rCell = CELL( nCol, nRow );
     930      206598 :             bool bOverlapX = rCell.mbOverlapX;
     931      206598 :             bool bOverlapY = rCell.mbOverlapY;
     932      206598 :             bool bFirstCol = nCol == nFirstCol;
     933      206598 :             bool bFirstRow = nRow == nFirstRow;
     934      206746 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
     935         181 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
     936             :             {
     937      206452 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
     938      206452 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
     939             :                 {
     940      206452 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     941      206452 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     942             : 
     943      206452 :                     const Style aTlbrStyle = GetCellStyleTLBR( _nFirstCol, _nFirstRow, true );
     944      206452 :                     if ( aTlbrStyle.GetWidth( ) )
     945             :                         pProcessor->process( CreateClippedBorderPrimitives(
     946             :                                     aRect.TopLeft(), aRect.BottomRight(),
     947           0 :                                     aTlbrStyle, aRect ) );
     948             : 
     949      206452 :                     const Style aBltrStyle = GetCellStyleBLTR( _nFirstCol, _nFirstRow, true );
     950      206452 :                     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       29089 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
     962             :     {
     963       26098 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
     964       26098 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
     965             : 
     966             :         // *Start*** variables store the data of the left end of the cached frame border
     967       26098 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
     968       26098 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
     969       26098 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
     970       26098 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
     971       26098 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
     972       26098 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
     973       26098 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
     974             : 
     975             :         // *End*** variables store the data of the right end of the cached frame border
     976       26098 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
     977       26098 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
     978       26098 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
     979       26098 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
     980       26098 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
     981             : 
     982      229023 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
     983             :         {
     984      202925 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
     985      202925 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
     986             : 
     987      202925 :             const Style& rCurr = *pEndRFromR;
     988             : 
     989      202925 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
     990      202925 :             const Style& rLFromT = *pEndRFromT;
     991      202925 :             const Style& rLFromL = *pStart;
     992      202925 :             const Style& rLFromB = *pEndRFromB;
     993      202925 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
     994             : 
     995      202925 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
     996      202925 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
     997      202925 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
     998      202925 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
     999      202925 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1000             : 
    1001             :             // check if current frame border can be connected to cached frame border
    1002      202925 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1003      202925 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1004             :             {
    1005             :                 // draw previous frame border
    1006         820 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1007         820 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1008             :                    pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1009             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1010         538 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1011             : 
    1012             :                 // re-init "*Start***" variables
    1013         820 :                 aStartPos = aEndPos;
    1014         820 :                 pStart = &rCurr;
    1015         820 :                 aStartLFromTR = aLFromTR;
    1016         820 :                 pStartLFromT = &rLFromT;
    1017         820 :                 pStartLFromL = &rLFromL;
    1018         820 :                 pStartLFromB = &rLFromB;
    1019         820 :                 aStartLFromBR = aLFromBR;
    1020             :             }
    1021             : 
    1022             :             // store current styles in "*End***" variables
    1023      202925 :             aEndRFromTL = aRFromTL;
    1024      202925 :             pEndRFromT = &rRFromT;
    1025      202925 :             pEndRFromR = &rRFromR;
    1026      202925 :             pEndRFromB = &rRFromB;
    1027      202925 :             aEndRFromBL = aRFromBL;
    1028             :         }
    1029             : 
    1030             :         // draw last frame border
    1031       26098 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1032       26098 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1033             :             pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1034             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1035        1054 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1036             :     }
    1037             : 
    1038             :     // *** vertical frame borders ***
    1039       28407 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1040             :     {
    1041       25416 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1042       25416 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1043             : 
    1044             :         // *Start*** variables store the data of the top end of the cached frame border
    1045       25416 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1046       25416 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1047       25416 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1048       25416 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1049       25416 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1050       25416 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1051       25416 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1052             : 
    1053             :         // *End*** variables store the data of the bottom end of the cached frame border
    1054       25416 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1055       25416 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1056       25416 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1057       25416 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1058       25416 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1059             : 
    1060      229705 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1061             :         {
    1062      204289 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1063      204289 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1064             : 
    1065      204289 :             const Style& rCurr = *pEndBFromB;
    1066             : 
    1067      204289 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1068      204289 :             const Style& rTFromL = *pEndBFromL;
    1069      204289 :             const Style& rTFromT = *pStart;
    1070      204289 :             const Style& rTFromR = *pEndBFromR;
    1071      204289 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1072             : 
    1073      204289 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1074      204289 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1075      204289 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1076      204289 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1077      204289 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1078             : 
    1079             :             // check if current frame border can be connected to cached frame border
    1080      204289 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1081      204289 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1082             :             {
    1083             :                 // draw previous frame border
    1084         949 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1085         949 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1086             :                     pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1087             :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1088         540 :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1089             : 
    1090             :                 // re-init "*Start***" variables
    1091         949 :                 aStartPos = aEndPos;
    1092         949 :                 pStart = &rCurr;
    1093         949 :                 aStartTFromBL = aTFromBL;
    1094         949 :                 pStartTFromL = &rTFromL;
    1095         949 :                 pStartTFromT = &rTFromT;
    1096         949 :                 pStartTFromR = &rTFromR;
    1097         949 :                 aStartTFromBR = aTFromBR;
    1098             :             }
    1099             : 
    1100             :             // store current styles in "*End***" variables
    1101      204289 :             aEndBFromTL = aBFromTL;
    1102      204289 :             pEndBFromL = &rBFromL;
    1103      204289 :             pEndBFromB = &rBFromB;
    1104      204289 :             pEndBFromR = &rBFromR;
    1105      204289 :             aEndBFromTR = aBFromTR;
    1106             :         }
    1107             : 
    1108             :         // draw last frame border
    1109       25416 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1110       25416 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1111             :             pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1112             :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1113         756 :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1114             :     }
    1115        2991 : }
    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             : }
    1347         390 : }
    1348             : 
    1349             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11