LCOV - code coverage report
Current view: top level - svx/source/dialog - framelinkarray.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 644 0.0 %
Date: 2014-04-14 Functions: 0 99 0.0 %
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           0 :     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           0 : Cell::Cell() :
      57             :     mnAddLeft( 0 ),
      58             :     mnAddRight( 0 ),
      59             :     mnAddTop( 0 ),
      60             :     mnAddBottom( 0 ),
      61             :     mbMergeOrig( false ),
      62             :     mbOverlapX( false ),
      63           0 :     mbOverlapY( false )
      64             : {
      65           0 : }
      66             : 
      67           0 : void Cell::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
      68             : {
      69           0 :     std::swap( maLeft, maRight );
      70           0 :     std::swap( mnAddLeft, mnAddRight );
      71           0 :     if( bMirrorStyles )
      72             :     {
      73           0 :         maLeft.MirrorSelf();
      74           0 :         maRight.MirrorSelf();
      75             :     }
      76           0 :     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           0 : }
      86             : 
      87             : 
      88             : 
      89             : 
      90           0 : void lclRecalcCoordVec( LongVec& rCoords, const LongVec& rSizes )
      91             : {
      92             :     DBG_ASSERT( rCoords.size() == rSizes.size() + 1, "lclRecalcCoordVec - inconsistent vectors" );
      93           0 :     LongVec::iterator aCIt = rCoords.begin();
      94           0 :     LongVec::const_iterator aSIt = rSizes.begin(), aSEnd = rSizes.end();
      95           0 :     for( ; aSIt != aSEnd; ++aCIt, ++aSIt )
      96           0 :         *(aCIt + 1) = *aCIt + *aSIt;
      97           0 : }
      98             : 
      99           0 : void lclSetMergedRange( CellVec& rCells, size_t nWidth, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
     100             : {
     101           0 :     for( size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     102             :     {
     103           0 :         for( size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     104             :         {
     105           0 :             Cell& rCell = rCells[ nRow * nWidth + nCol ];
     106           0 :             rCell.mbMergeOrig = false;
     107           0 :             rCell.mbOverlapX = nCol > nFirstCol;
     108           0 :             rCell.mbOverlapY = nRow > nFirstRow;
     109             :         }
     110             :     }
     111           0 :     rCells[ nFirstRow * nWidth + nFirstCol ].mbMergeOrig = true;
     112           0 : }
     113             : 
     114             : 
     115             : 
     116           0 : static const Style OBJ_STYLE_NONE;
     117           0 : static const Cell OBJ_CELL_NONE;
     118             : 
     119             : const bool DIAG_DBL_CLIP_DEFAULT = false;
     120             : 
     121           0 : 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           0 :     inline bool         IsValidPos( size_t nCol, size_t nRow ) const
     141           0 :                             { return (nCol < mnWidth) && (nRow < mnHeight); }
     142           0 :     inline size_t       GetIndex( size_t nCol, size_t nRow ) const
     143           0 :                             { 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           0 :     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           0 : ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
     177             :     mnWidth( nWidth ),
     178             :     mnHeight( nHeight ),
     179             :     mnFirstClipCol( 0 ),
     180             :     mnFirstClipRow( 0 ),
     181           0 :     mnLastClipCol( nWidth - 1 ),
     182           0 :     mnLastClipRow( nHeight - 1 ),
     183             :     mbXCoordsDirty( false ),
     184             :     mbYCoordsDirty( false ),
     185           0 :     mbDiagDblClip( bDiagDblClip )
     186             : {
     187             :     // default-construct all vectors
     188           0 :     maCells.resize( mnWidth * mnHeight );
     189           0 :     maWidths.resize( mnWidth, 0L );
     190           0 :     maHeights.resize( mnHeight, 0L );
     191           0 :     maXCoords.resize( mnWidth + 1, 0L );
     192           0 :     maYCoords.resize( mnHeight + 1, 0L );
     193           0 : }
     194             : 
     195           0 : const Cell& ArrayImpl::GetCell( size_t nCol, size_t nRow ) const
     196             : {
     197           0 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : OBJ_CELL_NONE;
     198             : }
     199             : 
     200           0 : Cell& ArrayImpl::GetCellAcc( size_t nCol, size_t nRow )
     201             : {
     202           0 :     static Cell aDummy;
     203           0 :     return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : aDummy;
     204             : }
     205             : 
     206           0 : size_t ArrayImpl::GetMergedFirstCol( size_t nCol, size_t nRow ) const
     207             : {
     208           0 :     size_t nFirstCol = nCol;
     209           0 :     while( (nFirstCol > 0) && GetCell( nFirstCol, nRow ).mbOverlapX ) --nFirstCol;
     210           0 :     return nFirstCol;
     211             : }
     212             : 
     213           0 : size_t ArrayImpl::GetMergedFirstRow( size_t nCol, size_t nRow ) const
     214             : {
     215           0 :     size_t nFirstRow = nRow;
     216           0 :     while( (nFirstRow > 0) && GetCell( nCol, nFirstRow ).mbOverlapY ) --nFirstRow;
     217           0 :     return nFirstRow;
     218             : }
     219             : 
     220           0 : size_t ArrayImpl::GetMergedLastCol( size_t nCol, size_t nRow ) const
     221             : {
     222           0 :     size_t nLastCol = nCol + 1;
     223           0 :     while( (nLastCol < mnWidth) && GetCell( nLastCol, nRow ).mbOverlapX ) ++nLastCol;
     224           0 :     return nLastCol - 1;
     225             : }
     226             : 
     227           0 : size_t ArrayImpl::GetMergedLastRow( size_t nCol, size_t nRow ) const
     228             : {
     229           0 :     size_t nLastRow = nRow + 1;
     230           0 :     while( (nLastRow < mnHeight) && GetCell( nCol, nLastRow ).mbOverlapY ) ++nLastRow;
     231           0 :     return nLastRow - 1;
     232             : }
     233             : 
     234           0 : const Cell& ArrayImpl::GetMergedOriginCell( size_t nCol, size_t nRow ) const
     235             : {
     236           0 :     return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
     237             : }
     238             : 
     239           0 : bool ArrayImpl::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
     240             : {
     241           0 :     const Cell& rCell = GetCell( nCol, nRow );
     242           0 :     return rCell.mbOverlapX || (rCell.mnAddLeft > 0);
     243             : }
     244             : 
     245           0 : bool ArrayImpl::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
     246             : {
     247           0 :     return GetCell( nCol + 1, nRow ).mbOverlapX || (GetCell( nCol, nRow ).mnAddRight > 0);
     248             : }
     249             : 
     250           0 : bool ArrayImpl::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
     251             : {
     252           0 :     const Cell& rCell = GetCell( nCol, nRow );
     253           0 :     return rCell.mbOverlapY || (rCell.mnAddTop > 0);
     254             : }
     255             : 
     256           0 : bool ArrayImpl::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
     257             : {
     258           0 :     return GetCell( nCol, nRow + 1 ).mbOverlapY || (GetCell( nCol, nRow ).mnAddBottom > 0);
     259             : }
     260             : 
     261           0 : bool ArrayImpl::IsColInClipRange( size_t nCol ) const
     262             : {
     263           0 :     return (mnFirstClipCol <= nCol) && (nCol <= mnLastClipCol);
     264             : }
     265             : 
     266           0 : bool ArrayImpl::IsRowInClipRange( size_t nRow ) const
     267             : {
     268           0 :     return (mnFirstClipRow <= nRow) && (nRow <= mnLastClipRow);
     269             : }
     270             : 
     271           0 : bool ArrayImpl::IsInClipRange( size_t nCol, size_t nRow ) const
     272             : {
     273           0 :     return IsColInClipRange( nCol ) && IsRowInClipRange( nRow );
     274             : }
     275             : 
     276           0 : long ArrayImpl::GetColPosition( size_t nCol ) const
     277             : {
     278           0 :     if( mbXCoordsDirty )
     279             :     {
     280           0 :         lclRecalcCoordVec( maXCoords, maWidths );
     281           0 :         mbXCoordsDirty = false;
     282             :     }
     283           0 :     return maXCoords[ nCol ];
     284             : }
     285             : 
     286           0 : long ArrayImpl::GetRowPosition( size_t nRow ) const
     287             : {
     288           0 :     if( mbYCoordsDirty )
     289             :     {
     290           0 :         lclRecalcCoordVec( maYCoords, maHeights );
     291           0 :         mbYCoordsDirty = false;
     292             :     }
     293           0 :     return maYCoords[ nRow ];
     294             : }
     295             : 
     296           0 : long ArrayImpl::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
     297             : {
     298           0 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     299             : }
     300             : 
     301           0 : long ArrayImpl::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
     302             : {
     303           0 :     return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
     304             : }
     305             : 
     306           0 : double ArrayImpl::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     307             : {
     308           0 :     double fAngle = 0.0;
     309           0 :     if( IsValidPos( nCol, nRow ) )
     310             :     {
     311           0 :         if( bSimple || !GetCell( nCol, nRow ).IsMerged() )
     312             :         {
     313           0 :             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           0 :             size_t nFirstCol = GetMergedFirstCol( nCol, nRow );
     319           0 :             size_t nFirstRow = GetMergedFirstRow( nCol, nRow );
     320           0 :             const Cell& rCell = GetCell( nFirstCol, nFirstRow );
     321           0 :             long nWidth = GetColWidth( nFirstCol, GetMergedLastCol( nCol, nRow ) ) + rCell.mnAddLeft + rCell.mnAddRight;
     322           0 :             long nHeight = GetRowHeight( nFirstRow, GetMergedLastRow( nCol, nRow ) ) + rCell.mnAddTop + rCell.mnAddBottom;
     323           0 :             fAngle = frame::GetHorDiagAngle( nWidth + 1, nHeight + 1 );
     324             :         }
     325             :     }
     326           0 :     return fAngle;
     327             : }
     328             : 
     329           0 : double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
     330             : {
     331           0 :     double fAngle = GetHorDiagAngle( nCol, nRow, bSimple );
     332           0 :     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           0 :     inline bool         Is() const { return (mnCol <= mnLastCol) && (mnRow <= mnLastRow); }
     343           0 :     inline size_t       Col() const { return mnCol; }
     344           0 :     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           0 : 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           0 :     rArray.GetMergedRange( mnFirstCol, mnFirstRow, mnLastCol, mnLastRow, nCol, nRow );
     363           0 :     mnCol = mnFirstCol;
     364           0 :     mnRow = mnFirstRow;
     365           0 : }
     366             : 
     367           0 : MergedCellIterator& MergedCellIterator::operator++()
     368             : {
     369             :     DBG_ASSERT( Is(), "svx::frame::MergedCellIterator::operator++() - already invalid" );
     370           0 :     if( ++mnCol > mnLastCol )
     371             :     {
     372           0 :         mnCol = mnFirstCol;
     373           0 :         ++mnRow;
     374             :     }
     375           0 :     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           0 : Array::Array()
     396             : {
     397           0 :     Initialize( 0, 0 );
     398           0 : }
     399             : 
     400           0 : Array::~Array()
     401             : {
     402           0 : }
     403             : 
     404             : // array size and column/row indexes ------------------------------------------
     405             : 
     406           0 : void Array::Initialize( size_t nWidth, size_t nHeight )
     407             : {
     408           0 :     bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
     409           0 :     mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
     410           0 : }
     411             : 
     412           0 : size_t Array::GetColCount() const
     413             : {
     414           0 :     return mxImpl->mnWidth;
     415             : }
     416             : 
     417           0 : size_t Array::GetRowCount() const
     418             : {
     419           0 :     return mxImpl->mnHeight;
     420             : }
     421             : 
     422           0 : size_t Array::GetCellCount() const
     423             : {
     424           0 :     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           0 : void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
     438             : {
     439             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
     440           0 :     CELLACC( nCol, nRow ).maLeft = rStyle;
     441           0 : }
     442             : 
     443           0 : void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
     444             : {
     445             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
     446           0 :     CELLACC( nCol, nRow ).maRight = rStyle;
     447           0 : }
     448             : 
     449           0 : void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
     450             : {
     451             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
     452           0 :     CELLACC( nCol, nRow ).maTop = rStyle;
     453           0 : }
     454             : 
     455           0 : void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
     456             : {
     457             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
     458           0 :     CELLACC( nCol, nRow ).maBottom = rStyle;
     459           0 : }
     460             : 
     461           0 : void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
     462             : {
     463             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
     464           0 :     CELLACC( nCol, nRow ).maTLBR = rStyle;
     465           0 : }
     466             : 
     467           0 : void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
     468             : {
     469             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
     470           0 :     CELLACC( nCol, nRow ).maBLTR = rStyle;
     471           0 : }
     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           0 : const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple ) const
     510             : {
     511             :     // simple: always return own left style
     512           0 :     if( bSimple )
     513           0 :         return CELL( nCol, nRow ).maLeft;
     514             :     // outside clipping rows or overlapped in merged cells: invisible
     515           0 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedLeft( nCol, nRow ) )
     516           0 :         return OBJ_STYLE_NONE;
     517             :     // left clipping border: always own left style
     518           0 :     if( nCol == mxImpl->mnFirstClipCol )
     519           0 :         return ORIGCELL( nCol, nRow ).maLeft;
     520             :     // right clipping border: always right style of left neighbor cell
     521           0 :     if( nCol == mxImpl->mnLastClipCol + 1 )
     522           0 :         return ORIGCELL( nCol - 1, nRow ).maRight;
     523             :     // outside clipping columns: invisible
     524           0 :     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           0 :     return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
     528             : }
     529             : 
     530           0 : const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple ) const
     531             : {
     532             :     // simple: always return own right style
     533           0 :     if( bSimple )
     534           0 :         return CELL( nCol, nRow ).maRight;
     535             :     // outside clipping rows or overlapped in merged cells: invisible
     536           0 :     if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedRight( nCol, nRow ) )
     537           0 :         return OBJ_STYLE_NONE;
     538             :     // left clipping border: always left style of right neighbor cell
     539           0 :     if( nCol + 1 == mxImpl->mnFirstClipCol )
     540           0 :         return ORIGCELL( nCol + 1, nRow ).maLeft;
     541             :     // right clipping border: always own right style
     542           0 :     if( nCol == mxImpl->mnLastClipCol )
     543           0 :         return ORIGCELL( nCol, nRow ).maRight;
     544             :     // outside clipping columns: invisible
     545           0 :     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           0 :     return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
     549             : }
     550             : 
     551           0 : const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple ) const
     552             : {
     553             :     // simple: always return own top style
     554           0 :     if( bSimple )
     555           0 :         return CELL( nCol, nRow ).maTop;
     556             :     // outside clipping columns or overlapped in merged cells: invisible
     557           0 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedTop( nCol, nRow ) )
     558           0 :         return OBJ_STYLE_NONE;
     559             :     // top clipping border: always own top style
     560           0 :     if( nRow == mxImpl->mnFirstClipRow )
     561           0 :         return ORIGCELL( nCol, nRow ).maTop;
     562             :     // bottom clipping border: always bottom style of top neighbor cell
     563           0 :     if( nRow == mxImpl->mnLastClipRow + 1 )
     564           0 :         return ORIGCELL( nCol, nRow - 1 ).maBottom;
     565             :     // outside clipping rows: invisible
     566           0 :     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           0 :     return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
     570             : }
     571             : 
     572           0 : const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple ) const
     573             : {
     574             :     // simple: always return own bottom style
     575           0 :     if( bSimple )
     576           0 :         return CELL( nCol, nRow ).maBottom;
     577             :     // outside clipping columns or overlapped in merged cells: invisible
     578           0 :     if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedBottom( nCol, nRow ) )
     579           0 :         return OBJ_STYLE_NONE;
     580             :     // top clipping border: always top style of bottom neighbor cell
     581           0 :     if( nRow + 1 == mxImpl->mnFirstClipRow )
     582           0 :         return ORIGCELL( nCol, nRow + 1 ).maTop;
     583             :     // bottom clipping border: always own bottom style
     584           0 :     if( nRow == mxImpl->mnLastClipRow )
     585           0 :         return ORIGCELL( nCol, nRow ).maBottom;
     586             :     // outside clipping rows: invisible
     587           0 :     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           0 :     return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
     591             : }
     592             : 
     593           0 : const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple ) const
     594             : {
     595           0 :     return bSimple ? CELL( nCol, nRow ).maTLBR :
     596           0 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maTLBR : OBJ_STYLE_NONE);
     597             : }
     598             : 
     599           0 : const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple ) const
     600             : {
     601           0 :     return bSimple ? CELL( nCol, nRow ).maBLTR :
     602           0 :         (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maBLTR : OBJ_STYLE_NONE);
     603             : }
     604             : 
     605           0 : const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
     606             : {
     607             :     // not in clipping range: always invisible
     608           0 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     609           0 :         return OBJ_STYLE_NONE;
     610             :     // return style only for top-left cell
     611           0 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     612           0 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     613           0 :     return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
     614           0 :         CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
     615             : }
     616             : 
     617           0 : const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
     618             : {
     619             :     // not in clipping range: always invisible
     620           0 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     621           0 :         return OBJ_STYLE_NONE;
     622             :     // return style only for bottom-right cell
     623           0 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     624           0 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     625           0 :     return ((nCol == nLastCol) && (nRow == nLastRow)) ?
     626           0 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
     627             : }
     628             : 
     629           0 : const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
     630             : {
     631             :     // not in clipping range: always invisible
     632           0 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     633           0 :         return OBJ_STYLE_NONE;
     634             :     // return style only for bottom-left cell
     635           0 :     size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     636           0 :     size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     637           0 :     return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
     638           0 :         CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
     639             : }
     640             : 
     641           0 : const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
     642             : {
     643             :     // not in clipping range: always invisible
     644           0 :     if( !mxImpl->IsInClipRange( nCol, nRow ) )
     645           0 :         return OBJ_STYLE_NONE;
     646             :     // return style only for top-right cell
     647           0 :     size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     648           0 :     size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     649           0 :     return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
     650           0 :         CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
     651             : }
     652             : 
     653             : // cell merging ---------------------------------------------------------------
     654             : 
     655           0 : 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           0 :     if( mxImpl->IsValidPos( nFirstCol, nFirstRow ) && mxImpl->IsValidPos( nLastCol, nLastRow ) )
     669           0 :         lclSetMergedRange( mxImpl->maCells, mxImpl->mnWidth, nFirstCol, nFirstRow, nLastCol, nLastRow );
     670           0 : }
     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           0 : 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           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     685           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddRight = nAddSize;
     686           0 : }
     687             : 
     688           0 : 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           0 :     for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
     693           0 :         CELLACC( aIt.Col(), aIt.Row() ).mnAddTop = nAddSize;
     694           0 : }
     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           0 : bool Array::IsMerged( size_t nCol, size_t nRow ) const
     705             : {
     706             :     DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMerged" );
     707           0 :     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           0 : 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           0 :     rnFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     726           0 :     rnFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     727           0 : }
     728             : 
     729           0 : 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           0 :     GetMergedOrigin( rnFirstCol, rnFirstRow, nCol, nRow );
     733           0 :     rnLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
     734           0 :     rnLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
     735           0 : }
     736             : 
     737             : // clipping -------------------------------------------------------------------
     738             : 
     739           0 : 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           0 :     mxImpl->mnFirstClipCol = nFirstCol;
     744           0 :     mxImpl->mnFirstClipRow = nFirstRow;
     745           0 :     mxImpl->mnLastClipCol = nLastCol;
     746           0 :     mxImpl->mnLastClipRow = nLastRow;
     747           0 : }
     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           0 : void Array::SetXOffset( long nXOffset )
     761             : {
     762           0 :     mxImpl->maXCoords[ 0 ] = nXOffset;
     763           0 :     mxImpl->mbXCoordsDirty = true;
     764           0 : }
     765             : 
     766           0 : void Array::SetYOffset( long nYOffset )
     767             : {
     768           0 :     mxImpl->maYCoords[ 0 ] = nYOffset;
     769           0 :     mxImpl->mbYCoordsDirty = true;
     770           0 : }
     771             : 
     772           0 : void Array::SetColWidth( size_t nCol, long nWidth )
     773             : {
     774             :     DBG_FRAME_CHECK_COL( nCol, "SetColWidth" );
     775           0 :     mxImpl->maWidths[ nCol ] = nWidth;
     776           0 :     mxImpl->mbXCoordsDirty = true;
     777           0 : }
     778             : 
     779           0 : void Array::SetRowHeight( size_t nRow, long nHeight )
     780             : {
     781             :     DBG_FRAME_CHECK_ROW( nRow, "SetRowHeight" );
     782           0 :     mxImpl->maHeights[ nRow ] = nHeight;
     783           0 :     mxImpl->mbYCoordsDirty = true;
     784           0 : }
     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           0 : long Array::GetColPosition( size_t nCol ) const
     799             : {
     800             :     DBG_FRAME_CHECK_COL_1( nCol, "GetColPosition" );
     801           0 :     return mxImpl->GetColPosition( nCol );
     802             : }
     803             : 
     804           0 : long Array::GetRowPosition( size_t nRow ) const
     805             : {
     806             :     DBG_FRAME_CHECK_ROW_1( nRow, "GetRowPosition" );
     807           0 :     return mxImpl->GetRowPosition( nRow );
     808             : }
     809             : 
     810           0 : 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           0 :     return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
     815             : }
     816             : 
     817           0 : 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           0 :     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           0 : Point Array::GetCellPosition( size_t nCol, size_t nRow, bool bSimple ) const
     835             : {
     836           0 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     837           0 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     838           0 :     return Point( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     839             : }
     840             : 
     841           0 : Size Array::GetCellSize( size_t nCol, size_t nRow, bool bSimple ) const
     842             : {
     843           0 :     size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
     844           0 :     size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
     845           0 :     size_t nLastCol = bSimple ? nCol : mxImpl->GetMergedLastCol( nCol, nRow );
     846           0 :     size_t nLastRow = bSimple ? nRow : mxImpl->GetMergedLastRow( nCol, nRow );
     847           0 :     return Size( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     848             : }
     849             : 
     850           0 : Rectangle Array::GetCellRect( size_t nCol, size_t nRow, bool bSimple ) const
     851             : {
     852           0 :     Rectangle aRect( GetCellPosition( nCol, nRow, bSimple ), GetCellSize( nCol, nRow, bSimple ) );
     853             : 
     854             :     // adjust rectangle for partly visible merged cells
     855           0 :     const Cell& rCell = CELL( nCol, nRow );
     856           0 :     if( !bSimple && rCell.IsMerged() )
     857             :     {
     858           0 :         aRect.Left() -= rCell.mnAddLeft;
     859           0 :         aRect.Right() += rCell.mnAddRight;
     860           0 :         aRect.Top() -= rCell.mnAddTop;
     861           0 :         aRect.Bottom() += rCell.mnAddBottom;
     862             :     }
     863           0 :     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           0 : void Array::SetUseDiagDoubleClipping( bool bSet )
     881             : {
     882           0 :     mxImpl->mbDiagDblClip = bSet;
     883           0 : }
     884             : 
     885             : // mirroring ------------------------------------------------------------------
     886             : 
     887           0 : void Array::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
     888             : {
     889           0 :     CellVec aNewCells;
     890           0 :     aNewCells.reserve( GetCellCount() );
     891             : 
     892             :     size_t nCol, nRow;
     893           0 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     894             :     {
     895           0 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     896             :         {
     897           0 :             aNewCells.push_back( CELL( mxImpl->GetMirrorCol( nCol ), nRow ) );
     898           0 :             aNewCells.back().MirrorSelfX( bMirrorStyles, bSwapDiag );
     899             :         }
     900             :     }
     901           0 :     for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
     902             :     {
     903           0 :         for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
     904             :         {
     905           0 :             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           0 :     mxImpl->maCells.swap( aNewCells );
     916             : 
     917           0 :     std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
     918           0 :     mxImpl->mbXCoordsDirty = true;
     919           0 : }
     920             : 
     921             : // drawing --------------------------------------------------------------------
     922             : 
     923           0 : 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           0 :     for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
     934             :     {
     935           0 :         for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
     936             :         {
     937           0 :             const Cell& rCell = CELL( nCol, nRow );
     938           0 :             bool bOverlapX = rCell.mbOverlapX;
     939           0 :             bool bOverlapY = rCell.mbOverlapY;
     940           0 :             bool bFirstCol = nCol == nFirstCol;
     941           0 :             bool bFirstRow = nRow == nFirstRow;
     942           0 :             if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
     943           0 :                 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
     944             :             {
     945           0 :                 Rectangle aRect( GetCellRect( nCol, nRow ) );
     946           0 :                 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
     947             :                 {
     948           0 :                     size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
     949           0 :                     size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
     950             : 
     951           0 :                     const Style aTlbrStyle = GetCellStyleTLBR( _nFirstCol, _nFirstRow, true );
     952           0 :                     if ( aTlbrStyle.GetWidth( ) )
     953             :                         pProcessor->process( CreateClippedBorderPrimitives(
     954             :                                     aRect.TopLeft(), aRect.BottomRight(),
     955           0 :                                     aTlbrStyle, aRect ) );
     956             : 
     957           0 :                     const Style aBltrStyle = GetCellStyleBLTR( _nFirstCol, _nFirstRow, true );
     958           0 :                     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           0 :     for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
     970             :     {
     971           0 :         double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
     972           0 :         double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
     973             : 
     974             :         // *Start*** variables store the data of the left end of the cached frame border
     975           0 :         Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
     976           0 :         const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
     977           0 :         DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
     978           0 :         const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
     979           0 :         const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
     980           0 :         const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
     981           0 :         DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
     982             : 
     983             :         // *End*** variables store the data of the right end of the cached frame border
     984           0 :         DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
     985           0 :         const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
     986           0 :         const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
     987           0 :         const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
     988           0 :         DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
     989             : 
     990           0 :         for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
     991             :         {
     992           0 :             fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
     993           0 :             fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
     994             : 
     995           0 :             const Style& rCurr = *pEndRFromR;
     996             : 
     997           0 :             DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
     998           0 :             const Style& rLFromT = *pEndRFromT;
     999           0 :             const Style& rLFromL = *pStart;
    1000           0 :             const Style& rLFromB = *pEndRFromB;
    1001           0 :             DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1002             : 
    1003           0 :             DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
    1004           0 :             const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
    1005           0 :             const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
    1006           0 :             const Style& rRFromB = GetCellStyleRight( nCol, nRow );
    1007           0 :             DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
    1008             : 
    1009             :             // check if current frame border can be connected to cached frame border
    1010           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1011           0 :                     aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
    1012             :             {
    1013             :                 // draw previous frame border
    1014           0 :                 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1015           0 :                 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1016             :                    pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1017             :                         aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1018           0 :                         aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1019             : 
    1020             :                 // re-init "*Start***" variables
    1021           0 :                 aStartPos = aEndPos;
    1022           0 :                 pStart = &rCurr;
    1023           0 :                 aStartLFromTR = aLFromTR;
    1024           0 :                 pStartLFromT = &rLFromT;
    1025           0 :                 pStartLFromL = &rLFromL;
    1026           0 :                 pStartLFromB = &rLFromB;
    1027           0 :                 aStartLFromBR = aLFromBR;
    1028             :             }
    1029             : 
    1030             :             // store current styles in "*End***" variables
    1031           0 :             aEndRFromTL = aRFromTL;
    1032           0 :             pEndRFromT = &rRFromT;
    1033           0 :             pEndRFromR = &rRFromR;
    1034           0 :             pEndRFromB = &rRFromB;
    1035           0 :             aEndRFromBL = aRFromBL;
    1036             :         }
    1037             : 
    1038             :         // draw last frame border
    1039           0 :         Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
    1040           0 :         if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
    1041             :             pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart,
    1042             :                 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
    1043           0 :                 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) );
    1044             :     }
    1045             : 
    1046             :     // *** vertical frame borders ***
    1047           0 :     for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    1048             :     {
    1049           0 :         double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
    1050           0 :         double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
    1051             : 
    1052             :         // *Start*** variables store the data of the top end of the cached frame border
    1053           0 :         Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
    1054           0 :         const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
    1055           0 :         DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
    1056           0 :         const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
    1057           0 :         const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
    1058           0 :         const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
    1059           0 :         DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
    1060             : 
    1061             :         // *End*** variables store the data of the bottom end of the cached frame border
    1062           0 :         DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
    1063           0 :         const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
    1064           0 :         const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
    1065           0 :         const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
    1066           0 :         DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
    1067             : 
    1068           0 :         for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
    1069             :         {
    1070           0 :             fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
    1071           0 :             fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
    1072             : 
    1073           0 :             const Style& rCurr = *pEndBFromB;
    1074             : 
    1075           0 :             DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
    1076           0 :             const Style& rTFromL = *pEndBFromL;
    1077           0 :             const Style& rTFromT = *pStart;
    1078           0 :             const Style& rTFromR = *pEndBFromR;
    1079           0 :             DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
    1080             : 
    1081           0 :             DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
    1082           0 :             const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
    1083           0 :             const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
    1084           0 :             const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
    1085           0 :             DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
    1086             : 
    1087             :             // check if current frame border can be connected to cached frame border
    1088           0 :             if( !CheckFrameBorderConnectable( *pStart, rCurr,
    1089           0 :                     aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
    1090             :             {
    1091             :                 // draw previous frame border
    1092           0 :                 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1093           0 :                 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1094             :                     pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1095             :                         aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1096           0 :                         aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1097             : 
    1098             :                 // re-init "*Start***" variables
    1099           0 :                 aStartPos = aEndPos;
    1100           0 :                 pStart = &rCurr;
    1101           0 :                 aStartTFromBL = aTFromBL;
    1102           0 :                 pStartTFromL = &rTFromL;
    1103           0 :                 pStartTFromT = &rTFromT;
    1104           0 :                 pStartTFromR = &rTFromR;
    1105           0 :                 aStartTFromBR = aTFromBR;
    1106             :             }
    1107             : 
    1108             :             // store current styles in "*End***" variables
    1109           0 :             aEndBFromTL = aBFromTL;
    1110           0 :             pEndBFromL = &rBFromL;
    1111           0 :             pEndBFromB = &rBFromB;
    1112           0 :             pEndBFromR = &rBFromR;
    1113           0 :             aEndBFromTR = aBFromTR;
    1114             :         }
    1115             : 
    1116             :         // draw last frame border
    1117           0 :         Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
    1118           0 :         if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
    1119             :             pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart,
    1120             :                 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR,
    1121           0 :                 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) );
    1122             :     }
    1123           0 : }
    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           0 : } // namespace svx
    1356             : 
    1357             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10