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/brshitem.hxx>
25 #include <editeng/editdata.hxx>
26 #include <svtools/colorcfg.hxx>
27 #include "svtools/optionsdrawinglayer.hxx"
28 #include <svx/rotmodit.hxx>
29 #include <editeng/shaditem.hxx>
30 #include <editeng/svxfont.hxx>
31 #include <svx/svdoole2.hxx>
32 #include <tools/poly.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/pdfextoutdevdata.hxx>
35 #include <svtools/accessibilityoptions.hxx>
36 #include <svx/framelinkarray.hxx>
37 #include <drawinglayer/geometry/viewinformation2d.hxx>
38 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
41 #include <vcl/lineinfo.hxx>
42 #include <vcl/gradient.hxx>
43 #include <svx/unoapi.hxx>
46 #include "document.hxx"
47 #include "drwlayer.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"
73 using namespace com::sun::star
;
75 // STATIC DATA -----------------------------------------------------------
77 // Farben fuer ChangeTracking "nach Autor" wie im Writer (swmodul1.cxx)
79 #define SC_AUTHORCOLORCOUNT 9
81 static ColorData nAuthorColor
[ SC_AUTHORCOLORCOUNT
] = {
82 COL_LIGHTRED
, COL_LIGHTBLUE
, COL_LIGHTMAGENTA
,
83 COL_GREEN
, COL_RED
, COL_BLUE
,
84 COL_BROWN
, COL_MAGENTA
, COL_CYAN
};
87 // Hilfsklasse, fuer die Farbzuordnung,
88 // um nicht mehrfach hintereinander denselben User aus der Liste zu suchen
90 class ScActionColorChanger
93 const ScAppOptions
& rOpt
;
94 const std::set
<rtl::OUString
>& rUsers
;
95 rtl::OUString aLastUserName
;
96 size_t nLastUserIndex
;
100 ScActionColorChanger( const ScChangeTrack
& rTrack
);
101 ~ScActionColorChanger() {}
103 void Update( const ScChangeAction
& rAction
);
104 ColorData
GetColor() const { return nColor
; }
107 //------------------------------------------------------------------
109 ScActionColorChanger::ScActionColorChanger( const ScChangeTrack
& rTrack
) :
110 rOpt( SC_MOD()->GetAppOptions() ),
111 rUsers( rTrack
.GetUserCollection() ),
117 void ScActionColorChanger::Update( const ScChangeAction
& rAction
)
120 switch (rAction
.GetType())
122 case SC_CAT_INSERT_COLS
:
123 case SC_CAT_INSERT_ROWS
:
124 case SC_CAT_INSERT_TABS
:
125 nSetColor
= rOpt
.GetTrackInsertColor();
127 case SC_CAT_DELETE_COLS
:
128 case SC_CAT_DELETE_ROWS
:
129 case SC_CAT_DELETE_TABS
:
130 nSetColor
= rOpt
.GetTrackDeleteColor();
133 nSetColor
= rOpt
.GetTrackMoveColor();
136 nSetColor
= rOpt
.GetTrackContentColor();
139 if ( nSetColor
!= COL_TRANSPARENT
) // Farbe eingestellt
143 if (!aLastUserName
.equals(rAction
.GetUser()))
145 aLastUserName
= rAction
.GetUser();
146 std::set
<rtl::OUString
>::const_iterator it
= rUsers
.find(aLastUserName
);
147 if (it
== rUsers
.end())
149 // empty string is possible if a name wasn't found while saving a 5.0 file
150 SAL_INFO_IF( aLastUserName
.isEmpty(), "sc.ui", "Author not found" );
155 size_t nPos
= std::distance(rUsers
.begin(), it
);
156 nLastUserIndex
= nPos
% SC_AUTHORCOLORCOUNT
;
159 nColor
= nAuthorColor
[nLastUserIndex
];
163 //==================================================================
165 ScOutputData::ScOutputData( OutputDevice
* pNewDev
, ScOutputType eNewType
,
166 ScTableInfo
& rTabInfo
, ScDocument
* pNewDoc
,
167 SCTAB nNewTab
, long nNewScrX
, long nNewScrY
,
168 SCCOL nNewX1
, SCROW nNewY1
, SCCOL nNewX2
, SCROW nNewY2
,
169 double nPixelPerTwipsX
, double nPixelPerTwipsY
,
170 const Fraction
* pZoomX
, const Fraction
* pZoomY
) :
172 mpRefDevice( pNewDev
), // default is output device
173 pFmtDevice( pNewDev
), // default is output device
174 mrTabInfo( rTabInfo
),
175 pRowInfo( rTabInfo
.mpRowInfo
),
176 nArrCount( rTabInfo
.mnArrCount
),
186 mnPPTX( nPixelPerTwipsX
),
187 mnPPTY( nPixelPerTwipsY
),
190 pDrawView( NULL
), // #114135#
193 bSingleGrid( false ),
194 bPagebreakMode( false ),
195 bSolidBackground( false ),
196 mbUseStyleColor( false ),
197 mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
198 mbSyntaxMode( false ),
201 pFormulaColor( NULL
),
202 aGridColor( COL_BLACK
),
203 mbShowNullValues( sal_True
),
204 mbShowFormulas( false ),
205 bShowSpellErrors( false ),
206 bMarkClipped( false ), // sal_False fuer Drucker/Metafile etc.
208 bAnyRotated( false ),
209 bAnyClipped( false ),
210 mpTargetPaintWindow(0) // #i74769# use SdrPaintWindow direct
215 aZoomX
= Fraction(1,1);
219 aZoomY
= Fraction(1,1);
225 mpDoc
->StripHidden( nVisX1
, nVisY1
, nVisX2
, nVisY2
, nTab
);
228 for (SCCOL nX
=nVisX1
; nX
<=nVisX2
; nX
++)
229 nScrW
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
234 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
235 nScrH
+= pRowInfo
[nArrY
].nHeight
;
237 bTabProtected
= mpDoc
->IsTabProtected( nTab
);
238 nTabTextDirection
= mpDoc
->GetEditTextDirection( nTab
);
239 bLayoutRTL
= mpDoc
->IsLayoutRTL( nTab
);
242 ScOutputData::~ScOutputData()
246 delete pFormulaColor
;
249 void ScOutputData::SetContentDevice( OutputDevice
* pContentDev
)
251 // use pContentDev instead of pDev where used
253 if ( mpRefDevice
== mpDev
)
254 mpRefDevice
= pContentDev
;
255 if ( pFmtDevice
== mpDev
)
256 pFmtDevice
= pContentDev
;
260 void ScOutputData::SetMirrorWidth( long nNew
)
265 void ScOutputData::SetGridColor( const Color
& rColor
)
270 void ScOutputData::SetMarkClipped( sal_Bool bSet
)
275 void ScOutputData::SetShowNullValues( sal_Bool bSet
)
277 mbShowNullValues
= bSet
;
280 void ScOutputData::SetShowFormulas( sal_Bool bSet
)
282 mbShowFormulas
= bSet
;
285 void ScOutputData::SetShowSpellErrors( sal_Bool bSet
)
287 bShowSpellErrors
= bSet
;
290 void ScOutputData::SetSnapPixel( sal_Bool bSet
)
295 void ScOutputData::SetEditCell( SCCOL nCol
, SCROW nRow
)
299 bEditMode
= sal_True
;
302 void ScOutputData::SetMetaFileMode( sal_Bool bNewMode
)
304 bMetaFile
= bNewMode
;
307 void ScOutputData::SetSingleGrid( sal_Bool bNewMode
)
309 bSingleGrid
= bNewMode
;
312 void ScOutputData::SetSyntaxMode( sal_Bool bNewMode
)
314 mbSyntaxMode
= bNewMode
;
318 pValueColor
= new Color( COL_LIGHTBLUE
);
319 pTextColor
= new Color( COL_BLACK
);
320 pFormulaColor
= new Color( COL_GREEN
);
324 void ScOutputData::DrawGrid( sal_Bool bGrid
, sal_Bool bPage
)
331 ScBreakType nBreak
= BREAK_NONE
;
332 ScBreakType nBreakOld
= BREAK_NONE
;
339 bPage
= false; // keine "normalen" Umbrueche ueber volle Breite/Hoehe
341 //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
342 //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
344 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
345 long nOneX
= aOnePixel
.Width();
346 long nOneY
= aOnePixel
.Height();
350 long nLayoutSign
= bLayoutRTL
? -1 : 1;
351 long nSignedOneX
= nOneX
* nLayoutSign
;
353 if ( eType
== OUTTYPE_WINDOW
)
355 const svtools::ColorConfig
& rColorCfg
= SC_MOD()->GetColorConfig();
356 aPageColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC
).nColor
);
357 aManualColor
.SetColor( rColorCfg
.GetColorValue(svtools::CALCPAGEBREAKMANUAL
).nColor
);
361 aPageColor
= aGridColor
;
362 aManualColor
= aGridColor
;
365 mpDev
->SetLineColor( aGridColor
);
366 ScGridMerger
aGrid( mpDev
, nOneX
, nOneY
);
374 nPosX
+= nMirrorW
- nOneX
;
376 for (nX
=nX1
; nX
<=nX2
; nX
++)
378 SCCOL nXplus1
= nX
+1;
379 SCCOL nXplus2
= nX
+2;
380 sal_uInt16 nWidth
= pRowInfo
[0].pCellInfo
[nXplus1
].nWidth
;
383 nPosX
+= nWidth
* nLayoutSign
;
387 // Seitenumbrueche auch in ausgeblendeten suchen
388 SCCOL nCol
= nXplus1
;
389 while (nCol
<= MAXCOL
)
391 nBreak
= mpDoc
->HasColBreak(nCol
, nTab
);
392 bool bHidden
= mpDoc
->ColHidden(nCol
, nTab
);
394 if ( nBreak
|| !bHidden
)
399 if (nBreak
!= nBreakOld
)
402 mpDev
->SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
403 nBreak
? aPageColor
: aGridColor
);
408 sal_Bool bDraw
= bGrid
|| nBreakOld
; // einfaches Gitter nur wenn eingestellt
410 sal_uInt16 nWidthXplus2
= pRowInfo
[0].pCellInfo
[nXplus2
].nWidth
;
411 bSingle
= bSingleGrid
; //! in Fillinfo holen !!!!!
412 if ( nX
<MAXCOL
&& !bSingle
)
414 bSingle
= ( nWidthXplus2
== 0 );
415 for (nArrY
=1; nArrY
+1<nArrCount
&& !bSingle
; nArrY
++)
417 if (pRowInfo
[nArrY
].pCellInfo
[nXplus2
].bHOverlapped
)
419 if (pRowInfo
[nArrY
].pCellInfo
[nXplus1
].bHideGrid
)
426 if ( nX
<MAXCOL
&& bSingle
)
428 SCCOL nVisX
= nXplus1
;
429 while ( nVisX
< MAXCOL
&& !mpDoc
->GetColWidth(nVisX
,nTab
) )
434 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
436 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
437 nNextY
= nPosY
+ pThisRowInfo
->nHeight
;
439 sal_Bool bHOver
= pThisRowInfo
->pCellInfo
[nXplus1
].bHideGrid
;
443 bHOver
= pThisRowInfo
->pCellInfo
[nXplus2
].bHOverlapped
;
447 bHOver
= pThisRowInfo
->pCellInfo
[nVisX
+1].bHOverlapped
;
449 bHOver
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
450 nVisX
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
453 bHOver
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
454 nXplus1
,pThisRowInfo
->nRowNo
,nTab
,ATTR_MERGE_FLAG
))
459 if (pThisRowInfo
->bChanged
&& !bHOver
)
461 aGrid
.AddVerLine( nPosX
-nSignedOneX
, nPosY
, nNextY
-nOneY
);
468 aGrid
.AddVerLine( nPosX
-nSignedOneX
, nScrY
, nScrY
+nScrH
-nOneY
);
475 // Horizontale Linien
478 bool bHiddenRow
= true;
479 SCROW nHiddenEndRow
= -1;
481 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
483 SCSIZE nArrYplus1
= nArrY
+1;
484 nY
= pRowInfo
[nArrY
].nRowNo
;
485 SCROW nYplus1
= nY
+1;
486 nPosY
+= pRowInfo
[nArrY
].nHeight
;
488 if (pRowInfo
[nArrY
].bChanged
)
492 for (SCROW i
= nYplus1
; i
<= MAXROW
; ++i
)
494 if (i
> nHiddenEndRow
)
495 bHiddenRow
= mpDoc
->RowHidden(i
, nTab
, NULL
, &nHiddenEndRow
);
496 /* TODO: optimize the row break thing for large hidden
497 * segments where HasRowBreak() has to be called
498 * nevertheless for each row, as a row break is drawn also
499 * for hidden rows, above them. This needed to be done only
500 * once per hidden segment, maybe giving manual breaks
501 * priority. Something like GetNextRowBreak() and
502 * GetNextManualRowBreak(). */
503 nBreak
= mpDoc
->HasRowBreak(i
, nTab
);
504 if (!bHiddenRow
|| nBreak
)
508 if (nBreakOld
!= nBreak
)
511 mpDev
->SetLineColor( (nBreak
& BREAK_MANUAL
) ? aManualColor
:
512 (nBreak
) ? aPageColor
: aGridColor
);
517 sal_Bool bDraw
= bGrid
|| nBreakOld
; // einfaches Gitter nur wenn eingestellt
519 sal_Bool bNextYisNextRow
= (pRowInfo
[nArrYplus1
].nRowNo
== nYplus1
);
520 bSingle
= !bNextYisNextRow
; // Hidden
521 for (SCCOL i
=nX1
; i
<=nX2
&& !bSingle
; i
++)
523 if (pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
)
529 if ( bSingle
&& nY
<MAXROW
)
531 SCROW nVisY
= pRowInfo
[nArrYplus1
].nRowNo
;
535 nPosX
+= nMirrorW
- nOneX
;
538 for (SCCOL i
=nX1
; i
<=nX2
; i
++)
540 nNextX
= nPosX
+ pRowInfo
[0].pCellInfo
[i
+1].nWidth
* nLayoutSign
;
541 if (nNextX
!= nPosX
) // sichtbar
544 if ( bNextYisNextRow
)
545 bVOver
= pRowInfo
[nArrYplus1
].pCellInfo
[i
+1].bVOverlapped
;
548 bVOver
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
549 i
,nYplus1
,nTab
,ATTR_MERGE_FLAG
))
551 && ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
552 i
,nVisY
,nTab
,ATTR_MERGE_FLAG
))
554 //! nVisY aus Array ??
558 aGrid
.AddHorLine( nPosX
, nNextX
-nSignedOneX
, nPosY
-nOneY
);
566 aGrid
.AddHorLine( nScrX
, nScrX
+nScrW
-nOneX
, nPosY
-nOneY
);
573 // ----------------------------------------------------------------------------
575 void ScOutputData::SetPagebreakMode( ScPageBreakData
* pPageData
)
577 bPagebreakMode
= sal_True
;
579 return; // noch nicht initialisiert -> alles "nicht gedruckt"
581 // gedruckten Bereich markieren
582 // (in FillInfo ist schon alles auf sal_False initialisiert)
584 sal_uInt16 nRangeCount
= sal::static_int_cast
<sal_uInt16
>(pPageData
->GetCount());
585 for (sal_uInt16 nPos
=0; nPos
<nRangeCount
; nPos
++)
587 ScRange aRange
= pPageData
->GetData( nPos
).GetPrintRange();
589 SCCOL nStartX
= Max( aRange
.aStart
.Col(), nX1
);
590 SCCOL nEndX
= Min( aRange
.aEnd
.Col(), nX2
);
591 SCROW nStartY
= Max( aRange
.aStart
.Row(), nY1
);
592 SCROW nEndY
= Min( aRange
.aEnd
.Row(), nY2
);
594 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
596 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
597 if ( pThisRowInfo
->bChanged
&& pThisRowInfo
->nRowNo
>= nStartY
&&
598 pThisRowInfo
->nRowNo
<= nEndY
)
600 for (SCCOL nX
=nStartX
; nX
<=nEndX
; nX
++)
601 pThisRowInfo
->pCellInfo
[nX
+1].bPrinted
= sal_True
;
607 void ScOutputData::FindRotated()
609 //! nRotMax speichern
611 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
612 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
613 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
615 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
617 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
618 if ( pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
&&
619 ( pThisRowInfo
->bChanged
|| pRowInfo
[nArrY
-1].bChanged
||
620 ( nArrY
+1<nArrCount
&& pRowInfo
[nArrY
+1].bChanged
) ) )
622 SCROW nY
= pThisRowInfo
->nRowNo
;
624 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
626 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
627 const ScPatternAttr
* pPattern
= pInfo
->pPatternAttr
;
628 const SfxItemSet
* pCondSet
= pInfo
->pConditionSet
;
630 if ( !pPattern
&& !mpDoc
->ColHidden(nX
, nTab
) )
632 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
633 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
636 if ( pPattern
) // Spalte nicht ausgeblendet
638 sal_uInt8 nDir
= pPattern
->GetRotateDir( pCondSet
);
639 if (nDir
!= SC_ROTDIR_NONE
)
641 pInfo
->nRotateDir
= nDir
;
642 bAnyRotated
= sal_True
;
650 // ----------------------------------------------------------------------------
652 static sal_uInt16
lcl_GetRotateDir( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
654 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
655 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
657 sal_uInt16 nRet
= SC_ROTDIR_NONE
;
659 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
662 SvxRotateMode eRotMode
= (SvxRotateMode
)((const SvxRotateModeItem
&)
663 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
665 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
666 nRet
= SC_ROTDIR_STANDARD
;
667 else if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
668 nRet
= SC_ROTDIR_CENTER
;
669 else if ( eRotMode
== SVX_ROTATE_MODE_TOP
|| eRotMode
== SVX_ROTATE_MODE_BOTTOM
)
671 long nRot180
= nAttrRotate
% 18000; // 1/100 Grad
672 if ( nRot180
== 9000 )
673 nRet
= SC_ROTDIR_CENTER
;
674 else if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nRot180
< 9000 ) ||
675 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nRot180
> 9000 ) )
676 nRet
= SC_ROTDIR_LEFT
;
678 nRet
= SC_ROTDIR_RIGHT
;
685 static const SvxBrushItem
* lcl_FindBackground( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
687 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
688 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
689 const SvxBrushItem
* pBackground
= (const SvxBrushItem
*)
690 &pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
);
692 sal_uInt16 nDir
= lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
);
694 // CENTER wird wie RIGHT behandelt...
695 if ( nDir
== SC_ROTDIR_RIGHT
|| nDir
== SC_ROTDIR_CENTER
)
697 // Text geht nach rechts -> Hintergrund von links nehmen
698 while ( nCol
> 0 && lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
699 pBackground
->GetColor().GetTransparency() != 255 )
702 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
703 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
704 pBackground
= (const SvxBrushItem
*)&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
);
707 else if ( nDir
== SC_ROTDIR_LEFT
)
709 // Text geht nach links -> Hintergrund von rechts nehmen
710 while ( nCol
< MAXCOL
&& lcl_GetRotateDir( pDoc
, nCol
, nRow
, nTab
) == nDir
&&
711 pBackground
->GetColor().GetTransparency() != 255 )
714 pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
715 pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
716 pBackground
= (const SvxBrushItem
*)&pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
);
723 // ----------------------------------------------------------------------------
725 static sal_Bool
lcl_EqualBack( const RowInfo
& rFirst
, const RowInfo
& rOther
,
726 SCCOL nX1
, SCCOL nX2
, sal_Bool bShowProt
, sal_Bool bPagebreakMode
)
728 if ( rFirst
.bChanged
!= rOther
.bChanged
||
729 rFirst
.bEmptyBack
!= rOther
.bEmptyBack
)
735 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
737 const ScPatternAttr
* pPat1
= rFirst
.pCellInfo
[nX
+1].pPatternAttr
;
738 const ScPatternAttr
* pPat2
= rOther
.pCellInfo
[nX
+1].pPatternAttr
;
739 if ( !pPat1
|| !pPat2
||
740 &pPat1
->GetItem(ATTR_PROTECTION
) != &pPat2
->GetItem(ATTR_PROTECTION
) )
746 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
747 if ( rFirst
.pCellInfo
[nX
+1].pBackground
!= rOther
.pCellInfo
[nX
+1].pBackground
)
751 if ( rFirst
.nRotMaxCol
!= SC_ROTMAX_NONE
|| rOther
.nRotMaxCol
!= SC_ROTMAX_NONE
)
752 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
753 if ( rFirst
.pCellInfo
[nX
+1].nRotateDir
!= rOther
.pCellInfo
[nX
+1].nRotateDir
)
756 if ( bPagebreakMode
)
757 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
758 if ( rFirst
.pCellInfo
[nX
+1].bPrinted
!= rOther
.pCellInfo
[nX
+1].bPrinted
)
761 for ( nX
=nX1
; nX
<=nX2
; nX
++ )
763 const Color
* pCol1
= rFirst
.pCellInfo
[nX
+1].pColorScale
;
764 const Color
* pCol2
= rOther
.pCellInfo
[nX
+1].pColorScale
;
765 if( (pCol1
&& !pCol2
) || (!pCol1
&& pCol2
) )
768 if (pCol1
&& (*pCol1
!= *pCol2
))
771 const ScDataBarInfo
* pInfo1
= rFirst
.pCellInfo
[nX
+1].pDataBar
;
772 const ScDataBarInfo
* pInfo2
= rOther
.pCellInfo
[nX
+1].pDataBar
;
774 if( (pInfo1
&& !pInfo2
) || (!pInfo1
&& pInfo2
) )
777 if (pInfo1
&& (*pInfo1
!= *pInfo2
))
780 // each cell with an icon set should be painted the same way
781 const ScIconSetInfo
* pIconSet1
= rFirst
.pCellInfo
[nX
+1].pIconSet
;
782 const ScIconSetInfo
* pIconSet2
= rOther
.pCellInfo
[nX
+1].pIconSet
;
784 if(pIconSet1
|| pIconSet2
)
791 void ScOutputData::DrawDocumentBackground()
793 if ( !bSolidBackground
)
796 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
797 long nOneX
= aOnePixel
.Width();
798 long nOneY
= aOnePixel
.Height();
799 Rectangle
aRect(nScrX
- nOneX
, nScrY
- nOneY
, nScrX
+ nScrW
, nScrY
+ nScrH
);
800 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
801 mpDev
->SetFillColor(aBgColor
);
802 mpDev
->DrawRect(aRect
);
807 void drawDataBars( const ScDataBarInfo
* pOldDataBarInfo
, OutputDevice
* pDev
, const Rectangle
& rRect
)
810 Rectangle aPaintRect
= rRect
;
811 aPaintRect
.Top() += 2;
812 aPaintRect
.Bottom() -= 2;
813 aPaintRect
.Left() += 2;
814 aPaintRect
.Right() -= 2;
815 if(pOldDataBarInfo
->mnZero
)
817 //need to calculate null point in cell
818 long nLength
= aPaintRect
.Right() - aPaintRect
.Left();
819 nPosZero
= static_cast<long>(aPaintRect
.Left() + nLength
*pOldDataBarInfo
->mnZero
/100.0);
823 nPosZero
= aPaintRect
.Left();
826 if(pOldDataBarInfo
->mnLength
< 0)
828 aPaintRect
.Right() = nPosZero
;
829 long nLength
= nPosZero
- aPaintRect
.Left();
830 aPaintRect
.Left() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
832 else if(pOldDataBarInfo
->mnLength
> 0)
834 aPaintRect
.Left() = nPosZero
;
835 long nLength
= aPaintRect
.Right() - nPosZero
;
836 aPaintRect
.Right() = nPosZero
+ static_cast<long>(nLength
* pOldDataBarInfo
->mnLength
/100.0);
841 if(pOldDataBarInfo
->mbGradient
)
843 pDev
->SetLineColor(pOldDataBarInfo
->maColor
);
844 Gradient
aGradient(GradientStyle_LINEAR
, pOldDataBarInfo
->maColor
, COL_TRANSPARENT
);
846 if(pOldDataBarInfo
->mnLength
< 0)
847 aGradient
.SetAngle(2700);
849 aGradient
.SetAngle(900);
851 pDev
->DrawGradient(aPaintRect
, aGradient
);
853 pDev
->SetLineColor();
857 pDev
->SetFillColor(pOldDataBarInfo
->maColor
);
858 pDev
->DrawRect(aPaintRect
);
862 if(pOldDataBarInfo
->mnZero
&& pOldDataBarInfo
->mnZero
!= 100)
864 Point
aPoint1(nPosZero
, rRect
.Top());
865 Point
aPoint2(nPosZero
, rRect
.Bottom());
866 LineInfo
aLineInfo(LINE_DASH
, 1);
867 aLineInfo
.SetDashCount( 4 );
868 aLineInfo
.SetDistance( 3 );
869 aLineInfo
.SetDashLen( 3 );
870 pDev
->SetFillColor(pOldDataBarInfo
->maAxisColor
);
871 pDev
->SetLineColor(pOldDataBarInfo
->maAxisColor
);
872 pDev
->DrawLine(aPoint1
, aPoint2
, aLineInfo
);
873 pDev
->SetLineColor();
874 pDev
->SetFillColor();
878 BitmapEx
& getIcon( ScIconSetType eType
, sal_Int32 nIndex
)
880 return ScIconSetFormat::getBitmap( eType
, nIndex
);
883 void drawIconSets( const ScIconSetInfo
* pOldIconSetInfo
, OutputDevice
* pDev
, const Rectangle
& rRect
)
886 ScIconSetType eType
= pOldIconSetInfo
->eIconSetType
;
887 sal_Int32 nIndex
= pOldIconSetInfo
->nIconIndex
;
888 BitmapEx
& rIcon
= getIcon( eType
, nIndex
);
889 pDev
->DrawBitmapEx( Point( rRect
.Left() +2, rRect
.Top() + 2 ), Size( nSize
, nSize
), rIcon
);
892 void drawCells(const Color
* pColor
, const SvxBrushItem
* pBackground
, const Color
*& pOldColor
, const SvxBrushItem
*& pOldBackground
,
893 Rectangle
& rRect
, long nPosX
, long nSignedOneX
, OutputDevice
* pDev
, const ScDataBarInfo
* pDataBarInfo
, const ScDataBarInfo
*& pOldDataBarInfo
,
894 const ScIconSetInfo
* pIconSetInfo
, const ScIconSetInfo
*& pOldIconSetInfo
)
897 // need to paint if old color scale has been used and now
898 // we have a different color or a style based background
899 // we can here fall back to pointer comparison
900 if (pOldColor
&& (pBackground
|| pOldColor
!= pColor
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
))
902 rRect
.Right() = nPosX
-nSignedOneX
;
903 if( !pOldColor
->GetTransparency() )
905 pDev
->SetFillColor( *pOldColor
);
906 pDev
->DrawRect( rRect
);
908 if( pOldDataBarInfo
)
909 drawDataBars( pOldDataBarInfo
, pDev
, rRect
);
910 if( pOldIconSetInfo
)
911 drawIconSets( pOldIconSetInfo
, pDev
, rRect
);
913 rRect
.Left() = nPosX
- nSignedOneX
;
916 if ( pOldBackground
&& (pColor
||pBackground
!= pOldBackground
|| pOldDataBarInfo
|| pDataBarInfo
|| pIconSetInfo
|| pOldIconSetInfo
) )
918 rRect
.Right() = nPosX
-nSignedOneX
;
919 if (pOldBackground
) // ==0 if hidden
921 Color aBackCol
= pOldBackground
->GetColor();
922 if ( !aBackCol
.GetTransparency() ) //! partial transparency?
924 pDev
->SetFillColor( aBackCol
);
925 pDev
->DrawRect( rRect
);
928 if( pOldDataBarInfo
)
929 drawDataBars( pOldDataBarInfo
, pDev
, rRect
);
930 if( pOldIconSetInfo
)
931 drawIconSets( pOldIconSetInfo
, pDev
, rRect
);
933 rRect
.Left() = nPosX
- nSignedOneX
;
936 if (!pOldBackground
&& !pOldColor
&& (pDataBarInfo
|| pIconSetInfo
))
938 rRect
.Right() = nPosX
-nSignedOneX
;
939 rRect
.Left() = nPosX
- nSignedOneX
;
944 // only update pOldColor if the colors changed
945 if (!pOldColor
|| *pOldColor
!= *pColor
)
948 pOldBackground
= NULL
;
952 pOldBackground
= pBackground
;
957 pOldDataBarInfo
= pDataBarInfo
;
959 pOldDataBarInfo
= NULL
;
962 pOldIconSetInfo
= pIconSetInfo
;
964 pOldIconSetInfo
= NULL
;
969 void ScOutputData::DrawBackground()
971 FindRotated(); //! von aussen ?
974 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
975 long nOneX
= aOnePixel
.Width();
976 long nOneY
= aOnePixel
.Height();
981 long nLayoutSign
= bLayoutRTL
? -1 : 1;
982 long nSignedOneX
= nOneX
* nLayoutSign
;
984 mpDev
->SetLineColor();
986 sal_Bool bShowProt
= mbSyntaxMode
&& mpDoc
->IsTabProtected(nTab
);
987 sal_Bool bDoAll
= bShowProt
|| bPagebreakMode
|| bSolidBackground
;
989 sal_Bool bCellContrast
= mbUseStyleColor
&&
990 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
993 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
995 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
996 long nRowHeight
= pThisRowInfo
->nHeight
;
998 if ( pThisRowInfo
->bChanged
)
1000 if ( ( ( pThisRowInfo
->bEmptyBack
) || mbSyntaxMode
) && !bDoAll
)
1006 // scan for rows with the same background:
1008 while ( nArrY
+nSkip
+2<nArrCount
&&
1009 lcl_EqualBack( *pThisRowInfo
, pRowInfo
[nArrY
+nSkip
+1],
1010 nX1
, nX2
, bShowProt
, bPagebreakMode
) )
1013 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
1018 nPosX
+= nMirrorW
- nOneX
;
1019 aRect
= Rectangle( nPosX
, nPosY
-nOneY
, nPosX
, nPosY
+nRowHeight
-nOneY
);
1021 const SvxBrushItem
* pOldBackground
= NULL
;
1022 const SvxBrushItem
* pBackground
;
1023 const Color
* pOldColor
= NULL
;
1024 const Color
* pColor
= NULL
;
1025 const ScDataBarInfo
* pOldDataBarInfo
= NULL
;
1026 const ScIconSetInfo
* pOldIconSetInfo
= NULL
;
1027 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
1029 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
1033 // high contrast for cell borders and backgrounds -> empty background
1034 pBackground
= ScGlobal::GetEmptyBrushItem();
1036 else if (bShowProt
) // show cell protection in syntax mode
1038 const ScPatternAttr
* pP
= pInfo
->pPatternAttr
;
1041 const ScProtectionAttr
& rProt
= (const ScProtectionAttr
&)
1042 pP
->GetItem(ATTR_PROTECTION
);
1043 if (rProt
.GetProtection() || rProt
.GetHideCell())
1044 pBackground
= ScGlobal::GetProtectedBrushItem();
1046 pBackground
= ScGlobal::GetEmptyBrushItem();
1052 pBackground
= pInfo
->pBackground
;
1054 if ( bPagebreakMode
&& !pInfo
->bPrinted
)
1055 pBackground
= ScGlobal::GetProtectedBrushItem();
1057 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1058 pBackground
->GetColor().GetTransparency() != 255 &&
1061 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
1062 pBackground
= lcl_FindBackground( mpDoc
, nX
, nY
, nTab
);
1065 pColor
= pInfo
->pColorScale
;
1066 const ScDataBarInfo
* pDataBarInfo
= pInfo
->pDataBar
;
1067 const ScIconSetInfo
* pIconSetInfo
= pInfo
->pIconSet
;
1068 drawCells( pColor
, pBackground
, pOldColor
, pOldBackground
, aRect
, nPosX
, nSignedOneX
, mpDev
, pDataBarInfo
, pOldDataBarInfo
, pIconSetInfo
, pOldIconSetInfo
);
1070 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
1072 drawCells( NULL
, NULL
, pOldColor
, pOldBackground
, aRect
, nPosX
, nSignedOneX
, mpDev
, NULL
, pOldDataBarInfo
, NULL
, pOldIconSetInfo
);
1077 nPosY
+= nRowHeight
;
1081 void ScOutputData::DrawShadow()
1083 DrawExtraShadow( false, false, false, false );
1086 void ScOutputData::DrawExtraShadow(sal_Bool bLeft
, sal_Bool bTop
, sal_Bool bRight
, sal_Bool bBottom
)
1088 mpDev
->SetLineColor();
1090 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1091 sal_Bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1092 Color aAutoTextColor
;
1093 if ( bCellContrast
)
1094 aAutoTextColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1096 long nInitPosX
= nScrX
;
1099 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1100 long nOneX
= aOnePixel
.Width();
1101 nInitPosX
+= nMirrorW
- nOneX
;
1103 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1105 long nPosY
= nScrY
- pRowInfo
[0].nHeight
;
1106 for (SCSIZE nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1108 sal_Bool bCornerY
= ( nArrY
== 0 ) || ( nArrY
+1 == nArrCount
);
1109 sal_Bool bSkipY
= ( nArrY
==0 && !bTop
) || ( nArrY
+1 == nArrCount
&& !bBottom
);
1111 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1112 long nRowHeight
= pThisRowInfo
->nHeight
;
1114 if ( pThisRowInfo
->bChanged
&& !bSkipY
)
1116 long nPosX
= nInitPosX
- pRowInfo
[0].pCellInfo
[nX1
].nWidth
* nLayoutSign
;
1117 for (SCCOL nArrX
=nX1
; nArrX
<=nX2
+2; nArrX
++)
1119 sal_Bool bCornerX
= ( nArrX
==nX1
|| nArrX
==nX2
+2 );
1120 sal_Bool bSkipX
= ( nArrX
==nX1
&& !bLeft
) || ( nArrX
==nX2
+2 && !bRight
);
1122 for (sal_uInt16 nPass
=0; nPass
<2; nPass
++) // horizontal / vertikal
1124 const SvxShadowItem
* pAttr
= nPass
?
1125 pThisRowInfo
->pCellInfo
[nArrX
].pVShadowOrigin
:
1126 pThisRowInfo
->pCellInfo
[nArrX
].pHShadowOrigin
;
1127 if ( pAttr
&& !bSkipX
)
1129 ScShadowPart ePart
= nPass
?
1130 pThisRowInfo
->pCellInfo
[nArrX
].eVShadowPart
:
1131 pThisRowInfo
->pCellInfo
[nArrX
].eHShadowPart
;
1133 sal_Bool bDo
= sal_True
;
1134 if ( (nPass
==0 && bCornerX
) || (nPass
==1 && bCornerY
) )
1135 if ( ePart
!= SC_SHADOW_CORNER
)
1140 long nThisWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1141 long nMaxWidth
= nThisWidth
;
1144 //! direction must depend on shadow location
1145 SCCOL nWx
= nArrX
; // nX+1
1146 while (nWx
<nX2
&& !pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
)
1148 nMaxWidth
= pRowInfo
[0].pCellInfo
[nWx
+1].nWidth
;
1151 // rectangle is in logical orientation
1152 Rectangle
aRect( nPosX
, nPosY
,
1153 nPosX
+ ( nThisWidth
- 1 ) * nLayoutSign
,
1154 nPosY
+ pRowInfo
[nArrY
].nHeight
- 1 );
1156 long nSize
= pAttr
->GetWidth();
1157 long nSizeX
= (long)(nSize
*mnPPTX
);
1158 if (nSizeX
>= nMaxWidth
) nSizeX
= nMaxWidth
-1;
1159 long nSizeY
= (long)(nSize
*mnPPTY
);
1160 if (nSizeY
>= nRowHeight
) nSizeY
= nRowHeight
-1;
1162 nSizeX
*= nLayoutSign
; // used only to add to rectangle values
1164 SvxShadowLocation eLoc
= pAttr
->GetLocation();
1167 // Shadow location is specified as "visual" (right is always right),
1168 // so the attribute's location value is mirrored here and in FillInfo.
1171 case SVX_SHADOW_BOTTOMRIGHT
: eLoc
= SVX_SHADOW_BOTTOMLEFT
; break;
1172 case SVX_SHADOW_BOTTOMLEFT
: eLoc
= SVX_SHADOW_BOTTOMRIGHT
; break;
1173 case SVX_SHADOW_TOPRIGHT
: eLoc
= SVX_SHADOW_TOPLEFT
; break;
1174 case SVX_SHADOW_TOPLEFT
: eLoc
= SVX_SHADOW_TOPRIGHT
; break;
1177 // added to avoid warnings
1182 if (ePart
== SC_SHADOW_HORIZ
|| ePart
== SC_SHADOW_HSTART
||
1183 ePart
== SC_SHADOW_CORNER
)
1185 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1186 aRect
.Top() = aRect
.Bottom() - nSizeY
;
1188 aRect
.Bottom() = aRect
.Top() + nSizeY
;
1190 if (ePart
== SC_SHADOW_VERT
|| ePart
== SC_SHADOW_VSTART
||
1191 ePart
== SC_SHADOW_CORNER
)
1193 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1194 aRect
.Left() = aRect
.Right() - nSizeX
;
1196 aRect
.Right() = aRect
.Left() + nSizeX
;
1198 if (ePart
== SC_SHADOW_HSTART
)
1200 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_BOTTOMLEFT
)
1201 aRect
.Right() -= nSizeX
;
1203 aRect
.Left() += nSizeX
;
1205 if (ePart
== SC_SHADOW_VSTART
)
1207 if (eLoc
== SVX_SHADOW_TOPLEFT
|| eLoc
== SVX_SHADOW_TOPRIGHT
)
1208 aRect
.Bottom() -= nSizeY
;
1210 aRect
.Top() += nSizeY
;
1213 //! merge rectangles?
1214 mpDev
->SetFillColor( bCellContrast
? aAutoTextColor
: pAttr
->GetColor() );
1215 mpDev
->DrawRect( aRect
);
1220 nPosX
+= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
* nLayoutSign
;
1223 nPosY
+= nRowHeight
;
1231 void ScOutputData::DrawClear()
1234 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1235 long nOneX
= aOnePixel
.Width();
1236 long nOneY
= aOnePixel
.Height();
1238 // (called only for ScGridWindow)
1239 Color
aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1244 mpDev
->SetLineColor();
1246 mpDev
->SetFillColor( aBgColor
);
1249 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1251 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1252 long nRowHeight
= pThisRowInfo
->nHeight
;
1254 if ( pThisRowInfo
->bChanged
)
1256 // scan for more rows which must be painted:
1258 while ( nArrY
+nSkip
+2<nArrCount
&& pRowInfo
[nArrY
+nSkip
+1].bChanged
)
1261 nRowHeight
+= pRowInfo
[nArrY
+nSkip
].nHeight
; // after incrementing
1264 aRect
= Rectangle( Point( nScrX
, nPosY
),
1265 Size( nScrW
+1-nOneX
, nRowHeight
+1-nOneY
) );
1266 mpDev
->DrawRect( aRect
);
1270 nPosY
+= nRowHeight
;
1276 long lclGetSnappedX( OutputDevice
& rDev
, long nPosX
, bool bSnapPixel
)
1278 return (bSnapPixel
&& nPosX
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( nPosX
, 0 ) ) ).Width() : nPosX
;
1281 long lclGetSnappedY( OutputDevice
& rDev
, long nPosY
, bool bSnapPixel
)
1283 return (bSnapPixel
&& nPosY
) ? rDev
.PixelToLogic( rDev
.LogicToPixel( Size( 0, nPosY
) ) ).Height() : nPosY
;
1286 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX
, sal_uInt16 nCellInfoFirstX
, sal_uInt16 nCellInfoLastX
, bool bRTL
)
1288 return static_cast< size_t >( bRTL
? (nCellInfoLastX
+ 2 - nCellInfoX
) : (nCellInfoX
- nCellInfoFirstX
) );
1292 * Temporarily turn off antialiasing.
1294 class AntiAliasingSwitch
1296 SvtOptionsDrawinglayer maDrawOpt
;
1299 AntiAliasingSwitch(bool bOn
) : mbOldSetting(maDrawOpt
.IsAntiAliasing())
1301 maDrawOpt
.SetAntiAliasing(bOn
);
1304 ~AntiAliasingSwitch()
1306 maDrawOpt
.SetAntiAliasing(mbOldSetting
);
1312 void ScOutputData::DrawFrame()
1314 // No anti-aliasing for drawing cell borders.
1315 AntiAliasingSwitch
aAASwitch(false);
1317 sal_uLong nOldDrawMode
= mpDev
->GetDrawMode();
1320 sal_Bool bUseSingleColor
= false;
1321 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1322 sal_Bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1324 // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1325 // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1326 // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1327 // must be reset and the border colors handled here.
1329 if ( ( nOldDrawMode
& DRAWMODE_WHITEFILL
) && ( nOldDrawMode
& DRAWMODE_BLACKLINE
) )
1331 mpDev
->SetDrawMode( nOldDrawMode
& (~DRAWMODE_WHITEFILL
) );
1332 aSingleColor
.SetColor( COL_BLACK
);
1333 bUseSingleColor
= sal_True
;
1335 else if ( ( nOldDrawMode
& DRAWMODE_SETTINGSFILL
) && ( nOldDrawMode
& DRAWMODE_SETTINGSLINE
) )
1337 mpDev
->SetDrawMode( nOldDrawMode
& (~DRAWMODE_SETTINGSFILL
) );
1338 aSingleColor
= rStyleSettings
.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE
1339 bUseSingleColor
= sal_True
;
1341 else if ( bCellContrast
)
1343 aSingleColor
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
1344 bUseSingleColor
= sal_True
;
1347 const Color
* pForceColor
= bUseSingleColor
? &aSingleColor
: 0;
1350 DrawRotatedFrame( pForceColor
); // removes the lines that must not be painted here
1352 long nInitPosX
= nScrX
;
1355 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1356 long nOneX
= aOnePixel
.Width();
1357 nInitPosX
+= nMirrorW
- nOneX
;
1359 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1362 // *** set column and row sizes of the frame border array ***
1364 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1365 size_t nColCount
= rArray
.GetColCount();
1366 size_t nRowCount
= rArray
.GetRowCount();
1370 // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1371 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1372 long nOldPosY
= nScrY
- 1 - pRowInfo
[ 0 ].nHeight
;
1373 long nOldSnapY
= lclGetSnappedY( *mpDev
, nOldPosY
, bSnapPixel
);
1374 rArray
.SetYOffset( nOldSnapY
);
1375 for( size_t nRow
= 0; nRow
< nRowCount
; ++nRow
)
1377 long nNewPosY
= nOldPosY
+ pRowInfo
[ nRow
].nHeight
;
1378 long nNewSnapY
= lclGetSnappedY( *mpDev
, nNewPosY
, bSnapPixel
);
1379 rArray
.SetRowHeight( nRow
, nNewSnapY
- nOldSnapY
);
1380 nOldPosY
= nNewPosY
;
1381 nOldSnapY
= nNewSnapY
;
1386 // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1387 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1388 long nOldPosX
= nInitPosX
- nLayoutSign
* (1 + pRowInfo
[ 0 ].pCellInfo
[ nX1
].nWidth
);
1389 long nOldSnapX
= lclGetSnappedX( *mpDev
, nOldPosX
, bSnapPixel
);
1390 // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1392 rArray
.SetXOffset( nOldSnapX
);
1393 for( sal_uInt16 nInfoIdx
= nX1
; nInfoIdx
<= nX2
+ 2; ++nInfoIdx
)
1395 size_t nCol
= lclGetArrayColFromCellInfoX( nInfoIdx
, nX1
, nX2
, bLayoutRTL
);
1396 long nNewPosX
= nOldPosX
+ pRowInfo
[ 0 ].pCellInfo
[ nInfoIdx
].nWidth
* nLayoutSign
;
1397 long nNewSnapX
= lclGetSnappedX( *mpDev
, nNewPosX
, bSnapPixel
);
1398 rArray
.SetColWidth( nCol
, Abs( nNewSnapX
- nOldSnapX
) );
1399 nOldPosX
= nNewPosX
;
1400 nOldSnapX
= nNewSnapX
;
1403 rArray
.SetXOffset( nOldSnapX
);
1405 // *** draw the array ***
1407 size_t nFirstCol
= 1;
1408 size_t nFirstRow
= 1;
1409 size_t nLastCol
= nColCount
- 2;
1410 size_t nLastRow
= nRowCount
- 2;
1412 if( mrTabInfo
.mbPageMode
)
1413 rArray
.SetClipRange( nFirstCol
, nFirstRow
, nLastCol
, nLastRow
);
1415 // draw only rows with set RowInfo::bChanged flag
1416 size_t nRow1
= nFirstRow
;
1417 drawinglayer::processor2d::BaseProcessor2D
* pProcessor
= CreateProcessor2D();
1421 while( nRow1
<= nLastRow
)
1423 while( (nRow1
<= nLastRow
) && !pRowInfo
[ nRow1
].bChanged
) ++nRow1
;
1424 if( nRow1
<= nLastRow
)
1426 size_t nRow2
= nRow1
;
1427 while( (nRow2
+ 1 <= nLastRow
) && pRowInfo
[ nRow2
+ 1 ].bChanged
) ++nRow2
;
1428 rArray
.DrawRange( pProcessor
, nFirstCol
, nRow1
, nLastCol
, nRow2
, pForceColor
);
1435 mpDev
->SetDrawMode(nOldDrawMode
);
1438 // -------------------------------------------------------------------------
1440 // Linie unter der Zelle
1442 static const ::editeng::SvxBorderLine
* lcl_FindHorLine( ScDocument
* pDoc
,
1443 SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_uInt16 nRotDir
,
1446 if ( nRotDir
!= SC_ROTDIR_LEFT
&& nRotDir
!= SC_ROTDIR_RIGHT
)
1449 sal_Bool bFound
= false;
1452 if ( nRotDir
== SC_ROTDIR_LEFT
)
1454 // Text nach links -> Linie von rechts
1455 if ( nCol
< MAXCOL
)
1458 return NULL
; // war nix
1462 // Text nach rechts -> Linie von links
1466 return NULL
; // war nix
1468 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
1469 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
1470 if ( !pPattern
->GetRotateVal( pCondSet
) ||
1471 ((const SvxRotateModeItem
&)pPattern
->GetItem(
1472 ATTR_ROTATE_MODE
, pCondSet
)).GetValue() == SVX_ROTATE_MODE_STANDARD
)
1478 const ::editeng::SvxBorderLine
* pThisBottom
;
1479 if ( ValidRow(nRow
) )
1480 pThisBottom
= ((const SvxBoxItem
*)pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
))->GetBottom();
1483 const ::editeng::SvxBorderLine
* pNextTop
;
1484 if ( nRow
< MAXROW
)
1485 pNextTop
= ((const SvxBoxItem
*)pDoc
->GetAttr( nCol
, nRow
+1, nTab
, ATTR_BORDER
))->GetTop();
1489 if ( ScHasPriority( pThisBottom
, pNextTop
) )
1496 static long lcl_getRotate( ScDocument
* pDoc
, SCTAB nTab
, SCCOL nX
, SCROW nY
)
1500 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nX
, nY
, nTab
);
1501 const SfxItemSet
* pCondSet
= pDoc
->GetCondResult( nX
, nY
, nTab
);
1503 nRotate
= pPattern
->GetRotateVal( pCondSet
);
1508 void ScOutputData::DrawRotatedFrame( const Color
* pForceColor
)
1510 //! nRotMax speichern
1511 SCCOL nRotMax
= nX2
;
1512 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
1513 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
1514 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
1516 const ScPatternAttr
* pPattern
;
1517 const SfxItemSet
* pCondSet
;
1519 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1520 sal_Bool bCellContrast
= mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode();
1522 // color (pForceColor) is determined externally, including DrawMode changes
1524 long nInitPosX
= nScrX
;
1527 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
1528 long nOneX
= aOnePixel
.Width();
1529 nInitPosX
+= nMirrorW
- nOneX
;
1531 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1533 Rectangle
aClipRect( Point(nScrX
, nScrY
), Size(nScrW
, nScrH
) );
1537 mpDev
->IntersectClipRegion( aClipRect
);
1540 mpDev
->SetClipRegion( Region( aClipRect
) );
1542 svx::frame::Array
& rArray
= mrTabInfo
.maArray
;
1543 drawinglayer::processor2d::BaseProcessor2D
* pProcessor
= CreateProcessor2D( );
1546 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++)
1548 // Rotated wird auch 1 Zeile ueber/unter Changed gezeichnet, falls Teile
1549 // in die Zeile hineinragen...
1551 RowInfo
& rPrevRowInfo
= pRowInfo
[nArrY
-1];
1552 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1553 RowInfo
& rNextRowInfo
= pRowInfo
[nArrY
+1];
1555 size_t nRow
= static_cast< size_t >( nArrY
);
1557 long nRowHeight
= rThisRowInfo
.nHeight
;
1558 if ( rThisRowInfo
.nRotMaxCol
!= SC_ROTMAX_NONE
&&
1559 ( rThisRowInfo
.bChanged
|| rPrevRowInfo
.bChanged
||
1560 ( nArrY
+1<nArrCount
&& rNextRowInfo
.bChanged
) ) )
1562 SCROW nY
= rThisRowInfo
.nRowNo
;
1565 for (nX
=0; nX
<=nRotMax
; nX
++)
1567 if (nX
==nX1
) nPosX
= nInitPosX
; // calculated individually for preceding positions
1569 sal_uInt16 nArrX
= nX
+ 1;
1571 CellInfo
* pInfo
= &rThisRowInfo
.pCellInfo
[nArrX
];
1572 long nColWidth
= pRowInfo
[0].pCellInfo
[nArrX
].nWidth
;
1573 if ( pInfo
->nRotateDir
> SC_ROTDIR_STANDARD
&&
1574 !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
1576 pPattern
= pInfo
->pPatternAttr
;
1577 pCondSet
= pInfo
->pConditionSet
;
1580 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1581 pInfo
->pPatternAttr
= pPattern
;
1582 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
1583 pInfo
->pConditionSet
= pCondSet
;
1586 //! LastPattern etc.
1588 long nAttrRotate
= pPattern
->GetRotateVal( pCondSet
);
1589 SvxRotateMode eRotMode
= (SvxRotateMode
)((const SvxRotateModeItem
&)
1590 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
1594 if (nX
<nX1
) // negative Position berechnen
1601 nPosX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
1605 // Startposition minus 1, damit auch schraege Hintergruende
1606 // zur Umrandung passen (Umrandung ist auf dem Gitter)
1608 long nTop
= nPosY
- 1;
1609 long nBottom
= nPosY
+ nRowHeight
- 1;
1610 long nTopLeft
= nPosX
- nLayoutSign
;
1611 long nTopRight
= nPosX
+ ( nColWidth
- 1 ) * nLayoutSign
;
1612 long nBotLeft
= nTopLeft
;
1613 long nBotRight
= nTopRight
;
1615 // inclusion of the sign here hasn't been decided yet
1616 // (if not, the extension of the non-rotated background must also be changed)
1617 double nRealOrient
= nLayoutSign
* nAttrRotate
* F_PI18000
; // 1/100th degrees
1618 double nCos
= cos( nRealOrient
);
1619 double nSin
= sin( nRealOrient
);
1621 long nSkew
= (long) ( nRowHeight
* nCos
/ nSin
);
1625 case SVX_ROTATE_MODE_BOTTOM
:
1629 case SVX_ROTATE_MODE_CENTER
:
1636 case SVX_ROTATE_MODE_TOP
:
1642 // added to avoid warnings
1647 aPoints
[0] = Point( nTopLeft
, nTop
);
1648 aPoints
[1] = Point( nTopRight
, nTop
);
1649 aPoints
[2] = Point( nBotRight
, nBottom
);
1650 aPoints
[3] = Point( nBotLeft
, nBottom
);
1652 const SvxBrushItem
* pBackground
= pInfo
->pBackground
;
1654 pBackground
= (const SvxBrushItem
*) &pPattern
->GetItem(
1655 ATTR_BACKGROUND
, pCondSet
);
1658 // high contrast for cell borders and backgrounds -> empty background
1659 pBackground
= ScGlobal::GetEmptyBrushItem();
1661 if(!pInfo
->pColorScale
)
1663 const Color
& rColor
= pBackground
->GetColor();
1664 if ( rColor
.GetTransparency() != 255 )
1666 // draw background only for the changed row itself
1667 // (background doesn't extend into other cells).
1668 // For the borders (rotated and normal), clipping should be
1669 // set if the row isn't changed, but at least the borders
1670 // don't cover the cell contents.
1671 if ( rThisRowInfo
.bChanged
)
1673 Polygon
aPoly( 4, aPoints
);
1675 // ohne Pen wird bei DrawPolygon rechts und unten
1676 // ein Pixel weggelassen...
1677 if ( rColor
.GetTransparency() == 0 )
1678 mpDev
->SetLineColor(rColor
);
1680 mpDev
->SetLineColor();
1681 mpDev
->SetFillColor(rColor
);
1682 mpDev
->DrawPolygon( aPoly
);
1688 Polygon
aPoly( 4, aPoints
);
1689 const Color
* pColor
= pInfo
->pColorScale
;
1691 // ohne Pen wird bei DrawPolygon rechts und unten
1692 // ein Pixel weggelassen...
1693 if ( pColor
->GetTransparency() == 0 )
1694 mpDev
->SetLineColor(*pColor
);
1696 mpDev
->SetLineColor();
1697 mpDev
->SetFillColor(*pColor
);
1698 mpDev
->DrawPolygon( aPoly
);
1702 svx::frame::Style aTopLine
, aBottomLine
, aLeftLine
, aRightLine
;
1704 if ( nX
< nX1
|| nX
> nX2
) // Attribute in FillInfo nicht gesetzt
1706 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
1707 const ::editeng::SvxBorderLine
* pLeftLine
;
1708 const ::editeng::SvxBorderLine
* pTopLine
;
1709 const ::editeng::SvxBorderLine
* pRightLine
;
1710 const ::editeng::SvxBorderLine
* pBottomLine
;
1711 mpDoc
->GetBorderLines( nX
, nY
, nTab
,
1712 &pLeftLine
, &pTopLine
, &pRightLine
, &pBottomLine
);
1713 aTopLine
.Set( pTopLine
, mnPPTY
);
1714 aBottomLine
.Set( pBottomLine
, mnPPTY
);
1715 aLeftLine
.Set( pLeftLine
, mnPPTX
);
1716 aRightLine
.Set( pRightLine
, mnPPTX
);
1720 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1721 aTopLine
= rArray
.GetCellStyleTop( nCol
, nRow
);
1722 aBottomLine
= rArray
.GetCellStyleBottom( nCol
, nRow
);
1723 aLeftLine
= rArray
.GetCellStyleLeft( nCol
, nRow
);
1724 aRightLine
= rArray
.GetCellStyleRight( nCol
, nRow
);
1725 // in RTL mode the array is already mirrored -> swap back left/right borders
1727 std::swap( aLeftLine
, aRightLine
);
1730 const svx::frame::Style noStyle
;
1732 long nUpperRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
- 1 );
1733 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1734 aPoints
[bLayoutRTL
?1:0], aPoints
[bLayoutRTL
?0:1], aTopLine
,
1735 svx::frame::Style(),
1736 svx::frame::Style(),
1738 svx::frame::Style(),
1739 svx::frame::Style(),
1741 pForceColor
, nUpperRotate
, nAttrRotate
) );
1743 long nLowerRotate
= lcl_getRotate( mpDoc
, nTab
, nX
, nY
+ 1 );
1744 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1745 aPoints
[bLayoutRTL
?2:3], aPoints
[bLayoutRTL
?3:2], aBottomLine
,
1747 svx::frame::Style(),
1748 svx::frame::Style(),
1750 svx::frame::Style(),
1751 svx::frame::Style(),
1752 pForceColor
, 18000 - nAttrRotate
, 18000 - nLowerRotate
) );
1754 // Vertical slanted lines
1755 long nLeftRotate
= lcl_getRotate( mpDoc
, nTab
, nX
- 1, nY
);
1756 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1757 aPoints
[0], aPoints
[3], aLeftLine
,
1759 svx::frame::Style(),
1760 svx::frame::Style(),
1762 svx::frame::Style(),
1763 svx::frame::Style(),
1764 pForceColor
, nAttrRotate
, nLeftRotate
) );
1766 long nRightRotate
= lcl_getRotate( mpDoc
, nTab
, nX
+ 1, nY
);
1767 pProcessor
->process( svx::frame::CreateBorderPrimitives(
1768 aPoints
[1], aPoints
[2], aRightLine
,
1769 svx::frame::Style(),
1770 svx::frame::Style(),
1772 svx::frame::Style(),
1773 svx::frame::Style(),
1775 pForceColor
, 18000 - nRightRotate
, 18000 - nAttrRotate
) );
1778 nPosX
+= nColWidth
* nLayoutSign
;
1781 // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1783 nX
= nX1
> 0 ? (nX1
-1) : static_cast<SCCOL
>(0);
1784 for (; nX
<=nX2
+1; nX
++) // sichtbarer Teil +- 1
1786 sal_uInt16 nArrX
= nX
+ 1;
1787 CellInfo
& rInfo
= rThisRowInfo
.pCellInfo
[nArrX
];
1788 if ( rInfo
.nRotateDir
> SC_ROTDIR_STANDARD
&&
1789 !rInfo
.bHOverlapped
&& !rInfo
.bVOverlapped
)
1791 pPattern
= rInfo
.pPatternAttr
;
1792 pCondSet
= rInfo
.pConditionSet
;
1794 size_t nCol
= lclGetArrayColFromCellInfoX( nArrX
, nX1
, nX2
, bLayoutRTL
);
1796 // horizontal: angrenzende Linie verlaengern
1797 // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1798 sal_uInt16 nDir
= rInfo
.nRotateDir
;
1799 if ( rArray
.GetCellStyleTop( nCol
, nRow
).Prim() )
1801 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, sal_True
), mnPPTY
);
1802 rArray
.SetCellStyleTop( nCol
, nRow
, aStyle
);
1804 rArray
.SetCellStyleBottom( nCol
, nRow
- 1, aStyle
);
1806 if ( rArray
.GetCellStyleBottom( nCol
, nRow
).Prim() )
1808 svx::frame::Style
aStyle( lcl_FindHorLine( mpDoc
, nX
, nY
, nTab
, nDir
, false ), mnPPTY
);
1809 rArray
.SetCellStyleBottom( nCol
, nRow
, aStyle
);
1810 if( nRow
+ 1 < rArray
.GetRowCount() )
1811 rArray
.SetCellStyleTop( nCol
, nRow
+ 1, aStyle
);
1814 // always remove vertical borders
1815 if( !rArray
.IsMergedOverlappedLeft( nCol
, nRow
) )
1817 rArray
.SetCellStyleLeft( nCol
, nRow
, svx::frame::Style() );
1819 rArray
.SetCellStyleRight( nCol
- 1, nRow
, svx::frame::Style() );
1821 if( !rArray
.IsMergedOverlappedRight( nCol
, nRow
) )
1823 rArray
.SetCellStyleRight( nCol
, nRow
, svx::frame::Style() );
1824 if( nCol
+ 1 < rArray
.GetColCount() )
1825 rArray
.SetCellStyleLeft( nCol
+ 1, nRow
, svx::frame::Style() );
1828 // remove diagonal borders
1829 rArray
.SetCellStyleTLBR( nCol
, nRow
, svx::frame::Style() );
1830 rArray
.SetCellStyleBLTR( nCol
, nRow
, svx::frame::Style() );
1834 nPosY
+= nRowHeight
;
1837 if ( pProcessor
) delete pProcessor
;
1842 mpDev
->SetClipRegion();
1845 drawinglayer::processor2d::BaseProcessor2D
* ScOutputData::CreateProcessor2D( )
1847 mpDoc
->InitDrawLayer(mpDoc
->GetDocumentShell());
1848 ScDrawLayer
* pDrawLayer
= mpDoc
->GetDrawLayer();
1852 basegfx::B2DRange aViewRange
;
1853 SdrPage
*pDrawPage
= pDrawLayer
->GetPage( static_cast< sal_uInt16
>( nTab
) );
1854 const drawinglayer::geometry::ViewInformation2D
aNewViewInfos(
1855 basegfx::B2DHomMatrix( ),
1856 mpDev
->GetViewTransformation(),
1858 GetXDrawPageForSdrPage( pDrawPage
),
1860 uno::Sequence
< beans::PropertyValue
>() );
1862 return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1863 *mpDev
, aNewViewInfos
);
1868 PolyPolygon
ScOutputData::GetChangedArea()
1872 Rectangle aDrawingRect
;
1873 aDrawingRect
.Left() = nScrX
;
1874 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1876 sal_Bool bHad
= false;
1879 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1881 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1883 if ( pThisRowInfo
->bChanged
)
1887 aDrawingRect
.Top() = nPosY
;
1890 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1894 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1897 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1901 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1906 sal_Bool
ScOutputData::SetChangedClip()
1910 Rectangle aDrawingRect
;
1911 aDrawingRect
.Left() = nScrX
;
1912 aDrawingRect
.Right() = nScrX
+nScrW
-1;
1914 sal_Bool bHad
= false;
1917 for (nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1919 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1921 if ( pThisRowInfo
->bChanged
)
1925 aDrawingRect
.Top() = nPosY
;
1928 aDrawingRect
.Bottom() = nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
1932 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1935 nPosY
+= pRowInfo
[nArrY
].nHeight
;
1939 aPoly
.Insert( Polygon( mpDev
->PixelToLogic(aDrawingRect
) ) );
1941 sal_Bool bRet
= (aPoly
.Count() != 0);
1943 mpDev
->SetClipRegion(Region(aPoly
));
1947 void ScOutputData::FindChanged()
1952 bool bWasIdleDisabled
= mpDoc
->IsIdleDisabled();
1953 mpDoc
->DisableIdle(true);
1954 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1955 pRowInfo
[nArrY
].bChanged
= false;
1957 bool bProgress
= false;
1958 for (nArrY
=0; nArrY
<nArrCount
; nArrY
++)
1960 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1961 for (nX
=nX1
; nX
<=nX2
; nX
++)
1963 ScBaseCell
* pCell
= pThisRowInfo
->pCellInfo
[nX
+1].pCell
;
1967 if (pCell
->GetCellType() != CELLTYPE_FORMULA
)
1970 ScFormulaCell
* pFCell
= (ScFormulaCell
*)pCell
;
1971 if ( !bProgress
&& pFCell
->GetDirty() )
1973 ScProgress::CreateInterpretProgress(mpDoc
, true);
1976 if (pFCell
->IsRunning())
1977 // still being interpreted. Skip it.
1980 (void)pFCell
->GetValue();
1981 if (!pFCell
->IsChanged())
1982 // the result hasn't changed. Skip it.
1985 pThisRowInfo
->bChanged
= true;
1986 if ( pThisRowInfo
->pCellInfo
[nX
+1].bMerged
)
1988 SCSIZE nOverY
= nArrY
+ 1;
1989 while ( nOverY
<nArrCount
&&
1990 pRowInfo
[nOverY
].pCellInfo
[nX
+1].bVOverlapped
)
1992 pRowInfo
[nOverY
].bChanged
= true;
1999 ScProgress::DeleteInterpretProgress();
2000 mpDoc
->DisableIdle( bWasIdleDisabled
);
2003 void ScOutputData::DrawRefMark( SCCOL nRefStartX
, SCROW nRefStartY
,
2004 SCCOL nRefEndX
, SCROW nRefEndY
,
2005 const Color
& rColor
, sal_Bool bHandle
)
2007 PutInOrder( nRefStartX
, nRefEndX
);
2008 PutInOrder( nRefStartY
, nRefEndY
);
2010 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
2011 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
2013 if ( nRefStartX
<= nVisX2
&& nRefEndX
>= nVisX1
&&
2014 nRefStartY
<= nVisY2
&& nRefEndY
>= nVisY1
)
2018 long nMaxX
= nScrX
+nScrW
-1;
2019 long nMaxY
= nScrY
+nScrH
-1;
2026 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2028 sal_Bool bTop
= false;
2029 sal_Bool bBottom
= false;
2030 sal_Bool bLeft
= false;
2031 sal_Bool bRight
= false;
2034 sal_Bool bNoStartY
= ( nY1
< nRefStartY
);
2035 sal_Bool bNoEndY
= false;
2036 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2038 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2040 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2047 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 2;
2050 if ( nY
>nRefEndY
&& bNoEndY
)
2055 bNoStartY
= ( nY
< nRefStartY
);
2056 bNoEndY
= ( nY
< nRefEndY
);
2057 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2062 nPosX
+= nMirrorW
- 1; // always in pixels
2064 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2066 if ( nX
==nRefStartX
)
2073 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 2 ) * nLayoutSign
;
2076 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2079 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2082 mpDev
->SetLineColor( rColor
);
2083 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2085 mpDev
->SetFillColor();
2086 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2091 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMaxX
,nMinY
) );
2093 mpDev
->DrawLine( Point( nMinX
,nMaxY
), Point( nMaxX
,nMaxY
) );
2095 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMinX
,nMaxY
) );
2097 mpDev
->DrawLine( Point( nMaxX
,nMinY
), Point( nMaxX
,nMaxY
) );
2099 if ( bHandle
&& bRight
&& bBottom
)
2101 mpDev
->SetLineColor();
2102 mpDev
->SetFillColor( rColor
);
2103 mpDev
->DrawRect( Rectangle( nMaxX
-3*nLayoutSign
, nMaxY
-3, nMaxX
+nLayoutSign
, nMaxY
+1 ) );
2109 void ScOutputData::DrawOneChange( SCCOL nRefStartX
, SCROW nRefStartY
,
2110 SCCOL nRefEndX
, SCROW nRefEndY
,
2111 const Color
& rColor
, sal_uInt16 nType
)
2113 PutInOrder( nRefStartX
, nRefEndX
);
2114 PutInOrder( nRefStartY
, nRefEndY
);
2116 if ( nRefStartX
== nRefEndX
&& nRefStartY
== nRefEndY
)
2117 mpDoc
->ExtendMerge( nRefStartX
, nRefStartY
, nRefEndX
, nRefEndY
, nTab
);
2119 if ( nRefStartX
<= nVisX2
+ 1 && nRefEndX
>= nVisX1
&&
2120 nRefStartY
<= nVisY2
+ 1 && nRefEndY
>= nVisY1
) // +1 because it touches next cells left/top
2124 long nMaxX
= nScrX
+nScrW
-1;
2125 long nMaxY
= nScrY
+nScrH
-1;
2132 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2134 sal_Bool bTop
= false;
2135 sal_Bool bBottom
= false;
2136 sal_Bool bLeft
= false;
2137 sal_Bool bRight
= false;
2140 sal_Bool bNoStartY
= ( nY1
< nRefStartY
);
2141 sal_Bool bNoEndY
= false;
2142 for (SCSIZE nArrY
=1; nArrY
<nArrCount
; nArrY
++) // loop to end for bNoEndY check
2144 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2146 if ( nY
==nRefStartY
|| (nY
>nRefStartY
&& bNoStartY
) )
2153 nMaxY
= nPosY
+ pRowInfo
[nArrY
].nHeight
- 1;
2156 if ( nY
>nRefEndY
&& bNoEndY
)
2161 bNoStartY
= ( nY
< nRefStartY
);
2162 bNoEndY
= ( nY
< nRefEndY
);
2163 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2168 nPosX
+= nMirrorW
- 1; // always in pixels
2170 for (SCCOL nX
=nX1
; nX
<=nX2
+1; nX
++)
2172 if ( nX
==nRefStartX
)
2174 nMinX
= nPosX
- nLayoutSign
;
2179 nMaxX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 1 ) * nLayoutSign
;
2182 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2185 if ( nMaxX
* nLayoutSign
>= nMinX
* nLayoutSign
&&
2188 if ( nType
== SC_CAT_DELETE_ROWS
)
2189 bLeft
= bRight
= bBottom
= false; //! dicke Linie ???
2190 else if ( nType
== SC_CAT_DELETE_COLS
)
2191 bTop
= bBottom
= bRight
= false; //! dicke Linie ???
2193 mpDev
->SetLineColor( rColor
);
2194 if (bTop
&& bBottom
&& bLeft
&& bRight
)
2196 mpDev
->SetFillColor();
2197 mpDev
->DrawRect( Rectangle( nMinX
, nMinY
, nMaxX
, nMaxY
) );
2203 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMaxX
,nMinY
) );
2204 if ( nType
== SC_CAT_DELETE_ROWS
)
2205 mpDev
->DrawLine( Point( nMinX
,nMinY
+1 ), Point( nMaxX
,nMinY
+1 ) );
2208 mpDev
->DrawLine( Point( nMinX
,nMaxY
), Point( nMaxX
,nMaxY
) );
2211 mpDev
->DrawLine( Point( nMinX
,nMinY
), Point( nMinX
,nMaxY
) );
2212 if ( nType
== SC_CAT_DELETE_COLS
)
2213 mpDev
->DrawLine( Point( nMinX
+nLayoutSign
,nMinY
), Point( nMinX
+nLayoutSign
,nMaxY
) );
2216 mpDev
->DrawLine( Point( nMaxX
,nMinY
), Point( nMaxX
,nMaxY
) );
2218 if ( bLeft
&& bTop
)
2220 mpDev
->SetLineColor();
2221 mpDev
->SetFillColor( rColor
);
2222 mpDev
->DrawRect( Rectangle( nMinX
+nLayoutSign
, nMinY
+1, nMinX
+3*nLayoutSign
, nMinY
+3 ) );
2228 void ScOutputData::DrawChangeTrack()
2230 ScChangeTrack
* pTrack
= mpDoc
->GetChangeTrack();
2231 ScChangeViewSettings
* pSettings
= mpDoc
->GetChangeViewSettings();
2232 if ( !pTrack
|| !pTrack
->GetFirst() || !pSettings
|| !pSettings
->ShowChanges() )
2233 return; // nix da oder abgeschaltet
2235 ScActionColorChanger
aColorChanger(*pTrack
);
2237 // Clipping passiert von aussen
2238 //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2242 if ( nEndX
< MAXCOL
) ++nEndX
; // auch noch von der naechsten Zelle, weil die Markierung
2243 if ( nEndY
< MAXROW
) ++nEndY
; // in die jeweils vorhergehende Zelle hineinragt
2244 ScRange
aViewRange( nX1
, nY1
, nTab
, nEndX
, nEndY
, nTab
);
2245 const ScChangeAction
* pAction
= pTrack
->GetFirst();
2248 ScChangeActionType eActionType
;
2249 if ( pAction
->IsVisible() )
2251 eActionType
= pAction
->GetType();
2252 const ScBigRange
& rBig
= pAction
->GetBigRange();
2253 if ( rBig
.aStart
.Tab() == nTab
)
2255 ScRange aRange
= rBig
.MakeRange();
2257 if ( eActionType
== SC_CAT_DELETE_ROWS
)
2258 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
2259 else if ( eActionType
== SC_CAT_DELETE_COLS
)
2260 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
2262 if ( aRange
.Intersects( aViewRange
) &&
2263 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2265 aColorChanger
.Update( *pAction
);
2266 Color
aColor( aColorChanger
.GetColor() );
2267 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2268 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2272 if ( eActionType
== SC_CAT_MOVE
&&
2273 ((const ScChangeActionMove
*)pAction
)->
2274 GetFromRange().aStart
.Tab() == nTab
)
2276 ScRange aRange
= ((const ScChangeActionMove
*)pAction
)->
2277 GetFromRange().MakeRange();
2278 if ( aRange
.Intersects( aViewRange
) &&
2279 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *mpDoc
) )
2281 aColorChanger
.Update( *pAction
);
2282 Color
aColor( aColorChanger
.GetColor() );
2283 DrawOneChange( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2284 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aColor
, sal::static_int_cast
<sal_uInt16
>(eActionType
) );
2289 pAction
= pAction
->GetNext();
2293 //TODO: moggi Need to check if this can't be written simpler
2294 void ScOutputData::DrawNoteMarks()
2297 sal_Bool bFirst
= sal_True
;
2299 long nInitPosX
= nScrX
;
2301 nInitPosX
+= nMirrorW
- 1; // always in pixels
2302 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2305 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2307 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2308 if ( pThisRowInfo
->bChanged
)
2310 long nPosX
= nInitPosX
;
2311 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2313 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2314 sal_Bool bIsMerged
= false;
2316 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2318 // find start of merged cell
2319 bIsMerged
= sal_True
;
2320 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2323 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2324 // use origin's pCell for NotePtr test below
2327 if ( mpDoc
->GetNotes(nTab
)->findByAddress(nX
, pRowInfo
[nArrY
].nRowNo
) && ( bIsMerged
||
2328 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2332 mpDev
->SetLineColor();
2334 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2335 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2336 mpDev
->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2338 mpDev
->SetFillColor(COL_LIGHTRED
);
2343 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- 4 ) * nLayoutSign
;
2344 if ( bIsMerged
|| pInfo
->bMerged
)
2346 // if merged, add widths of all cells
2347 SCCOL nNextX
= nX
+ 1;
2348 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2350 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2354 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2355 mpDev
->DrawRect( Rectangle( nMarkX
,nPosY
,nMarkX
+2*nLayoutSign
,nPosY
+2 ) );
2358 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2361 nPosY
+= pThisRowInfo
->nHeight
;
2365 void ScOutputData::AddPDFNotes()
2367 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, mpDev
->GetExtOutDevData() );
2368 if ( !pPDFData
|| !pPDFData
->GetIsExportNotes() )
2371 long nInitPosX
= nScrX
;
2374 Size aOnePixel
= mpDev
->PixelToLogic(Size(1,1));
2375 long nOneX
= aOnePixel
.Width();
2376 nInitPosX
+= nMirrorW
- nOneX
;
2378 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2381 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2383 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2384 if ( pThisRowInfo
->bChanged
)
2386 long nPosX
= nInitPosX
;
2387 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2389 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2390 sal_Bool bIsMerged
= false;
2391 SCROW nY
= pRowInfo
[nArrY
].nRowNo
;
2395 if ( nX
==nX1
&& pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
)
2397 // find start of merged cell
2398 bIsMerged
= sal_True
;
2399 mpDoc
->ExtendOverlapped( nMergeX
, nMergeY
, nX
, nY
, nTab
);
2400 // use origin's pCell for NotePtr test below
2403 if ( mpDoc
->GetNotes(nTab
)->findByAddress(nMergeX
, nMergeY
) && ( bIsMerged
||
2404 ( !pInfo
->bHOverlapped
&& !pInfo
->bVOverlapped
) ) )
2406 long nNoteWidth
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2407 long nNoteHeight
= (long)( SC_CLIPMARK_SIZE
* mnPPTY
);
2409 long nMarkX
= nPosX
+ ( pRowInfo
[0].pCellInfo
[nX
+1].nWidth
- nNoteWidth
) * nLayoutSign
;
2410 if ( bIsMerged
|| pInfo
->bMerged
)
2412 // if merged, add widths of all cells
2413 SCCOL nNextX
= nX
+ 1;
2414 while ( nNextX
<= nX2
+ 1 && pThisRowInfo
->pCellInfo
[nNextX
+1].bHOverlapped
)
2416 nMarkX
+= pRowInfo
[0].pCellInfo
[nNextX
+1].nWidth
* nLayoutSign
;
2420 if ( bLayoutRTL
? ( nMarkX
>= 0 ) : ( nMarkX
< nScrX
+nScrW
) )
2422 Rectangle
aNoteRect( nMarkX
, nPosY
, nMarkX
+nNoteWidth
*nLayoutSign
, nPosY
+nNoteHeight
);
2423 const ScPostIt
* pNote
= mpDoc
->GetNotes(nTab
)->findByAddress(nMergeX
, nMergeY
);
2425 // Note title is the cell address (as on printed note pages)
2427 ScAddress
aAddress( nMergeX
, nMergeY
, nTab
);
2428 aAddress
.Format( aTitle
, SCA_VALID
, mpDoc
, mpDoc
->GetAddressConvention() );
2430 // Content has to be a simple string without line breaks
2431 String aContent
= pNote
->GetText();
2433 while ( (nPos
=aContent
.Search('\n')) != STRING_NOTFOUND
)
2434 aContent
.SetChar( nPos
, ' ' );
2437 aNote
.Title
= aTitle
;
2438 aNote
.Contents
= aContent
;
2439 pPDFData
->CreateNote( aNoteRect
, aNote
);
2443 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2446 nPosY
+= pThisRowInfo
->nHeight
;
2450 void ScOutputData::DrawClipMarks()
2455 Color
aArrowFillCol( COL_LIGHTRED
);
2457 sal_uLong nOldDrawMode
= mpDev
->GetDrawMode();
2458 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2459 if ( mbUseStyleColor
&& rStyleSettings
.GetHighContrastMode() )
2461 // use DrawMode to change the arrow's outline color
2462 mpDev
->SetDrawMode( nOldDrawMode
| DRAWMODE_SETTINGSLINE
);
2463 // use text color also for the fill color
2464 aArrowFillCol
.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
);
2467 long nInitPosX
= nScrX
;
2469 nInitPosX
+= nMirrorW
- 1; // always in pixels
2470 long nLayoutSign
= bLayoutRTL
? -1 : 1;
2472 Rectangle aCellRect
;
2474 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
2476 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
2477 if ( pThisRowInfo
->bChanged
)
2479 SCROW nY
= pThisRowInfo
->nRowNo
;
2480 long nPosX
= nInitPosX
;
2481 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
2483 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
2484 if (pInfo
->nClipMark
)
2486 if (pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
)
2488 // merge origin may be outside of visible area - use document functions
2492 long nStartPosX
= nPosX
;
2493 long nStartPosY
= nPosY
;
2495 while ( nOverX
> 0 && ( ((const ScMergeFlagAttr
*)mpDoc
->GetAttr(
2496 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & SC_MF_HOR
) )
2499 nStartPosX
-= nLayoutSign
* (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2502 while ( nOverY
> 0 && ( ((const ScMergeFlagAttr
*)mpDoc
->GetAttr(
2503 nOverX
, nOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue() & SC_MF_VER
) )
2506 nStartPosY
-= nLayoutSign
* (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2509 long nOutWidth
= (long) ( mpDoc
->GetColWidth(nOverX
,nTab
) * mnPPTX
);
2510 long nOutHeight
= (long) ( mpDoc
->GetRowHeight(nOverY
,nTab
) * mnPPTY
);
2512 const ScMergeAttr
* pMerge
= (const ScMergeAttr
*)
2513 mpDoc
->GetAttr( nOverX
, nOverY
, nTab
, ATTR_MERGE
);
2514 SCCOL nCountX
= pMerge
->GetColMerge();
2515 for (SCCOL i
=1; i
<nCountX
; i
++)
2516 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2517 SCROW nCountY
= pMerge
->GetRowMerge();
2518 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2521 nStartPosX
-= nOutWidth
- 1;
2522 aCellRect
= Rectangle( Point( nStartPosX
, nStartPosY
), Size( nOutWidth
, nOutHeight
) );
2526 long nOutWidth
= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
2527 long nOutHeight
= pThisRowInfo
->nHeight
;
2529 if ( pInfo
->bMerged
&& pInfo
->pPatternAttr
)
2533 const ScMergeAttr
* pMerge
=
2534 (ScMergeAttr
*)&pInfo
->pPatternAttr
->GetItem(ATTR_MERGE
);
2535 SCCOL nCountX
= pMerge
->GetColMerge();
2536 for (SCCOL i
=1; i
<nCountX
; i
++)
2537 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nOverX
+i
,nTab
) * mnPPTX
);
2538 SCROW nCountY
= pMerge
->GetRowMerge();
2539 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nOverY
+1, nOverY
+nCountY
-1, nTab
, mnPPTY
);
2542 long nStartPosX
= nPosX
;
2544 nStartPosX
-= nOutWidth
- 1;
2545 // #i80447# create aCellRect from two points in case nOutWidth is 0
2546 aCellRect
= Rectangle( Point( nStartPosX
, nPosY
),
2547 Point( nStartPosX
+nOutWidth
-1, nPosY
+nOutHeight
-1 ) );
2550 aCellRect
.Bottom() -= 1; // don't paint over the cell grid
2552 aCellRect
.Left() += 1;
2554 aCellRect
.Right() -= 1;
2556 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2557 Size
aMarkSize( nMarkPixel
, (nMarkPixel
-1)*2 );
2559 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_RIGHT
: SC_CLIPMARK_LEFT
) )
2562 Rectangle aMarkRect
= aCellRect
;
2563 aMarkRect
.Right() = aCellRect
.Left()+nMarkPixel
-1;
2564 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, true );
2566 if ( pInfo
->nClipMark
& ( bLayoutRTL
? SC_CLIPMARK_LEFT
: SC_CLIPMARK_RIGHT
) )
2569 Rectangle aMarkRect
= aCellRect
;
2570 aMarkRect
.Left() = aCellRect
.Right()-nMarkPixel
+1;
2571 SvxFont::DrawArrow( *mpDev
, aMarkRect
, aMarkSize
, aArrowFillCol
, false );
2574 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2577 nPosY
+= pThisRowInfo
->nHeight
;
2580 mpDev
->SetDrawMode(nOldDrawMode
);
2585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */