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"
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
),
167 pViewShell( nullptr ),
168 pDrawView( nullptr ),
173 bSingleGrid( false ),
174 bPagebreakMode( false ),
175 bSolidBackground( false ),
176 mbUseStyleColor( false ),
177 mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
178 mbSyntaxMode( false ),
179 pValueColor( nullptr ),
180 pTextColor( nullptr ),
181 pFormulaColor( nullptr ),
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(nullptr), // #i74769# use SdrPaintWindow direct
191 mpSpellCheckCxt(nullptr)
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()
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(vcl::RenderContext
& rRenderContext
, 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 // It is a big mess to distinguish when we are using pixels and when logic
328 // units for drawing. Ultimately we want to work only in the logic units,
329 // but until that happens, we need to special-case:
332 // * drawing to the screen - everything is internally counted in pixels there
334 // 'Internally' in the above means the pCellInfo[...].nWidth and
335 // pRowInfo[...]->nHeight:
337 // * when bWorksInPixels is true: these are in pixels
338 // * when bWorksInPixels is false: these are in the logic units
340 // This is where all the confusion comes from, ultimately we want them
341 // always in the logic units (100th of millimiters), but we need to get
342 // there gradually (get rid of setting MAP_PIXEL first), otherwise we'd
343 // break all the drawing by one change.
344 // So until that happens, we need to special case.
345 bool bWorksInPixels
= bMetaFile
;
347 if ( eType
== OUTTYPE_WINDOW
)
349 bWorksInPixels
= true;
350 const svtools::ColorConfig
& rColorCfg
= SC_MOD()->GetColorConfig();
351 aPageColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC
).nColor
);
352 aManualColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKMANUAL
).nColor
);
356 aPageColor
= aGridColor
;
357 aManualColor
= aGridColor
;
364 Size aOnePixel
= rRenderContext
.PixelToLogic(Size(1,1));
365 nOneX
= aOnePixel
.Width();
366 nOneY
= aOnePixel
.Height();
369 long nLayoutSign
= bLayoutRTL
? -1 : 1;
370 long nSignedOneX
= nOneX
* nLayoutSign
;
372 rRenderContext
.SetLineColor(aGridColor
);
373 ScGridMerger
aGrid(&rRenderContext
, nOneX
, nOneY
);
379 nPosX
+= nMirrorW
- nOneX
;
381 for (nX
=nX1
; nX
<=nX2
; nX
++)
383 SCCOL nXplus1
= nX
+1;
384 SCCOL nXplus2
= nX
+2;
385 sal_uInt16 nWidth
= pRowInfo
[0].pCellInfo
[nXplus1
].nWidth
;
388 nPosX
+= nWidth
* nLayoutSign
;
392 // Search also in hidden part for page breaks
393 SCCOL nCol
= nXplus1
;
394 while (nCol
<= MAXCOL
)
396 nBreak
= mpDoc
->HasColBreak(nCol
, nTab
);
397 bool bHidden
= mpDoc
->ColHidden(nCol
, nTab
);
399 if ( nBreak
|| !bHidden
)
404 if (nBreak
!= nBreakOld
)
407 rRenderContext
.SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
408 nBreak
? aPageColor
: aGridColor
);
413 bool bDraw
= bGrid
|| nBreakOld
; // simple grid only if set that way
415 sal_uInt16 nWidthXplus2
= pRowInfo
[0].pCellInfo
[nXplus2
].nWidth
;
416 bSingle
= bSingleGrid
; //! get into Fillinfo !!!!!
417 if ( nX
<MAXCOL
&& !bSingle
)
419 bSingle
= ( nWidthXplus2
== 0 );
420 for (nArrY
=1; nArrY
+1<nArrCount
&& !bSingle
; nArrY
++)
422 if (pRowInfo
[nArrY
].pCellInfo
[nXplus2
].bHOverlapped
)
424 if (pRowInfo
[nArrY
].pCellInfo
[nXplus1
].bHideGrid
)
431 if ( nX
<MAXCOL
&& bSingle
)
433 SCCOL nVisX
= nXplus1
;
434 while ( nVisX
< MAXCOL
&& !mpDoc
->GetColWidth(nVisX
,nTab
) )
438 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
440 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
441 const long nNextY
= nPosY
+ pThisRowInfo
->nHeight
;
443 bool bHOver
= pThisRowInfo
->pCellInfo
[nXplus1
].bHideGrid
;
447 bHOver
= pThisRowInfo
->pCellInfo
[nXplus2
].bHOverlapped
;
451 bHOver
= pThisRowInfo
->pCellInfo
[nVisX
+1].bHOverlapped
;
453 bHOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
454 nVisX
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
457 bHOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
458 nXplus1
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
463 if (pThisRowInfo
->bChanged
&& !bHOver
)
465 aGrid
.AddVerLine(bWorksInPixels
, nPosX
-nSignedOneX
, nPosY
, nNextY
-nOneY
);
472 aGrid
.AddVerLine(bWorksInPixels
, nPosX
-nSignedOneX
, nScrY
, nScrY
+nScrH
-nOneY
);
480 bool bHiddenRow
= true;
481 SCROW nHiddenEndRow
= -1;
483 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
485 SCSIZE nArrYplus1
= nArrY
+1;
486 nY
= pRowInfo
[nArrY
].nRowNo
;
487 SCROW nYplus1
= nY
+1;
488 nPosY
+= pRowInfo
[nArrY
].nHeight
;
490 if (pRowInfo
[nArrY
].bChanged
)
494 for (SCROW i
= nYplus1
; i
<= MAXROW
; ++i
)
496 if (i
> nHiddenEndRow
)
497 bHiddenRow
= mpDoc
->RowHidden(i
, nTab
, nullptr, &nHiddenEndRow
);
498 /* TODO: optimize the row break thing for large hidden
499 * segments where HasRowBreak() has to be called
500 * nevertheless for each row, as a row break is drawn also
501 * for hidden rows, above them. This needed to be done only
502 * once per hidden segment, maybe giving manual breaks
503 * priority. Something like GetNextRowBreak() and
504 * GetNextManualRowBreak(). */
505 nBreak
= mpDoc
->HasRowBreak(i
, nTab
);
506 if (!bHiddenRow
|| nBreak
)
510 if (nBreakOld
!= nBreak
)
513 rRenderContext
.SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
514 (nBreak
) ? aPageColor
: aGridColor
);
519 bool bDraw
= bGrid
|| nBreakOld
; // simple grid only if set so
521 bool bNextYisNextRow
= (pRowInfo
[nArrYplus1
].nRowNo
== nYplus1
);
522 bSingle
= !bNextYisNextRow
; // Hidden
523 for (SCCOL i
=nX1
; i
<=nX2
&& !bSingle
; i
++)
525 if (pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
)
531 if ( bSingle
&& nY
<MAXROW
)
533 SCROW nVisY
= pRowInfo
[nArrYplus1
].nRowNo
;
537 nPosX
+= nMirrorW
- nOneX
;
539 for (SCCOL i
=nX1
; i
<=nX2
; i
++)
541 const long nNextX
= nPosX
+ pRowInfo
[0].pCellInfo
[i
+1].nWidth
* nLayoutSign
;
542 if (nNextX
!= nPosX
) // visible
545 if ( bNextYisNextRow
)
546 bVOver
= pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
;
549 bVOver
= static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
550 i
,nYplus1
,nTab
,ATTR_MERGE_FLAG
))
552 && static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
553 i
,nVisY
,nTab
,ATTR_MERGE_FLAG
))
555 //! nVisY from Array ??
559 aGrid
.AddHorLine(bWorksInPixels
, nPosX
, nNextX
-nSignedOneX
, nPosY
-nOneY
);
567 aGrid
.AddHorLine(bWorksInPixels
, nScrX
, nScrX
+nScrW
-nOneX
, nPosY
-nOneY
);
574 void ScOutputData::SetPagebreakMode( ScPageBreakData
* pPageData
)
576 bPagebreakMode
= true;
578 return; // not yet initialized -> everything "not printed"
580 // mark printed range
581 // (everything in FillInfo is already initialized to sal_False)
583 sal_uInt16 nRangeCount
= sal::static_int_cast
<sal_uInt16
>(pPageData
->GetCount());
584 for (sal_uInt16 nPos
=0; nPos
<nRangeCount
; nPos
++)
586 ScRange aRange
= pPageData
->GetData( nPos
).GetPrintRange();
588 SCCOL nStartX
= std::max( aRange
.aStart
.Col(), nX1
);
589 SCCOL nEndX
= std::min( aRange
.aEnd
.Col(), nX2
);
590 SCROW nStartY
= std::max( aRange
.aStart
.Row(), nY1
);
591 SCROW nEndY
= std::min( aRange
.aEnd
.Row(), nY2
);
593 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
595 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
596 if ( pThisRowInfo
->bChanged
&& pThisRowInfo
->nRowNo
>= nStartY
&&
597 pThisRowInfo
->nRowNo
<= nEndY
)
599 for (SCCOL nX
=nStartX
; nX
<=nEndX
; nX
++)
600 pThisRowInfo
->pCellInfo
[nX
+1].bPrinted
= true;
606 void ScOutputData::FindRotated()
610 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
611 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
612 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
614 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
616 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
617 if ( pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
&&
618 ( pThisRowInfo
->bChanged
|| pRowInfo
[nArrY
-1].bChanged
||
619 ( nArrY
+1<nArrCount
&& pRowInfo
[nArrY
+1].bChanged
) ) )
621 SCROW nY
= pThisRowInfo
->nRowNo
;
623 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
625 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
626 const ScPatternAttr
* pPattern
= pInfo
->pPatternAttr
;
627 const SfxItemSet
* pCondSet
= pInfo
->pConditionSet
;
629 if ( !pPattern
&& !mpDoc
->ColHidden(nX
, nTab
) )
631 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
632 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
635 if ( pPattern
) // column isn't hidden
637 sal_uInt8 nDir
= pPattern
->GetRotateDir( pCondSet
);
638 if (nDir
!= SC_ROTDIR_NONE
)
640 pInfo
->nRotateDir
= nDir
;
649 static sal_uInt16
lcl_GetRotateDir( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
651 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
652 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
654 sal_uInt16 nRet
= SC_ROTDIR_NONE
;
656 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
659 SvxRotateMode eRotMode
= (SvxRotateMode
)static_cast<const SvxRotateModeItem
&>(
660 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
662 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
663 nRet
= SC_ROTDIR_STANDARD
;
664 else if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
665 nRet
= SC_ROTDIR_CENTER
;
666 else if ( eRotMode
== SVX_ROTATE_MODE_TOP
|| eRotMode
== SVX_ROTATE_MODE_BOTTOM
)
668 long nRot180
= nAttrRotate
% 18000; // 1/100 degree
669 if ( nRot180
== 9000 )
670 nRet
= SC_ROTDIR_CENTER
;
671 else if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nRot180
< 9000 ) ||
672 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nRot180
> 9000 ) )
673 nRet
= SC_ROTDIR_LEFT
;
675 nRet
= SC_ROTDIR_RIGHT
;
682 static const SvxBrushItem
* lcl_FindBackground( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
684 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
685 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
686 const SvxBrushItem
* pBackground
= static_cast<const SvxBrushItem
*>(
687 &pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
689 sal_uInt16 nDir
= lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
);
691 // treat CENTER like RIGHT
692 if ( nDir
== SC_ROTDIR_RIGHT
|| nDir
== SC_ROTDIR_CENTER
)
694 // text goes to the right -> take background from the left
695 while ( nCol
> 0 && lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
696 pBackground
->GetColor().GetTransparency() != 255 )
699 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
700 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
701 pBackground
= static_cast<const SvxBrushItem
*>(&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
704 else if ( nDir
== SC_ROTDIR_LEFT
)
706 // text goes to the left -> take background from the right
707 while ( nCol
< MAXCOL
&& lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
708 pBackground
->GetColor().GetTransparency() != 255 )
711 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
712 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
713 pBackground
= static_cast<const SvxBrushItem
*>(&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
));
720 static bool lcl_EqualBack( const RowInfo
& rFirst
, const RowInfo
& rOther
,
721 SCCOL nX1
, SCCOL nX2
, bool bShowProt
, bool bPagebreakMode
)
723 if ( rFirst
.bChanged
!= rOther
.bChanged
||
724 rFirst
.bEmptyBack
!= rOther
.bEmptyBack
)
730 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
732 const ScPatternAttr
* pPat1
= rFirst
.pCellInfo
[nX
+1].pPatternAttr
;
733 const ScPatternAttr
* pPat2
= rOther
.pCellInfo
[nX
+1].pPatternAttr
;
734 if ( !pPat1
|| !pPat2
||
735 &pPat1
->GetItem(ATTR_PROTECTION
) != &pPat2
->GetItem(ATTR_PROTECTION
) )
741 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
742 if ( rFirst
.pCellInfo
[nX
+1].pBackground
!= rOther
.pCellInfo
[nX
+1].pBackground
)
746 if ( rFirst
.nRotMaxCol
!= SC_ROTMAX_NONE
|| rOther
.nRotMaxCol
!= SC_ROTMAX_NONE
)
747 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
748 if ( rFirst
.pCellInfo
[nX
+1].nRotateDir
!= rOther
.pCellInfo
[nX
+1].nRotateDir
)
751 if ( bPagebreakMode
)
752 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
753 if ( rFirst
.pCellInfo
[nX
+1].bPrinted
!= rOther
.pCellInfo
[nX
+1].bPrinted
)
756 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
758 const Color
* pCol1
= rFirst
.pCellInfo
[nX
+1].pColorScale
.get();
759 const Color
* pCol2
= rOther
.pCellInfo
[nX
+1].pColorScale
.get();
760 if( (pCol1
&& !pCol2
) || (!pCol1
&& pCol2
) )
763 if (pCol1
&& (*pCol1
!= *pCol2
))
766 const ScDataBarInfo
* pInfo1
= rFirst
.pCellInfo
[nX
+1].pDataBar
.get();
767 const ScDataBarInfo
* pInfo2
= rOther
.pCellInfo
[nX
+1].pDataBar
.get();
769 if( (pInfo1
&& !pInfo2
) || (!pInfo1
&& pInfo2
) )
772 if (pInfo1
&& (*pInfo1
!= *pInfo2
))
775 // each cell with an icon set should be painted the same way
776 const ScIconSetInfo
* pIconSet1
= rFirst
.pCellInfo
[nX
+1].pIconSet
.get();
777 const ScIconSetInfo
* pIconSet2
= rOther
.pCellInfo
[nX
+1].pIconSet
.get();
779 if(pIconSet1
|| pIconSet2
)
786 void ScOutputData::DrawDocumentBackground()
788 if ( !bSolidBackground
)
791 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
792 mpDev
->SetLineColor(aBgColor
);
793 mpDev
->SetFillColor(aBgColor
);
795 Point aScreenPos
= mpDev
->PixelToLogic(Point(nScrX
, nScrY
));
796 Size aScreenSize
= mpDev
->PixelToLogic(Size(nScrW
- 1,nScrH
- 1));
798 mpDev
->DrawRect(Rectangle(aScreenPos
, aScreenSize
));
803 static const double lclCornerRectTransparency
= 40.0;
805 void drawDataBars(vcl::RenderContext
& rRenderContext
, const ScDataBarInfo
* pOldDataBarInfo
, const Rectangle
& rRect
, long nOneX
, long nOneY
)
808 Rectangle aPaintRect
= rRect
;
809 aPaintRect
.Top() += 2 * nOneY
;
810 aPaintRect
.Bottom() -= 2 * nOneY
;
811 aPaintRect
.Left() += 2 * nOneX
;
812 aPaintRect
.Right() -= 2 * nOneX
;
813 if(pOldDataBarInfo
->mnZero
)
815 // need to calculate null point in cell
816 long nLength
= aPaintRect
.Right() - aPaintRect
.Left();
817 nPosZero
= static_cast<long>(aPaintRect
.Left() + nLength
*pOldDataBarInfo
->mnZero
/100.0);
821 nPosZero
= aPaintRect
.Left();
824 if(pOldDataBarInfo
->mnLength
< 0)
826 aPaintRect
.Right() = nPosZero
;
827 long nLength
= nPosZero
- aPaintRect
.Left();
828 aPaintRect
.Left() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
830 else if(pOldDataBarInfo
->mnLength
> 0)
832 aPaintRect
.Left() = nPosZero
;
833 long nLength
= aPaintRect
.Right() - nPosZero
;
834 aPaintRect
.Right() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
839 if(pOldDataBarInfo
->mbGradient
)
841 rRenderContext
.SetLineColor(pOldDataBarInfo
->maColor
);
842 Gradient
aGradient(GradientStyle_LINEAR
, pOldDataBarInfo
->maColor
, COL_TRANSPARENT
);
844 if(pOldDataBarInfo
->mnLength
< 0)
845 aGradient
.SetAngle(2700);
847 aGradient
.SetAngle(900);
849 rRenderContext
.DrawGradient(aPaintRect
, aGradient
);
851 rRenderContext
.SetLineColor();
855 rRenderContext
.SetFillColor(pOldDataBarInfo
->maColor
);
856 rRenderContext
.DrawRect(aPaintRect
);
860 if(pOldDataBarInfo
->mnZero
&& pOldDataBarInfo
->mnZero
!= 100)
862 Point
aPoint1(nPosZero
, rRect
.Top());
863 Point
aPoint2(nPosZero
, rRect
.Bottom());
864 LineInfo
aLineInfo(LINE_DASH
, 1);
865 aLineInfo
.SetDashCount( 4 );
866 aLineInfo
.SetDistance( 3 );
867 aLineInfo
.SetDashLen( 3 );
868 rRenderContext
.SetFillColor(pOldDataBarInfo
->maAxisColor
);
869 rRenderContext
.SetLineColor(pOldDataBarInfo
->maAxisColor
);
870 rRenderContext
.DrawLine(aPoint1
, aPoint2
, aLineInfo
);
871 rRenderContext
.SetLineColor();
872 rRenderContext
.SetFillColor();
876 const BitmapEx
& getIcon(sc::IconSetBitmapMap
& rIconSetBitmapMap
, ScIconSetType eType
, sal_Int32 nIndex
)
878 return ScIconSetFormat::getBitmap(rIconSetBitmapMap
, eType
, nIndex
);
881 void drawIconSets(vcl::RenderContext
& rRenderContext
, const ScIconSetInfo
* pOldIconSetInfo
, const Rectangle
& rRect
, long nOneX
, long nOneY
,
882 sc::IconSetBitmapMap
& rIconSetBitmapMap
)
885 ScIconSetType eType
= pOldIconSetInfo
->eIconSetType
;
886 sal_Int32 nIndex
= pOldIconSetInfo
->nIconIndex
;
887 const BitmapEx
& rIcon
= getIcon(rIconSetBitmapMap
, eType
, nIndex
);
888 long aOrigSize
= std::max
<long>(0,std::min(rRect
.GetSize().getWidth() - 4 * nOneX
, rRect
.GetSize().getHeight() -4 * nOneY
));
889 rRenderContext
.DrawBitmapEx( Point( rRect
.Left() + 2 * nOneX
, rRect
.Top() + 2 * nOneY
), Size(aOrigSize
, aOrigSize
), rIcon
);
892 void drawCells(vcl::RenderContext
& rRenderContext
, const Color
* pColor
, const SvxBrushItem
* pBackground
, const Color
*& pOldColor
, const SvxBrushItem
*& pOldBackground
,
893 Rectangle
& rRect
, long nPosX
, long nLayoutSign
, long nOneX
, long nOneY
, const ScDataBarInfo
* pDataBarInfo
, const ScDataBarInfo
*& pOldDataBarInfo
,
894 const ScIconSetInfo
* pIconSetInfo
, const ScIconSetInfo
*& pOldIconSetInfo
,
895 sc::IconSetBitmapMap
& rIconSetBitmapMap
)
897 long nSignedOneX
= nOneX
* nLayoutSign
;
898 // need to paint if old color scale has been used and now
899 // we have a different color or a style based background
900 // we can here fall back to pointer comparison
901 if (pOldColor
&& (pBackground
|| pOldColor
!= pColor
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
))
903 rRect
.Right() = nPosX
-nSignedOneX
;
904 if( !pOldColor
->GetTransparency() )
906 rRenderContext
.SetFillColor( *pOldColor
);
907 rRenderContext
.DrawRect( rRect
);
909 if( pOldDataBarInfo
)
910 drawDataBars(rRenderContext
, pOldDataBarInfo
, rRect
, nOneX
, nOneY
);
911 if( pOldIconSetInfo
)
912 drawIconSets(rRenderContext
, pOldIconSetInfo
, rRect
, nOneX
, nOneY
, rIconSetBitmapMap
);
914 rRect
.Left() = nPosX
- nSignedOneX
;
917 if ( pOldBackground
&& (pColor
||pBackground
!= pOldBackground
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
) )
919 rRect
.Right() = nPosX
-nSignedOneX
;
920 if (pOldBackground
) // ==0 if hidden
922 Color aBackCol
= pOldBackground
->GetColor();
923 if ( !aBackCol
.GetTransparency() ) //! partial transparency?
925 rRenderContext
.SetFillColor( aBackCol
);
926 rRenderContext
.DrawRect( rRect
);
929 if( pOldDataBarInfo
)
930 drawDataBars(rRenderContext
, pOldDataBarInfo
, rRect
, nOneX
, nOneY
);
931 if( pOldIconSetInfo
)
932 drawIconSets(rRenderContext
, pOldIconSetInfo
, rRect
, nOneX
, nOneY
, rIconSetBitmapMap
);
934 rRect
.Left() = nPosX
- nSignedOneX
;
937 if (!pOldBackground
&& !pOldColor
&& (pDataBarInfo
|| pIconSetInfo
))
939 rRect
.Right() = nPosX
-nSignedOneX
;
940 rRect
.Left() = nPosX
- nSignedOneX
;
945 // only update pOldColor if the colors changed
946 if (!pOldColor
|| *pOldColor
!= *pColor
)
949 pOldBackground
= nullptr;
953 pOldBackground
= pBackground
;
958 pOldDataBarInfo
= pDataBarInfo
;
960 pOldDataBarInfo
= nullptr;
963 pOldIconSetInfo
= pIconSetInfo
;
965 pOldIconSetInfo
= nullptr;
970 void ScOutputData::DrawBackground(vcl::RenderContext
& rRenderContext
)
972 FindRotated(); //! from the outside?
974 Size aOnePixel
= rRenderContext
.PixelToLogic(Size(1,1));
975 long nOneXLogic
= aOnePixel
.Width();
976 long nOneYLogic
= aOnePixel
.Height();
978 // See more about bWorksInPixels in ScOutputData::DrawGrid
979 bool bWorksInPixels
= false;
980 if (eType
== OUTTYPE_WINDOW
)
981 bWorksInPixels
= true;
993 long nLayoutSign
= bLayoutRTL
? -1 : 1;
995 rRenderContext
.SetLineColor();
997 bool bShowProt
= mbSyntaxMode
&& mpDoc
->IsTabProtected(nTab
);
998 bool bDoAll
= bShowProt
|| bPagebreakMode
|| bSolidBackground
;
1000 bool bCellContrast
= mbUseStyleColor
&&
1001 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1004 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1006 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1007 long nRowHeight
= pThisRowInfo
->nHeight
;
1009 if ( pThisRowInfo
->bChanged
)
1011 if ( ( ( pThisRowInfo
->bEmptyBack
) || mbSyntaxMode
) && !bDoAll
)
1017 // scan for rows with the same background:
1019 while ( nArrY
+nSkip
+2<nArrCount
&&
1020 lcl_EqualBack( *pThisRowInfo
, pRowInfo
[nArrY
+nSkip
+1],
1021 nX1
, nX2
, bShowProt
, bPagebreakMode
) )
1024 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
1030 nPosX
+= nMirrorW
- nOneX
;
1032 aRect
= Rectangle(nPosX
, nPosY
- nOneY
, nPosX
, nPosY
- nOneY
+ nRowHeight
);
1034 aRect
= rRenderContext
.PixelToLogic(aRect
); // internal data in pixels, but we'll be drawing in logic units
1036 const SvxBrushItem
* pOldBackground
= nullptr;
1037 const SvxBrushItem
* pBackground
;
1038 const Color
* pOldColor
= nullptr;
1039 const ScDataBarInfo
* pOldDataBarInfo
= nullptr;
1040 const ScIconSetInfo
* pOldIconSetInfo
= nullptr;
1041 SCCOL nMergedCells
= 1;
1042 SCCOL nOldMerged
= 0;
1044 for (SCCOL nX
=nX1
; nX
+ nMergedCells
<= nX2
+ 1; nX
+= nOldMerged
)
1046 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+nMergedCells
];
1048 nOldMerged
= nMergedCells
;
1052 // high contrast for cell borders and backgrounds -> empty background
1053 pBackground
= ScGlobal::GetEmptyBrushItem();
1055 else if (bShowProt
) // show cell protection in syntax mode
1057 const ScPatternAttr
* pP
= pInfo
->pPatternAttr
;
1060 const ScProtectionAttr
& rProt
= static_cast<const ScProtectionAttr
&>(
1061 pP
->GetItem(ATTR_PROTECTION
));
1062 if (rProt
.GetProtection() || rProt
.GetHideCell())
1063 pBackground
= ScGlobal::GetProtectedBrushItem();
1065 pBackground
= ScGlobal::GetEmptyBrushItem();
1068 pBackground
= nullptr;
1071 pBackground
= pInfo
->pBackground
;
1073 if ( bPagebreakMode
&& !pInfo
->bPrinted
)
1074 pBackground
= ScGlobal::GetProtectedBrushItem();
1076 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1077 pBackground
->GetColor().GetTransparency() != 255 &&
1080 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
1081 pBackground
= lcl_FindBackground( mpDoc
, nX
, nY
, nTab
);
1084 const Color
* pColor
= pInfo
->pColorScale
.get();
1085 const ScDataBarInfo
* pDataBarInfo
= pInfo
->pDataBar
.get();
1086 const ScIconSetInfo
* pIconSetInfo
= pInfo
->pIconSet
.get();
1088 long nPosXLogic
= nPosX
;
1090 nPosXLogic
= rRenderContext
.PixelToLogic(Point(nPosX
, 0)).X();
1092 drawCells(rRenderContext
, pColor
, pBackground
, pOldColor
, pOldBackground
, aRect
, nPosXLogic
, nLayoutSign
, nOneXLogic
, nOneYLogic
, pDataBarInfo
, pOldDataBarInfo
, pIconSetInfo
, pOldIconSetInfo
, mpDoc
->GetIconSetBitmapMap());
1094 // extend for all merged cells
1096 if (pInfo
->bMerged
&& pInfo
->pPatternAttr
)
1098 const ScMergeAttr
* pMerge
=
1099 static_cast<const ScMergeAttr
*>(&pInfo
->pPatternAttr
->GetItem(ATTR_MERGE
));
1100 nMergedCells
= std::max
<SCCOL
>(1, pMerge
->GetColMerge());
1103 for (SCCOL nMerged
= 0; nMerged
< nMergedCells
; ++nMerged
)
1105 SCCOL nCol
= nX
+nOldMerged
+nMerged
;
1108 nPosX
+= pRowInfo
[0].pCellInfo
[nCol
].nWidth
* nLayoutSign
;
1112 long nPosXLogic
= nPosX
;
1114 nPosXLogic
= rRenderContext
.PixelToLogic(Point(nPosX
, 0)).X();
1116 drawCells(rRenderContext
, nullptr, nullptr, pOldColor
, pOldBackground
, aRect
, nPosXLogic
, nLayoutSign
, nOneXLogic
, nOneYLogic
, nullptr, pOldDataBarInfo
, nullptr, pOldIconSetInfo
, mpDoc
->GetIconSetBitmapMap());
1121 nPosY
+= nRowHeight
;
1125 void ScOutputData::DrawShadow()
1127 DrawExtraShadow( false, false, false, false );
1130 void ScOutputData::DrawExtraShadow(bool bLeft
, bool bTop
, bool bRight
, bool bBottom
)
1132 mpDev
->SetLineColor();
1134 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1135 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1136 Color aAutoTextColor
;
1137 if ( bCellContrast
)
1138 aAutoTextColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1140 long nInitPosX
= nScrX
;
1143 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1144 long nOneX
= aOnePixel
.Width();
1145 nInitPosX
+= nMirrorW
- nOneX
;
1147 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1149 long nPosY
= nScrY
- pRowInfo
[0].nHeight
;
1150 for (SCSIZE nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1152 bool bCornerY
= ( nArrY
== 0 ) || ( nArrY
+1 == nArrCount
);
1153 bool bSkipY
= ( nArrY
==0 && !bTop
) || ( nArrY
+1 == nArrCount
&& !bBottom
);
1155 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1156 long nRowHeight
= pThisRowInfo
->nHeight
;
1158 if ( pThisRowInfo
->bChanged
&& !bSkipY
)
1160 long nPosX
= nInitPosX
- pRowInfo
[0].pCellInfo
[nX1
].nWidth
* nLayoutSign
;
1161 for (SCCOL nArrX
=nX1
; nArrX
<=nX2
+2; nArrX
++)
1163 bool bCornerX
= ( nArrX
==nX1
|| nArrX
==nX2
+2 );
1164 bool bSkipX
= ( nArrX
==nX1
&& !bLeft
) || ( nArrX
==nX2
+2 && !bRight
);
1166 for (sal_uInt16 nPass
=0; nPass
<2; nPass
++) // horizontal / vertical
1168 const SvxShadowItem
* pAttr
= nPass
?
1169 pThisRowInfo
->pCellInfo
[nArrX
].pVShadowOrigin
:
1170 pThisRowInfo
->pCellInfo
[nArrX
].pHShadowOrigin
;
1171 if ( pAttr
&& !bSkipX
)
1173 ScShadowPart ePart
= nPass
?
1174 pThisRowInfo
->pCellInfo
[nArrX
].eVShadowPart
:
1175 pThisRowInfo
->pCellInfo
[nArrX
].eHShadowPart
;
1178 if ( (nPass
==0 && bCornerX
) || (nPass
==1 && bCornerY
) )
1179 if ( ePart
!= SC_SHADOW_CORNER
)
1184 long nThisWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1185 long nMaxWidth
= nThisWidth
;
1188 //! direction must depend on shadow location
1189 SCCOL nWx
= nArrX
; // nX+1
1190 while (nWx
<nX2
&& !pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
)
1192 nMaxWidth
= pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
;
1195 // rectangle is in logical orientation
1196 Rectangle
aRect( nPosX
, nPosY
,
1197 nPosX
+ ( nThisWidth
- 1 ) * nLayoutSign
,
1198 nPosY
+ pRowInfo
[nArrY
].nHeight
- 1 );
1200 long nSize
= pAttr
->GetWidth();
1201 long nSizeX
= (long)(nSize
*mnPPTX
);
1202 if (nSizeX
>= nMaxWidth
) nSizeX
= nMaxWidth
-1;
1203 long nSizeY
= (long)(nSize
*mnPPTY
);
1204 if (nSizeY
>= nRowHeight
) nSizeY
= nRowHeight
-1;
1206 nSizeX
*= nLayoutSign
; // used only to add to rectangle values
1208 SvxShadowLocation eLoc
= pAttr
->GetLocation();
1211 // Shadow location is specified as "visual" (right is always right),
1212 // so the attribute's location value is mirrored here and in FillInfo.
1215 case SVX_SHADOW_BOTTOMRIGHT
: eLoc
= SVX_SHADOW_BOTTOMLEFT
; break;
1216 case SVX_SHADOW_BOTTOMLEFT
: eLoc
= SVX_SHADOW_BOTTOMRIGHT
; break;
1217 case SVX_SHADOW_TOPRIGHT
: eLoc
= SVX_SHADOW_TOPLEFT
; break;
1218 case SVX_SHADOW_TOPLEFT
: eLoc
= SVX_SHADOW_TOPRIGHT
; break;
1221 // added to avoid warnings
1226 if (ePart
== SC_SHADOW_HORIZ
|| ePart
== SC_SHADOW_HSTART
||
1227 ePart
== SC_SHADOW_CORNER
)
1229 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1230 aRect
.Top() = aRect
.Bottom() - nSizeY
;
1232 aRect
.Bottom() = aRect
.Top() + nSizeY
;
1234 if (ePart
== SC_SHADOW_VERT
|| ePart
== SC_SHADOW_VSTART
||
1235 ePart
== SC_SHADOW_CORNER
)
1237 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1238 aRect
.Left() = aRect
.Right() - nSizeX
;
1240 aRect
.Right() = aRect
.Left() + nSizeX
;
1242 if (ePart
== SC_SHADOW_HSTART
)
1244 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1245 aRect
.Right() -= nSizeX
;
1247 aRect
.Left() += nSizeX
;
1249 if (ePart
== SC_SHADOW_VSTART
)
1251 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1252 aRect
.Bottom() -= nSizeY
;
1254 aRect
.Top() += nSizeY
;
1257 //! merge rectangles?
1258 mpDev
->SetFillColor( bCellContrast
? aAutoTextColor
: pAttr
->GetColor() );
1259 mpDev
->DrawRect( aRect
);
1264 nPosX
+= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
* nLayoutSign
;
1267 nPosY
+= nRowHeight
;
1271 void ScOutputData::DrawClear()
1274 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1275 long nOneX
= aOnePixel
.Width();
1276 long nOneY
= aOnePixel
.Height();
1278 // (called only for ScGridWindow)
1279 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1284 mpDev
->SetLineColor();
1286 mpDev
->SetFillColor( aBgColor
);
1289 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1291 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1292 long nRowHeight
= pThisRowInfo
->nHeight
;
1294 if ( pThisRowInfo
->bChanged
)
1296 // scan for more rows which must be painted:
1298 while ( nArrY
+nSkip
+2<nArrCount
&& pRowInfo
[nArrY
+nSkip
+1].bChanged
)
1301 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
1304 aRect
= Rectangle( Point( nScrX
, nPosY
),
1305 Size( nScrW
+1-nOneX
, nRowHeight
+1-nOneY
) );
1306 mpDev
->DrawRect( aRect
);
1310 nPosY
+= nRowHeight
;
1316 long lclGetSnappedX( OutputDevice
& rDev
, long nPosX
, bool bSnapPixel
)
1318 return (bSnapPixel
&& nPosX
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( nPosX
, 0 ) ) ).Width() : nPosX
;
1321 long lclGetSnappedY( OutputDevice
& rDev
, long nPosY
, bool bSnapPixel
)
1323 return (bSnapPixel
&& nPosY
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( 0, nPosY
) ) ).Height() : nPosY
;
1326 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX
, sal_uInt16 nCellInfoFirstX
, sal_uInt16 nCellInfoLastX
, bool bRTL
)
1328 return static_cast< size_t >( bRTL
? (nCellInfoLastX
+ 2 - nCellInfoX
) : (nCellInfoX
- nCellInfoFirstX
) );
1331 void ScOutputData::DrawFrame(vcl::RenderContext
& rRenderContext
)
1333 DrawModeFlags nOldDrawMode
= rRenderContext
.GetDrawMode();
1336 bool bUseSingleColor
= false;
1337 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1338 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1340 // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1341 // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1342 // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1343 // must be reset and the border colors handled here.
1345 if ( ( nOldDrawMode
& DrawModeFlags::WhiteFill
) && ( nOldDrawMode
& DrawModeFlags::BlackLine
) )
1347 rRenderContext
.SetDrawMode( nOldDrawMode
& (~DrawModeFlags::WhiteFill
) );
1348 aSingleColor
.SetColor( COL_BLACK
);
1349 bUseSingleColor
= true;
1351 else if ( ( nOldDrawMode
& DrawModeFlags::SettingsFill
) && ( nOldDrawMode
& DrawModeFlags::SettingsLine
) )
1353 rRenderContext
.SetDrawMode( nOldDrawMode
& (~DrawModeFlags::SettingsFill
) );
1354 aSingleColor
= rStyleSettings
.GetWindowTextColor(); // same as used in VCL for DrawModeFlags::SettingsLine
1355 bUseSingleColor
= true;
1357 else if ( bCellContrast
)
1359 aSingleColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1360 bUseSingleColor
= true;
1363 const Color
* pForceColor
= bUseSingleColor
? &aSingleColor
: nullptr;
1366 DrawRotatedFrame(rRenderContext
, pForceColor
); // removes the lines that must not be painted here
1368 long nInitPosX
= nScrX
;
1371 Size aOnePixel
= rRenderContext
.PixelToLogic(Size(1,1));
1372 long nOneX
= aOnePixel
.Width();
1373 nInitPosX
+= nMirrorW
- nOneX
;
1375 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1377 // *** set column and row sizes of the frame border array ***
1379 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1380 size_t nColCount
= rArray
.GetColCount();
1381 size_t nRowCount
= rArray
.GetRowCount();
1385 // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1386 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1387 long nOldPosY
= nScrY
- 1 - pRowInfo
[ 0 ].nHeight
;
1388 long nOldSnapY
= lclGetSnappedY( rRenderContext
, nOldPosY
, bSnapPixel
);
1389 rArray
.SetYOffset( nOldSnapY
);
1390 for( size_t nRow
= 0; nRow
< nRowCount
; ++nRow
)
1392 long nNewPosY
= nOldPosY
+ pRowInfo
[ nRow
].nHeight
;
1393 long nNewSnapY
= lclGetSnappedY( rRenderContext
, nNewPosY
, bSnapPixel
);
1394 rArray
.SetRowHeight( nRow
, nNewSnapY
- nOldSnapY
);
1395 nOldPosY
= nNewPosY
;
1396 nOldSnapY
= nNewSnapY
;
1401 // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1402 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1403 long nOldPosX
= nInitPosX
- nLayoutSign
* (1 + pRowInfo
[ 0 ].pCellInfo
[ nX1
].nWidth
);
1404 long nOldSnapX
= lclGetSnappedX( rRenderContext
, nOldPosX
, bSnapPixel
);
1405 // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1407 rArray
.SetXOffset( nOldSnapX
);
1408 for( sal_uInt16 nInfoIdx
= nX1
; nInfoIdx
<= nX2
+ 2; ++nInfoIdx
)
1410 size_t nCol
= lclGetArrayColFromCellInfoX( nInfoIdx
, nX1
, nX2
, bLayoutRTL
);
1411 long nNewPosX
= nOldPosX
+ pRowInfo
[ 0 ].pCellInfo
[ nInfoIdx
].nWidth
* nLayoutSign
;
1412 long nNewSnapX
= lclGetSnappedX( rRenderContext
, nNewPosX
, bSnapPixel
);
1413 rArray
.SetColWidth( nCol
, std::abs( nNewSnapX
- nOldSnapX
) );
1414 nOldPosX
= nNewPosX
;
1415 nOldSnapX
= nNewSnapX
;
1418 rArray
.SetXOffset( nOldSnapX
);
1420 // *** draw the array ***
1422 size_t nFirstCol
= 1;
1423 size_t nFirstRow
= 1;
1424 size_t nLastCol
= nColCount
- 2;
1425 size_t nLastRow
= nRowCount
- 2;
1427 if( mrTabInfo
.mbPageMode
)
1428 rArray
.SetClipRange( nFirstCol
, nFirstRow
, nLastCol
, nLastRow
);
1430 // draw only rows with set RowInfo::bChanged flag
1431 size_t nRow1
= nFirstRow
;
1432 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(CreateProcessor2D());
1436 while( nRow1
<= nLastRow
)
1438 while( (nRow1
<= nLastRow
) && !pRowInfo
[ nRow1
].bChanged
) ++nRow1
;
1439 if( nRow1
<= nLastRow
)
1441 size_t nRow2
= nRow1
;
1442 while( (nRow2
+ 1 <= nLastRow
) && pRowInfo
[ nRow2
+ 1 ].bChanged
) ++nRow2
;
1443 rArray
.DrawRange( pProcessor
.get(), nFirstCol
, nRow1
, nLastCol
, nRow2
, pForceColor
);
1449 rRenderContext
.SetDrawMode(nOldDrawMode
);
1452 // Line below the cell
1454 static const ::editeng::SvxBorderLine
* lcl_FindHorLine( ScDocument
* pDoc
,
1455 SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_uInt16 nRotDir
,
1458 if ( nRotDir
!= SC_ROTDIR_LEFT
&& nRotDir
!= SC_ROTDIR_RIGHT
)
1461 bool bFound
= false;
1464 if ( nRotDir
== SC_ROTDIR_LEFT
)
1466 // text to the left -> line from the right
1467 if ( nCol
< MAXCOL
)
1470 return nullptr; // couldn't find it
1474 // text to the right -> line from the left
1478 return nullptr; // couldn't find it
1480 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
1481 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
1482 if ( !pPattern
->GetRotateVal( pCondSet
) ||
1483 static_cast<const SvxRotateModeItem
&>(pPattern
->GetItem(
1484 ATTR_ROTATE_MODE
, pCondSet
)).GetValue() == SVX_ROTATE_MODE_STANDARD
)
1490 const ::editeng::SvxBorderLine
* pThisBottom
;
1491 if ( ValidRow(nRow
) )
1492 pThisBottom
= static_cast<const SvxBoxItem
*>(pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
))->GetBottom();
1494 pThisBottom
= nullptr;
1495 const ::editeng::SvxBorderLine
* pNextTop
;
1496 if ( nRow
< MAXROW
)
1497 pNextTop
= static_cast<const SvxBoxItem
*>(pDoc
->GetAttr( nCol
, nRow
+1, nTab
, ATTR_BORDER
))->GetTop();
1501 if ( ScHasPriority( pThisBottom
, pNextTop
) )
1507 static long lcl_getRotate( ScDocument
* pDoc
, SCTAB nTab
, SCCOL nX
, SCROW nY
)
1511 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nX
, nY
, nTab
);
1512 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nX
, nY
, nTab
);
1514 nRotate
= pPattern
->GetRotateVal( pCondSet
);
1519 void ScOutputData::DrawRotatedFrame(vcl::RenderContext
& rRenderContext
, const Color
* pForceColor
)
1522 SCCOL nRotMax
= nX2
;
1523 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
1524 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
1525 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
1527 const ScPatternAttr
* pPattern
;
1528 const SfxItemSet
* pCondSet
;
1530 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1531 bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1533 // color (pForceColor) is determined externally, including DrawMode changes
1535 long nInitPosX
= nScrX
;
1538 Size aOnePixel
= rRenderContext
.PixelToLogic(Size(1,1));
1539 long nOneX
= aOnePixel
.Width();
1540 nInitPosX
+= nMirrorW
- nOneX
;
1542 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1544 Rectangle
aClipRect( Point(nScrX
, nScrY
), Size(nScrW
, nScrH
) );
1547 rRenderContext
.Push();
1548 rRenderContext
.IntersectClipRegion( aClipRect
);
1551 rRenderContext
.SetClipRegion( vcl::Region( aClipRect
) );
1553 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1554 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(CreateProcessor2D( ));
1557 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
1559 // Rotated is also drawn one line above/below Changed if parts extend into the cell
1561 RowInfo
& rPrevRowInfo
= pRowInfo
[nArrY
-1];
1562 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1563 RowInfo
& rNextRowInfo
= pRowInfo
[nArrY
+1];
1565 size_t nRow
= static_cast< size_t >( nArrY
);
1567 long nRowHeight
= rThisRowInfo
.nHeight
;
1568 if ( rThisRowInfo
.nRotMaxCol
!= SC_ROTMAX_NONE
&&
1569 ( rThisRowInfo
.bChanged
|| rPrevRowInfo
.bChanged
||
1570 ( nArrY
+1<nArrCount
&& rNextRowInfo
.bChanged
) ) )
1572 SCROW nY
= rThisRowInfo
.nRowNo
;
1575 for (nX
=0; nX
<=nRotMax
; nX
++)
1577 if (nX
==nX1
) nPosX
= nInitPosX
; // calculated individually for preceding positions
1579 sal_uInt16 nArrX
= nX
+ 1;
1581 CellInfo
* pInfo
= &rThisRowInfo
.pCellInfo
[nArrX
];
1582 long nColWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1583 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1584 !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
1586 pPattern
= pInfo
->pPatternAttr
;
1587 pCondSet
= pInfo
->pConditionSet
;
1590 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1591 pInfo
->pPatternAttr
= pPattern
;
1592 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
1593 pInfo
->pConditionSet
= pCondSet
;
1596 //! LastPattern etc.
1598 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
1599 SvxRotateMode eRotMode
= (SvxRotateMode
)static_cast<const SvxRotateModeItem
&>(
1600 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
1604 if (nX
<nX1
) // compute negative position
1611 nPosX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
1615 // start position minus 1 so rotated backgrounds suit the border
1616 // (border is on the grid)
1618 long nTop
= nPosY
- 1;
1619 long nBottom
= nPosY
+ nRowHeight
- 1;
1620 long nTopLeft
= nPosX
- nLayoutSign
;
1621 long nTopRight
= nPosX
+ ( nColWidth
- 1 ) * nLayoutSign
;
1622 long nBotLeft
= nTopLeft
;
1623 long nBotRight
= nTopRight
;
1625 // inclusion of the sign here hasn't been decided yet
1626 // (if not, the extension of the non-rotated background must also be changed)
1627 double nRealOrient
= nLayoutSign
* nAttrRotate
* F_PI18000
; // 1/100th degrees
1628 double nCos
= cos( nRealOrient
);
1629 double nSin
= sin( nRealOrient
);
1631 long nSkew
= (long) ( nRowHeight
* nCos
/ nSin
);
1635 case SVX_ROTATE_MODE_BOTTOM
:
1639 case SVX_ROTATE_MODE_CENTER
:
1646 case SVX_ROTATE_MODE_TOP
:
1652 // added to avoid warnings
1657 aPoints
[0] = Point( nTopLeft
, nTop
);
1658 aPoints
[1] = Point( nTopRight
, nTop
);
1659 aPoints
[2] = Point( nBotRight
, nBottom
);
1660 aPoints
[3] = Point( nBotLeft
, nBottom
);
1662 const SvxBrushItem
* pBackground
= pInfo
->pBackground
;
1664 pBackground
= static_cast<const SvxBrushItem
*>( &pPattern
->GetItem(
1665 ATTR_BACKGROUND
, pCondSet
));
1668 // high contrast for cell borders and backgrounds -> empty background
1669 pBackground
= ScGlobal::GetEmptyBrushItem();
1671 if(!pInfo
->pColorScale
)
1673 const Color
& rColor
= pBackground
->GetColor();
1674 if ( rColor
.GetTransparency() != 255 )
1676 // draw background only for the changed row itself
1677 // (background doesn't extend into other cells).
1678 // For the borders (rotated and normal), clipping should be
1679 // set if the row isn't changed, but at least the borders
1680 // don't cover the cell contents.
1681 if ( rThisRowInfo
.bChanged
)
1683 tools::Polygon
aPoly( 4, aPoints
);
1685 // for DrawPolygon, whitout Pen one pixel is left out
1686 // to the right and below...
1687 if ( rColor
.GetTransparency() == 0 )
1688 rRenderContext
.SetLineColor(rColor
);
1690 rRenderContext
.SetLineColor();
1691 rRenderContext
.SetFillColor(rColor
);
1692 rRenderContext
.DrawPolygon( aPoly
);
1698 tools::Polygon
aPoly( 4, aPoints
);
1699 const Color
* pColor
= pInfo
->pColorScale
.get();
1701 // for DrawPolygon, whitout Pen one pixel is left out
1702 // to the right and below...
1703 if ( pColor
->GetTransparency() == 0 )
1704 rRenderContext
.SetLineColor(*pColor
);
1706 rRenderContext
.SetLineColor();
1707 rRenderContext
.SetFillColor(*pColor
);
1708 rRenderContext
.DrawPolygon( aPoly
);
1712 svx::frame::Style aTopLine
, aBottomLine
, aLeftLine
, aRightLine
;
1714 if ( nX
< nX1
|| nX
> nX2
) // Attributes in FillInfo not set
1716 //! consider page borders for printing !!!!!
1717 const ::editeng::SvxBorderLine
* pLeftLine
;
1718 const ::editeng::SvxBorderLine
* pTopLine
;
1719 const ::editeng::SvxBorderLine
* pRightLine
;
1720 const ::editeng::SvxBorderLine
* pBottomLine
;
1721 mpDoc
->GetBorderLines( nX
, nY
, nTab
,
1722 &pLeftLine
, &pTopLine
, &pRightLine
, &pBottomLine
);
1723 aTopLine
.Set( pTopLine
, mnPPTY
);
1724 aBottomLine
.Set( pBottomLine
, mnPPTY
);
1725 aLeftLine
.Set( pLeftLine
, mnPPTX
);
1726 aRightLine
.Set( pRightLine
, mnPPTX
);
1730 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1731 aTopLine
= rArray
.GetCellStyleTop( nCol
, nRow
);
1732 aBottomLine
= rArray
.GetCellStyleBottom( nCol
, nRow
);
1733 aLeftLine
= rArray
.GetCellStyleLeft( nCol
, nRow
);
1734 aRightLine
= rArray
.GetCellStyleRight( nCol
, nRow
);
1735 // in RTL mode the array is already mirrored -> swap back left/right borders
1737 std::swap( aLeftLine
, aRightLine
);
1741 if (aTopLine
.Prim() || aTopLine
.Secn())
1743 long nUpperRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
- 1 );
1744 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1745 aPoints
[bLayoutRTL
?1:0], aPoints
[bLayoutRTL
?0:1], aTopLine
,
1746 svx::frame::Style(),
1747 svx::frame::Style(),
1749 svx::frame::Style(),
1750 svx::frame::Style(),
1752 pForceColor
, nUpperRotate
, nAttrRotate
) );
1755 if (aBottomLine
.Prim() || aBottomLine
.Secn())
1757 long nLowerRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
+ 1 );
1758 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1759 aPoints
[bLayoutRTL
?2:3], aPoints
[bLayoutRTL
?3:2], aBottomLine
,
1761 svx::frame::Style(),
1762 svx::frame::Style(),
1764 svx::frame::Style(),
1765 svx::frame::Style(),
1766 pForceColor
, 18000 - nAttrRotate
, 18000 - nLowerRotate
) );
1769 // Vertical slanted lines
1770 if (aLeftLine
.Prim() || aLeftLine
.Secn())
1772 long nLeftRotate
= lcl_getRotate( mpDoc
, nTab
, nX
- 1, nY
);
1773 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1774 aPoints
[0], aPoints
[3], aLeftLine
,
1776 svx::frame::Style(),
1777 svx::frame::Style(),
1779 svx::frame::Style(),
1780 svx::frame::Style(),
1781 pForceColor
, nAttrRotate
, nLeftRotate
) );
1784 if (aRightLine
.Prim() || aRightLine
.Secn())
1786 long nRightRotate
= lcl_getRotate( mpDoc
, nTab
, nX
+ 1, nY
);
1787 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1788 aPoints
[1], aPoints
[2], aRightLine
,
1789 svx::frame::Style(),
1790 svx::frame::Style(),
1792 svx::frame::Style(),
1793 svx::frame::Style(),
1795 pForceColor
, 18000 - nRightRotate
, 18000 - nAttrRotate
) );
1799 nPosX
+= nColWidth
* nLayoutSign
;
1802 // delete the lines for normal output only afterwards in the second step
1804 nX
= nX1
> 0 ? (nX1
-1) : static_cast<SCCOL
>(0);
1805 for (; nX
<=nX2
+1; nX
++) // visible part +- 1
1807 sal_uInt16 nArrX
= nX
+ 1;
1808 CellInfo
& rInfo
= rThisRowInfo
.pCellInfo
[nArrX
];
1809 if ( rInfo
.nRotateDir
> SC_ROTDIR_STANDARD
&&
1810 !rInfo
.bHOverlapped
&& !rInfo
.bVOverlapped
)
1812 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1814 // horizontal: extend adjacent line
1815 // (only when the rotated cell has a border)
1816 sal_uInt16 nDir
= rInfo
.nRotateDir
;
1817 if ( rArray
.GetCellStyleTop( nCol
, nRow
).Prim() )
1819 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, true ), mnPPTY
);
1820 rArray
.SetCellStyleTop( nCol
, nRow
, aStyle
);
1822 rArray
.SetCellStyleBottom( nCol
, nRow
- 1, aStyle
);
1824 if ( rArray
.GetCellStyleBottom( nCol
, nRow
).Prim() )
1826 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, false ), mnPPTY
);
1827 rArray
.SetCellStyleBottom( nCol
, nRow
, aStyle
);
1828 if( nRow
+ 1 < rArray
.GetRowCount() )
1829 rArray
.SetCellStyleTop( nCol
, nRow
+ 1, aStyle
);
1832 // always remove vertical borders
1833 if( !rArray
.IsMergedOverlappedLeft( nCol
, nRow
) )
1835 rArray
.SetCellStyleLeft( nCol
, nRow
, svx::frame::Style() );
1837 rArray
.SetCellStyleRight( nCol
- 1, nRow
, svx::frame::Style() );
1839 if( !rArray
.IsMergedOverlappedRight( nCol
, nRow
) )
1841 rArray
.SetCellStyleRight( nCol
, nRow
, svx::frame::Style() );
1842 if( nCol
+ 1 < rArray
.GetColCount() )
1843 rArray
.SetCellStyleLeft( nCol
+ 1, nRow
, svx::frame::Style() );
1846 // remove diagonal borders
1847 rArray
.SetCellStyleTLBR( nCol
, nRow
, svx::frame::Style() );
1848 rArray
.SetCellStyleBLTR( nCol
, nRow
, svx::frame::Style() );
1852 nPosY
+= nRowHeight
;
1858 rRenderContext
.Pop();
1860 rRenderContext
.SetClipRegion();
1863 drawinglayer::processor2d::BaseProcessor2D
* ScOutputData::CreateProcessor2D( )
1865 mpDoc
->InitDrawLayer(mpDoc
->GetDocumentShell());
1866 ScDrawLayer
* pDrawLayer
= mpDoc
->GetDrawLayer();
1870 basegfx::B2DRange aViewRange
;
1871 SdrPage
*pDrawPage
= pDrawLayer
->GetPage( static_cast< sal_uInt16
>( nTab
) );
1872 const drawinglayer::geometry::ViewInformation2D
aNewViewInfos(
1873 basegfx::B2DHomMatrix( ),
1874 mpDev
->GetViewTransformation(),
1876 GetXDrawPageForSdrPage( pDrawPage
),
1878 uno::Sequence
< beans::PropertyValue
>() );
1880 return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1881 *mpDev
, aNewViewInfos
);
1886 vcl::Region
ScOutputData::GetChangedAreaRegion()
1888 vcl::Region aRegion
;
1889 Rectangle aDrawingRect
;
1894 aDrawingRect
.Left() = nScrX
;
1895 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1897 for(nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1899 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1901 if(pThisRowInfo
->bChanged
)
1905 aDrawingRect
.Top() = nPosY
;
1909 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1913 aRegion
.Union(mpDev
->PixelToLogic(aDrawingRect
));
1917 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1922 aRegion
.Union(mpDev
->PixelToLogic(aDrawingRect
));
1928 bool ScOutputData::SetChangedClip()
1930 tools::PolyPolygon aPoly
;
1932 Rectangle aDrawingRect
;
1933 aDrawingRect
.Left() = nScrX
;
1934 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1939 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1941 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1943 if ( pThisRowInfo
->bChanged
)
1947 aDrawingRect
.Top() = nPosY
;
1950 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1954 aPoly
.Insert( tools::Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1957 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1961 aPoly
.Insert( tools::Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1963 bool bRet
= (aPoly
.Count() != 0);
1965 mpDev
->SetClipRegion(vcl::Region(aPoly
));
1969 void ScOutputData::FindChanged()
1974 bool bWasIdleEnabled
= mpDoc
->IsIdleEnabled();
1975 mpDoc
->EnableIdle(false);
1976 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1977 pRowInfo
[nArrY
].bChanged
= false;
1979 bool bProgress
= false;
1980 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1982 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1983 for (nX
=nX1
; nX
<=nX2
; nX
++)
1985 const ScRefCellValue
& rCell
= pThisRowInfo
->pCellInfo
[nX
+1].maCell
;
1987 if (rCell
.meType
!= CELLTYPE_FORMULA
)
1990 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
1991 if ( !bProgress
&& pFCell
->GetDirty() )
1993 ScProgress::CreateInterpretProgress(mpDoc
);
1996 if (pFCell
->IsRunning())
1997 // still being interpreted. Skip it.
2000 (void)pFCell
->GetValue();
2001 if (!pFCell
->IsChanged())
2002 // the result hasn't changed. Skip it.
2005 pThisRowInfo
->bChanged
= true;
2006 if ( pThisRowInfo
->pCellInfo
[nX
+1].bMerged
)
2008 SCSIZE nOverY
= nArrY
+ 1;
2009 while ( nOverY
<nArrCount
&&
2010 pRowInfo
[nOverY
].pCellInfo
[nX
+1].bVOverlapped
)
2012 pRowInfo
[nOverY
].bChanged
= true;
2019 ScProgress::DeleteInterpretProgress();
2020 mpDoc
->EnableIdle(bWasIdleEnabled
);
2023 void ScOutputData::DrawRefMark( SCCOL nRefStartX
, SCROW nRefStartY
,
2024 SCCOL nRefEndX
, SCROW nRefEndY
,
2025 const Color
& rColor
, bool bHandle
)
2027 PutInOrder( nRefStartX
, nRefEndX
);
2028 PutInOrder( nRefStartY
, nRefEndY
);
2030 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
2031 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
2033 if ( nRefStartX
<= nVisX2
&& nRefEndX
>= nVisX1
&&
2034 nRefStartY
<= nVisY2
&& nRefEndY
>= nVisY1
)
2038 long nMaxX
= nScrX
+ nScrW
- 1;
2039 long nMaxY
= nScrY
+ nScrH
- 1;
2046 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2049 bool bBottom
= false;
2051 bool bRight
= false;
2054 bool bNoStartY
= ( nY1
< nRefStartY
);
2055 bool bNoEndY
= false;
2056 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2058 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2060 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2067 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 2;
2070 if ( nY
>nRefEndY
&& bNoEndY
)
2075 bNoStartY
= ( nY
< nRefStartY
);
2076 bNoEndY
= ( nY
< nRefEndY
);
2077 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2082 nPosX
+= nMirrorW
- 1; // always in pixels
2084 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2086 if ( nX
==nRefStartX
)
2093 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 2 ) * nLayoutSign
;
2096 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2099 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2102 mpDev
->SetLineColor( rColor
);
2103 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2105 mpDev
->SetFillColor();
2106 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2111 mpDev
->DrawLine( Point( nMinX
, nMinY
), Point( nMaxX
, nMinY
) );
2113 mpDev
->DrawLine( Point( nMinX
, nMaxY
), Point( nMaxX
, nMaxY
) );
2115 mpDev
->DrawLine( Point( nMinX
, nMinY
), Point( nMinX
, nMaxY
) );
2117 mpDev
->DrawLine( Point( nMaxX
, nMinY
), Point( nMaxX
, nMaxY
) );
2119 if ( bHandle
&& bRight
&& bBottom
)
2121 mpDev
->SetLineColor( rColor
);
2122 mpDev
->SetFillColor( rColor
);
2124 const sal_Int32 aRadius
= 4;
2126 sal_Int32 aRectMaxX1
= nMaxX
- nLayoutSign
* aRadius
;
2127 sal_Int32 aRectMaxX2
= nMaxX
+ nLayoutSign
;
2128 sal_Int32 aRectMinX1
= nMinX
- nLayoutSign
;
2129 sal_Int32 aRectMinX2
= nMinX
+ nLayoutSign
* aRadius
;
2131 sal_Int32 aRectMaxY1
= nMaxY
- aRadius
;
2132 sal_Int32 aRectMaxY2
= nMaxY
+ 1;
2133 sal_Int32 aRectMinY1
= nMinY
- 1;
2134 sal_Int32 aRectMinY2
= nMinY
+ aRadius
;
2136 // Draw corner rectangles
2137 Rectangle
aLowerRight( aRectMaxX1
, aRectMaxY1
, aRectMaxX2
, aRectMaxY2
);
2138 Rectangle
aUpperLeft ( aRectMinX1
, aRectMinY1
, aRectMinX2
, aRectMinY2
);
2139 Rectangle
aLowerLeft ( aRectMinX1
, aRectMaxY1
, aRectMinX2
, aRectMaxY2
);
2140 Rectangle
aUpperRight( aRectMaxX1
, aRectMinY1
, aRectMaxX2
, aRectMinY2
);
2142 mpDev
->DrawTransparent( tools::PolyPolygon( tools::Polygon( aLowerRight
) ), lclCornerRectTransparency
);
2143 mpDev
->DrawTransparent( tools::PolyPolygon( tools::Polygon( aUpperLeft
) ), lclCornerRectTransparency
);
2144 mpDev
->DrawTransparent( tools::PolyPolygon( tools::Polygon( aLowerLeft
) ), lclCornerRectTransparency
);
2145 mpDev
->DrawTransparent( tools::PolyPolygon( tools::Polygon( aUpperRight
) ), lclCornerRectTransparency
);
2151 void ScOutputData::DrawOneChange( SCCOL nRefStartX
, SCROW nRefStartY
,
2152 SCCOL nRefEndX
, SCROW nRefEndY
,
2153 const Color
& rColor
, sal_uInt16 nType
)
2155 PutInOrder( nRefStartX
, nRefEndX
);
2156 PutInOrder( nRefStartY
, nRefEndY
);
2158 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
2159 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
2161 if ( nRefStartX
<= nVisX2
+ 1 && nRefEndX
>= nVisX1
&&
2162 nRefStartY
<= nVisY2
+ 1 && nRefEndY
>= nVisY1
) // +1 because it touches next cells left/top
2166 long nMaxX
= nScrX
+nScrW
-1;
2167 long nMaxY
= nScrY
+nScrH
-1;
2174 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2177 bool bBottom
= false;
2179 bool bRight
= false;
2182 bool bNoStartY
= ( nY1
< nRefStartY
);
2183 bool bNoEndY
= false;
2184 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2186 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2188 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2195 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
2198 if ( nY
>nRefEndY
&& bNoEndY
)
2203 bNoStartY
= ( nY
< nRefStartY
);
2204 bNoEndY
= ( nY
< nRefEndY
);
2205 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2210 nPosX
+= nMirrorW
- 1; // always in pixels
2212 for (SCCOL nX
=nX1
; nX
<=nX2
+1; nX
++)
2214 if ( nX
==nRefStartX
)
2216 nMinX
= nPosX
- nLayoutSign
;
2221 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 1 ) * nLayoutSign
;
2224 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2227 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2230 if ( nType
== SC_CAT_DELETE_ROWS
)
2231 bLeft
= bRight
= bBottom
= false; //! thick lines???
2232 else if ( nType
== SC_CAT_DELETE_COLS
)
2233 bTop
= bBottom
= bRight
= false; //! thick lines???
2235 mpDev
->SetLineColor( rColor
);
2236 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2238 mpDev
->SetFillColor();
2239 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2245 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMaxX
,nMinY
) );
2246 if ( nType
== SC_CAT_DELETE_ROWS
)
2247 mpDev
->DrawLine( Point( nMinX
,nMinY
+1 ), Point( nMaxX
,nMinY
+1 ) );
2250 mpDev
->DrawLine( Point( nMinX
,nMaxY
), Point( nMaxX
,nMaxY
) );
2253 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMinX
,nMaxY
) );
2254 if ( nType
== SC_CAT_DELETE_COLS
)
2255 mpDev
->DrawLine( Point( nMinX
+nLayoutSign
,nMinY
), Point( nMinX
+nLayoutSign
,nMaxY
) );
2258 mpDev
->DrawLine( Point( nMaxX
,nMinY
), Point( nMaxX
,nMaxY
) );
2260 if ( bLeft
&& bTop
)
2262 mpDev
->SetLineColor();
2263 mpDev
->SetFillColor( rColor
);
2264 mpDev
->DrawRect( Rectangle( nMinX
+nLayoutSign
, nMinY
+1, nMinX
+3*nLayoutSign
, nMinY
+3 ) );
2270 void ScOutputData::DrawChangeTrack()
2272 ScChangeTrack
* pTrack
= mpDoc
->GetChangeTrack();
2273 ScChangeViewSettings
* pSettings
= mpDoc
->GetChangeViewSettings();
2274 if ( !pTrack
|| !pTrack
->GetFirst() || !pSettings
|| !pSettings
->ShowChanges() )
2275 return; // nothing there or hidden
2277 ScActionColorChanger
aColorChanger(*pTrack
);
2279 // clipping happens from the outside
2280 //! without clipping, only paÃnt affected cells ??!??!?
2284 if ( nEndX
< MAXCOL
) ++nEndX
; // also from the next cell since the mark
2285 if ( nEndY
< MAXROW
) ++nEndY
; // protrudes from the preceding cell
2286 ScRange
aViewRange( nX1
, nY1
, nTab
, nEndX
, nEndY
, nTab
);
2287 const ScChangeAction
* pAction
= pTrack
->GetFirst();
2290 ScChangeActionType eActionType
;
2291 if ( pAction
->IsVisible() )
2293 eActionType
= pAction
->GetType();
2294 const ScBigRange
& rBig
= pAction
->GetBigRange();
2295 if ( rBig
.aStart
.Tab() == nTab
)
2297 ScRange aRange
= rBig
.MakeRange();
2299 if ( eActionType
== SC_CAT_DELETE_ROWS
)
2300 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
2301 else if ( eActionType
== SC_CAT_DELETE_COLS
)
2302 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
2304 if ( aRange
.Intersects( aViewRange
) &&
2305 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2307 aColorChanger
.Update( *pAction
);
2308 Color
aColor( aColorChanger
.GetColor() );
2309 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2310 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2314 if ( eActionType
== SC_CAT_MOVE
&&
2315 static_cast<const ScChangeActionMove
*>(pAction
)->
2316 GetFromRange().aStart
.Tab() == nTab
)
2318 ScRange aRange
= static_cast<const ScChangeActionMove
*>(pAction
)->
2319 GetFromRange().MakeRange();
2320 if ( aRange
.Intersects( aViewRange
) &&
2321 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2323 aColorChanger
.Update( *pAction
);
2324 Color
aColor( aColorChanger
.GetColor() );
2325 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2326 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2331 pAction
= pAction
->GetNext();
2335 //TODO: moggi Need to check if this can't be written simpler
2336 void ScOutputData::DrawNoteMarks(vcl::RenderContext
& rRenderContext
)
2341 long nInitPosX
= nScrX
;
2343 nInitPosX
+= nMirrorW
- 1; // always in pixels
2344 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2347 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2349 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2350 if ( pThisRowInfo
->bChanged
)
2352 long nPosX
= nInitPosX
;
2353 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2355 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2356 bool bIsMerged
= false;
2358 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2360 // find start of merged cell
2362 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2365 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2366 // use origin's pCell for NotePtr test below
2369 if ( mpDoc
->GetNote(nX
, pRowInfo
[nArrY
].nRowNo
, nTab
) && ( bIsMerged
||
2370 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2374 rRenderContext
.SetLineColor(COL_WHITE
);
2376 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2377 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2378 rRenderContext
.SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2380 rRenderContext
.SetFillColor(COL_LIGHTRED
);
2385 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 4 ) * nLayoutSign
;
2386 if ( bIsMerged
|| pInfo
->bMerged
)
2388 // if merged, add widths of all cells
2389 SCCOL nNextX
= nX
+ 1;
2390 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2392 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2396 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2397 rRenderContext
.DrawRect( Rectangle( nMarkX
-5*nLayoutSign
,nPosY
,nMarkX
+1*nLayoutSign
,nPosY
+6 ) );
2400 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2403 nPosY
+= pThisRowInfo
->nHeight
;
2407 void ScOutputData::AddPDFNotes()
2409 vcl::PDFExtOutDevData
* pPDFData
= dynamic_cast< vcl::PDFExtOutDevData
* >( mpDev
->GetExtOutDevData() );
2410 if ( !pPDFData
|| !pPDFData
->GetIsExportNotes() )
2413 long nInitPosX
= nScrX
;
2416 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
2417 long nOneX
= aOnePixel
.Width();
2418 nInitPosX
+= nMirrorW
- nOneX
;
2420 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2423 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2425 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2426 if ( pThisRowInfo
->bChanged
)
2428 long nPosX
= nInitPosX
;
2429 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2431 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2432 bool bIsMerged
= false;
2433 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2437 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2439 // find start of merged cell
2441 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2442 // use origin's pCell for NotePtr test below
2445 if ( mpDoc
->GetNote(nMergeX
, nMergeY
, nTab
) && ( bIsMerged
||
2446 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2448 long nNoteWidth
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2449 long nNoteHeight
= (long)( SC_CLIPMARK_SIZE
* mnPPTY
);
2451 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- nNoteWidth
) * nLayoutSign
;
2452 if ( bIsMerged
|| pInfo
->bMerged
)
2454 // if merged, add widths of all cells
2455 SCCOL nNextX
= nX
+ 1;
2456 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2458 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2462 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2464 Rectangle
aNoteRect( nMarkX
, nPosY
, nMarkX
+nNoteWidth
*nLayoutSign
, nPosY
+nNoteHeight
);
2465 const ScPostIt
* pNote
= mpDoc
->GetNote(nMergeX
, nMergeY
, nTab
);
2467 // Note title is the cell address (as on printed note pages)
2468 ScAddress
aAddress( nMergeX
, nMergeY
, nTab
);
2469 OUString
aTitle(aAddress
.Format(ScRefFlags::VALID
, mpDoc
, mpDoc
->GetAddressConvention()));
2471 // Content has to be a simple string without line breaks
2472 OUString aContent
= pNote
->GetText();
2473 aContent
= aContent
.replaceAll("\n", " ");
2476 aNote
.Title
= aTitle
;
2477 aNote
.Contents
= aContent
;
2478 pPDFData
->CreateNote( aNoteRect
, aNote
);
2482 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2485 nPosY
+= pThisRowInfo
->nHeight
;
2489 void ScOutputData::DrawClipMarks()
2494 Color
aArrowFillCol( COL_LIGHTRED
);
2496 DrawModeFlags nOldDrawMode
= mpDev
->GetDrawMode();
2497 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2498 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2500 // use DrawMode to change the arrow's outline color
2501 mpDev
->SetDrawMode( nOldDrawMode
| DrawModeFlags::SettingsLine
);
2502 // use text color also for the fill color
2503 aArrowFillCol
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2506 long nInitPosX
= nScrX
;
2508 nInitPosX
+= nMirrorW
- 1; // always in pixels
2509 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2511 Rectangle aCellRect
;
2513 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2515 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2516 if ( pThisRowInfo
->bChanged
)
2518 SCROW nY
= pThisRowInfo
->nRowNo
;
2519 long nPosX
= nInitPosX
;
2520 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2522 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2523 if (pInfo
->nClipMark
)
2525 if (pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
)
2527 // merge origin may be outside of visible area - use document functions
2531 long nStartPosX
= nPosX
;
2532 long nStartPosY
= nPosY
;
2534 while ( nOverX
> 0 && ( static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
2535 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & ScMF::Hor
) )
2538 nStartPosX
-= nLayoutSign
* (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2541 while ( nOverY
> 0 && ( static_cast<const ScMergeFlagAttr
*>(mpDoc
->GetAttr(
2542 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & ScMF::Ver
) )
2545 nStartPosY
-= nLayoutSign
* (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2548 long nOutWidth
= (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2549 long nOutHeight
= (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2551 const ScMergeAttr
* pMerge
= static_cast<const ScMergeAttr
*>(
2552 mpDoc
->GetAttr( nOverX
, nOverY
, nTab
, ATTR_MERGE
));
2553 SCCOL nCountX
= pMerge
->GetColMerge();
2554 for (SCCOL i
=1; i
<nCountX
; i
++)
2555 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2556 SCROW nCountY
= pMerge
->GetRowMerge();
2557 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2560 nStartPosX
-= nOutWidth
- 1;
2561 aCellRect
= Rectangle( Point( nStartPosX
, nStartPosY
), Size( nOutWidth
, nOutHeight
) );
2565 long nOutWidth
= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
2566 long nOutHeight
= pThisRowInfo
->nHeight
;
2568 if ( pInfo
->bMerged
&& pInfo
->pPatternAttr
)
2572 const ScMergeAttr
* pMerge
=
2573 static_cast<const ScMergeAttr
*>(&pInfo
->pPatternAttr
->GetItem(ATTR_MERGE
));
2574 SCCOL nCountX
= pMerge
->GetColMerge();
2575 for (SCCOL i
=1; i
<nCountX
; i
++)
2576 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2577 SCROW nCountY
= pMerge
->GetRowMerge();
2578 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2581 long nStartPosX
= nPosX
;
2583 nStartPosX
-= nOutWidth
- 1;
2584 // #i80447# create aCellRect from two points in case nOutWidth is 0
2585 aCellRect
= Rectangle( Point( nStartPosX
, nPosY
),
2586 Point( nStartPosX
+nOutWidth
-1, nPosY
+nOutHeight
-1 ) );
2589 aCellRect
.Bottom() -= 1; // don't paint over the cell grid
2591 aCellRect
.Left() += 1;
2593 aCellRect
.Right() -= 1;
2595 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2596 Size
aMarkSize( nMarkPixel
, (nMarkPixel
-1)*2 );
2598 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_RIGHT
: SC_CLIPMARK_LEFT
) )
2601 Rectangle aMarkRect
= aCellRect
;
2602 aMarkRect
.Right() = aCellRect
.Left()+nMarkPixel
-1;
2603 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, true );
2605 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_LEFT
: SC_CLIPMARK_RIGHT
) )
2608 Rectangle aMarkRect
= aCellRect
;
2609 aMarkRect
.Left() = aCellRect
.Right()-nMarkPixel
+1;
2610 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, false );
2613 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2616 nPosY
+= pThisRowInfo
->nHeight
;
2619 mpDev
->SetDrawMode(nOldDrawMode
);
2622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */