Update ooo320-m1
[ooovba.git] / svx / source / dialog / framelinkarray.cxx
blobb0b25d8355312e9a578400337c016ca6c0ec5fbc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: framelinkarray.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/framelinkarray.hxx>
35 #include <math.h>
36 #include <vector>
37 #include <algorithm>
38 #include <vcl/outdev.hxx>
40 namespace svx {
41 namespace frame {
43 // ============================================================================
46 Cell::Cell() :
47 mnAddLeft( 0 ),
48 mnAddRight( 0 ),
49 mnAddTop( 0 ),
50 mnAddBottom( 0 ),
51 mbMergeOrig( false ),
52 mbOverlapX( false ),
53 mbOverlapY( false )
57 void Cell::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
59 std::swap( maLeft, maRight );
60 std::swap( mnAddLeft, mnAddRight );
61 if( bMirrorStyles )
63 maLeft.MirrorSelf();
64 maRight.MirrorSelf();
66 if( bSwapDiag )
68 std::swap( maTLBR, maBLTR );
69 if( bMirrorStyles )
71 maTLBR.MirrorSelf();
72 maBLTR.MirrorSelf();
77 void Cell::MirrorSelfY( bool bMirrorStyles, bool bSwapDiag )
79 std::swap( maTop, maBottom );
80 std::swap( mnAddTop, mnAddBottom );
81 if( bMirrorStyles )
83 maTop.MirrorSelf();
84 maBottom.MirrorSelf();
86 if( bSwapDiag )
87 std::swap( maTLBR, maBLTR );
88 /* Do not mirror diagonal styles, because they are oriented vertical.
89 Therefore swapping the styles is sufficient for correct behaviour. */
92 // ----------------------------------------------------------------------------
95 void lclRecalcCoordVec( LongVec& rCoords, const LongVec& rSizes )
97 DBG_ASSERT( rCoords.size() == rSizes.size() + 1, "lclRecalcCoordVec - inconsistent vectors" );
98 LongVec::iterator aCIt = rCoords.begin();
99 LongVec::const_iterator aSIt = rSizes.begin(), aSEnd = rSizes.end();
100 for( ; aSIt != aSEnd; ++aCIt, ++aSIt )
101 *(aCIt + 1) = *aCIt + *aSIt;
104 void lclSetMergedRange( CellVec& rCells, size_t nWidth, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
106 for( size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol )
108 for( size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow )
110 Cell& rCell = rCells[ nRow * nWidth + nCol ];
111 rCell.mbMergeOrig = false;
112 rCell.mbOverlapX = nCol > nFirstCol;
113 rCell.mbOverlapY = nRow > nFirstRow;
116 rCells[ nFirstRow * nWidth + nFirstCol ].mbMergeOrig = true;
119 // ----------------------------------------------------------------------------
121 static const Style OBJ_STYLE_NONE;
122 static const Cell OBJ_CELL_NONE;
124 const bool DIAG_DBL_CLIP_DEFAULT = false;
126 // ============================================================================
128 ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
129 mnWidth( nWidth ),
130 mnHeight( nHeight ),
131 mnFirstClipCol( 0 ),
132 mnFirstClipRow( 0 ),
133 mnLastClipCol( nWidth - 1 ),
134 mnLastClipRow( nHeight - 1 ),
135 mbXCoordsDirty( false ),
136 mbYCoordsDirty( false ),
137 mbDiagDblClip( bDiagDblClip )
139 // default-construct all vectors
140 maCells.resize( mnWidth * mnHeight );
141 maWidths.resize( mnWidth, 0L );
142 maHeights.resize( mnHeight, 0L );
143 maXCoords.resize( mnWidth + 1, 0L );
144 maYCoords.resize( mnHeight + 1, 0L );
147 const Cell& ArrayImpl::GetCell( size_t nCol, size_t nRow ) const
149 return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : OBJ_CELL_NONE;
152 Cell& ArrayImpl::GetCellAcc( size_t nCol, size_t nRow )
154 static Cell aDummy;
155 return IsValidPos( nCol, nRow ) ? maCells[ GetIndex( nCol, nRow ) ] : aDummy;
158 size_t ArrayImpl::GetMergedFirstCol( size_t nCol, size_t nRow ) const
160 size_t nFirstCol = nCol;
161 while( (nFirstCol > 0) && GetCell( nFirstCol, nRow ).mbOverlapX ) --nFirstCol;
162 return nFirstCol;
165 size_t ArrayImpl::GetMergedFirstRow( size_t nCol, size_t nRow ) const
167 size_t nFirstRow = nRow;
168 while( (nFirstRow > 0) && GetCell( nCol, nFirstRow ).mbOverlapY ) --nFirstRow;
169 return nFirstRow;
172 size_t ArrayImpl::GetMergedLastCol( size_t nCol, size_t nRow ) const
174 size_t nLastCol = nCol + 1;
175 while( (nLastCol < mnWidth) && GetCell( nLastCol, nRow ).mbOverlapX ) ++nLastCol;
176 return nLastCol - 1;
179 size_t ArrayImpl::GetMergedLastRow( size_t nCol, size_t nRow ) const
181 size_t nLastRow = nRow + 1;
182 while( (nLastRow < mnHeight) && GetCell( nCol, nLastRow ).mbOverlapY ) ++nLastRow;
183 return nLastRow - 1;
186 const Cell& ArrayImpl::GetMergedOriginCell( size_t nCol, size_t nRow ) const
188 return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
191 Cell& ArrayImpl::GetMergedOriginCellAcc( size_t nCol, size_t nRow )
193 return GetCellAcc( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, nRow ) );
196 bool ArrayImpl::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
198 const Cell& rCell = GetCell( nCol, nRow );
199 return rCell.mbOverlapX || (rCell.mnAddLeft > 0);
202 bool ArrayImpl::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
204 return GetCell( nCol + 1, nRow ).mbOverlapX || (GetCell( nCol, nRow ).mnAddRight > 0);
207 bool ArrayImpl::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
209 const Cell& rCell = GetCell( nCol, nRow );
210 return rCell.mbOverlapY || (rCell.mnAddTop > 0);
213 bool ArrayImpl::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
215 return GetCell( nCol, nRow + 1 ).mbOverlapY || (GetCell( nCol, nRow ).mnAddBottom > 0);
218 bool ArrayImpl::IsColInClipRange( size_t nCol ) const
220 return (mnFirstClipCol <= nCol) && (nCol <= mnLastClipCol);
223 bool ArrayImpl::IsRowInClipRange( size_t nRow ) const
225 return (mnFirstClipRow <= nRow) && (nRow <= mnLastClipRow);
228 bool ArrayImpl::IsInClipRange( size_t nCol, size_t nRow ) const
230 return IsColInClipRange( nCol ) && IsRowInClipRange( nRow );
233 long ArrayImpl::GetColPosition( size_t nCol ) const
235 if( mbXCoordsDirty )
237 lclRecalcCoordVec( maXCoords, maWidths );
238 mbXCoordsDirty = false;
240 return maXCoords[ nCol ];
243 long ArrayImpl::GetRowPosition( size_t nRow ) const
245 if( mbYCoordsDirty )
247 lclRecalcCoordVec( maYCoords, maHeights );
248 mbYCoordsDirty = false;
250 return maYCoords[ nRow ];
253 long ArrayImpl::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
255 return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
258 long ArrayImpl::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
260 return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
263 double ArrayImpl::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
265 double fAngle = 0.0;
266 if( IsValidPos( nCol, nRow ) )
268 if( bSimple || !GetCell( nCol, nRow ).IsMerged() )
270 fAngle = frame::GetHorDiagAngle( maWidths[ nCol ] + 1, maHeights[ nRow ] + 1 );
272 else
274 // return correct angle for each cell in the merged range
275 size_t nFirstCol = GetMergedFirstCol( nCol, nRow );
276 size_t nFirstRow = GetMergedFirstRow( nCol, nRow );
277 const Cell& rCell = GetCell( nFirstCol, nFirstRow );
278 long nWidth = GetColWidth( nFirstCol, GetMergedLastCol( nCol, nRow ) ) + rCell.mnAddLeft + rCell.mnAddRight;
279 long nHeight = GetRowHeight( nFirstRow, GetMergedLastRow( nCol, nRow ) ) + rCell.mnAddTop + rCell.mnAddBottom;
280 fAngle = frame::GetHorDiagAngle( nWidth + 1, nHeight + 1 );
283 return fAngle;
286 double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
288 double fAngle = GetHorDiagAngle( nCol, nRow, bSimple );
289 return (fAngle > 0.0) ? (F_PI2 - fAngle) : 0.0;
292 // ============================================================================
294 class MergedCellIterator
296 public:
297 explicit MergedCellIterator( const Array& rArray, size_t nCol, size_t nRow );
299 inline bool Is() const { return (mnCol <= mnLastCol) && (mnRow <= mnLastRow); }
300 inline size_t Col() const { return mnCol; }
301 inline size_t Row() const { return mnRow; }
303 MergedCellIterator& operator++();
305 private:
306 size_t mnFirstCol;
307 size_t mnFirstRow;
308 size_t mnLastCol;
309 size_t mnLastRow;
310 size_t mnCol;
311 size_t mnRow;
314 // ----------------------------------------------------------------------------
316 MergedCellIterator::MergedCellIterator( const Array& rArray, size_t nCol, size_t nRow )
318 DBG_ASSERT( rArray.IsMerged( nCol, nRow ), "svx::frame::MergedCellIterator::MergedCellIterator - not in merged range" );
319 rArray.GetMergedRange( mnFirstCol, mnFirstRow, mnLastCol, mnLastRow, nCol, nRow );
320 mnCol = mnFirstCol;
321 mnRow = mnFirstRow;
324 MergedCellIterator& MergedCellIterator::operator++()
326 DBG_ASSERT( Is(), "svx::frame::MergedCellIterator::operator++() - already invalid" );
327 if( ++mnCol > mnLastCol )
329 mnCol = mnFirstCol;
330 ++mnRow;
332 return *this;
335 // ============================================================================
337 #define DBG_FRAME_ERROR( funcname, error ) DBG_ERRORFILE( "svx::frame::Array::" funcname " - " error )
338 #define DBG_FRAME_CHECK( cond, funcname, error ) DBG_ASSERT( cond, "svx::frame::Array::" funcname " - " error )
339 #define DBG_FRAME_CHECK_COL( col, funcname ) DBG_FRAME_CHECK( (col) < GetColCount(), funcname, "invalid column index" )
340 #define DBG_FRAME_CHECK_ROW( row, funcname ) DBG_FRAME_CHECK( (row) < GetRowCount(), funcname, "invalid row index" )
341 #define DBG_FRAME_CHECK_COLROW( col, row, funcname ) DBG_FRAME_CHECK( ((col) < GetColCount()) && ((row) < GetRowCount()), funcname, "invalid cell index" )
342 #define DBG_FRAME_CHECK_INDEX( index, funcname ) DBG_FRAME_CHECK( (index) < GetCellCount(), funcname, "invalid cell index" )
343 #define DBG_FRAME_CHECK_COL_1( col, funcname ) DBG_FRAME_CHECK( (col) <= GetColCount(), funcname, "invalid column index" )
344 #define DBG_FRAME_CHECK_ROW_1( row, funcname ) DBG_FRAME_CHECK( (row) <= GetRowCount(), funcname, "invalid row index" )
346 // ----------------------------------------------------------------------------
348 #define CELL( col, row ) mxImpl->GetCell( col, row )
349 #define CELLACC( col, row ) mxImpl->GetCellAcc( col, row )
350 #define ORIGCELL( col, row ) mxImpl->GetMergedOriginCell( col, row )
351 #define ORIGCELLACC( col, row ) mxImpl->GetMergedOriginCellAcc( col, row )
353 // ----------------------------------------------------------------------------
355 Array::Array()
357 Initialize( 0, 0 );
360 Array::Array( size_t nWidth, size_t nHeight )
362 Initialize( nWidth, nHeight );
365 Array::~Array()
369 // array size and column/row indexes ------------------------------------------
371 void Array::Initialize( size_t nWidth, size_t nHeight )
373 bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
374 mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
377 void Array::Clear()
379 Initialize( mxImpl->mnWidth, mxImpl->mnHeight );
382 size_t Array::GetColCount() const
384 return mxImpl->mnWidth;
387 size_t Array::GetRowCount() const
389 return mxImpl->mnHeight;
392 size_t Array::GetCellCount() const
394 return mxImpl->maCells.size();
397 size_t Array::GetColFromIndex( size_t nCellIndex ) const
399 DBG_FRAME_CHECK_INDEX( nCellIndex, "GetColFromIndex" );
400 return mxImpl->mnWidth ? (nCellIndex % mxImpl->mnWidth) : 0;
403 size_t Array::GetRowFromIndex( size_t nCellIndex ) const
405 DBG_FRAME_CHECK_INDEX( nCellIndex, "GetRowFromIndex" );
406 return mxImpl->mnWidth ? (nCellIndex / mxImpl->mnWidth) : 0;
409 size_t Array::GetCellIndex( size_t nCol, size_t nRow, bool bRTL ) const
411 DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetCellIndex" );
412 if (bRTL)
413 nCol = mxImpl->GetMirrorCol(nCol);
414 return mxImpl->GetIndex( nCol, nRow );
417 // cell border styles ---------------------------------------------------------
419 void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
421 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
422 CELLACC( nCol, nRow ).maLeft = rStyle;
425 void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
427 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
428 CELLACC( nCol, nRow ).maRight = rStyle;
431 void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
433 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
434 CELLACC( nCol, nRow ).maTop = rStyle;
437 void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
439 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
440 CELLACC( nCol, nRow ).maBottom = rStyle;
443 void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
445 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
446 CELLACC( nCol, nRow ).maTLBR = rStyle;
449 void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
451 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
452 CELLACC( nCol, nRow ).maBLTR = rStyle;
455 void Array::SetCellStyleDiag( size_t nCol, size_t nRow, const Style& rTLBR, const Style& rBLTR )
457 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleDiag" );
458 Cell& rCell = CELLACC( nCol, nRow );
459 rCell.maTLBR = rTLBR;
460 rCell.maBLTR = rBLTR;
463 void Array::SetColumnStyleLeft( size_t nCol, const Style& rStyle )
465 DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleLeft" );
466 for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
467 SetCellStyleLeft( nCol, nRow, rStyle );
470 void Array::SetColumnStyleRight( size_t nCol, const Style& rStyle )
472 DBG_FRAME_CHECK_COL( nCol, "SetColumnStyleRight" );
473 for( size_t nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
474 SetCellStyleRight( nCol, nRow, rStyle );
477 void Array::SetRowStyleTop( size_t nRow, const Style& rStyle )
479 DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleTop" );
480 for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
481 SetCellStyleTop( nCol, nRow, rStyle );
484 void Array::SetRowStyleBottom( size_t nRow, const Style& rStyle )
486 DBG_FRAME_CHECK_ROW( nRow, "SetRowStyleBottom" );
487 for( size_t nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
488 SetCellStyleBottom( nCol, nRow, rStyle );
491 const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple ) const
493 // simple: always return own left style
494 if( bSimple )
495 return CELL( nCol, nRow ).maLeft;
496 // outside clipping rows or overlapped in merged cells: invisible
497 if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedLeft( nCol, nRow ) )
498 return OBJ_STYLE_NONE;
499 // left clipping border: always own left style
500 if( nCol == mxImpl->mnFirstClipCol )
501 return ORIGCELL( nCol, nRow ).maLeft;
502 // right clipping border: always right style of left neighbor cell
503 if( nCol == mxImpl->mnLastClipCol + 1 )
504 return ORIGCELL( nCol - 1, nRow ).maRight;
505 // outside clipping columns: invisible
506 if( !mxImpl->IsColInClipRange( nCol ) )
507 return OBJ_STYLE_NONE;
508 // inside clipping range: maximum of own left style and right style of left neighbor cell
509 return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
512 const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple ) const
514 // simple: always return own right style
515 if( bSimple )
516 return CELL( nCol, nRow ).maRight;
517 // outside clipping rows or overlapped in merged cells: invisible
518 if( !mxImpl->IsRowInClipRange( nRow ) || mxImpl->IsMergedOverlappedRight( nCol, nRow ) )
519 return OBJ_STYLE_NONE;
520 // left clipping border: always left style of right neighbor cell
521 if( nCol + 1 == mxImpl->mnFirstClipCol )
522 return ORIGCELL( nCol + 1, nRow ).maLeft;
523 // right clipping border: always own right style
524 if( nCol == mxImpl->mnLastClipCol )
525 return ORIGCELL( nCol, nRow ).maRight;
526 // outside clipping columns: invisible
527 if( !mxImpl->IsColInClipRange( nCol ) )
528 return OBJ_STYLE_NONE;
529 // inside clipping range: maximum of own right style and left style of right neighbor cell
530 return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
533 const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple ) const
535 // simple: always return own top style
536 if( bSimple )
537 return CELL( nCol, nRow ).maTop;
538 // outside clipping columns or overlapped in merged cells: invisible
539 if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedTop( nCol, nRow ) )
540 return OBJ_STYLE_NONE;
541 // top clipping border: always own top style
542 if( nRow == mxImpl->mnFirstClipRow )
543 return ORIGCELL( nCol, nRow ).maTop;
544 // bottom clipping border: always bottom style of top neighbor cell
545 if( nRow == mxImpl->mnLastClipRow + 1 )
546 return ORIGCELL( nCol, nRow - 1 ).maBottom;
547 // outside clipping rows: invisible
548 if( !mxImpl->IsRowInClipRange( nRow ) )
549 return OBJ_STYLE_NONE;
550 // inside clipping range: maximum of own top style and bottom style of top neighbor cell
551 return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
554 const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple ) const
556 // simple: always return own bottom style
557 if( bSimple )
558 return CELL( nCol, nRow ).maBottom;
559 // outside clipping columns or overlapped in merged cells: invisible
560 if( !mxImpl->IsColInClipRange( nCol ) || mxImpl->IsMergedOverlappedBottom( nCol, nRow ) )
561 return OBJ_STYLE_NONE;
562 // top clipping border: always top style of bottom neighbor cell
563 if( nRow + 1 == mxImpl->mnFirstClipRow )
564 return ORIGCELL( nCol, nRow + 1 ).maTop;
565 // bottom clipping border: always own bottom style
566 if( nRow == mxImpl->mnLastClipRow )
567 return ORIGCELL( nCol, nRow ).maBottom;
568 // outside clipping rows: invisible
569 if( !mxImpl->IsRowInClipRange( nRow ) )
570 return OBJ_STYLE_NONE;
571 // inside clipping range: maximum of own bottom style and top style of bottom neighbor cell
572 return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
575 const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple ) const
577 return bSimple ? CELL( nCol, nRow ).maTLBR :
578 (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maTLBR : OBJ_STYLE_NONE);
581 const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple ) const
583 return bSimple ? CELL( nCol, nRow ).maBLTR :
584 (mxImpl->IsInClipRange( nCol, nRow ) ? ORIGCELL( nCol, nRow ).maBLTR : OBJ_STYLE_NONE);
587 const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
589 // not in clipping range: always invisible
590 if( !mxImpl->IsInClipRange( nCol, nRow ) )
591 return OBJ_STYLE_NONE;
592 // return style only for top-left cell
593 size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
594 size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
595 return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
596 CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
599 const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
601 // not in clipping range: always invisible
602 if( !mxImpl->IsInClipRange( nCol, nRow ) )
603 return OBJ_STYLE_NONE;
604 // return style only for bottom-right cell
605 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
606 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
607 return ((nCol == nLastCol) && (nRow == nLastRow)) ?
608 CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
611 const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
613 // not in clipping range: always invisible
614 if( !mxImpl->IsInClipRange( nCol, nRow ) )
615 return OBJ_STYLE_NONE;
616 // return style only for bottom-left cell
617 size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
618 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
619 return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
620 CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
623 const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
625 // not in clipping range: always invisible
626 if( !mxImpl->IsInClipRange( nCol, nRow ) )
627 return OBJ_STYLE_NONE;
628 // return style only for top-right cell
629 size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
630 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
631 return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
632 CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
635 // cell merging ---------------------------------------------------------------
637 void Array::SetMergedRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
639 DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetMergedRange" );
640 DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetMergedRange" );
641 #if OSL_DEBUG_LEVEL >= 2
643 bool bFound = false;
644 for( size_t nCurrCol = nFirstCol; !bFound && (nCurrCol <= nLastCol); ++nCurrCol )
645 for( size_t nCurrRow = nFirstRow; !bFound && (nCurrRow <= nLastRow); ++nCurrRow )
646 bFound = CELL( nCurrCol, nCurrRow ).IsMerged();
647 DBG_FRAME_CHECK( !bFound, "SetMergedRange", "overlapping merged ranges" );
649 #endif
650 if( mxImpl->IsValidPos( nFirstCol, nFirstRow ) && mxImpl->IsValidPos( nLastCol, nLastRow ) )
651 lclSetMergedRange( mxImpl->maCells, mxImpl->mnWidth, nFirstCol, nFirstRow, nLastCol, nLastRow );
654 void Array::RemoveMergedRange( size_t nCol, size_t nRow )
656 DBG_FRAME_CHECK_COLROW( nCol, nRow, "RemoveMergedRange" );
657 for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
659 Cell& rCell = CELLACC( aIt.Col(), aIt.Row() );
660 rCell.mbMergeOrig = rCell.mbOverlapX = rCell.mbOverlapY = false;
661 rCell.mnAddLeft = rCell.mnAddRight = rCell.mnAddTop = rCell.mnAddBottom = 0;
665 void Array::SetAddMergedLeftSize( size_t nCol, size_t nRow, long nAddSize )
667 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedLeftSize" );
668 DBG_FRAME_CHECK( mxImpl->GetMergedFirstCol( nCol, nRow ) == 0, "SetAddMergedLeftSize", "additional border inside array" );
669 for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
670 CELLACC( aIt.Col(), aIt.Row() ).mnAddLeft = nAddSize;
673 void Array::SetAddMergedRightSize( size_t nCol, size_t nRow, long nAddSize )
675 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedRightSize" );
676 DBG_FRAME_CHECK( mxImpl->GetMergedLastCol( nCol, nRow ) + 1 == mxImpl->mnWidth, "SetAddMergedRightSize", "additional border inside array" );
677 for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
678 CELLACC( aIt.Col(), aIt.Row() ).mnAddRight = nAddSize;
681 void Array::SetAddMergedTopSize( size_t nCol, size_t nRow, long nAddSize )
683 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedTopSize" );
684 DBG_FRAME_CHECK( mxImpl->GetMergedFirstRow( nCol, nRow ) == 0, "SetAddMergedTopSize", "additional border inside array" );
685 for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
686 CELLACC( aIt.Col(), aIt.Row() ).mnAddTop = nAddSize;
689 void Array::SetAddMergedBottomSize( size_t nCol, size_t nRow, long nAddSize )
691 DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetAddMergedBottomSize" );
692 DBG_FRAME_CHECK( mxImpl->GetMergedLastRow( nCol, nRow ) + 1 == mxImpl->mnHeight, "SetAddMergedBottomSize", "additional border inside array" );
693 for( MergedCellIterator aIt( *this, nCol, nRow ); aIt.Is(); ++aIt )
694 CELLACC( aIt.Col(), aIt.Row() ).mnAddBottom = nAddSize;
697 bool Array::IsMerged( size_t nCol, size_t nRow ) const
699 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMerged" );
700 return CELL( nCol, nRow ).IsMerged();
703 bool Array::IsMergedOrigin( size_t nCol, size_t nRow ) const
705 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOrigin" );
706 return CELL( nCol, nRow ).mbMergeOrig;
709 bool Array::IsMergedOverlapped( size_t nCol, size_t nRow ) const
711 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlapped" );
712 return CELL( nCol, nRow ).IsOverlapped();
715 bool Array::IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const
717 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedLeft" );
718 return mxImpl->IsMergedOverlappedLeft( nCol, nRow );
721 bool Array::IsMergedOverlappedRight( size_t nCol, size_t nRow ) const
723 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedRight" );
724 return mxImpl->IsMergedOverlappedRight( nCol, nRow );
727 bool Array::IsMergedOverlappedTop( size_t nCol, size_t nRow ) const
729 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedTop" );
730 return mxImpl->IsMergedOverlappedTop( nCol, nRow );
733 bool Array::IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const
735 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsMergedOverlappedBottom" );
736 return mxImpl->IsMergedOverlappedBottom( nCol, nRow );
739 void Array::GetMergedOrigin( size_t& rnFirstCol, size_t& rnFirstRow, size_t nCol, size_t nRow ) const
741 DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetMergedOrigin" );
742 rnFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
743 rnFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
746 void Array::GetMergedSize( size_t& rnWidth, size_t& rnHeight, size_t nCol, size_t nRow ) const
748 size_t nFirstCol, nFirstRow, nLastCol, nLastRow;
749 GetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow, nCol, nRow );
750 rnWidth = nLastCol - nFirstCol + 1;
751 rnHeight = nLastRow - nFirstRow + 1;
754 void Array::GetMergedRange( size_t& rnFirstCol, size_t& rnFirstRow,
755 size_t& rnLastCol, size_t& rnLastRow, size_t nCol, size_t nRow ) const
757 GetMergedOrigin( rnFirstCol, rnFirstRow, nCol, nRow );
758 rnLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
759 rnLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
762 // clipping -------------------------------------------------------------------
764 void Array::SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow )
766 DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "SetClipRange" );
767 DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "SetClipRange" );
768 mxImpl->mnFirstClipCol = nFirstCol;
769 mxImpl->mnFirstClipRow = nFirstRow;
770 mxImpl->mnLastClipCol = nLastCol;
771 mxImpl->mnLastClipRow = nLastRow;
774 void Array::RemoveClipRange()
776 if( !mxImpl->maCells.empty() )
777 SetClipRange( 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1 );
780 bool Array::IsInClipRange( size_t nCol, size_t nRow ) const
782 DBG_FRAME_CHECK_COLROW( nCol, nRow, "IsInClipRange" );
783 return mxImpl->IsInClipRange( nCol, nRow );
786 Rectangle Array::GetClipRangeRectangle() const
788 return Rectangle(
789 mxImpl->GetColPosition( mxImpl->mnFirstClipCol ),
790 mxImpl->GetRowPosition( mxImpl->mnFirstClipRow ),
791 mxImpl->GetColPosition( mxImpl->mnLastClipCol + 1 ),
792 mxImpl->GetRowPosition( mxImpl->mnLastClipRow + 1 ) );
795 // cell coordinates -----------------------------------------------------------
797 void Array::SetXOffset( long nXOffset )
799 mxImpl->maXCoords[ 0 ] = nXOffset;
800 mxImpl->mbXCoordsDirty = true;
803 void Array::SetYOffset( long nYOffset )
805 mxImpl->maYCoords[ 0 ] = nYOffset;
806 mxImpl->mbYCoordsDirty = true;
809 void Array::SetColWidth( size_t nCol, long nWidth )
811 DBG_FRAME_CHECK_COL( nCol, "SetColWidth" );
812 mxImpl->maWidths[ nCol ] = nWidth;
813 mxImpl->mbXCoordsDirty = true;
816 void Array::SetRowHeight( size_t nRow, long nHeight )
818 DBG_FRAME_CHECK_ROW( nRow, "SetRowHeight" );
819 mxImpl->maHeights[ nRow ] = nHeight;
820 mxImpl->mbYCoordsDirty = true;
823 void Array::SetAllColWidths( long nWidth )
825 std::fill( mxImpl->maWidths.begin(), mxImpl->maWidths.end(), nWidth );
826 mxImpl->mbXCoordsDirty = true;
829 void Array::SetAllRowHeights( long nHeight )
831 std::fill( mxImpl->maHeights.begin(), mxImpl->maHeights.end(), nHeight );
832 mxImpl->mbYCoordsDirty = true;
835 long Array::GetColPosition( size_t nCol ) const
837 DBG_FRAME_CHECK_COL_1( nCol, "GetColPosition" );
838 return mxImpl->GetColPosition( nCol );
841 long Array::GetRowPosition( size_t nRow ) const
843 DBG_FRAME_CHECK_ROW_1( nRow, "GetRowPosition" );
844 return mxImpl->GetRowPosition( nRow );
847 long Array::GetColWidth( size_t nCol ) const
849 DBG_FRAME_CHECK_COL( nCol, "GetColWidth" );
850 return mxImpl->maWidths[ nCol ];
853 long Array::GetColWidth( size_t nFirstCol, size_t nLastCol ) const
855 DBG_FRAME_CHECK_COL( nFirstCol, "GetColWidth" );
856 DBG_FRAME_CHECK_COL( nLastCol, "GetColWidth" );
857 return GetColPosition( nLastCol + 1 ) - GetColPosition( nFirstCol );
860 long Array::GetRowHeight( size_t nRow ) const
862 DBG_FRAME_CHECK_ROW( nRow, "GetRowHeight" );
863 return mxImpl->maHeights[ nRow ];
866 long Array::GetRowHeight( size_t nFirstRow, size_t nLastRow ) const
868 DBG_FRAME_CHECK_ROW( nFirstRow, "GetRowHeight" );
869 DBG_FRAME_CHECK_ROW( nLastRow, "GetRowHeight" );
870 return GetRowPosition( nLastRow + 1 ) - GetRowPosition( nFirstRow );
873 long Array::GetWidth() const
875 return GetColPosition( mxImpl->mnWidth ) - GetColPosition( 0 );
878 long Array::GetHeight() const
880 return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
883 Point Array::GetCellPosition( size_t nCol, size_t nRow, bool bSimple ) const
885 size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
886 size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
887 return Point( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
890 Size Array::GetCellSize( size_t nCol, size_t nRow, bool bSimple ) const
892 size_t nFirstCol = bSimple ? nCol : mxImpl->GetMergedFirstCol( nCol, nRow );
893 size_t nFirstRow = bSimple ? nRow : mxImpl->GetMergedFirstRow( nCol, nRow );
894 size_t nLastCol = bSimple ? nCol : mxImpl->GetMergedLastCol( nCol, nRow );
895 size_t nLastRow = bSimple ? nRow : mxImpl->GetMergedLastRow( nCol, nRow );
896 return Size( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
899 Rectangle Array::GetCellRect( size_t nCol, size_t nRow, bool bSimple ) const
901 Rectangle aRect( GetCellPosition( nCol, nRow, bSimple ), GetCellSize( nCol, nRow, bSimple ) );
903 // adjust rectangle for partly visible merged cells
904 const Cell& rCell = CELL( nCol, nRow );
905 if( !bSimple && rCell.IsMerged() )
907 aRect.Left() -= rCell.mnAddLeft;
908 aRect.Right() += rCell.mnAddRight;
909 aRect.Top() -= rCell.mnAddTop;
910 aRect.Bottom() += rCell.mnAddBottom;
912 return aRect;
915 // diagonal frame borders -----------------------------------------------------
917 double Array::GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
919 DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetHorDiagAngle" );
920 return mxImpl->GetHorDiagAngle( nCol, nRow, bSimple );
923 double Array::GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple ) const
925 DBG_FRAME_CHECK_COLROW( nCol, nRow, "GetVerDiagAngle" );
926 return mxImpl->GetVerDiagAngle( nCol, nRow, bSimple );
929 void Array::SetUseDiagDoubleClipping( bool bSet )
931 mxImpl->mbDiagDblClip = bSet;
934 bool Array::GetUseDiagDoubleClipping() const
936 return mxImpl->mbDiagDblClip;
939 // mirroring ------------------------------------------------------------------
941 void Array::MirrorSelfX( bool bMirrorStyles, bool bSwapDiag )
943 CellVec aNewCells;
944 aNewCells.reserve( GetCellCount() );
946 size_t nCol, nRow;
947 for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
949 for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
951 aNewCells.push_back( CELL( mxImpl->GetMirrorCol( nCol ), nRow ) );
952 aNewCells.back().MirrorSelfX( bMirrorStyles, bSwapDiag );
955 for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
957 for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
959 if( CELL( nCol, nRow ).mbMergeOrig )
961 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
962 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
963 lclSetMergedRange( aNewCells, mxImpl->mnWidth,
964 mxImpl->GetMirrorCol( nLastCol ), nRow,
965 mxImpl->GetMirrorCol( nCol ), nLastRow );
969 mxImpl->maCells.swap( aNewCells );
971 std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
972 mxImpl->mbXCoordsDirty = true;
975 void Array::MirrorSelfY( bool bMirrorStyles, bool bSwapDiag )
977 CellVec aNewCells;
978 aNewCells.reserve( GetCellCount() );
980 size_t nCol, nRow;
981 for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
983 for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
985 aNewCells.push_back( CELL( nCol, mxImpl->GetMirrorRow( nRow ) ) );
986 aNewCells.back().MirrorSelfY( bMirrorStyles, bSwapDiag );
989 for( nRow = 0; nRow < mxImpl->mnHeight; ++nRow )
991 for( nCol = 0; nCol < mxImpl->mnWidth; ++nCol )
993 if( CELL( nCol, nRow ).mbMergeOrig )
995 size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
996 size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
997 lclSetMergedRange( aNewCells, mxImpl->mnWidth,
998 nCol, mxImpl->GetMirrorRow( nLastRow ),
999 nLastCol, mxImpl->GetMirrorRow( nRow ) );
1003 mxImpl->maCells.swap( aNewCells );
1005 std::reverse( mxImpl->maHeights.begin(), mxImpl->maHeights.end() );
1006 mxImpl->mbYCoordsDirty = true;
1009 // drawing --------------------------------------------------------------------
1011 void Array::DrawCell( OutputDevice& rDev, size_t nCol, size_t nRow, const Color* pForceColor ) const
1013 DrawRange( rDev, nCol, nRow, nCol, nRow, pForceColor );
1016 void Array::DrawRange( OutputDevice& rDev,
1017 size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
1018 const Color* pForceColor ) const
1020 DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
1021 DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
1023 size_t nCol, nRow;
1025 // *** diagonal frame borders ***
1027 // set clipping region to clip partly visible merged cells
1028 rDev.Push( PUSH_CLIPREGION );
1029 rDev.IntersectClipRegion( GetClipRangeRectangle() );
1030 for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
1032 for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
1034 const Cell& rCell = CELL( nCol, nRow );
1035 bool bOverlapX = rCell.mbOverlapX;
1036 bool bOverlapY = rCell.mbOverlapY;
1037 bool bFirstCol = nCol == nFirstCol;
1038 bool bFirstRow = nRow == nFirstRow;
1039 if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
1040 (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
1042 Rectangle aRect( GetCellRect( nCol, nRow ) );
1043 if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
1045 size_t _nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
1046 size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
1047 size_t _nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
1048 size_t _nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
1050 DrawDiagFrameBorders( rDev, aRect,
1051 GetCellStyleTLBR( _nFirstCol, _nFirstRow, true ), GetCellStyleBLTR( _nFirstCol, _nFirstRow, true ),
1052 GetCellStyleLeft( _nFirstCol, _nFirstRow ), GetCellStyleTop( _nFirstCol, _nFirstRow ),
1053 GetCellStyleRight( _nLastCol, _nLastRow ), GetCellStyleBottom( _nLastCol, _nLastRow ),
1054 GetCellStyleLeft( _nFirstCol, _nLastRow ), GetCellStyleBottom( _nFirstCol, _nLastRow ),
1055 GetCellStyleRight( _nLastCol, _nFirstRow ), GetCellStyleTop( _nLastCol, _nFirstRow ),
1056 pForceColor, mxImpl->mbDiagDblClip );
1061 rDev.Pop(); // clip region
1063 // *** horizontal frame borders ***
1065 for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
1067 double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
1068 double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
1070 // *Start*** variables store the data of the left end of the cached frame border
1071 Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
1072 const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
1073 DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
1074 const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
1075 const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
1076 const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
1077 DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
1079 // *End*** variables store the data of the right end of the cached frame border
1080 DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
1081 const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
1082 const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
1083 const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
1084 DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
1086 for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
1088 fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
1089 fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
1091 const Style& rCurr = *pEndRFromR;
1093 DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
1094 const Style& rLFromT = *pEndRFromT;
1095 const Style& rLFromL = *pStart;
1096 const Style& rLFromB = *pEndRFromB;
1097 DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
1099 DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
1100 const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
1101 const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
1102 const Style& rRFromB = GetCellStyleRight( nCol, nRow );
1103 DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
1105 // check if current frame border can be connected to cached frame border
1106 if( !CheckFrameBorderConnectable( *pStart, rCurr,
1107 aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
1109 // draw previous frame border
1110 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
1111 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
1112 DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
1113 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
1114 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
1116 // re-init "*Start***" variables
1117 aStartPos = aEndPos;
1118 pStart = &rCurr;
1119 aStartLFromTR = aLFromTR;
1120 pStartLFromT = &rLFromT;
1121 pStartLFromL = &rLFromL;
1122 pStartLFromB = &rLFromB;
1123 aStartLFromBR = aLFromBR;
1126 // store current styles in "*End***" variables
1127 aEndRFromTL = aRFromTL;
1128 pEndRFromT = &rRFromT;
1129 pEndRFromR = &rRFromR;
1130 pEndRFromB = &rRFromB;
1131 aEndRFromBL = aRFromBL;
1134 // draw last frame border
1135 Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
1136 if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
1137 DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
1138 aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
1139 aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor );
1142 // *** vertical frame borders ***
1144 for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
1146 double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
1147 double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
1149 // *Start*** variables store the data of the top end of the cached frame border
1150 Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
1151 const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
1152 DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
1153 const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
1154 const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
1155 const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
1156 DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
1158 // *End*** variables store the data of the bottom end of the cached frame border
1159 DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
1160 const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
1161 const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
1162 const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
1163 DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
1165 for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
1167 fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
1168 fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
1170 const Style& rCurr = *pEndBFromB;
1172 DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
1173 const Style& rTFromL = *pEndBFromL;
1174 const Style& rTFromT = *pStart;
1175 const Style& rTFromR = *pEndBFromR;
1176 DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
1178 DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
1179 const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
1180 const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
1181 const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
1182 DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
1184 // check if current frame border can be connected to cached frame border
1185 if( !CheckFrameBorderConnectable( *pStart, rCurr,
1186 aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
1188 // draw previous frame border
1189 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
1190 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
1191 DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
1192 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
1193 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
1195 // re-init "*Start***" variables
1196 aStartPos = aEndPos;
1197 pStart = &rCurr;
1198 aStartTFromBL = aTFromBL;
1199 pStartTFromL = &rTFromL;
1200 pStartTFromT = &rTFromT;
1201 pStartTFromR = &rTFromR;
1202 aStartTFromBR = aTFromBR;
1205 // store current styles in "*End***" variables
1206 aEndBFromTL = aBFromTL;
1207 pEndBFromL = &rBFromL;
1208 pEndBFromB = &rBFromB;
1209 pEndBFromR = &rBFromR;
1210 aEndBFromTR = aBFromTR;
1213 // draw last frame border
1214 Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
1215 if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
1216 DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
1217 aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
1218 aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, pForceColor );
1222 void Array::DrawArray( OutputDevice& rDev, const Color* pForceColor ) const
1224 if( mxImpl->mnWidth && mxImpl->mnHeight )
1225 DrawRange( rDev, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, pForceColor );
1228 // ----------------------------------------------------------------------------
1230 #undef ORIGCELLACC
1231 #undef ORIGCELL
1232 #undef CELLACC
1233 #undef CELL
1235 // ----------------------------------------------------------------------------
1237 #undef DBG_FRAME_CHECK_ROW_1
1238 #undef DBG_FRAME_CHECK_COL_1
1239 #undef DBG_FRAME_CHECK_INDEX
1240 #undef DBG_FRAME_CHECK_COLROW
1241 #undef DBG_FRAME_CHECK_ROW
1242 #undef DBG_FRAME_CHECK_COL
1243 #undef DBG_FRAME_CHECK
1244 #undef DBG_FRAME_ERROR
1246 // ============================================================================
1248 } // namespace frame
1249 } // namespace svx