1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/embed/EmbedMisc.hpp>
22 #include "scitems.hxx"
23 #include <editeng/boxitem.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/editdata.hxx>
26 #include <svtools/colorcfg.hxx>
27 #include <svx/rotmodit.hxx>
28 #include <editeng/shaditem.hxx>
29 #include <editeng/svxfont.hxx>
30 #include <svx/svdoole2.hxx>
31 #include <tools/poly.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/pdfextoutdevdata.hxx>
34 #include <svtools/accessibilityoptions.hxx>
35 #include <svx/framelinkarray.hxx>
36 #include <drawinglayer/geometry/viewinformation2d.hxx>
37 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
38 #include <basegfx/matrix/b2dhommatrix.hxx>
39 #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
40 #include <vcl/lineinfo.hxx>
41 #include <vcl/gradient.hxx>
42 #include <vcl/settings.hxx>
43 #include <svx/unoapi.hxx>
46 #include "document.hxx"
47 #include "drwlayer.hxx"
48 #include "formulacell.hxx"
50 #include "patattr.hxx"
51 #include "docpool.hxx"
52 #include "tabvwsh.hxx"
53 #include "progress.hxx"
54 #include "pagedata.hxx"
55 #include "chgtrack.hxx"
56 #include "chgviset.hxx"
57 #include "viewutil.hxx"
58 #include "gridmerg.hxx"
59 #include "invmerge.hxx"
60 #include "fillinfo.hxx"
62 #include "appoptio.hxx"
65 #include "scresid.hxx"
66 #include "colorscale.hxx"
72 #include <boost/scoped_ptr.hpp>
74 using namespace com::sun::star
;
78 // color for ChangeTracking "by author" as in the writer (swmodul1.cxx)
80 #define SC_AUTHORCOLORCOUNT 9
82 static const ColorData nAuthorColor
[ SC_AUTHORCOLORCOUNT
] = {
83 COL_LIGHTRED
, COL_LIGHTBLUE
, COL_LIGHTMAGENTA
,
84 COL_GREEN
, COL_RED
, COL_BLUE
,
85 COL_BROWN
, COL_MAGENTA
, COL_CYAN
};
87 // Helper class for color assignment to avoid repeated lookups for the same user
89 ScActionColorChanger::ScActionColorChanger( const ScChangeTrack
& rTrack
) :
90 rOpt( SC_MOD()->GetAppOptions() ),
91 rUsers( rTrack
.GetUserCollection() ),
97 void ScActionColorChanger::Update( const ScChangeAction
& rAction
)
100 switch (rAction
.GetType())
102 case SC_CAT_INSERT_COLS
:
103 case SC_CAT_INSERT_ROWS
:
104 case SC_CAT_INSERT_TABS
:
105 nSetColor
= rOpt
.GetTrackInsertColor();
107 case SC_CAT_DELETE_COLS
:
108 case SC_CAT_DELETE_ROWS
:
109 case SC_CAT_DELETE_TABS
:
110 nSetColor
= rOpt
.GetTrackDeleteColor();
113 nSetColor
= rOpt
.GetTrackMoveColor();
116 nSetColor
= rOpt
.GetTrackContentColor();
119 if ( nSetColor
!= COL_TRANSPARENT
) // color assigned
123 if (!aLastUserName
.equals(rAction
.GetUser()))
125 aLastUserName
= rAction
.GetUser();
126 std::set
<OUString
>::const_iterator it
= rUsers
.find(aLastUserName
);
127 if (it
== rUsers
.end())
129 // empty string is possible if a name wasn't found while saving a 5.0 file
130 SAL_INFO_IF( aLastUserName
.isEmpty(), "sc.ui", "Author not found" );
135 size_t nPos
= std::distance(rUsers
.begin(), it
);
136 nLastUserIndex
= nPos
% SC_AUTHORCOLORCOUNT
;
139 nColor
= nAuthorColor
[nLastUserIndex
];
143 ScOutputData::ScOutputData( OutputDevice
* pNewDev
, ScOutputType eNewType
,
144 ScTableInfo
& rTabInfo
, ScDocument
* pNewDoc
,
145 SCTAB nNewTab
, long nNewScrX
, long nNewScrY
,
146 SCCOL nNewX1
, SCROW nNewY1
, SCCOL nNewX2
, SCROW nNewY2
,
147 double nPixelPerTwipsX
, double nPixelPerTwipsY
,
148 const Fraction
* pZoomX
, const Fraction
* pZoomY
) :
150 mpRefDevice( pNewDev
), // default is output device
151 pFmtDevice( pNewDev
), // default is output device
152 mrTabInfo( rTabInfo
),
153 pRowInfo( rTabInfo
.mpRowInfo
),
154 nArrCount( rTabInfo
.mnArrCount
),
164 mnPPTX( nPixelPerTwipsX
),
165 mnPPTY( nPixelPerTwipsY
),
168 pDrawView( NULL
), // #114135#
173 bSingleGrid( false ),
174 bPagebreakMode( false ),
175 bSolidBackground( false ),
176 mbUseStyleColor( false ),
177 mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
178 mbSyntaxMode( false ),
181 pFormulaColor( NULL
),
182 aGridColor( COL_BLACK
),
183 mbShowNullValues( true ),
184 mbShowFormulas( false ),
185 bShowSpellErrors( false ),
186 bMarkClipped( false ), // sal_False for printer/metafile etc.
188 bAnyRotated( false ),
189 bAnyClipped( false ),
190 mpTargetPaintWindow(NULL
), // #i74769# use SdrPaintWindow direct
191 mpSpellCheckCxt(NULL
)
196 aZoomX
= Fraction(1,1);
200 aZoomY
= Fraction(1,1);
206 mpDoc
->StripHidden( nVisX1
, nVisY1
, nVisX2
, nVisY2
, nTab
);
209 for (SCCOL nX
=nVisX1
; nX
<=nVisX2
; nX
++)
210 nScrW
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
215 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
216 nScrH
+= pRowInfo
[nArrY
].nHeight
;
218 bTabProtected
= mpDoc
->IsTabProtected( nTab
);
219 nTabTextDirection
= mpDoc
->GetEditTextDirection( nTab
);
220 bLayoutRTL
= mpDoc
->IsLayoutRTL( nTab
);
223 ScOutputData::~ScOutputData()
227 delete pFormulaColor
;
230 void ScOutputData::SetSpellCheckContext( const sc::SpellCheckContext
* pCxt
)
232 mpSpellCheckCxt
= pCxt
;
235 void ScOutputData::SetContentDevice( OutputDevice
* pContentDev
)
237 // use pContentDev instead of pDev where used
239 if ( mpRefDevice
== mpDev
)
240 mpRefDevice
= pContentDev
;
241 if ( pFmtDevice
== mpDev
)
242 pFmtDevice
= pContentDev
;
246 void ScOutputData::SetMirrorWidth( long nNew
)
251 void ScOutputData::SetGridColor( const Color
& rColor
)
256 void ScOutputData::SetMarkClipped( bool bSet
)
261 void ScOutputData::SetShowNullValues( bool bSet
)
263 mbShowNullValues
= bSet
;
266 void ScOutputData::SetShowFormulas( bool bSet
)
268 mbShowFormulas
= bSet
;
271 void ScOutputData::SetShowSpellErrors( bool bSet
)
273 bShowSpellErrors
= bSet
;
276 void ScOutputData::SetSnapPixel( bool bSet
)
281 void ScOutputData::SetEditCell( SCCOL nCol
, SCROW nRow
)
288 void ScOutputData::SetMetaFileMode( bool bNewMode
)
290 bMetaFile
= bNewMode
;
293 void ScOutputData::SetSingleGrid( bool bNewMode
)
295 bSingleGrid
= bNewMode
;
298 void ScOutputData::SetSyntaxMode( bool bNewMode
)
300 mbSyntaxMode
= bNewMode
;
304 pValueColor
= new Color( COL_LIGHTBLUE
);
305 pTextColor
= new Color( COL_BLACK
);
306 pFormulaColor
= new Color( COL_GREEN
);
310 void ScOutputData::DrawGrid( bool bGrid
, bool bPage
)
317 ScBreakType nBreak
= BREAK_NONE
;
318 ScBreakType nBreakOld
= BREAK_NONE
;
325 bPage
= false; // no "normal" breaks over the whole width/height
327 //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
328 //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
330 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
331 long nOneX
= aOnePixel
.Width();
332 long nOneY
= aOnePixel
.Height();
336 long nLayoutSign
= bLayoutRTL
? -1 : 1;
337 long nSignedOneX
= nOneX
* nLayoutSign
;
339 if ( eType
== OUTTYPE_WINDOW
)
341 const svtools::ColorConfig
& rColorCfg
= SC_MOD()->GetColorConfig();
342 aPageColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC
).nColor
);
343 aManualColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKMANUAL
).nColor
);
347 aPageColor
= aGridColor
;
348 aManualColor
= aGridColor
;
351 mpDev
->SetLineColor( aGridColor
);
352 ScGridMerger
aGrid( mpDev
, nOneX
, nOneY
);
358 nPosX
+= nMirrorW
- nOneX
;
360 for (nX
=nX1
; nX
<=nX2
; nX
++)
362 SCCOL nXplus1
= nX
+1;
363 SCCOL nXplus2
= nX
+2;
364 sal_uInt16 nWidth
= pRowInfo
[0].pCellInfo
[nXplus1
].nWidth
;
367 nPosX
+= nWidth
* nLayoutSign
;
371 // Seitenumbrueche auch in ausgeblendeten suchen
372 SCCOL nCol
= nXplus1
;
373 while (nCol
<= MAXCOL
)
375 nBreak
= mpDoc
->HasColBreak(nCol
, nTab
);
376 bool bHidden
= mpDoc
->ColHidden(nCol
, nTab
);
378 if ( nBreak
|| !bHidden
)
383 if (nBreak
!= nBreakOld
)
386 mpDev
->SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
387 nBreak
? aPageColor
: aGridColor
);
392 bool bDraw
= bGrid
|| nBreakOld
; // simple grid only if set that way
394 sal_uInt16 nWidthXplus2
= pRowInfo
[0].pCellInfo
[nXplus2
].nWidth
;
395 bSingle
= bSingleGrid
; //! get into Fillinfo !!!!!
396 if ( nX
<MAXCOL
&& !bSingle
)
398 bSingle
= ( nWidthXplus2
== 0 );
399 for (nArrY
=1; nArrY
+1<nArrCount
&& !bSingle
; nArrY
++)
401 if (pRowInfo
[nArrY
].pCellInfo
[nXplus2
].bHOverlapped
)
403 if (pRowInfo
[nArrY
].pCellInfo
[nXplus1
].bHideGrid
)
410 if ( nX
<MAXCOL
&& bSingle
)
412 SCCOL nVisX
= nXplus1
;
413 while ( nVisX
< MAXCOL
&& !mpDoc
->GetColWidth(nVisX
,nTab
) )
417 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
419 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
420 const long nNextY
= nPosY
+ pThisRowInfo
->nHeight
;
422 bool bHOver
= pThisRowInfo
->pCellInfo
[nXplus1
].bHideGrid
;
426 bHOver
= pThisRowInfo
->pCellInfo
[nXplus2
].bHOverlapped
;
430 bHOver
= pThisRowInfo
->pCellInfo
[nVisX
+1].bHOverlapped
;
432 bHOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
433 nVisX
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
436 bHOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
437 nXplus1
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
442 if (pThisRowInfo
->bChanged
&& !bHOver
)
444 aGrid
.AddVerLine( nPosX
-nSignedOneX
, nPosY
, nNextY
-nOneY
);
451 aGrid
.AddVerLine( nPosX
-nSignedOneX
, nScrY
, nScrY
+nScrH
-nOneY
);
459 bool bHiddenRow
= true;
460 SCROW nHiddenEndRow
= -1;
462 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
464 SCSIZE nArrYplus1
= nArrY
+1;
465 nY
= pRowInfo
[nArrY
].nRowNo
;
466 SCROW nYplus1
= nY
+1;
467 nPosY
+= pRowInfo
[nArrY
].nHeight
;
469 if (pRowInfo
[nArrY
].bChanged
)
473 for (SCROW i
= nYplus1
; i
<= MAXROW
; ++i
)
475 if (i
> nHiddenEndRow
)
476 bHiddenRow
= mpDoc
->RowHidden(i
, nTab
, NULL
, &nHiddenEndRow
);
477 /* TODO: optimize the row break thing for large hidden
478 * segments where HasRowBreak() has to be called
479 * nevertheless for each row, as a row break is drawn also
480 * for hidden rows, above them. This needed to be done only
481 * once per hidden segment, maybe giving manual breaks
482 * priority. Something like GetNextRowBreak() and
483 * GetNextManualRowBreak(). */
484 nBreak
= mpDoc
->HasRowBreak(i
, nTab
);
485 if (!bHiddenRow
|| nBreak
)
489 if (nBreakOld
!= nBreak
)
492 mpDev
->SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
493 (nBreak
) ? aPageColor
: aGridColor
);
498 bool bDraw
= bGrid
|| nBreakOld
; // simple grid only if set so
500 bool bNextYisNextRow
= (pRowInfo
[nArrYplus1
].nRowNo
== nYplus1
);
501 bSingle
= !bNextYisNextRow
; // Hidden
502 for (SCCOL i
=nX1
; i
<=nX2
&& !bSingle
; i
++)
504 if (pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
)
510 if ( bSingle
&& nY
<MAXROW
)
512 SCROW nVisY
= pRowInfo
[nArrYplus1
].nRowNo
;
516 nPosX
+= nMirrorW
- nOneX
;
518 for (SCCOL i
=nX1
; i
<=nX2
; i
++)
520 const long nNextX
= nPosX
+ pRowInfo
[0].pCellInfo
[i
+1].nWidth
* nLayoutSign
;
521 if (nNextX
!= nPosX
) // visible
524 if ( bNextYisNextRow
)
525 bVOver
= pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
;
528 bVOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
529 i
,nYplus1
,nTab
,ATTR_MERGE_FLAG
))
531 && static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
532 i
,nVisY
,nTab
,ATTR_MERGE_FLAG
))
534 //! nVisY from Array ??
538 aGrid
.AddHorLine( nPosX
, nNextX
-nSignedOneX
, nPosY
-nOneY
);
546 aGrid
.AddHorLine( nScrX
, nScrX
+nScrW
-nOneX
, nPosY
-nOneY
);
553 void ScOutputData::SetPagebreakMode( ScPageBreakData
* pPageData
)
555 bPagebreakMode
= true;
557 return; // not yet initialized -> everything "not printed"
559 // mark printed range
560 // (everything in FillInfo is already initialized to sal_False)
562 sal_uInt16 nRangeCount
= sal::static_int_cast
<sal_uInt16
>(pPageData
->GetCount());
563 for (sal_uInt16 nPos
=0; nPos
<nRangeCount
; nPos
++)
565 ScRange aRange
= pPageData
->GetData( nPos
).GetPrintRange();
567 SCCOL nStartX
= std::max( aRange
.aStart
.Col(), nX1
);
568 SCCOL nEndX
= std::min( aRange
.aEnd
.Col(), nX2
);
569 SCROW nStartY
= std::max( aRange
.aStart
.Row(), nY1
);
570 SCROW nEndY
= std::min( aRange
.aEnd
.Row(), nY2
);
572 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
574 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
575 if ( pThisRowInfo
->bChanged
&& pThisRowInfo
->nRowNo
>= nStartY
&&
576 pThisRowInfo
->nRowNo
<= nEndY
)
578 for (SCCOL nX
=nStartX
; nX
<=nEndX
; nX
++)
579 pThisRowInfo
->pCellInfo
[nX
+1].bPrinted
= true;
585 void ScOutputData::FindRotated()
589 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
590 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
591 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
593 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
595 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
596 if ( pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
&&
597 ( pThisRowInfo
->bChanged
|| pRowInfo
[nArrY
-1].bChanged
||
598 ( nArrY
+1<nArrCount
&& pRowInfo
[nArrY
+1].bChanged
) ) )
600 SCROW nY
= pThisRowInfo
->nRowNo
;
602 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
604 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
605 const ScPatternAttr
* pPattern
= pInfo
->pPatternAttr
;
606 const SfxItemSet
* pCondSet
= pInfo
->pConditionSet
;
608 if ( !pPattern
&& !mpDoc
->ColHidden(nX
, nTab
) )
610 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
611 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
614 if ( pPattern
) // column isn't hidden
616 sal_uInt8 nDir
= pPattern
->GetRotateDir( pCondSet
);
617 if (nDir
!= SC_ROTDIR_NONE
)
619 pInfo
->nRotateDir
= nDir
;
628 static sal_uInt16
lcl_GetRotateDir( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
630 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
631 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
633 sal_uInt16 nRet
= SC_ROTDIR_NONE
;
635 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
638 SvxRotateMode eRotMode
= (SvxRotateMode
)static_cast<const SvxRotateModeItem
&>(
639 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
641 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
642 nRet
= SC_ROTDIR_STANDARD
;
643 else if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
644 nRet
= SC_ROTDIR_CENTER
;
645 else if ( eRotMode
== SVX_ROTATE_MODE_TOP
|| eRotMode
== SVX_ROTATE_MODE_BOTTOM
)
647 long nRot180
= nAttrRotate
% 18000; // 1/100 degree
648 if ( nRot180
== 9000 )
649 nRet
= SC_ROTDIR_CENTER
;
650 else if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nRot180
< 9000 ) ||
651 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nRot180
> 9000 ) )
652 nRet
= SC_ROTDIR_LEFT
;
654 nRet
= SC_ROTDIR_RIGHT
;
661 static const SvxBrushItem
* lcl_FindBackground( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
663 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
664 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
665 const SvxBrushItem
* pBackground
= static_cast<const SvxBrushItem
*>(
666 &pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
668 sal_uInt16 nDir
= lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
);
670 // treat CENTER like RIGHT
671 if ( nDir
== SC_ROTDIR_RIGHT
|| nDir
== SC_ROTDIR_CENTER
)
673 // text goes to the right -> take background from the left
674 while ( nCol
> 0 && lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
675 pBackground
->GetColor().GetTransparency() != 255 )
678 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
679 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
680 pBackground
= static_cast<const SvxBrushItem
*>(&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
683 else if ( nDir
== SC_ROTDIR_LEFT
)
685 // text goes to the left -> take background from the right
686 while ( nCol
< MAXCOL
&& lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
687 pBackground
->GetColor().GetTransparency() != 255 )
690 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
691 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
692 pBackground
= static_cast<const SvxBrushItem
*>(&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
699 static bool lcl_EqualBack( const RowInfo
& rFirst
, const RowInfo
& rOther
,
700 SCCOL nX1
, SCCOL nX2
, bool bShowProt
, bool bPagebreakMode
)
702 if ( rFirst
.bChanged
!= rOther
.bChanged
||
703 rFirst
.bEmptyBack
!= rOther
.bEmptyBack
)
709 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
711 const ScPatternAttr
* pPat1
= rFirst
.pCellInfo
[nX
+1].pPatternAttr
;
712 const ScPatternAttr
* pPat2
= rOther
.pCellInfo
[nX
+1].pPatternAttr
;
713 if ( !pPat1
|| !pPat2
||
714 &pPat1
->GetItem(ATTR_PROTECTION
) != &pPat2
->GetItem(ATTR_PROTECTION
) )
720 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
721 if ( rFirst
.pCellInfo
[nX
+1].pBackground
!= rOther
.pCellInfo
[nX
+1].pBackground
)
725 if ( rFirst
.nRotMaxCol
!= SC_ROTMAX_NONE
|| rOther
.nRotMaxCol
!= SC_ROTMAX_NONE
)
726 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
727 if ( rFirst
.pCellInfo
[nX
+1].nRotateDir
!= rOther
.pCellInfo
[nX
+1].nRotateDir
)
730 if ( bPagebreakMode
)
731 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
732 if ( rFirst
.pCellInfo
[nX
+1].bPrinted
!= rOther
.pCellInfo
[nX
+1].bPrinted
)
735 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
737 const Color
* pCol1
= rFirst
.pCellInfo
[nX
+1].pColorScale
.get();
738 const Color
* pCol2
= rOther
.pCellInfo
[nX
+1].pColorScale
.get();
739 if( (pCol1
&& !pCol2
) || (!pCol1
&& pCol2
) )
742 if (pCol1
&& (*pCol1
!= *pCol2
))
745 const ScDataBarInfo
* pInfo1
= rFirst
.pCellInfo
[nX
+1].pDataBar
.get();
746 const ScDataBarInfo
* pInfo2
= rOther
.pCellInfo
[nX
+1].pDataBar
.get();
748 if( (pInfo1
&& !pInfo2
) || (!pInfo1
&& pInfo2
) )
751 if (pInfo1
&& (*pInfo1
!= *pInfo2
))
754 // each cell with an icon set should be painted the same way
755 const ScIconSetInfo
* pIconSet1
= rFirst
.pCellInfo
[nX
+1].pIconSet
.get();
756 const ScIconSetInfo
* pIconSet2
= rOther
.pCellInfo
[nX
+1].pIconSet
.get();
758 if(pIconSet1
|| pIconSet2
)
765 void ScOutputData::DrawDocumentBackground()
767 if ( !bSolidBackground
)
770 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
771 long nOneX
= aOnePixel
.Width();
772 long nOneY
= aOnePixel
.Height();
773 Rectangle
aRect(nScrX
- nOneX
, nScrY
- nOneY
, nScrX
+ nScrW
, nScrY
+ nScrH
);
774 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
775 mpDev
->SetFillColor(aBgColor
);
776 mpDev
->DrawRect(aRect
);
781 static const double lclCornerRectTransparency
= 40.0;
783 void drawDataBars( const ScDataBarInfo
* pOldDataBarInfo
, vcl::RenderContext
* pDev
, const Rectangle
& rRect
)
786 Rectangle aPaintRect
= rRect
;
787 aPaintRect
.Top() += 2;
788 aPaintRect
.Bottom() -= 2;
789 aPaintRect
.Left() += 2;
790 aPaintRect
.Right() -= 2;
791 if(pOldDataBarInfo
->mnZero
)
793 // need to calculate null point in cell
794 long nLength
= aPaintRect
.Right() - aPaintRect
.Left();
795 nPosZero
= static_cast<long>(aPaintRect
.Left() + nLength
*pOldDataBarInfo
->mnZero
/100.0);
799 nPosZero
= aPaintRect
.Left();
802 if(pOldDataBarInfo
->mnLength
< 0)
804 aPaintRect
.Right() = nPosZero
;
805 long nLength
= nPosZero
- aPaintRect
.Left();
806 aPaintRect
.Left() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
808 else if(pOldDataBarInfo
->mnLength
> 0)
810 aPaintRect
.Left() = nPosZero
;
811 long nLength
= aPaintRect
.Right() - nPosZero
;
812 aPaintRect
.Right() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
817 if(pOldDataBarInfo
->mbGradient
)
819 pDev
->SetLineColor(pOldDataBarInfo
->maColor
);
820 Gradient
aGradient(GradientStyle_LINEAR
, pOldDataBarInfo
->maColor
, COL_TRANSPARENT
);
822 if(pOldDataBarInfo
->mnLength
< 0)
823 aGradient
.SetAngle(2700);
825 aGradient
.SetAngle(900);
827 pDev
->DrawGradient(aPaintRect
, aGradient
);
829 pDev
->SetLineColor();
833 pDev
->SetFillColor(pOldDataBarInfo
->maColor
);
834 pDev
->DrawRect(aPaintRect
);
838 if(pOldDataBarInfo
->mnZero
&& pOldDataBarInfo
->mnZero
!= 100)
840 Point
aPoint1(nPosZero
, rRect
.Top());
841 Point
aPoint2(nPosZero
, rRect
.Bottom());
842 LineInfo
aLineInfo(LINE_DASH
, 1);
843 aLineInfo
.SetDashCount( 4 );
844 aLineInfo
.SetDistance( 3 );
845 aLineInfo
.SetDashLen( 3 );
846 pDev
->SetFillColor(pOldDataBarInfo
->maAxisColor
);
847 pDev
->SetLineColor(pOldDataBarInfo
->maAxisColor
);
848 pDev
->DrawLine(aPoint1
, aPoint2
, aLineInfo
);
849 pDev
->SetLineColor();
850 pDev
->SetFillColor();
854 BitmapEx
& getIcon( ScIconSetType eType
, sal_Int32 nIndex
)
856 return ScIconSetFormat::getBitmap( eType
, nIndex
);
859 void drawIconSets( const ScIconSetInfo
* pOldIconSetInfo
, vcl::RenderContext
* pDev
, const Rectangle
& rRect
)
862 ScIconSetType eType
= pOldIconSetInfo
->eIconSetType
;
863 sal_Int32 nIndex
= pOldIconSetInfo
->nIconIndex
;
864 BitmapEx
& rIcon
= getIcon( eType
, nIndex
);
865 long aOrigSize
= std::max
<long>(0,std::min(rRect
.GetSize().getWidth() - 4, rRect
.GetSize().getHeight() -4));
866 pDev
->DrawBitmapEx( Point( rRect
.Left() +2, rRect
.Top() + 2 ), Size(aOrigSize
, aOrigSize
), rIcon
);
869 void drawCells(const Color
* pColor
, const SvxBrushItem
* pBackground
, const Color
*& pOldColor
, const SvxBrushItem
*& pOldBackground
,
870 Rectangle
& rRect
, long nPosX
, long nSignedOneX
, vcl::RenderContext
* pDev
, const ScDataBarInfo
* pDataBarInfo
, const ScDataBarInfo
*& pOldDataBarInfo
,
871 const ScIconSetInfo
* pIconSetInfo
, const ScIconSetInfo
*& pOldIconSetInfo
)
874 // need to paint if old color scale has been used and now
875 // we have a different color or a style based background
876 // we can here fall back to pointer comparison
877 if (pOldColor
&& (pBackground
|| pOldColor
!= pColor
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
))
879 rRect
.Right() = nPosX
-nSignedOneX
;
880 if( !pOldColor
->GetTransparency() )
882 pDev
->SetFillColor( *pOldColor
);
883 pDev
->DrawRect( rRect
);
885 if( pOldDataBarInfo
)
886 drawDataBars( pOldDataBarInfo
, pDev
, rRect
);
887 if( pOldIconSetInfo
)
888 drawIconSets( pOldIconSetInfo
, pDev
, rRect
);
890 rRect
.Left() = nPosX
- nSignedOneX
;
893 if ( pOldBackground
&& (pColor
||pBackground
!= pOldBackground
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
) )
895 rRect
.Right() = nPosX
-nSignedOneX
;
896 if (pOldBackground
) // ==0 if hidden
898 Color aBackCol
= pOldBackground
->GetColor();
899 if ( !aBackCol
.GetTransparency() ) //! partial transparency?
901 pDev
->SetFillColor( aBackCol
);
902 pDev
->DrawRect( rRect
);
905 if( pOldDataBarInfo
)
906 drawDataBars( pOldDataBarInfo
, pDev
, rRect
);
907 if( pOldIconSetInfo
)
908 drawIconSets( pOldIconSetInfo
, pDev
, rRect
);
910 rRect
.Left() = nPosX
- nSignedOneX
;
913 if (!pOldBackground
&& !pOldColor
&& (pDataBarInfo
|| pIconSetInfo
))
915 rRect
.Right() = nPosX
-nSignedOneX
;
916 rRect
.Left() = nPosX
- nSignedOneX
;
921 // only update pOldColor if the colors changed
922 if (!pOldColor
|| *pOldColor
!= *pColor
)
925 pOldBackground
= NULL
;
929 pOldBackground
= pBackground
;
934 pOldDataBarInfo
= pDataBarInfo
;
936 pOldDataBarInfo
= NULL
;
939 pOldIconSetInfo
= pIconSetInfo
;
941 pOldIconSetInfo
= NULL
;
946 void ScOutputData::DrawBackground()
948 FindRotated(); //! from the outside?
951 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
952 long nOneX
= aOnePixel
.Width();
953 long nOneY
= aOnePixel
.Height();
958 long nLayoutSign
= bLayoutRTL
? -1 : 1;
959 long nSignedOneX
= nOneX
* nLayoutSign
;
961 mpDev
->SetLineColor();
963 bool bShowProt
= mbSyntaxMode
&& mpDoc
->IsTabProtected(nTab
);
964 bool bDoAll
= bShowProt
|| bPagebreakMode
|| bSolidBackground
;
966 bool bCellContrast
= mbUseStyleColor
&&
967 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
970 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
972 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
973 long nRowHeight
= pThisRowInfo
->nHeight
;
975 if ( pThisRowInfo
->bChanged
)
977 if ( ( ( pThisRowInfo
->bEmptyBack
) || mbSyntaxMode
) && !bDoAll
)
983 // scan for rows with the same background:
985 while ( nArrY
+nSkip
+2<nArrCount
&&
986 lcl_EqualBack( *pThisRowInfo
, pRowInfo
[nArrY
+nSkip
+1],
987 nX1
, nX2
, bShowProt
, bPagebreakMode
) )
990 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
995 nPosX
+= nMirrorW
- nOneX
;
996 aRect
= Rectangle( nPosX
, nPosY
-nOneY
, nPosX
, nPosY
+nRowHeight
-nOneY
);
998 const SvxBrushItem
* pOldBackground
= NULL
;
999 const SvxBrushItem
* pBackground
;
1000 const Color
* pOldColor
= NULL
;
1001 const ScDataBarInfo
* pOldDataBarInfo
= NULL
;
1002 const ScIconSetInfo
* pOldIconSetInfo
= NULL
;
1003 SCCOL nMergedCells
= 1;
1004 SCCOL nOldMerged
= 0;
1006 for (SCCOL nX
=nX1
; nX
+ nMergedCells
<= nX2
+ 1; nX
+= nOldMerged
)
1008 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+nMergedCells
];
1010 nOldMerged
= nMergedCells
;
1014 // high contrast for cell borders and backgrounds -> empty background
1015 pBackground
= ScGlobal::GetEmptyBrushItem();
1017 else if (bShowProt
) // show cell protection in syntax mode
1019 const ScPatternAttr
* pP
= pInfo
->pPatternAttr
;
1022 const ScProtectionAttr
& rProt
= static_cast<const ScProtectionAttr
&>(
1023 pP
->GetItem(ATTR_PROTECTION
));
1024 if (rProt
.GetProtection() || rProt
.GetHideCell())
1025 pBackground
= ScGlobal::GetProtectedBrushItem();
1027 pBackground
= ScGlobal::GetEmptyBrushItem();
1033 pBackground
= pInfo
->pBackground
;
1035 if ( bPagebreakMode
&& !pInfo
->bPrinted
)
1036 pBackground
= ScGlobal::GetProtectedBrushItem();
1038 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1039 pBackground
->GetColor().GetTransparency() != 255 &&
1042 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
1043 pBackground
= lcl_FindBackground( mpDoc
, nX
, nY
, nTab
);
1046 const Color
* pColor
= pInfo
->pColorScale
.get();
1047 const ScDataBarInfo
* pDataBarInfo
= pInfo
->pDataBar
.get();
1048 const ScIconSetInfo
* pIconSetInfo
= pInfo
->pIconSet
.get();
1049 drawCells( pColor
, pBackground
, pOldColor
, pOldBackground
, aRect
, nPosX
, nSignedOneX
, mpDev
, pDataBarInfo
, pOldDataBarInfo
, pIconSetInfo
, pOldIconSetInfo
);
1051 // extend for all merged cells
1053 if (pInfo
->bMerged
&& pInfo
->pPatternAttr
)
1055 const ScMergeAttr
* pMerge
=
1056 static_cast<const ScMergeAttr
*>(&pInfo
->pPatternAttr
->GetItem(ATTR_MERGE
));
1057 nMergedCells
= std::max
<SCCOL
>(1, pMerge
->GetColMerge());
1060 for (SCCOL nMerged
= 0; nMerged
< nMergedCells
; ++nMerged
)
1062 SCCOL nCol
= nX
+nOldMerged
+nMerged
;
1065 nPosX
+= pRowInfo
[0].pCellInfo
[nCol
].nWidth
* nLayoutSign
;
1068 drawCells( NULL
, NULL
, pOldColor
, pOldBackground
, aRect
, nPosX
, nSignedOneX
, mpDev
, NULL
, pOldDataBarInfo
, NULL
, pOldIconSetInfo
);
1073 nPosY
+= nRowHeight
;
1077 void ScOutputData::DrawShadow()
1079 DrawExtraShadow( false, false, false, false );
1082 void ScOutputData::DrawExtraShadow(bool bLeft
, bool bTop
, bool bRight
, bool bBottom
)
1084 mpDev
->SetLineColor();
1086 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1087 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1088 Color aAutoTextColor
;
1089 if ( bCellContrast
)
1090 aAutoTextColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1092 long nInitPosX
= nScrX
;
1095 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1096 long nOneX
= aOnePixel
.Width();
1097 nInitPosX
+= nMirrorW
- nOneX
;
1099 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1101 long nPosY
= nScrY
- pRowInfo
[0].nHeight
;
1102 for (SCSIZE nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1104 bool bCornerY
= ( nArrY
== 0 ) || ( nArrY
+1 == nArrCount
);
1105 bool bSkipY
= ( nArrY
==0 && !bTop
) || ( nArrY
+1 == nArrCount
&& !bBottom
);
1107 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1108 long nRowHeight
= pThisRowInfo
->nHeight
;
1110 if ( pThisRowInfo
->bChanged
&& !bSkipY
)
1112 long nPosX
= nInitPosX
- pRowInfo
[0].pCellInfo
[nX1
].nWidth
* nLayoutSign
;
1113 for (SCCOL nArrX
=nX1
; nArrX
<=nX2
+2; nArrX
++)
1115 bool bCornerX
= ( nArrX
==nX1
|| nArrX
==nX2
+2 );
1116 bool bSkipX
= ( nArrX
==nX1
&& !bLeft
) || ( nArrX
==nX2
+2 && !bRight
);
1118 for (sal_uInt16 nPass
=0; nPass
<2; nPass
++) // horizontal / vertical
1120 const SvxShadowItem
* pAttr
= nPass
?
1121 pThisRowInfo
->pCellInfo
[nArrX
].pVShadowOrigin
:
1122 pThisRowInfo
->pCellInfo
[nArrX
].pHShadowOrigin
;
1123 if ( pAttr
&& !bSkipX
)
1125 ScShadowPart ePart
= nPass
?
1126 pThisRowInfo
->pCellInfo
[nArrX
].eVShadowPart
:
1127 pThisRowInfo
->pCellInfo
[nArrX
].eHShadowPart
;
1130 if ( (nPass
==0 && bCornerX
) || (nPass
==1 && bCornerY
) )
1131 if ( ePart
!= SC_SHADOW_CORNER
)
1136 long nThisWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1137 long nMaxWidth
= nThisWidth
;
1140 //! direction must depend on shadow location
1141 SCCOL nWx
= nArrX
; // nX+1
1142 while (nWx
<nX2
&& !pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
)
1144 nMaxWidth
= pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
;
1147 // rectangle is in logical orientation
1148 Rectangle
aRect( nPosX
, nPosY
,
1149 nPosX
+ ( nThisWidth
- 1 ) * nLayoutSign
,
1150 nPosY
+ pRowInfo
[nArrY
].nHeight
- 1 );
1152 long nSize
= pAttr
->GetWidth();
1153 long nSizeX
= (long)(nSize
*mnPPTX
);
1154 if (nSizeX
>= nMaxWidth
) nSizeX
= nMaxWidth
-1;
1155 long nSizeY
= (long)(nSize
*mnPPTY
);
1156 if (nSizeY
>= nRowHeight
) nSizeY
= nRowHeight
-1;
1158 nSizeX
*= nLayoutSign
; // used only to add to rectangle values
1160 SvxShadowLocation eLoc
= pAttr
->GetLocation();
1163 // Shadow location is specified as "visual" (right is always right),
1164 // so the attribute's location value is mirrored here and in FillInfo.
1167 case SVX_SHADOW_BOTTOMRIGHT
: eLoc
= SVX_SHADOW_BOTTOMLEFT
; break;
1168 case SVX_SHADOW_BOTTOMLEFT
: eLoc
= SVX_SHADOW_BOTTOMRIGHT
; break;
1169 case SVX_SHADOW_TOPRIGHT
: eLoc
= SVX_SHADOW_TOPLEFT
; break;
1170 case SVX_SHADOW_TOPLEFT
: eLoc
= SVX_SHADOW_TOPRIGHT
; break;
1173 // added to avoid warnings
1178 if (ePart
== SC_SHADOW_HORIZ
|| ePart
== SC_SHADOW_HSTART
||
1179 ePart
== SC_SHADOW_CORNER
)
1181 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1182 aRect
.Top() = aRect
.Bottom() - nSizeY
;
1184 aRect
.Bottom() = aRect
.Top() + nSizeY
;
1186 if (ePart
== SC_SHADOW_VERT
|| ePart
== SC_SHADOW_VSTART
||
1187 ePart
== SC_SHADOW_CORNER
)
1189 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1190 aRect
.Left() = aRect
.Right() - nSizeX
;
1192 aRect
.Right() = aRect
.Left() + nSizeX
;
1194 if (ePart
== SC_SHADOW_HSTART
)
1196 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1197 aRect
.Right() -= nSizeX
;
1199 aRect
.Left() += nSizeX
;
1201 if (ePart
== SC_SHADOW_VSTART
)
1203 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1204 aRect
.Bottom() -= nSizeY
;
1206 aRect
.Top() += nSizeY
;
1209 //! merge rectangles?
1210 mpDev
->SetFillColor( bCellContrast
? aAutoTextColor
: pAttr
->GetColor() );
1211 mpDev
->DrawRect( aRect
);
1216 nPosX
+= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
* nLayoutSign
;
1219 nPosY
+= nRowHeight
;
1223 void ScOutputData::DrawClear()
1226 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1227 long nOneX
= aOnePixel
.Width();
1228 long nOneY
= aOnePixel
.Height();
1230 // (called only for ScGridWindow)
1231 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1236 mpDev
->SetLineColor();
1238 mpDev
->SetFillColor( aBgColor
);
1241 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1243 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1244 long nRowHeight
= pThisRowInfo
->nHeight
;
1246 if ( pThisRowInfo
->bChanged
)
1248 // scan for more rows which must be painted:
1250 while ( nArrY
+nSkip
+2<nArrCount
&& pRowInfo
[nArrY
+nSkip
+1].bChanged
)
1253 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
1256 aRect
= Rectangle( Point( nScrX
, nPosY
),
1257 Size( nScrW
+1-nOneX
, nRowHeight
+1-nOneY
) );
1258 mpDev
->DrawRect( aRect
);
1262 nPosY
+= nRowHeight
;
1268 long lclGetSnappedX( OutputDevice
& rDev
, long nPosX
, bool bSnapPixel
)
1270 return (bSnapPixel
&& nPosX
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( nPosX
, 0 ) ) ).Width() : nPosX
;
1273 long lclGetSnappedY( OutputDevice
& rDev
, long nPosY
, bool bSnapPixel
)
1275 return (bSnapPixel
&& nPosY
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( 0, nPosY
) ) ).Height() : nPosY
;
1278 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX
, sal_uInt16 nCellInfoFirstX
, sal_uInt16 nCellInfoLastX
, bool bRTL
)
1280 return static_cast< size_t >( bRTL
? (nCellInfoLastX
+ 2 - nCellInfoX
) : (nCellInfoX
- nCellInfoFirstX
) );
1283 void ScOutputData::DrawFrame()
1285 DrawModeFlags nOldDrawMode
= mpDev
->GetDrawMode();
1288 bool bUseSingleColor
= false;
1289 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1290 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1292 // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1293 // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1294 // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1295 // must be reset and the border colors handled here.
1297 if ( ( nOldDrawMode
& DrawModeFlags::WhiteFill
) && ( nOldDrawMode
& DrawModeFlags::BlackLine
) )
1299 mpDev
->SetDrawMode( nOldDrawMode
& (~DrawModeFlags::WhiteFill
) );
1300 aSingleColor
.SetColor( COL_BLACK
);
1301 bUseSingleColor
= true;
1303 else if ( ( nOldDrawMode
& DrawModeFlags::SettingsFill
) && ( nOldDrawMode
& DrawModeFlags::SettingsLine
) )
1305 mpDev
->SetDrawMode( nOldDrawMode
& (~DrawModeFlags::SettingsFill
) );
1306 aSingleColor
= rStyleSettings
.GetWindowTextColor(); // same as used in VCL for DrawModeFlags::SettingsLine
1307 bUseSingleColor
= true;
1309 else if ( bCellContrast
)
1311 aSingleColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1312 bUseSingleColor
= true;
1315 const Color
* pForceColor
= bUseSingleColor
? &aSingleColor
: 0;
1318 DrawRotatedFrame( pForceColor
); // removes the lines that must not be painted here
1320 long nInitPosX
= nScrX
;
1323 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1324 long nOneX
= aOnePixel
.Width();
1325 nInitPosX
+= nMirrorW
- nOneX
;
1327 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1329 // *** set column and row sizes of the frame border array ***
1331 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1332 size_t nColCount
= rArray
.GetColCount();
1333 size_t nRowCount
= rArray
.GetRowCount();
1337 // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1338 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1339 long nOldPosY
= nScrY
- 1 - pRowInfo
[ 0 ].nHeight
;
1340 long nOldSnapY
= lclGetSnappedY( *mpDev
, nOldPosY
, bSnapPixel
);
1341 rArray
.SetYOffset( nOldSnapY
);
1342 for( size_t nRow
= 0; nRow
< nRowCount
; ++nRow
)
1344 long nNewPosY
= nOldPosY
+ pRowInfo
[ nRow
].nHeight
;
1345 long nNewSnapY
= lclGetSnappedY( *mpDev
, nNewPosY
, bSnapPixel
);
1346 rArray
.SetRowHeight( nRow
, nNewSnapY
- nOldSnapY
);
1347 nOldPosY
= nNewPosY
;
1348 nOldSnapY
= nNewSnapY
;
1353 // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1354 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1355 long nOldPosX
= nInitPosX
- nLayoutSign
* (1 + pRowInfo
[ 0 ].pCellInfo
[ nX1
].nWidth
);
1356 long nOldSnapX
= lclGetSnappedX( *mpDev
, nOldPosX
, bSnapPixel
);
1357 // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1359 rArray
.SetXOffset( nOldSnapX
);
1360 for( sal_uInt16 nInfoIdx
= nX1
; nInfoIdx
<= nX2
+ 2; ++nInfoIdx
)
1362 size_t nCol
= lclGetArrayColFromCellInfoX( nInfoIdx
, nX1
, nX2
, bLayoutRTL
);
1363 long nNewPosX
= nOldPosX
+ pRowInfo
[ 0 ].pCellInfo
[ nInfoIdx
].nWidth
* nLayoutSign
;
1364 long nNewSnapX
= lclGetSnappedX( *mpDev
, nNewPosX
, bSnapPixel
);
1365 rArray
.SetColWidth( nCol
, std::abs( nNewSnapX
- nOldSnapX
) );
1366 nOldPosX
= nNewPosX
;
1367 nOldSnapX
= nNewSnapX
;
1370 rArray
.SetXOffset( nOldSnapX
);
1372 // *** draw the array ***
1374 size_t nFirstCol
= 1;
1375 size_t nFirstRow
= 1;
1376 size_t nLastCol
= nColCount
- 2;
1377 size_t nLastRow
= nRowCount
- 2;
1379 if( mrTabInfo
.mbPageMode
)
1380 rArray
.SetClipRange( nFirstCol
, nFirstRow
, nLastCol
, nLastRow
);
1382 // draw only rows with set RowInfo::bChanged flag
1383 size_t nRow1
= nFirstRow
;
1384 boost::scoped_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(CreateProcessor2D());
1388 while( nRow1
<= nLastRow
)
1390 while( (nRow1
<= nLastRow
) && !pRowInfo
[ nRow1
].bChanged
) ++nRow1
;
1391 if( nRow1
<= nLastRow
)
1393 size_t nRow2
= nRow1
;
1394 while( (nRow2
+ 1 <= nLastRow
) && pRowInfo
[ nRow2
+ 1 ].bChanged
) ++nRow2
;
1395 rArray
.DrawRange( pProcessor
.get(), nFirstCol
, nRow1
, nLastCol
, nRow2
, pForceColor
);
1401 mpDev
->SetDrawMode(nOldDrawMode
);
1404 // Line below the cell
1406 static const ::editeng::SvxBorderLine
* lcl_FindHorLine( ScDocument
* pDoc
,
1407 SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_uInt16 nRotDir
,
1410 if ( nRotDir
!= SC_ROTDIR_LEFT
&& nRotDir
!= SC_ROTDIR_RIGHT
)
1413 bool bFound
= false;
1416 if ( nRotDir
== SC_ROTDIR_LEFT
)
1418 // text to the left -> line from the right
1419 if ( nCol
< MAXCOL
)
1422 return NULL
; // couldn't find it
1426 // text to the right -> line from the left
1430 return NULL
; // couldn't find it
1432 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
1433 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
1434 if ( !pPattern
->GetRotateVal( pCondSet
) ||
1435 static_cast<const SvxRotateModeItem
&>(pPattern
->GetItem(
1436 ATTR_ROTATE_MODE
, pCondSet
)).GetValue() == SVX_ROTATE_MODE_STANDARD
)
1442 const ::editeng::SvxBorderLine
* pThisBottom
;
1443 if ( ValidRow(nRow
) )
1444 pThisBottom
= static_cast<const SvxBoxItem
*>(pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
))->GetBottom();
1447 const ::editeng::SvxBorderLine
* pNextTop
;
1448 if ( nRow
< MAXROW
)
1449 pNextTop
= static_cast<const SvxBoxItem
*>(pDoc
->GetAttr( nCol
, nRow
+1, nTab
, ATTR_BORDER
))->GetTop();
1453 if ( ScHasPriority( pThisBottom
, pNextTop
) )
1459 static long lcl_getRotate( ScDocument
* pDoc
, SCTAB nTab
, SCCOL nX
, SCROW nY
)
1463 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nX
, nY
, nTab
);
1464 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nX
, nY
, nTab
);
1466 nRotate
= pPattern
->GetRotateVal( pCondSet
);
1471 void ScOutputData::DrawRotatedFrame( const Color
* pForceColor
)
1474 SCCOL nRotMax
= nX2
;
1475 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
1476 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
1477 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
1479 const ScPatternAttr
* pPattern
;
1480 const SfxItemSet
* pCondSet
;
1482 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1483 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1485 // color (pForceColor) is determined externally, including DrawMode changes
1487 long nInitPosX
= nScrX
;
1490 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1491 long nOneX
= aOnePixel
.Width();
1492 nInitPosX
+= nMirrorW
- nOneX
;
1494 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1496 Rectangle
aClipRect( Point(nScrX
, nScrY
), Size(nScrW
, nScrH
) );
1500 mpDev
->IntersectClipRegion( aClipRect
);
1503 mpDev
->SetClipRegion( vcl::Region( aClipRect
) );
1505 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1506 boost::scoped_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(CreateProcessor2D( ));
1509 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
1511 // Rotated is also drawn one line above/below Changed if parts extend into the cell
1513 RowInfo
& rPrevRowInfo
= pRowInfo
[nArrY
-1];
1514 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1515 RowInfo
& rNextRowInfo
= pRowInfo
[nArrY
+1];
1517 size_t nRow
= static_cast< size_t >( nArrY
);
1519 long nRowHeight
= rThisRowInfo
.nHeight
;
1520 if ( rThisRowInfo
.nRotMaxCol
!= SC_ROTMAX_NONE
&&
1521 ( rThisRowInfo
.bChanged
|| rPrevRowInfo
.bChanged
||
1522 ( nArrY
+1<nArrCount
&& rNextRowInfo
.bChanged
) ) )
1524 SCROW nY
= rThisRowInfo
.nRowNo
;
1527 for (nX
=0; nX
<=nRotMax
; nX
++)
1529 if (nX
==nX1
) nPosX
= nInitPosX
; // calculated individually for preceding positions
1531 sal_uInt16 nArrX
= nX
+ 1;
1533 CellInfo
* pInfo
= &rThisRowInfo
.pCellInfo
[nArrX
];
1534 long nColWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1535 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1536 !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
1538 pPattern
= pInfo
->pPatternAttr
;
1539 pCondSet
= pInfo
->pConditionSet
;
1542 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1543 pInfo
->pPatternAttr
= pPattern
;
1544 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
1545 pInfo
->pConditionSet
= pCondSet
;
1548 //! LastPattern etc.
1550 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
1551 SvxRotateMode eRotMode
= (SvxRotateMode
)static_cast<const SvxRotateModeItem
&>(
1552 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
1556 if (nX
<nX1
) // compute negative position
1563 nPosX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
1567 // start position minus 1 so rotated backgrounds suit the border
1568 // (border is on the grid)
1570 long nTop
= nPosY
- 1;
1571 long nBottom
= nPosY
+ nRowHeight
- 1;
1572 long nTopLeft
= nPosX
- nLayoutSign
;
1573 long nTopRight
= nPosX
+ ( nColWidth
- 1 ) * nLayoutSign
;
1574 long nBotLeft
= nTopLeft
;
1575 long nBotRight
= nTopRight
;
1577 // inclusion of the sign here hasn't been decided yet
1578 // (if not, the extension of the non-rotated background must also be changed)
1579 double nRealOrient
= nLayoutSign
* nAttrRotate
* F_PI18000
; // 1/100th degrees
1580 double nCos
= cos( nRealOrient
);
1581 double nSin
= sin( nRealOrient
);
1583 long nSkew
= (long) ( nRowHeight
* nCos
/ nSin
);
1587 case SVX_ROTATE_MODE_BOTTOM
:
1591 case SVX_ROTATE_MODE_CENTER
:
1598 case SVX_ROTATE_MODE_TOP
:
1604 // added to avoid warnings
1609 aPoints
[0] = Point( nTopLeft
, nTop
);
1610 aPoints
[1] = Point( nTopRight
, nTop
);
1611 aPoints
[2] = Point( nBotRight
, nBottom
);
1612 aPoints
[3] = Point( nBotLeft
, nBottom
);
1614 const SvxBrushItem
* pBackground
= pInfo
->pBackground
;
1616 pBackground
= static_cast<const SvxBrushItem
*>( &pPattern
->GetItem(
1617 ATTR_BACKGROUND
, pCondSet
));
1620 // high contrast for cell borders and backgrounds -> empty background
1621 pBackground
= ScGlobal::GetEmptyBrushItem();
1623 if(!pInfo
->pColorScale
)
1625 const Color
& rColor
= pBackground
->GetColor();
1626 if ( rColor
.GetTransparency() != 255 )
1628 // draw background only for the changed row itself
1629 // (background doesn't extend into other cells).
1630 // For the borders (rotated and normal), clipping should be
1631 // set if the row isn't changed, but at least the borders
1632 // don't cover the cell contents.
1633 if ( rThisRowInfo
.bChanged
)
1635 Polygon
aPoly( 4, aPoints
);
1637 // ohne Pen wird bei DrawPolygon rechts und unten
1638 // ein Pixel weggelassen...
1639 if ( rColor
.GetTransparency() == 0 )
1640 mpDev
->SetLineColor(rColor
);
1642 mpDev
->SetLineColor();
1643 mpDev
->SetFillColor(rColor
);
1644 mpDev
->DrawPolygon( aPoly
);
1650 Polygon
aPoly( 4, aPoints
);
1651 const Color
* pColor
= pInfo
->pColorScale
.get();
1653 // ohne Pen wird bei DrawPolygon rechts und unten
1654 // ein Pixel weggelassen...
1655 if ( pColor
->GetTransparency() == 0 )
1656 mpDev
->SetLineColor(*pColor
);
1658 mpDev
->SetLineColor();
1659 mpDev
->SetFillColor(*pColor
);
1660 mpDev
->DrawPolygon( aPoly
);
1664 svx::frame::Style aTopLine
, aBottomLine
, aLeftLine
, aRightLine
;
1666 if ( nX
< nX1
|| nX
> nX2
) // Attribute in FillInfo nicht gesetzt
1668 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
1669 const ::editeng::SvxBorderLine
* pLeftLine
;
1670 const ::editeng::SvxBorderLine
* pTopLine
;
1671 const ::editeng::SvxBorderLine
* pRightLine
;
1672 const ::editeng::SvxBorderLine
* pBottomLine
;
1673 mpDoc
->GetBorderLines( nX
, nY
, nTab
,
1674 &pLeftLine
, &pTopLine
, &pRightLine
, &pBottomLine
);
1675 aTopLine
.Set( pTopLine
, mnPPTY
);
1676 aBottomLine
.Set( pBottomLine
, mnPPTY
);
1677 aLeftLine
.Set( pLeftLine
, mnPPTX
);
1678 aRightLine
.Set( pRightLine
, mnPPTX
);
1682 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1683 aTopLine
= rArray
.GetCellStyleTop( nCol
, nRow
);
1684 aBottomLine
= rArray
.GetCellStyleBottom( nCol
, nRow
);
1685 aLeftLine
= rArray
.GetCellStyleLeft( nCol
, nRow
);
1686 aRightLine
= rArray
.GetCellStyleRight( nCol
, nRow
);
1687 // in RTL mode the array is already mirrored -> swap back left/right borders
1689 std::swap( aLeftLine
, aRightLine
);
1693 if (aTopLine
.Prim() || aTopLine
.Secn())
1695 long nUpperRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
- 1 );
1696 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1697 aPoints
[bLayoutRTL
?1:0], aPoints
[bLayoutRTL
?0:1], aTopLine
,
1698 svx::frame::Style(),
1699 svx::frame::Style(),
1701 svx::frame::Style(),
1702 svx::frame::Style(),
1704 pForceColor
, nUpperRotate
, nAttrRotate
) );
1707 if (aBottomLine
.Prim() || aBottomLine
.Secn())
1709 long nLowerRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
+ 1 );
1710 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1711 aPoints
[bLayoutRTL
?2:3], aPoints
[bLayoutRTL
?3:2], aBottomLine
,
1713 svx::frame::Style(),
1714 svx::frame::Style(),
1716 svx::frame::Style(),
1717 svx::frame::Style(),
1718 pForceColor
, 18000 - nAttrRotate
, 18000 - nLowerRotate
) );
1721 // Vertical slanted lines
1722 if (aLeftLine
.Prim() || aLeftLine
.Secn())
1724 long nLeftRotate
= lcl_getRotate( mpDoc
, nTab
, nX
- 1, nY
);
1725 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1726 aPoints
[0], aPoints
[3], aLeftLine
,
1728 svx::frame::Style(),
1729 svx::frame::Style(),
1731 svx::frame::Style(),
1732 svx::frame::Style(),
1733 pForceColor
, nAttrRotate
, nLeftRotate
) );
1736 if (aRightLine
.Prim() || aRightLine
.Secn())
1738 long nRightRotate
= lcl_getRotate( mpDoc
, nTab
, nX
+ 1, nY
);
1739 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1740 aPoints
[1], aPoints
[2], aRightLine
,
1741 svx::frame::Style(),
1742 svx::frame::Style(),
1744 svx::frame::Style(),
1745 svx::frame::Style(),
1747 pForceColor
, 18000 - nRightRotate
, 18000 - nAttrRotate
) );
1751 nPosX
+= nColWidth
* nLayoutSign
;
1754 // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1756 nX
= nX1
> 0 ? (nX1
-1) : static_cast<SCCOL
>(0);
1757 for (; nX
<=nX2
+1; nX
++) // sichtbarer Teil +- 1
1759 sal_uInt16 nArrX
= nX
+ 1;
1760 CellInfo
& rInfo
= rThisRowInfo
.pCellInfo
[nArrX
];
1761 if ( rInfo
.nRotateDir
> SC_ROTDIR_STANDARD
&&
1762 !rInfo
.bHOverlapped
&& !rInfo
.bVOverlapped
)
1764 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1766 // horizontal: angrenzende Linie verlaengern
1767 // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1768 sal_uInt16 nDir
= rInfo
.nRotateDir
;
1769 if ( rArray
.GetCellStyleTop( nCol
, nRow
).Prim() )
1771 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, true ), mnPPTY
);
1772 rArray
.SetCellStyleTop( nCol
, nRow
, aStyle
);
1774 rArray
.SetCellStyleBottom( nCol
, nRow
- 1, aStyle
);
1776 if ( rArray
.GetCellStyleBottom( nCol
, nRow
).Prim() )
1778 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, false ), mnPPTY
);
1779 rArray
.SetCellStyleBottom( nCol
, nRow
, aStyle
);
1780 if( nRow
+ 1 < rArray
.GetRowCount() )
1781 rArray
.SetCellStyleTop( nCol
, nRow
+ 1, aStyle
);
1784 // always remove vertical borders
1785 if( !rArray
.IsMergedOverlappedLeft( nCol
, nRow
) )
1787 rArray
.SetCellStyleLeft( nCol
, nRow
, svx::frame::Style() );
1789 rArray
.SetCellStyleRight( nCol
- 1, nRow
, svx::frame::Style() );
1791 if( !rArray
.IsMergedOverlappedRight( nCol
, nRow
) )
1793 rArray
.SetCellStyleRight( nCol
, nRow
, svx::frame::Style() );
1794 if( nCol
+ 1 < rArray
.GetColCount() )
1795 rArray
.SetCellStyleLeft( nCol
+ 1, nRow
, svx::frame::Style() );
1798 // remove diagonal borders
1799 rArray
.SetCellStyleTLBR( nCol
, nRow
, svx::frame::Style() );
1800 rArray
.SetCellStyleBLTR( nCol
, nRow
, svx::frame::Style() );
1804 nPosY
+= nRowHeight
;
1812 mpDev
->SetClipRegion();
1815 drawinglayer::processor2d::BaseProcessor2D
* ScOutputData::CreateProcessor2D( )
1817 mpDoc
->InitDrawLayer(mpDoc
->GetDocumentShell());
1818 ScDrawLayer
* pDrawLayer
= mpDoc
->GetDrawLayer();
1822 basegfx::B2DRange aViewRange
;
1823 SdrPage
*pDrawPage
= pDrawLayer
->GetPage( static_cast< sal_uInt16
>( nTab
) );
1824 const drawinglayer::geometry::ViewInformation2D
aNewViewInfos(
1825 basegfx::B2DHomMatrix( ),
1826 mpDev
->GetViewTransformation(),
1828 GetXDrawPageForSdrPage( pDrawPage
),
1830 uno::Sequence
< beans::PropertyValue
>() );
1832 return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1833 *mpDev
, aNewViewInfos
);
1838 vcl::Region
ScOutputData::GetChangedAreaRegion()
1840 vcl::Region aRegion
;
1841 Rectangle aDrawingRect
;
1846 aDrawingRect
.Left() = nScrX
;
1847 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1849 for(nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1851 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1853 if(pThisRowInfo
->bChanged
)
1857 aDrawingRect
.Top() = nPosY
;
1861 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1865 aRegion
.Union(mpDev
->PixelToLogic(aDrawingRect
));
1869 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1874 aRegion
.Union(mpDev
->PixelToLogic(aDrawingRect
));
1880 bool ScOutputData::SetChangedClip()
1882 tools::PolyPolygon aPoly
;
1884 Rectangle aDrawingRect
;
1885 aDrawingRect
.Left() = nScrX
;
1886 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1891 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1893 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1895 if ( pThisRowInfo
->bChanged
)
1899 aDrawingRect
.Top() = nPosY
;
1902 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1906 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1909 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1913 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1915 bool bRet
= (aPoly
.Count() != 0);
1917 mpDev
->SetClipRegion(vcl::Region(aPoly
));
1921 void ScOutputData::FindChanged()
1926 bool bWasIdleEnabled
= mpDoc
->IsIdleEnabled();
1927 mpDoc
->EnableIdle(false);
1928 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1929 pRowInfo
[nArrY
].bChanged
= false;
1931 bool bProgress
= false;
1932 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1934 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1935 for (nX
=nX1
; nX
<=nX2
; nX
++)
1937 const ScRefCellValue
& rCell
= pThisRowInfo
->pCellInfo
[nX
+1].maCell
;
1939 if (rCell
.meType
!= CELLTYPE_FORMULA
)
1942 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
1943 if ( !bProgress
&& pFCell
->GetDirty() )
1945 ScProgress::CreateInterpretProgress(mpDoc
, true);
1948 if (pFCell
->IsRunning())
1949 // still being interpreted. Skip it.
1952 (void)pFCell
->GetValue();
1953 if (!pFCell
->IsChanged())
1954 // the result hasn't changed. Skip it.
1957 pThisRowInfo
->bChanged
= true;
1958 if ( pThisRowInfo
->pCellInfo
[nX
+1].bMerged
)
1960 SCSIZE nOverY
= nArrY
+ 1;
1961 while ( nOverY
<nArrCount
&&
1962 pRowInfo
[nOverY
].pCellInfo
[nX
+1].bVOverlapped
)
1964 pRowInfo
[nOverY
].bChanged
= true;
1971 ScProgress::DeleteInterpretProgress();
1972 mpDoc
->EnableIdle(bWasIdleEnabled
);
1975 void ScOutputData::DrawRefMark( SCCOL nRefStartX
, SCROW nRefStartY
,
1976 SCCOL nRefEndX
, SCROW nRefEndY
,
1977 const Color
& rColor
, bool bHandle
)
1979 PutInOrder( nRefStartX
, nRefEndX
);
1980 PutInOrder( nRefStartY
, nRefEndY
);
1982 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
1983 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
1985 if ( nRefStartX
<= nVisX2
&& nRefEndX
>= nVisX1
&&
1986 nRefStartY
<= nVisY2
&& nRefEndY
>= nVisY1
)
1990 long nMaxX
= nScrX
+ nScrW
- 1;
1991 long nMaxY
= nScrY
+ nScrH
- 1;
1998 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2001 bool bBottom
= false;
2003 bool bRight
= false;
2006 bool bNoStartY
= ( nY1
< nRefStartY
);
2007 bool bNoEndY
= false;
2008 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2010 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2012 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2019 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 2;
2022 if ( nY
>nRefEndY
&& bNoEndY
)
2027 bNoStartY
= ( nY
< nRefStartY
);
2028 bNoEndY
= ( nY
< nRefEndY
);
2029 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2034 nPosX
+= nMirrorW
- 1; // always in pixels
2036 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2038 if ( nX
==nRefStartX
)
2045 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 2 ) * nLayoutSign
;
2048 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2051 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2054 mpDev
->SetLineColor( rColor
);
2055 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2057 mpDev
->SetFillColor();
2058 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2063 mpDev
->DrawLine( Point( nMinX
, nMinY
), Point( nMaxX
, nMinY
) );
2065 mpDev
->DrawLine( Point( nMinX
, nMaxY
), Point( nMaxX
, nMaxY
) );
2067 mpDev
->DrawLine( Point( nMinX
, nMinY
), Point( nMinX
, nMaxY
) );
2069 mpDev
->DrawLine( Point( nMaxX
, nMinY
), Point( nMaxX
, nMaxY
) );
2071 if ( bHandle
&& bRight
&& bBottom
)
2073 mpDev
->SetLineColor( rColor
);
2074 mpDev
->SetFillColor( rColor
);
2076 const sal_Int32 aRadius
= 4;
2078 sal_Int32 aRectMaxX1
= nMaxX
- nLayoutSign
* aRadius
;
2079 sal_Int32 aRectMaxX2
= nMaxX
+ nLayoutSign
;
2080 sal_Int32 aRectMinX1
= nMinX
- nLayoutSign
;
2081 sal_Int32 aRectMinX2
= nMinX
+ nLayoutSign
* aRadius
;
2083 sal_Int32 aRectMaxY1
= nMaxY
- aRadius
;
2084 sal_Int32 aRectMaxY2
= nMaxY
+ 1;
2085 sal_Int32 aRectMinY1
= nMinY
- 1;
2086 sal_Int32 aRectMinY2
= nMinY
+ aRadius
;
2088 // Draw corner rectangles
2089 Rectangle
aLowerRight( aRectMaxX1
, aRectMaxY1
, aRectMaxX2
, aRectMaxY2
);
2090 Rectangle
aUpperLeft ( aRectMinX1
, aRectMinY1
, aRectMinX2
, aRectMinY2
);
2091 Rectangle
aLowerLeft ( aRectMinX1
, aRectMaxY1
, aRectMinX2
, aRectMaxY2
);
2092 Rectangle
aUpperRight( aRectMaxX1
, aRectMinY1
, aRectMaxX2
, aRectMinY2
);
2094 mpDev
->DrawTransparent( tools::PolyPolygon( Polygon( aLowerRight
) ), lclCornerRectTransparency
);
2095 mpDev
->DrawTransparent( tools::PolyPolygon( Polygon( aUpperLeft
) ), lclCornerRectTransparency
);
2096 mpDev
->DrawTransparent( tools::PolyPolygon( Polygon( aLowerLeft
) ), lclCornerRectTransparency
);
2097 mpDev
->DrawTransparent( tools::PolyPolygon( Polygon( aUpperRight
) ), lclCornerRectTransparency
);
2103 void ScOutputData::DrawOneChange( SCCOL nRefStartX
, SCROW nRefStartY
,
2104 SCCOL nRefEndX
, SCROW nRefEndY
,
2105 const Color
& rColor
, sal_uInt16 nType
)
2107 PutInOrder( nRefStartX
, nRefEndX
);
2108 PutInOrder( nRefStartY
, nRefEndY
);
2110 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
2111 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
2113 if ( nRefStartX
<= nVisX2
+ 1 && nRefEndX
>= nVisX1
&&
2114 nRefStartY
<= nVisY2
+ 1 && nRefEndY
>= nVisY1
) // +1 because it touches next cells left/top
2118 long nMaxX
= nScrX
+nScrW
-1;
2119 long nMaxY
= nScrY
+nScrH
-1;
2126 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2129 bool bBottom
= false;
2131 bool bRight
= false;
2134 bool bNoStartY
= ( nY1
< nRefStartY
);
2135 bool bNoEndY
= false;
2136 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2138 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2140 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2147 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
2150 if ( nY
>nRefEndY
&& bNoEndY
)
2155 bNoStartY
= ( nY
< nRefStartY
);
2156 bNoEndY
= ( nY
< nRefEndY
);
2157 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2162 nPosX
+= nMirrorW
- 1; // always in pixels
2164 for (SCCOL nX
=nX1
; nX
<=nX2
+1; nX
++)
2166 if ( nX
==nRefStartX
)
2168 nMinX
= nPosX
- nLayoutSign
;
2173 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 1 ) * nLayoutSign
;
2176 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2179 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2182 if ( nType
== SC_CAT_DELETE_ROWS
)
2183 bLeft
= bRight
= bBottom
= false; //! thick lines???
2184 else if ( nType
== SC_CAT_DELETE_COLS
)
2185 bTop
= bBottom
= bRight
= false; //! thick lines???
2187 mpDev
->SetLineColor( rColor
);
2188 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2190 mpDev
->SetFillColor();
2191 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2197 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMaxX
,nMinY
) );
2198 if ( nType
== SC_CAT_DELETE_ROWS
)
2199 mpDev
->DrawLine( Point( nMinX
,nMinY
+1 ), Point( nMaxX
,nMinY
+1 ) );
2202 mpDev
->DrawLine( Point( nMinX
,nMaxY
), Point( nMaxX
,nMaxY
) );
2205 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMinX
,nMaxY
) );
2206 if ( nType
== SC_CAT_DELETE_COLS
)
2207 mpDev
->DrawLine( Point( nMinX
+nLayoutSign
,nMinY
), Point( nMinX
+nLayoutSign
,nMaxY
) );
2210 mpDev
->DrawLine( Point( nMaxX
,nMinY
), Point( nMaxX
,nMaxY
) );
2212 if ( bLeft
&& bTop
)
2214 mpDev
->SetLineColor();
2215 mpDev
->SetFillColor( rColor
);
2216 mpDev
->DrawRect( Rectangle( nMinX
+nLayoutSign
, nMinY
+1, nMinX
+3*nLayoutSign
, nMinY
+3 ) );
2222 void ScOutputData::DrawChangeTrack()
2224 ScChangeTrack
* pTrack
= mpDoc
->GetChangeTrack();
2225 ScChangeViewSettings
* pSettings
= mpDoc
->GetChangeViewSettings();
2226 if ( !pTrack
|| !pTrack
->GetFirst() || !pSettings
|| !pSettings
->ShowChanges() )
2227 return; // nix da oder abgeschaltet
2229 ScActionColorChanger
aColorChanger(*pTrack
);
2231 // Clipping passiert von aussen
2232 //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2236 if ( nEndX
< MAXCOL
) ++nEndX
; // auch noch von der naechsten Zelle, weil die Markierung
2237 if ( nEndY
< MAXROW
) ++nEndY
; // in die jeweils vorhergehende Zelle hineinragt
2238 ScRange
aViewRange( nX1
, nY1
, nTab
, nEndX
, nEndY
, nTab
);
2239 const ScChangeAction
* pAction
= pTrack
->GetFirst();
2242 ScChangeActionType eActionType
;
2243 if ( pAction
->IsVisible() )
2245 eActionType
= pAction
->GetType();
2246 const ScBigRange
& rBig
= pAction
->GetBigRange();
2247 if ( rBig
.aStart
.Tab() == nTab
)
2249 ScRange aRange
= rBig
.MakeRange();
2251 if ( eActionType
== SC_CAT_DELETE_ROWS
)
2252 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
2253 else if ( eActionType
== SC_CAT_DELETE_COLS
)
2254 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
2256 if ( aRange
.Intersects( aViewRange
) &&
2257 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2259 aColorChanger
.Update( *pAction
);
2260 Color
aColor( aColorChanger
.GetColor() );
2261 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2262 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2266 if ( eActionType
== SC_CAT_MOVE
&&
2267 static_cast<const ScChangeActionMove
*>(pAction
)->
2268 GetFromRange().aStart
.Tab() == nTab
)
2270 ScRange aRange
= static_cast<const ScChangeActionMove
*>(pAction
)->
2271 GetFromRange().MakeRange();
2272 if ( aRange
.Intersects( aViewRange
) &&
2273 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2275 aColorChanger
.Update( *pAction
);
2276 Color
aColor( aColorChanger
.GetColor() );
2277 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2278 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2283 pAction
= pAction
->GetNext();
2287 //TODO: moggi Need to check if this can't be written simpler
2288 void ScOutputData::DrawNoteMarks()
2293 long nInitPosX
= nScrX
;
2295 nInitPosX
+= nMirrorW
- 1; // always in pixels
2296 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2299 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2301 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2302 if ( pThisRowInfo
->bChanged
)
2304 long nPosX
= nInitPosX
;
2305 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2307 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2308 bool bIsMerged
= false;
2310 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2312 // find start of merged cell
2314 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2317 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2318 // use origin's pCell for NotePtr test below
2321 if ( mpDoc
->GetNote(nX
, pRowInfo
[nArrY
].nRowNo
, nTab
) && ( bIsMerged
||
2322 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2326 mpDev
->SetLineColor(COL_WHITE
);
2328 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2329 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2330 mpDev
->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2332 mpDev
->SetFillColor(COL_LIGHTRED
);
2337 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 4 ) * nLayoutSign
;
2338 if ( bIsMerged
|| pInfo
->bMerged
)
2340 // if merged, add widths of all cells
2341 SCCOL nNextX
= nX
+ 1;
2342 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2344 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2348 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2349 mpDev
->DrawRect( Rectangle( nMarkX
-5*nLayoutSign
,nPosY
,nMarkX
+1*nLayoutSign
,nPosY
+6 ) );
2352 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2355 nPosY
+= pThisRowInfo
->nHeight
;
2359 void ScOutputData::AddPDFNotes()
2361 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, mpDev
->GetExtOutDevData() );
2362 if ( !pPDFData
|| !pPDFData
->GetIsExportNotes() )
2365 long nInitPosX
= nScrX
;
2368 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
2369 long nOneX
= aOnePixel
.Width();
2370 nInitPosX
+= nMirrorW
- nOneX
;
2372 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2375 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2377 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2378 if ( pThisRowInfo
->bChanged
)
2380 long nPosX
= nInitPosX
;
2381 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2383 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2384 bool bIsMerged
= false;
2385 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2389 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2391 // find start of merged cell
2393 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2394 // use origin's pCell for NotePtr test below
2397 if ( mpDoc
->GetNote(nMergeX
, nMergeY
, nTab
) && ( bIsMerged
||
2398 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2400 long nNoteWidth
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2401 long nNoteHeight
= (long)( SC_CLIPMARK_SIZE
* mnPPTY
);
2403 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- nNoteWidth
) * nLayoutSign
;
2404 if ( bIsMerged
|| pInfo
->bMerged
)
2406 // if merged, add widths of all cells
2407 SCCOL nNextX
= nX
+ 1;
2408 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2410 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2414 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2416 Rectangle
aNoteRect( nMarkX
, nPosY
, nMarkX
+nNoteWidth
*nLayoutSign
, nPosY
+nNoteHeight
);
2417 const ScPostIt
* pNote
= mpDoc
->GetNote(nMergeX
, nMergeY
, nTab
);
2419 // Note title is the cell address (as on printed note pages)
2420 ScAddress
aAddress( nMergeX
, nMergeY
, nTab
);
2421 OUString
aTitle(aAddress
.Format(SCA_VALID
, mpDoc
, mpDoc
->GetAddressConvention()));
2423 // Content has to be a simple string without line breaks
2424 OUString aContent
= pNote
->GetText();
2425 aContent
= aContent
.replaceAll("\n", " ");
2428 aNote
.Title
= aTitle
;
2429 aNote
.Contents
= aContent
;
2430 pPDFData
->CreateNote( aNoteRect
, aNote
);
2434 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2437 nPosY
+= pThisRowInfo
->nHeight
;
2441 void ScOutputData::DrawClipMarks()
2446 Color
aArrowFillCol( COL_LIGHTRED
);
2448 DrawModeFlags nOldDrawMode
= mpDev
->GetDrawMode();
2449 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2450 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2452 // use DrawMode to change the arrow's outline color
2453 mpDev
->SetDrawMode( nOldDrawMode
| DrawModeFlags::SettingsLine
);
2454 // use text color also for the fill color
2455 aArrowFillCol
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2458 long nInitPosX
= nScrX
;
2460 nInitPosX
+= nMirrorW
- 1; // always in pixels
2461 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2463 Rectangle aCellRect
;
2465 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2467 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2468 if ( pThisRowInfo
->bChanged
)
2470 SCROW nY
= pThisRowInfo
->nRowNo
;
2471 long nPosX
= nInitPosX
;
2472 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2474 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2475 if (pInfo
->nClipMark
)
2477 if (pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
)
2479 // merge origin may be outside of visible area - use document functions
2483 long nStartPosX
= nPosX
;
2484 long nStartPosY
= nPosY
;
2486 while ( nOverX
> 0 && ( static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
2487 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & SC_MF_HOR
) )
2490 nStartPosX
-= nLayoutSign
* (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2493 while ( nOverY
> 0 && ( static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
2494 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & SC_MF_VER
) )
2497 nStartPosY
-= nLayoutSign
* (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2500 long nOutWidth
= (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2501 long nOutHeight
= (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2503 const ScMergeAttr
* pMerge
= static_cast<const ScMergeAttr
*>(
2504 mpDoc
->GetAttr( nOverX
, nOverY
, nTab
, ATTR_MERGE
));
2505 SCCOL nCountX
= pMerge
->GetColMerge();
2506 for (SCCOL i
=1; i
<nCountX
; i
++)
2507 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2508 SCROW nCountY
= pMerge
->GetRowMerge();
2509 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2512 nStartPosX
-= nOutWidth
- 1;
2513 aCellRect
= Rectangle( Point( nStartPosX
, nStartPosY
), Size( nOutWidth
, nOutHeight
) );
2517 long nOutWidth
= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
2518 long nOutHeight
= pThisRowInfo
->nHeight
;
2520 if ( pInfo
->bMerged
&& pInfo
->pPatternAttr
)
2524 const ScMergeAttr
* pMerge
=
2525 static_cast<const ScMergeAttr
*>(&pInfo
->pPatternAttr
->GetItem(ATTR_MERGE
));
2526 SCCOL nCountX
= pMerge
->GetColMerge();
2527 for (SCCOL i
=1; i
<nCountX
; i
++)
2528 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2529 SCROW nCountY
= pMerge
->GetRowMerge();
2530 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2533 long nStartPosX
= nPosX
;
2535 nStartPosX
-= nOutWidth
- 1;
2536 // #i80447# create aCellRect from two points in case nOutWidth is 0
2537 aCellRect
= Rectangle( Point( nStartPosX
, nPosY
),
2538 Point( nStartPosX
+nOutWidth
-1, nPosY
+nOutHeight
-1 ) );
2541 aCellRect
.Bottom() -= 1; // don't paint over the cell grid
2543 aCellRect
.Left() += 1;
2545 aCellRect
.Right() -= 1;
2547 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2548 Size
aMarkSize( nMarkPixel
, (nMarkPixel
-1)*2 );
2550 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_RIGHT
: SC_CLIPMARK_LEFT
) )
2553 Rectangle aMarkRect
= aCellRect
;
2554 aMarkRect
.Right() = aCellRect
.Left()+nMarkPixel
-1;
2555 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, true );
2557 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_LEFT
: SC_CLIPMARK_RIGHT
) )
2560 Rectangle aMarkRect
= aCellRect
;
2561 aMarkRect
.Left() = aCellRect
.Right()-nMarkPixel
+1;
2562 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, false );
2565 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2568 nPosY
+= pThisRowInfo
->nHeight
;
2571 mpDev
->SetDrawMode(nOldDrawMode
);
2574 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */