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