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

Generated by: LCOV version 1.10