LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/svx/source/dialog - framelinkarray.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 431 637 67.7 %
Date: 2013-07-09 Functions: 75 94 79.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10