GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / sc / source / ui / view / output.cxx
blob71d469e780a1e9f3b28d0cfd9770fe2639325876
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "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>
45 #include "output.hxx"
46 #include "document.hxx"
47 #include "drwlayer.hxx"
48 #include "formulacell.hxx"
49 #include "attrib.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"
61 #include "scmod.hxx"
62 #include "appoptio.hxx"
63 #include "postit.hxx"
65 #include "scresid.hxx"
66 #include "colorscale.hxx"
68 #include <math.h>
69 #include <map>
70 #include <utility>
71 #include <iostream>
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 const 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
92 private:
93 const ScAppOptions& rOpt;
94 const std::set<OUString>& rUsers;
95 OUString aLastUserName;
96 size_t nLastUserIndex;
97 ColorData nColor;
99 public:
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() ),
112 nLastUserIndex( 0 ),
113 nColor( COL_BLACK )
117 void ScActionColorChanger::Update( const ScChangeAction& rAction )
119 ColorData nSetColor;
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();
126 break;
127 case SC_CAT_DELETE_COLS:
128 case SC_CAT_DELETE_ROWS:
129 case SC_CAT_DELETE_TABS:
130 nSetColor = rOpt.GetTrackDeleteColor();
131 break;
132 case SC_CAT_MOVE:
133 nSetColor = rOpt.GetTrackMoveColor();
134 break;
135 default:
136 nSetColor = rOpt.GetTrackContentColor();
137 break;
139 if ( nSetColor != COL_TRANSPARENT ) // Farbe eingestellt
140 nColor = nSetColor;
141 else // nach Autor
143 if (!aLastUserName.equals(rAction.GetUser()))
145 aLastUserName = rAction.GetUser();
146 std::set<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" );
151 nLastUserIndex = 0;
153 else
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 ) :
171 mpDev( pNewDev ),
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 ),
177 mpDoc( pNewDoc ),
178 nTab( nNewTab ),
179 nScrX( nNewScrX ),
180 nScrY( nNewScrY ),
181 nX1( nNewX1 ),
182 nY1( nNewY1 ),
183 nX2( nNewX2 ),
184 nY2( nNewY2 ),
185 eType( eNewType ),
186 mnPPTX( nPixelPerTwipsX ),
187 mnPPTY( nPixelPerTwipsY ),
188 pEditObj( NULL ),
189 pViewShell( NULL ),
190 pDrawView( NULL ), // #114135#
191 bEditMode( false ),
192 bMetaFile( false ),
193 bSingleGrid( false ),
194 bPagebreakMode( false ),
195 bSolidBackground( false ),
196 mbUseStyleColor( false ),
197 mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
198 mbSyntaxMode( false ),
199 pValueColor( NULL ),
200 pTextColor( NULL ),
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.
207 bSnapPixel( false ),
208 bAnyRotated( false ),
209 bAnyClipped( false ),
210 mpTargetPaintWindow(NULL), // #i74769# use SdrPaintWindow direct
211 mpSpellCheckCxt(NULL)
213 if (pZoomX)
214 aZoomX = *pZoomX;
215 else
216 aZoomX = Fraction(1,1);
217 if (pZoomY)
218 aZoomY = *pZoomY;
219 else
220 aZoomY = Fraction(1,1);
222 nVisX1 = nX1;
223 nVisY1 = nY1;
224 nVisX2 = nX2;
225 nVisY2 = nY2;
226 mpDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
228 nScrW = 0;
229 for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
230 nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
232 nMirrorW = nScrW;
234 nScrH = 0;
235 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
236 nScrH += pRowInfo[nArrY].nHeight;
238 bTabProtected = mpDoc->IsTabProtected( nTab );
239 nTabTextDirection = mpDoc->GetEditTextDirection( nTab );
240 bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
243 ScOutputData::~ScOutputData()
245 delete pValueColor;
246 delete pTextColor;
247 delete pFormulaColor;
250 void ScOutputData::SetSpellCheckContext( const sc::SpellCheckContext* pCxt )
252 mpSpellCheckCxt = pCxt;
255 void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
257 // use pContentDev instead of pDev where used
259 if ( mpRefDevice == mpDev )
260 mpRefDevice = pContentDev;
261 if ( pFmtDevice == mpDev )
262 pFmtDevice = pContentDev;
263 mpDev = pContentDev;
266 void ScOutputData::SetMirrorWidth( long nNew )
268 nMirrorW = nNew;
271 void ScOutputData::SetGridColor( const Color& rColor )
273 aGridColor = rColor;
276 void ScOutputData::SetMarkClipped( sal_Bool bSet )
278 bMarkClipped = bSet;
281 void ScOutputData::SetShowNullValues( sal_Bool bSet )
283 mbShowNullValues = bSet;
286 void ScOutputData::SetShowFormulas( sal_Bool bSet )
288 mbShowFormulas = bSet;
291 void ScOutputData::SetShowSpellErrors( sal_Bool bSet )
293 bShowSpellErrors = bSet;
296 void ScOutputData::SetSnapPixel( sal_Bool bSet )
298 bSnapPixel = bSet;
301 void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow )
303 nEditCol = nCol;
304 nEditRow = nRow;
305 bEditMode = sal_True;
308 void ScOutputData::SetMetaFileMode( sal_Bool bNewMode )
310 bMetaFile = bNewMode;
313 void ScOutputData::SetSingleGrid( sal_Bool bNewMode )
315 bSingleGrid = bNewMode;
318 void ScOutputData::SetSyntaxMode( sal_Bool bNewMode )
320 mbSyntaxMode = bNewMode;
321 if (bNewMode)
322 if (!pValueColor)
324 pValueColor = new Color( COL_LIGHTBLUE );
325 pTextColor = new Color( COL_BLACK );
326 pFormulaColor = new Color( COL_GREEN );
330 void ScOutputData::DrawGrid( sal_Bool bGrid, sal_Bool bPage )
332 SCCOL nX;
333 SCROW nY;
334 long nPosX;
335 long nPosY;
336 SCSIZE nArrY;
337 ScBreakType nBreak = BREAK_NONE;
338 ScBreakType nBreakOld = BREAK_NONE;
340 sal_Bool bSingle;
341 Color aPageColor;
342 Color aManualColor;
344 if (bPagebreakMode)
345 bPage = false; // keine "normalen" Umbrueche ueber volle Breite/Hoehe
347 //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
348 //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
350 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
351 long nOneX = aOnePixel.Width();
352 long nOneY = aOnePixel.Height();
353 if (bMetaFile)
354 nOneX = nOneY = 1;
356 long nLayoutSign = bLayoutRTL ? -1 : 1;
357 long nSignedOneX = nOneX * nLayoutSign;
359 if ( eType == OUTTYPE_WINDOW )
361 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
362 aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
363 aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
365 else
367 aPageColor = aGridColor;
368 aManualColor = aGridColor;
371 mpDev->SetLineColor( aGridColor );
372 ScGridMerger aGrid( mpDev, nOneX, nOneY );
375 // Vertikale Linien
378 nPosX = nScrX;
379 if ( bLayoutRTL )
380 nPosX += nMirrorW - nOneX;
382 for (nX=nX1; nX<=nX2; nX++)
384 SCCOL nXplus1 = nX+1;
385 SCCOL nXplus2 = nX+2;
386 sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
387 if (nWidth)
389 nPosX += nWidth * nLayoutSign;
391 if ( bPage )
393 // Seitenumbrueche auch in ausgeblendeten suchen
394 SCCOL nCol = nXplus1;
395 while (nCol <= MAXCOL)
397 nBreak = mpDoc->HasColBreak(nCol, nTab);
398 bool bHidden = mpDoc->ColHidden(nCol, nTab);
400 if ( nBreak || !bHidden )
401 break;
402 ++nCol;
405 if (nBreak != nBreakOld)
407 aGrid.Flush();
408 mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
409 nBreak ? aPageColor : aGridColor );
410 nBreakOld = nBreak;
414 sal_Bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
416 sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
417 bSingle = bSingleGrid; //! in Fillinfo holen !!!!!
418 if ( nX<MAXCOL && !bSingle )
420 bSingle = ( nWidthXplus2 == 0 );
421 for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
423 if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
424 bSingle = sal_True;
425 if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
426 bSingle = sal_True;
430 if (bDraw)
432 if ( nX<MAXCOL && bSingle )
434 SCCOL nVisX = nXplus1;
435 while ( nVisX < MAXCOL && !mpDoc->GetColWidth(nVisX,nTab) )
436 ++nVisX;
438 nPosY = nScrY;
439 long nNextY;
440 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
442 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
443 nNextY = nPosY + pThisRowInfo->nHeight;
445 sal_Bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
446 if (!bHOver)
448 if (nWidthXplus2)
449 bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped;
450 else
452 if (nVisX <= nX2)
453 bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped;
454 else
455 bHOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
456 nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
457 ->IsHorOverlapped();
458 if (bHOver)
459 bHOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
460 nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
461 ->IsHorOverlapped();
465 if (pThisRowInfo->bChanged && !bHOver)
467 aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
469 nPosY = nNextY;
472 else
474 aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
481 // Horizontale Linien
484 bool bHiddenRow = true;
485 SCROW nHiddenEndRow = -1;
486 nPosY = nScrY;
487 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
489 SCSIZE nArrYplus1 = nArrY+1;
490 nY = pRowInfo[nArrY].nRowNo;
491 SCROW nYplus1 = nY+1;
492 nPosY += pRowInfo[nArrY].nHeight;
494 if (pRowInfo[nArrY].bChanged)
496 if ( bPage )
498 for (SCROW i = nYplus1; i <= MAXROW; ++i)
500 if (i > nHiddenEndRow)
501 bHiddenRow = mpDoc->RowHidden(i, nTab, NULL, &nHiddenEndRow);
502 /* TODO: optimize the row break thing for large hidden
503 * segments where HasRowBreak() has to be called
504 * nevertheless for each row, as a row break is drawn also
505 * for hidden rows, above them. This needed to be done only
506 * once per hidden segment, maybe giving manual breaks
507 * priority. Something like GetNextRowBreak() and
508 * GetNextManualRowBreak(). */
509 nBreak = mpDoc->HasRowBreak(i, nTab);
510 if (!bHiddenRow || nBreak)
511 break;
514 if (nBreakOld != nBreak)
516 aGrid.Flush();
517 mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
518 (nBreak) ? aPageColor : aGridColor );
519 nBreakOld = nBreak;
523 bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
525 sal_Bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
526 bSingle = !bNextYisNextRow; // Hidden
527 for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
529 if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
530 bSingle = sal_True;
533 if (bDraw)
535 if ( bSingle && nY<MAXROW )
537 SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
539 nPosX = nScrX;
540 if ( bLayoutRTL )
541 nPosX += nMirrorW - nOneX;
543 long nNextX;
544 for (SCCOL i=nX1; i<=nX2; i++)
546 nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
547 if (nNextX != nPosX) // sichtbar
549 sal_Bool bVOver;
550 if ( bNextYisNextRow )
551 bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
552 else
554 bVOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
555 i,nYplus1,nTab,ATTR_MERGE_FLAG))
556 ->IsVerOverlapped()
557 && ((ScMergeFlagAttr*)mpDoc->GetAttr(
558 i,nVisY,nTab,ATTR_MERGE_FLAG))
559 ->IsVerOverlapped();
560 //! nVisY aus Array ??
562 if (!bVOver)
564 aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
567 nPosX = nNextX;
570 else
572 aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
579 // ----------------------------------------------------------------------------
581 void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
583 bPagebreakMode = true;
584 if (!pPageData)
585 return; // noch nicht initialisiert -> alles "nicht gedruckt"
587 // gedruckten Bereich markieren
588 // (in FillInfo ist schon alles auf sal_False initialisiert)
590 sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount());
591 for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++)
593 ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
595 SCCOL nStartX = std::max( aRange.aStart.Col(), nX1 );
596 SCCOL nEndX = std::min( aRange.aEnd.Col(), nX2 );
597 SCROW nStartY = std::max( aRange.aStart.Row(), nY1 );
598 SCROW nEndY = std::min( aRange.aEnd.Row(), nY2 );
600 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
602 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
603 if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
604 pThisRowInfo->nRowNo <= nEndY )
606 for (SCCOL nX=nStartX; nX<=nEndX; nX++)
607 pThisRowInfo->pCellInfo[nX+1].bPrinted = sal_True;
613 void ScOutputData::FindRotated()
615 //! nRotMax speichern
616 SCCOL nRotMax = nX2;
617 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
618 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
619 nRotMax = pRowInfo[nRotY].nRotMaxCol;
621 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
623 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
624 if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
625 ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
626 ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
628 SCROW nY = pThisRowInfo->nRowNo;
630 for (SCCOL nX=0; nX<=nRotMax; nX++)
632 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
633 const ScPatternAttr* pPattern = pInfo->pPatternAttr;
634 const SfxItemSet* pCondSet = pInfo->pConditionSet;
636 if ( !pPattern && !mpDoc->ColHidden(nX, nTab) )
638 pPattern = mpDoc->GetPattern( nX, nY, nTab );
639 pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
642 if ( pPattern ) // Spalte nicht ausgeblendet
644 sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet );
645 if (nDir != SC_ROTDIR_NONE)
647 pInfo->nRotateDir = nDir;
648 bAnyRotated = sal_True;
656 // ----------------------------------------------------------------------------
658 static sal_uInt16 lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
660 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
661 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
663 sal_uInt16 nRet = SC_ROTDIR_NONE;
665 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
666 if ( nAttrRotate )
668 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
669 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
671 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
672 nRet = SC_ROTDIR_STANDARD;
673 else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
674 nRet = SC_ROTDIR_CENTER;
675 else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
677 long nRot180 = nAttrRotate % 18000; // 1/100 Grad
678 if ( nRot180 == 9000 )
679 nRet = SC_ROTDIR_CENTER;
680 else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
681 ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
682 nRet = SC_ROTDIR_LEFT;
683 else
684 nRet = SC_ROTDIR_RIGHT;
688 return nRet;
691 static const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
693 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
694 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
695 const SvxBrushItem* pBackground = (const SvxBrushItem*)
696 &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
698 sal_uInt16 nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
700 // CENTER wird wie RIGHT behandelt...
701 if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER )
703 // Text geht nach rechts -> Hintergrund von links nehmen
704 while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
705 pBackground->GetColor().GetTransparency() != 255 )
707 --nCol;
708 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
709 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
710 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
713 else if ( nDir == SC_ROTDIR_LEFT )
715 // Text geht nach links -> Hintergrund von rechts nehmen
716 while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
717 pBackground->GetColor().GetTransparency() != 255 )
719 ++nCol;
720 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
721 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
722 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
726 return pBackground;
729 // ----------------------------------------------------------------------------
731 static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
732 SCCOL nX1, SCCOL nX2, bool bShowProt, bool bPagebreakMode )
734 if ( rFirst.bChanged != rOther.bChanged ||
735 rFirst.bEmptyBack != rOther.bEmptyBack )
736 return false;
738 SCCOL nX;
739 if ( bShowProt )
741 for ( nX=nX1; nX<=nX2; nX++ )
743 const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr;
744 const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr;
745 if ( !pPat1 || !pPat2 ||
746 &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
747 return false;
750 else
752 for ( nX=nX1; nX<=nX2; nX++ )
753 if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
754 return false;
757 if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
758 for ( nX=nX1; nX<=nX2; nX++ )
759 if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
760 return false;
762 if ( bPagebreakMode )
763 for ( nX=nX1; nX<=nX2; nX++ )
764 if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
765 return false;
767 for ( nX=nX1; nX<=nX2; nX++ )
769 const Color* pCol1 = rFirst.pCellInfo[nX+1].pColorScale;
770 const Color* pCol2 = rOther.pCellInfo[nX+1].pColorScale;
771 if( (pCol1 && !pCol2) || (!pCol1 && pCol2) )
772 return false;
774 if (pCol1 && (*pCol1 != *pCol2))
775 return false;
777 const ScDataBarInfo* pInfo1 = rFirst.pCellInfo[nX+1].pDataBar;
778 const ScDataBarInfo* pInfo2 = rOther.pCellInfo[nX+1].pDataBar;
780 if( (pInfo1 && !pInfo2) || (!pInfo1 && pInfo2) )
781 return false;
783 if (pInfo1 && (*pInfo1 != *pInfo2))
784 return false;
786 // each cell with an icon set should be painted the same way
787 const ScIconSetInfo* pIconSet1 = rFirst.pCellInfo[nX+1].pIconSet;
788 const ScIconSetInfo* pIconSet2 = rOther.pCellInfo[nX+1].pIconSet;
790 if(pIconSet1 || pIconSet2)
791 return false;
794 return true;
797 void ScOutputData::DrawDocumentBackground()
799 if ( !bSolidBackground )
800 return;
802 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
803 long nOneX = aOnePixel.Width();
804 long nOneY = aOnePixel.Height();
805 Rectangle aRect(nScrX - nOneX, nScrY - nOneY, nScrX + nScrW, nScrY + nScrH);
806 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
807 mpDev->SetFillColor(aBgColor);
808 mpDev->DrawRect(aRect);
811 namespace {
813 static const double lclCornerRectTransparency = 40.0;
815 void drawDataBars( const ScDataBarInfo* pOldDataBarInfo, OutputDevice* pDev, const Rectangle& rRect)
817 long nPosZero = 0;
818 Rectangle aPaintRect = rRect;
819 aPaintRect.Top() += 2;
820 aPaintRect.Bottom() -= 2;
821 aPaintRect.Left() += 2;
822 aPaintRect.Right() -= 2;
823 if(pOldDataBarInfo->mnZero)
825 //need to calculate null point in cell
826 long nLength = aPaintRect.Right() - aPaintRect.Left();
827 nPosZero = static_cast<long>(aPaintRect.Left() + nLength*pOldDataBarInfo->mnZero/100.0);
829 else
831 nPosZero = aPaintRect.Left();
834 if(pOldDataBarInfo->mnLength < 0)
836 aPaintRect.Right() = nPosZero;
837 long nLength = nPosZero - aPaintRect.Left();
838 aPaintRect.Left() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
840 else if(pOldDataBarInfo->mnLength > 0)
842 aPaintRect.Left() = nPosZero;
843 long nLength = aPaintRect.Right() - nPosZero;
844 aPaintRect.Right() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
846 else
847 return;
849 if(pOldDataBarInfo->mbGradient)
851 pDev->SetLineColor(pOldDataBarInfo->maColor);
852 Gradient aGradient(GradientStyle_LINEAR, pOldDataBarInfo->maColor, COL_TRANSPARENT);
854 if(pOldDataBarInfo->mnLength < 0)
855 aGradient.SetAngle(2700);
856 else
857 aGradient.SetAngle(900);
859 pDev->DrawGradient(aPaintRect, aGradient);
861 pDev->SetLineColor();
863 else
865 pDev->SetFillColor(pOldDataBarInfo->maColor);
866 pDev->DrawRect(aPaintRect);
869 //draw axis
870 if(pOldDataBarInfo->mnZero && pOldDataBarInfo->mnZero != 100)
872 Point aPoint1(nPosZero, rRect.Top());
873 Point aPoint2(nPosZero, rRect.Bottom());
874 LineInfo aLineInfo(LINE_DASH, 1);
875 aLineInfo.SetDashCount( 4 );
876 aLineInfo.SetDistance( 3 );
877 aLineInfo.SetDashLen( 3 );
878 pDev->SetFillColor(pOldDataBarInfo->maAxisColor);
879 pDev->SetLineColor(pOldDataBarInfo->maAxisColor);
880 pDev->DrawLine(aPoint1, aPoint2, aLineInfo);
881 pDev->SetLineColor();
882 pDev->SetFillColor();
886 BitmapEx& getIcon( ScIconSetType eType, sal_Int32 nIndex )
888 return ScIconSetFormat::getBitmap( eType, nIndex );
891 void drawIconSets( const ScIconSetInfo* pOldIconSetInfo, OutputDevice* pDev, const Rectangle& rRect )
893 //long nSize = 16;
894 ScIconSetType eType = pOldIconSetInfo->eIconSetType;
895 sal_Int32 nIndex = pOldIconSetInfo->nIconIndex;
896 BitmapEx& rIcon = getIcon( eType, nIndex );
897 long aOrigSize = std::max<long>(0,std::min(rRect.GetSize().getWidth() - 4, rRect.GetSize().getHeight() -4));
898 pDev->DrawBitmapEx( Point( rRect.Left() +2, rRect.Top() + 2 ), Size(aOrigSize, aOrigSize), rIcon );
901 void drawCells(const Color* pColor, const SvxBrushItem* pBackground, const Color*& pOldColor, const SvxBrushItem*& pOldBackground,
902 Rectangle& rRect, long nPosX, long nSignedOneX, OutputDevice* pDev, const ScDataBarInfo* pDataBarInfo, const ScDataBarInfo*& pOldDataBarInfo,
903 const ScIconSetInfo* pIconSetInfo, const ScIconSetInfo*& pOldIconSetInfo)
906 // need to paint if old color scale has been used and now
907 // we have a different color or a style based background
908 // we can here fall back to pointer comparison
909 if (pOldColor && (pBackground || pOldColor != pColor || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo))
911 rRect.Right() = nPosX-nSignedOneX;
912 if( !pOldColor->GetTransparency() )
914 pDev->SetFillColor( *pOldColor );
915 pDev->DrawRect( rRect );
917 if( pOldDataBarInfo )
918 drawDataBars( pOldDataBarInfo, pDev, rRect );
919 if( pOldIconSetInfo )
920 drawIconSets( pOldIconSetInfo, pDev, rRect );
922 rRect.Left() = nPosX - nSignedOneX;
925 if ( pOldBackground && (pColor ||pBackground != pOldBackground || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo) )
927 rRect.Right() = nPosX-nSignedOneX;
928 if (pOldBackground) // ==0 if hidden
930 Color aBackCol = pOldBackground->GetColor();
931 if ( !aBackCol.GetTransparency() ) //! partial transparency?
933 pDev->SetFillColor( aBackCol );
934 pDev->DrawRect( rRect );
937 if( pOldDataBarInfo )
938 drawDataBars( pOldDataBarInfo, pDev, rRect );
939 if( pOldIconSetInfo )
940 drawIconSets( pOldIconSetInfo, pDev, rRect );
942 rRect.Left() = nPosX - nSignedOneX;
945 if (!pOldBackground && !pOldColor && (pDataBarInfo || pIconSetInfo))
947 rRect.Right() = nPosX -nSignedOneX;
948 rRect.Left() = nPosX - nSignedOneX;
951 if(pColor)
953 // only update pOldColor if the colors changed
954 if (!pOldColor || *pOldColor != *pColor)
955 pOldColor = pColor;
957 pOldBackground = NULL;
959 else if(pBackground)
961 pOldBackground = pBackground;
962 pOldColor = NULL;
965 if(pDataBarInfo)
966 pOldDataBarInfo = pDataBarInfo;
967 else
968 pOldDataBarInfo = NULL;
970 if(pIconSetInfo)
971 pOldIconSetInfo = pIconSetInfo;
972 else
973 pOldIconSetInfo = NULL;
978 void ScOutputData::DrawBackground()
980 FindRotated(); //! von aussen ?
982 Rectangle aRect;
983 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
984 long nOneX = aOnePixel.Width();
985 long nOneY = aOnePixel.Height();
987 if (bMetaFile)
988 nOneX = nOneY = 0;
990 long nLayoutSign = bLayoutRTL ? -1 : 1;
991 long nSignedOneX = nOneX * nLayoutSign;
993 mpDev->SetLineColor();
995 bool bShowProt = mbSyntaxMode && mpDoc->IsTabProtected(nTab);
996 bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
998 bool bCellContrast = mbUseStyleColor &&
999 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1001 long nPosY = nScrY;
1002 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1004 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1005 long nRowHeight = pThisRowInfo->nHeight;
1007 if ( pThisRowInfo->bChanged )
1009 if ( ( ( pThisRowInfo->bEmptyBack ) || mbSyntaxMode ) && !bDoAll )
1011 // nichts
1013 else
1015 // scan for rows with the same background:
1016 SCSIZE nSkip = 0;
1017 while ( nArrY+nSkip+2<nArrCount &&
1018 lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
1019 nX1, nX2, bShowProt, bPagebreakMode ) )
1021 ++nSkip;
1022 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1025 long nPosX = nScrX;
1026 if ( bLayoutRTL )
1027 nPosX += nMirrorW - nOneX;
1028 aRect = Rectangle( nPosX, nPosY-nOneY, nPosX, nPosY+nRowHeight-nOneY );
1030 const SvxBrushItem* pOldBackground = NULL;
1031 const SvxBrushItem* pBackground;
1032 const Color* pOldColor = NULL;
1033 const Color* pColor = NULL;
1034 const ScDataBarInfo* pOldDataBarInfo = NULL;
1035 const ScIconSetInfo* pOldIconSetInfo = NULL;
1036 for (SCCOL nX=nX1; nX<=nX2; nX++)
1038 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1040 if (bCellContrast)
1042 // high contrast for cell borders and backgrounds -> empty background
1043 pBackground = ScGlobal::GetEmptyBrushItem();
1045 else if (bShowProt) // show cell protection in syntax mode
1047 const ScPatternAttr* pP = pInfo->pPatternAttr;
1048 if (pP)
1050 const ScProtectionAttr& rProt = (const ScProtectionAttr&)
1051 pP->GetItem(ATTR_PROTECTION);
1052 if (rProt.GetProtection() || rProt.GetHideCell())
1053 pBackground = ScGlobal::GetProtectedBrushItem();
1054 else
1055 pBackground = ScGlobal::GetEmptyBrushItem();
1057 else
1058 pBackground = NULL;
1060 else
1061 pBackground = pInfo->pBackground;
1063 if ( bPagebreakMode && !pInfo->bPrinted )
1064 pBackground = ScGlobal::GetProtectedBrushItem();
1066 if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1067 pBackground->GetColor().GetTransparency() != 255 &&
1068 !bCellContrast )
1070 SCROW nY = pRowInfo[nArrY].nRowNo;
1071 pBackground = lcl_FindBackground( mpDoc, nX, nY, nTab );
1074 pColor = pInfo->pColorScale;
1075 const ScDataBarInfo* pDataBarInfo = pInfo->pDataBar;
1076 const ScIconSetInfo* pIconSetInfo = pInfo->pIconSet;
1077 drawCells( pColor, pBackground, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo );
1079 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1081 drawCells( NULL, NULL, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, NULL, pOldDataBarInfo, NULL, pOldIconSetInfo );
1083 nArrY += nSkip;
1086 nPosY += nRowHeight;
1090 void ScOutputData::DrawShadow()
1092 DrawExtraShadow( false, false, false, false );
1095 void ScOutputData::DrawExtraShadow(sal_Bool bLeft, sal_Bool bTop, sal_Bool bRight, sal_Bool bBottom)
1097 mpDev->SetLineColor();
1099 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1100 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1101 Color aAutoTextColor;
1102 if ( bCellContrast )
1103 aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1105 long nInitPosX = nScrX;
1106 if ( bLayoutRTL )
1108 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1109 long nOneX = aOnePixel.Width();
1110 nInitPosX += nMirrorW - nOneX;
1112 long nLayoutSign = bLayoutRTL ? -1 : 1;
1114 long nPosY = nScrY - pRowInfo[0].nHeight;
1115 for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
1117 bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
1118 bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
1120 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1121 long nRowHeight = pThisRowInfo->nHeight;
1123 if ( pThisRowInfo->bChanged && !bSkipY )
1125 long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
1126 for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
1128 bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
1129 bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
1131 for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertikal
1133 const SvxShadowItem* pAttr = nPass ?
1134 pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
1135 pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
1136 if ( pAttr && !bSkipX )
1138 ScShadowPart ePart = nPass ?
1139 pThisRowInfo->pCellInfo[nArrX].eVShadowPart :
1140 pThisRowInfo->pCellInfo[nArrX].eHShadowPart;
1142 bool bDo = true;
1143 if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
1144 if ( ePart != SC_SHADOW_CORNER )
1145 bDo = false;
1147 if (bDo)
1149 long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1150 long nMaxWidth = nThisWidth;
1151 if (!nMaxWidth)
1153 //! direction must depend on shadow location
1154 SCCOL nWx = nArrX; // nX+1
1155 while (nWx<nX2 && !pRowInfo[0].pCellInfo[nWx+1].nWidth)
1156 ++nWx;
1157 nMaxWidth = pRowInfo[0].pCellInfo[nWx+1].nWidth;
1160 // rectangle is in logical orientation
1161 Rectangle aRect( nPosX, nPosY,
1162 nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1163 nPosY + pRowInfo[nArrY].nHeight - 1 );
1165 long nSize = pAttr->GetWidth();
1166 long nSizeX = (long)(nSize*mnPPTX);
1167 if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1;
1168 long nSizeY = (long)(nSize*mnPPTY);
1169 if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1;
1171 nSizeX *= nLayoutSign; // used only to add to rectangle values
1173 SvxShadowLocation eLoc = pAttr->GetLocation();
1174 if ( bLayoutRTL )
1176 // Shadow location is specified as "visual" (right is always right),
1177 // so the attribute's location value is mirrored here and in FillInfo.
1178 switch (eLoc)
1180 case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
1181 case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
1182 case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
1183 case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
1184 default:
1186 // added to avoid warnings
1191 if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1192 ePart == SC_SHADOW_CORNER)
1194 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1195 aRect.Top() = aRect.Bottom() - nSizeY;
1196 else
1197 aRect.Bottom() = aRect.Top() + nSizeY;
1199 if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1200 ePart == SC_SHADOW_CORNER)
1202 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1203 aRect.Left() = aRect.Right() - nSizeX;
1204 else
1205 aRect.Right() = aRect.Left() + nSizeX;
1207 if (ePart == SC_SHADOW_HSTART)
1209 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1210 aRect.Right() -= nSizeX;
1211 else
1212 aRect.Left() += nSizeX;
1214 if (ePart == SC_SHADOW_VSTART)
1216 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1217 aRect.Bottom() -= nSizeY;
1218 else
1219 aRect.Top() += nSizeY;
1222 //! merge rectangles?
1223 mpDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1224 mpDev->DrawRect( aRect );
1229 nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1232 nPosY += nRowHeight;
1237 // Loeschen
1240 void ScOutputData::DrawClear()
1242 Rectangle aRect;
1243 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1244 long nOneX = aOnePixel.Width();
1245 long nOneY = aOnePixel.Height();
1247 // (called only for ScGridWindow)
1248 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1250 if (bMetaFile)
1251 nOneX = nOneY = 0;
1253 mpDev->SetLineColor();
1255 mpDev->SetFillColor( aBgColor );
1257 long nPosY = nScrY;
1258 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1260 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1261 long nRowHeight = pThisRowInfo->nHeight;
1263 if ( pThisRowInfo->bChanged )
1265 // scan for more rows which must be painted:
1266 SCSIZE nSkip = 0;
1267 while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1269 ++nSkip;
1270 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1273 aRect = Rectangle( Point( nScrX, nPosY ),
1274 Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1275 mpDev->DrawRect( aRect );
1277 nArrY += nSkip;
1279 nPosY += nRowHeight;
1283 namespace {
1285 long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1287 return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1290 long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1292 return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1295 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL )
1297 return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) );
1301 * Temporarily turn off antialiasing.
1303 class AntiAliasingSwitch
1305 SvtOptionsDrawinglayer maDrawOpt;
1306 bool mbOldSetting;
1307 public:
1308 AntiAliasingSwitch(bool bOn) : mbOldSetting(maDrawOpt.IsAntiAliasing())
1310 maDrawOpt.SetAntiAliasing(bOn);
1313 ~AntiAliasingSwitch()
1315 maDrawOpt.SetAntiAliasing(mbOldSetting);
1321 void ScOutputData::DrawFrame()
1323 // No anti-aliasing for drawing cell borders.
1324 AntiAliasingSwitch aAASwitch(false);
1326 sal_uLong nOldDrawMode = mpDev->GetDrawMode();
1328 Color aSingleColor;
1329 bool bUseSingleColor = false;
1330 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1331 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1333 // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1334 // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1335 // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1336 // must be reset and the border colors handled here.
1338 if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) )
1340 mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) );
1341 aSingleColor.SetColor( COL_BLACK );
1342 bUseSingleColor = true;
1344 else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) )
1346 mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) );
1347 aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE
1348 bUseSingleColor = true;
1350 else if ( bCellContrast )
1352 aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1353 bUseSingleColor = true;
1356 const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1358 if (bAnyRotated)
1359 DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here
1361 long nInitPosX = nScrX;
1362 if ( bLayoutRTL )
1364 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1365 long nOneX = aOnePixel.Width();
1366 nInitPosX += nMirrorW - nOneX;
1368 long nLayoutSign = bLayoutRTL ? -1 : 1;
1371 // *** set column and row sizes of the frame border array ***
1373 svx::frame::Array& rArray = mrTabInfo.maArray;
1374 size_t nColCount = rArray.GetColCount();
1375 size_t nRowCount = rArray.GetRowCount();
1377 // row heights
1379 // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1380 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1381 long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1382 long nOldSnapY = lclGetSnappedY( *mpDev, nOldPosY, bSnapPixel );
1383 rArray.SetYOffset( nOldSnapY );
1384 for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1386 long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1387 long nNewSnapY = lclGetSnappedY( *mpDev, nNewPosY, bSnapPixel );
1388 rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1389 nOldPosY = nNewPosY;
1390 nOldSnapY = nNewSnapY;
1393 // column widths
1395 // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1396 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1397 long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth);
1398 long nOldSnapX = lclGetSnappedX( *mpDev, nOldPosX, bSnapPixel );
1399 // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1400 if( !bLayoutRTL )
1401 rArray.SetXOffset( nOldSnapX );
1402 for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
1404 size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL );
1405 long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign;
1406 long nNewSnapX = lclGetSnappedX( *mpDev, nNewPosX, bSnapPixel );
1407 rArray.SetColWidth( nCol, std::abs( nNewSnapX - nOldSnapX ) );
1408 nOldPosX = nNewPosX;
1409 nOldSnapX = nNewSnapX;
1411 if( bLayoutRTL )
1412 rArray.SetXOffset( nOldSnapX );
1414 // *** draw the array ***
1416 size_t nFirstCol = 1;
1417 size_t nFirstRow = 1;
1418 size_t nLastCol = nColCount - 2;
1419 size_t nLastRow = nRowCount - 2;
1421 if( mrTabInfo.mbPageMode )
1422 rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1424 // draw only rows with set RowInfo::bChanged flag
1425 size_t nRow1 = nFirstRow;
1426 drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D();
1427 if (!pProcessor)
1428 return;
1430 while( nRow1 <= nLastRow )
1432 while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1433 if( nRow1 <= nLastRow )
1435 size_t nRow2 = nRow1;
1436 while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1437 rArray.DrawRange( pProcessor, nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
1438 nRow1 = nRow2 + 1;
1441 if ( pProcessor )
1442 delete pProcessor;
1444 mpDev->SetDrawMode(nOldDrawMode);
1447 // -------------------------------------------------------------------------
1449 // Linie unter der Zelle
1451 static const ::editeng::SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc,
1452 SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nRotDir,
1453 bool bTopLine )
1455 if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT )
1456 return NULL;
1458 bool bFound = false;
1459 while (!bFound)
1461 if ( nRotDir == SC_ROTDIR_LEFT )
1463 // Text nach links -> Linie von rechts
1464 if ( nCol < MAXCOL )
1465 ++nCol;
1466 else
1467 return NULL; // war nix
1469 else
1471 // Text nach rechts -> Linie von links
1472 if ( nCol > 0 )
1473 --nCol;
1474 else
1475 return NULL; // war nix
1477 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
1478 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
1479 if ( !pPattern->GetRotateVal( pCondSet ) ||
1480 ((const SvxRotateModeItem&)pPattern->GetItem(
1481 ATTR_ROTATE_MODE, pCondSet)).GetValue() == SVX_ROTATE_MODE_STANDARD )
1482 bFound = true;
1485 if (bTopLine)
1486 --nRow;
1487 const ::editeng::SvxBorderLine* pThisBottom;
1488 if ( ValidRow(nRow) )
1489 pThisBottom = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ))->GetBottom();
1490 else
1491 pThisBottom = NULL;
1492 const ::editeng::SvxBorderLine* pNextTop;
1493 if ( nRow < MAXROW )
1494 pNextTop = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
1495 else
1496 pNextTop = NULL;
1498 if ( ScHasPriority( pThisBottom, pNextTop ) )
1499 return pThisBottom;
1500 else
1501 return pNextTop;
1505 static long lcl_getRotate( ScDocument* pDoc, SCTAB nTab, SCCOL nX, SCROW nY )
1507 long nRotate = 0;
1509 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1510 const SfxItemSet* pCondSet = pDoc->GetCondResult( nX, nY, nTab );
1512 nRotate = pPattern->GetRotateVal( pCondSet );
1514 return nRotate;
1517 void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
1519 //! nRotMax speichern
1520 SCCOL nRotMax = nX2;
1521 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1522 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
1523 nRotMax = pRowInfo[nRotY].nRotMaxCol;
1525 const ScPatternAttr* pPattern;
1526 const SfxItemSet* pCondSet;
1528 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1529 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1531 // color (pForceColor) is determined externally, including DrawMode changes
1533 long nInitPosX = nScrX;
1534 if ( bLayoutRTL )
1536 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1537 long nOneX = aOnePixel.Width();
1538 nInitPosX += nMirrorW - nOneX;
1540 long nLayoutSign = bLayoutRTL ? -1 : 1;
1542 Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1543 if (bMetaFile)
1545 mpDev->Push();
1546 mpDev->IntersectClipRegion( aClipRect );
1548 else
1549 mpDev->SetClipRegion( Region( aClipRect ) );
1551 svx::frame::Array& rArray = mrTabInfo.maArray;
1552 drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D( );
1554 long nPosY = nScrY;
1555 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1557 // Rotated wird auch 1 Zeile ueber/unter Changed gezeichnet, falls Teile
1558 // in die Zeile hineinragen...
1560 RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1561 RowInfo& rThisRowInfo = pRowInfo[nArrY];
1562 RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1564 size_t nRow = static_cast< size_t >( nArrY );
1566 long nRowHeight = rThisRowInfo.nHeight;
1567 if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1568 ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1569 ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1571 SCROW nY = rThisRowInfo.nRowNo;
1572 long nPosX = 0;
1573 SCCOL nX;
1574 for (nX=0; nX<=nRotMax; nX++)
1576 if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1578 sal_uInt16 nArrX = nX + 1;
1580 CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX];
1581 long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1582 if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1583 !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1585 pPattern = pInfo->pPatternAttr;
1586 pCondSet = pInfo->pConditionSet;
1587 if (!pPattern)
1589 pPattern = mpDoc->GetPattern( nX, nY, nTab );
1590 pInfo->pPatternAttr = pPattern;
1591 pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
1592 pInfo->pConditionSet = pCondSet;
1595 //! LastPattern etc.
1597 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
1598 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1599 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1601 if ( nAttrRotate )
1603 if (nX<nX1) // negative Position berechnen
1605 nPosX = nInitPosX;
1606 SCCOL nCol = nX1;
1607 while (nCol > nX)
1609 --nCol;
1610 nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
1614 // Startposition minus 1, damit auch schraege Hintergruende
1615 // zur Umrandung passen (Umrandung ist auf dem Gitter)
1617 long nTop = nPosY - 1;
1618 long nBottom = nPosY + nRowHeight - 1;
1619 long nTopLeft = nPosX - nLayoutSign;
1620 long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign;
1621 long nBotLeft = nTopLeft;
1622 long nBotRight = nTopRight;
1624 // inclusion of the sign here hasn't been decided yet
1625 // (if not, the extension of the non-rotated background must also be changed)
1626 double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000; // 1/100th degrees
1627 double nCos = cos( nRealOrient );
1628 double nSin = sin( nRealOrient );
1629 //! begrenzen !!!
1630 long nSkew = (long) ( nRowHeight * nCos / nSin );
1632 switch (eRotMode)
1634 case SVX_ROTATE_MODE_BOTTOM:
1635 nTopLeft += nSkew;
1636 nTopRight += nSkew;
1637 break;
1638 case SVX_ROTATE_MODE_CENTER:
1639 nSkew /= 2;
1640 nTopLeft += nSkew;
1641 nTopRight += nSkew;
1642 nBotLeft -= nSkew;
1643 nBotRight -= nSkew;
1644 break;
1645 case SVX_ROTATE_MODE_TOP:
1646 nBotLeft -= nSkew;
1647 nBotRight -= nSkew;
1648 break;
1649 default:
1651 // added to avoid warnings
1655 Point aPoints[4];
1656 aPoints[0] = Point( nTopLeft, nTop );
1657 aPoints[1] = Point( nTopRight, nTop );
1658 aPoints[2] = Point( nBotRight, nBottom );
1659 aPoints[3] = Point( nBotLeft, nBottom );
1661 const SvxBrushItem* pBackground = pInfo->pBackground;
1662 if (!pBackground)
1663 pBackground = (const SvxBrushItem*) &pPattern->GetItem(
1664 ATTR_BACKGROUND, pCondSet );
1665 if (bCellContrast)
1667 // high contrast for cell borders and backgrounds -> empty background
1668 pBackground = ScGlobal::GetEmptyBrushItem();
1670 if(!pInfo->pColorScale)
1672 const Color& rColor = pBackground->GetColor();
1673 if ( rColor.GetTransparency() != 255 )
1675 // draw background only for the changed row itself
1676 // (background doesn't extend into other cells).
1677 // For the borders (rotated and normal), clipping should be
1678 // set if the row isn't changed, but at least the borders
1679 // don't cover the cell contents.
1680 if ( rThisRowInfo.bChanged )
1682 Polygon aPoly( 4, aPoints );
1684 // ohne Pen wird bei DrawPolygon rechts und unten
1685 // ein Pixel weggelassen...
1686 if ( rColor.GetTransparency() == 0 )
1687 mpDev->SetLineColor(rColor);
1688 else
1689 mpDev->SetLineColor();
1690 mpDev->SetFillColor(rColor);
1691 mpDev->DrawPolygon( aPoly );
1695 else
1697 Polygon aPoly( 4, aPoints );
1698 const Color* pColor = pInfo->pColorScale;
1700 // ohne Pen wird bei DrawPolygon rechts und unten
1701 // ein Pixel weggelassen...
1702 if ( pColor->GetTransparency() == 0 )
1703 mpDev->SetLineColor(*pColor);
1704 else
1705 mpDev->SetLineColor();
1706 mpDev->SetFillColor(*pColor);
1707 mpDev->DrawPolygon( aPoly );
1711 svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
1713 if ( nX < nX1 || nX > nX2 ) // Attribute in FillInfo nicht gesetzt
1715 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
1716 const ::editeng::SvxBorderLine* pLeftLine;
1717 const ::editeng::SvxBorderLine* pTopLine;
1718 const ::editeng::SvxBorderLine* pRightLine;
1719 const ::editeng::SvxBorderLine* pBottomLine;
1720 mpDoc->GetBorderLines( nX, nY, nTab,
1721 &pLeftLine, &pTopLine, &pRightLine, &pBottomLine );
1722 aTopLine.Set( pTopLine, mnPPTY );
1723 aBottomLine.Set( pBottomLine, mnPPTY );
1724 aLeftLine.Set( pLeftLine, mnPPTX );
1725 aRightLine.Set( pRightLine, mnPPTX );
1727 else
1729 size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1730 aTopLine = rArray.GetCellStyleTop( nCol, nRow );
1731 aBottomLine = rArray.GetCellStyleBottom( nCol, nRow );
1732 aLeftLine = rArray.GetCellStyleLeft( nCol, nRow );
1733 aRightLine = rArray.GetCellStyleRight( nCol, nRow );
1734 // in RTL mode the array is already mirrored -> swap back left/right borders
1735 if( bLayoutRTL )
1736 std::swap( aLeftLine, aRightLine );
1739 const svx::frame::Style noStyle;
1740 // Horizontal lines
1741 long nUpperRotate = lcl_getRotate( mpDoc, nTab, nX, nY - 1 );
1742 pProcessor->process( svx::frame::CreateBorderPrimitives(
1743 aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine,
1744 svx::frame::Style(),
1745 svx::frame::Style(),
1746 aLeftLine,
1747 svx::frame::Style(),
1748 svx::frame::Style(),
1749 aRightLine,
1750 pForceColor, nUpperRotate, nAttrRotate ) );
1752 long nLowerRotate = lcl_getRotate( mpDoc, nTab, nX, nY + 1 );
1753 pProcessor->process( svx::frame::CreateBorderPrimitives(
1754 aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine,
1755 aLeftLine,
1756 svx::frame::Style(),
1757 svx::frame::Style(),
1758 aRightLine,
1759 svx::frame::Style(),
1760 svx::frame::Style(),
1761 pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate ) );
1763 // Vertical slanted lines
1764 long nLeftRotate = lcl_getRotate( mpDoc, nTab, nX - 1, nY );
1765 pProcessor->process( svx::frame::CreateBorderPrimitives(
1766 aPoints[0], aPoints[3], aLeftLine,
1767 aTopLine,
1768 svx::frame::Style(),
1769 svx::frame::Style(),
1770 aBottomLine,
1771 svx::frame::Style(),
1772 svx::frame::Style(),
1773 pForceColor, nAttrRotate, nLeftRotate ) );
1775 long nRightRotate = lcl_getRotate( mpDoc, nTab, nX + 1, nY );
1776 pProcessor->process( svx::frame::CreateBorderPrimitives(
1777 aPoints[1], aPoints[2], aRightLine,
1778 svx::frame::Style(),
1779 svx::frame::Style(),
1780 aTopLine,
1781 svx::frame::Style(),
1782 svx::frame::Style(),
1783 aBottomLine,
1784 pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate ) );
1787 nPosX += nColWidth * nLayoutSign;
1790 // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1792 nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1793 for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1
1795 sal_uInt16 nArrX = nX + 1;
1796 CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1797 if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD &&
1798 !rInfo.bHOverlapped && !rInfo.bVOverlapped )
1800 pPattern = rInfo.pPatternAttr;
1801 pCondSet = rInfo.pConditionSet;
1803 size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1805 // horizontal: angrenzende Linie verlaengern
1806 // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1807 sal_uInt16 nDir = rInfo.nRotateDir;
1808 if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() )
1810 svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, true ), mnPPTY );
1811 rArray.SetCellStyleTop( nCol, nRow, aStyle );
1812 if( nRow > 0 )
1813 rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
1815 if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() )
1817 svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, false ), mnPPTY );
1818 rArray.SetCellStyleBottom( nCol, nRow, aStyle );
1819 if( nRow + 1 < rArray.GetRowCount() )
1820 rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
1823 // always remove vertical borders
1824 if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
1826 rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
1827 if( nCol > 0 )
1828 rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
1830 if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
1832 rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
1833 if( nCol + 1 < rArray.GetColCount() )
1834 rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
1837 // remove diagonal borders
1838 rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
1839 rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
1843 nPosY += nRowHeight;
1846 if ( pProcessor ) delete pProcessor;
1848 if (bMetaFile)
1849 mpDev->Pop();
1850 else
1851 mpDev->SetClipRegion();
1854 drawinglayer::processor2d::BaseProcessor2D* ScOutputData::CreateProcessor2D( )
1856 mpDoc->InitDrawLayer(mpDoc->GetDocumentShell());
1857 ScDrawLayer* pDrawLayer = mpDoc->GetDrawLayer();
1858 if (!pDrawLayer)
1859 return NULL;
1861 basegfx::B2DRange aViewRange;
1862 SdrPage *pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
1863 const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
1864 basegfx::B2DHomMatrix( ),
1865 mpDev->GetViewTransformation(),
1866 aViewRange,
1867 GetXDrawPageForSdrPage( pDrawPage ),
1868 0.0,
1869 uno::Sequence< beans::PropertyValue >() );
1871 return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1872 *mpDev, aNewViewInfos );
1875 // Drucker
1877 Region ScOutputData::GetChangedAreaRegion()
1879 Region aRegion;
1880 Rectangle aDrawingRect;
1881 bool bHad(false);
1882 long nPosY = nScrY;
1883 SCSIZE nArrY;
1885 aDrawingRect.Left() = nScrX;
1886 aDrawingRect.Right() = nScrX+nScrW-1;
1888 for(nArrY=1; nArrY+1<nArrCount; nArrY++)
1890 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1892 if(pThisRowInfo->bChanged)
1894 if(!bHad)
1896 aDrawingRect.Top() = nPosY;
1897 bHad = true;
1900 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1902 else if(bHad)
1904 aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1905 bHad = false;
1908 nPosY += pRowInfo[nArrY].nHeight;
1911 if(bHad)
1913 aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1916 return aRegion;
1919 sal_Bool ScOutputData::SetChangedClip()
1921 PolyPolygon aPoly;
1923 Rectangle aDrawingRect;
1924 aDrawingRect.Left() = nScrX;
1925 aDrawingRect.Right() = nScrX+nScrW-1;
1927 bool bHad = false;
1928 long nPosY = nScrY;
1929 SCSIZE nArrY;
1930 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1932 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1934 if ( pThisRowInfo->bChanged )
1936 if (!bHad)
1938 aDrawingRect.Top() = nPosY;
1939 bHad = true;
1941 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1943 else if (bHad)
1945 aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1946 bHad = false;
1948 nPosY += pRowInfo[nArrY].nHeight;
1951 if (bHad)
1952 aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1954 sal_Bool bRet = (aPoly.Count() != 0);
1955 if (bRet)
1956 mpDev->SetClipRegion(Region(aPoly));
1957 return bRet;
1960 void ScOutputData::FindChanged()
1962 SCCOL nX;
1963 SCSIZE nArrY;
1965 bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
1966 mpDoc->EnableIdle(false);
1967 for (nArrY=0; nArrY<nArrCount; nArrY++)
1968 pRowInfo[nArrY].bChanged = false;
1970 bool bProgress = false;
1971 for (nArrY=0; nArrY<nArrCount; nArrY++)
1973 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1974 for (nX=nX1; nX<=nX2; nX++)
1976 const ScRefCellValue& rCell = pThisRowInfo->pCellInfo[nX+1].maCell;
1978 if (rCell.meType != CELLTYPE_FORMULA)
1979 continue;
1981 ScFormulaCell* pFCell = rCell.mpFormula;
1982 if ( !bProgress && pFCell->GetDirty() )
1984 ScProgress::CreateInterpretProgress(mpDoc, true);
1985 bProgress = true;
1987 if (pFCell->IsRunning())
1988 // still being interpreted. Skip it.
1989 continue;
1991 (void)pFCell->GetValue();
1992 if (!pFCell->IsChanged())
1993 // the result hasn't changed. Skip it.
1994 continue;
1996 pThisRowInfo->bChanged = true;
1997 if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1999 SCSIZE nOverY = nArrY + 1;
2000 while ( nOverY<nArrCount &&
2001 pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
2003 pRowInfo[nOverY].bChanged = true;
2004 ++nOverY;
2009 if ( bProgress )
2010 ScProgress::DeleteInterpretProgress();
2011 mpDoc->EnableIdle(bWasIdleEnabled);
2014 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
2015 SCCOL nRefEndX, SCROW nRefEndY,
2016 const Color& rColor, sal_Bool bHandle )
2018 PutInOrder( nRefStartX, nRefEndX );
2019 PutInOrder( nRefStartY, nRefEndY );
2021 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2022 mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2024 if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
2025 nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
2027 long nMinX = nScrX;
2028 long nMinY = nScrY;
2029 long nMaxX = nScrX + nScrW - 1;
2030 long nMaxY = nScrY + nScrH - 1;
2031 if ( bLayoutRTL )
2033 long nTemp = nMinX;
2034 nMinX = nMaxX;
2035 nMaxX = nTemp;
2037 long nLayoutSign = bLayoutRTL ? -1 : 1;
2039 sal_Bool bTop = false;
2040 sal_Bool bBottom = false;
2041 sal_Bool bLeft = false;
2042 sal_Bool bRight = false;
2044 long nPosY = nScrY;
2045 bool bNoStartY = ( nY1 < nRefStartY );
2046 bool bNoEndY = false;
2047 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2049 SCROW nY = pRowInfo[nArrY].nRowNo;
2051 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2053 nMinY = nPosY;
2054 bTop = sal_True;
2056 if ( nY==nRefEndY )
2058 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
2059 bBottom = sal_True;
2061 if ( nY>nRefEndY && bNoEndY )
2063 nMaxY = nPosY-2;
2064 bBottom = sal_True;
2066 bNoStartY = ( nY < nRefStartY );
2067 bNoEndY = ( nY < nRefEndY );
2068 nPosY += pRowInfo[nArrY].nHeight;
2071 long nPosX = nScrX;
2072 if ( bLayoutRTL )
2073 nPosX += nMirrorW - 1; // always in pixels
2075 for (SCCOL nX=nX1; nX<=nX2; nX++)
2077 if ( nX==nRefStartX )
2079 nMinX = nPosX;
2080 bLeft = sal_True;
2082 if ( nX==nRefEndX )
2084 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
2085 bRight = sal_True;
2087 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2090 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2091 nMaxY >= nMinY )
2093 mpDev->SetLineColor( rColor );
2094 if (bTop && bBottom && bLeft && bRight)
2096 mpDev->SetFillColor();
2097 mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2099 else
2101 if (bTop)
2102 mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMaxX, nMinY ) );
2103 if (bBottom)
2104 mpDev->DrawLine( Point( nMinX, nMaxY ), Point( nMaxX, nMaxY ) );
2105 if (bLeft)
2106 mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMinX, nMaxY ) );
2107 if (bRight)
2108 mpDev->DrawLine( Point( nMaxX, nMinY ), Point( nMaxX, nMaxY ) );
2110 if ( bHandle && bRight && bBottom )
2112 mpDev->SetLineColor( rColor );
2113 mpDev->SetFillColor( rColor );
2115 const sal_Int32 aRadius = 4;
2117 sal_Int32 aRectMaxX1 = nMaxX - nLayoutSign * aRadius;
2118 sal_Int32 aRectMaxX2 = nMaxX + nLayoutSign;
2119 sal_Int32 aRectMinX1 = nMinX - nLayoutSign;
2120 sal_Int32 aRectMinX2 = nMinX + nLayoutSign * aRadius;
2122 sal_Int32 aRectMaxY1 = nMaxY - aRadius;
2123 sal_Int32 aRectMaxY2 = nMaxY + 1;
2124 sal_Int32 aRectMinY1 = nMinY - 1;
2125 sal_Int32 aRectMinY2 = nMinY + aRadius;
2127 // Draw corner rectangles
2128 Rectangle aLowerRight( aRectMaxX1, aRectMaxY1, aRectMaxX2, aRectMaxY2 );
2129 Rectangle aUpperLeft ( aRectMinX1, aRectMinY1, aRectMinX2, aRectMinY2 );
2130 Rectangle aLowerLeft ( aRectMinX1, aRectMaxY1, aRectMinX2, aRectMaxY2 );
2131 Rectangle aUpperRight( aRectMaxX1, aRectMinY1, aRectMaxX2, aRectMinY2 );
2133 mpDev->DrawTransparent( PolyPolygon( Polygon( aLowerRight ) ), lclCornerRectTransparency );
2134 mpDev->DrawTransparent( PolyPolygon( Polygon( aUpperLeft ) ), lclCornerRectTransparency );
2135 mpDev->DrawTransparent( PolyPolygon( Polygon( aLowerLeft ) ), lclCornerRectTransparency );
2136 mpDev->DrawTransparent( PolyPolygon( Polygon( aUpperRight ) ), lclCornerRectTransparency );
2142 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
2143 SCCOL nRefEndX, SCROW nRefEndY,
2144 const Color& rColor, sal_uInt16 nType )
2146 PutInOrder( nRefStartX, nRefEndX );
2147 PutInOrder( nRefStartY, nRefEndY );
2149 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2150 mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2152 if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
2153 nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top
2155 long nMinX = nScrX;
2156 long nMinY = nScrY;
2157 long nMaxX = nScrX+nScrW-1;
2158 long nMaxY = nScrY+nScrH-1;
2159 if ( bLayoutRTL )
2161 long nTemp = nMinX;
2162 nMinX = nMaxX;
2163 nMaxX = nTemp;
2165 long nLayoutSign = bLayoutRTL ? -1 : 1;
2167 sal_Bool bTop = false;
2168 sal_Bool bBottom = false;
2169 sal_Bool bLeft = false;
2170 sal_Bool bRight = false;
2172 long nPosY = nScrY;
2173 bool bNoStartY = ( nY1 < nRefStartY );
2174 bool bNoEndY = false;
2175 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2177 SCROW nY = pRowInfo[nArrY].nRowNo;
2179 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2181 nMinY = nPosY - 1;
2182 bTop = sal_True;
2184 if ( nY==nRefEndY )
2186 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2187 bBottom = sal_True;
2189 if ( nY>nRefEndY && bNoEndY )
2191 nMaxY = nPosY - 1;
2192 bBottom = sal_True;
2194 bNoStartY = ( nY < nRefStartY );
2195 bNoEndY = ( nY < nRefEndY );
2196 nPosY += pRowInfo[nArrY].nHeight;
2199 long nPosX = nScrX;
2200 if ( bLayoutRTL )
2201 nPosX += nMirrorW - 1; // always in pixels
2203 for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2205 if ( nX==nRefStartX )
2207 nMinX = nPosX - nLayoutSign;
2208 bLeft = sal_True;
2210 if ( nX==nRefEndX )
2212 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2213 bRight = sal_True;
2215 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2218 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2219 nMaxY >= nMinY )
2221 if ( nType == SC_CAT_DELETE_ROWS )
2222 bLeft = bRight = bBottom = false; //! dicke Linie ???
2223 else if ( nType == SC_CAT_DELETE_COLS )
2224 bTop = bBottom = bRight = false; //! dicke Linie ???
2226 mpDev->SetLineColor( rColor );
2227 if (bTop && bBottom && bLeft && bRight)
2229 mpDev->SetFillColor();
2230 mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2232 else
2234 if (bTop)
2236 mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2237 if ( nType == SC_CAT_DELETE_ROWS )
2238 mpDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2240 if (bBottom)
2241 mpDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2242 if (bLeft)
2244 mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2245 if ( nType == SC_CAT_DELETE_COLS )
2246 mpDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2248 if (bRight)
2249 mpDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2251 if ( bLeft && bTop )
2253 mpDev->SetLineColor();
2254 mpDev->SetFillColor( rColor );
2255 mpDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2261 void ScOutputData::DrawChangeTrack()
2263 ScChangeTrack* pTrack = mpDoc->GetChangeTrack();
2264 ScChangeViewSettings* pSettings = mpDoc->GetChangeViewSettings();
2265 if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2266 return; // nix da oder abgeschaltet
2268 ScActionColorChanger aColorChanger(*pTrack);
2270 // Clipping passiert von aussen
2271 //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2273 SCCOL nEndX = nX2;
2274 SCROW nEndY = nY2;
2275 if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung
2276 if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt
2277 ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2278 const ScChangeAction* pAction = pTrack->GetFirst();
2279 while (pAction)
2281 ScChangeActionType eActionType;
2282 if ( pAction->IsVisible() )
2284 eActionType = pAction->GetType();
2285 const ScBigRange& rBig = pAction->GetBigRange();
2286 if ( rBig.aStart.Tab() == nTab )
2288 ScRange aRange = rBig.MakeRange();
2290 if ( eActionType == SC_CAT_DELETE_ROWS )
2291 aRange.aEnd.SetRow( aRange.aStart.Row() );
2292 else if ( eActionType == SC_CAT_DELETE_COLS )
2293 aRange.aEnd.SetCol( aRange.aStart.Col() );
2295 if ( aRange.Intersects( aViewRange ) &&
2296 ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2298 aColorChanger.Update( *pAction );
2299 Color aColor( aColorChanger.GetColor() );
2300 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2301 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2305 if ( eActionType == SC_CAT_MOVE &&
2306 ((const ScChangeActionMove*)pAction)->
2307 GetFromRange().aStart.Tab() == nTab )
2309 ScRange aRange = ((const ScChangeActionMove*)pAction)->
2310 GetFromRange().MakeRange();
2311 if ( aRange.Intersects( aViewRange ) &&
2312 ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2314 aColorChanger.Update( *pAction );
2315 Color aColor( aColorChanger.GetColor() );
2316 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2317 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2322 pAction = pAction->GetNext();
2326 //TODO: moggi Need to check if this can't be written simpler
2327 void ScOutputData::DrawNoteMarks()
2330 bool bFirst = true;
2332 long nInitPosX = nScrX;
2333 if ( bLayoutRTL )
2334 nInitPosX += nMirrorW - 1; // always in pixels
2335 long nLayoutSign = bLayoutRTL ? -1 : 1;
2337 long nPosY = nScrY;
2338 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2340 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2341 if ( pThisRowInfo->bChanged )
2343 long nPosX = nInitPosX;
2344 for (SCCOL nX=nX1; nX<=nX2; nX++)
2346 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2347 bool bIsMerged = false;
2349 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2351 // find start of merged cell
2352 bIsMerged = true;
2353 SCROW nY = pRowInfo[nArrY].nRowNo;
2354 SCCOL nMergeX = nX;
2355 SCROW nMergeY = nY;
2356 mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2357 // use origin's pCell for NotePtr test below
2360 if ( mpDoc->GetNote(nX, pRowInfo[nArrY].nRowNo, nTab) && ( bIsMerged ||
2361 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2363 if (bFirst)
2365 mpDev->SetLineColor();
2367 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2368 if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2369 mpDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2370 else
2371 mpDev->SetFillColor(COL_LIGHTRED);
2373 bFirst = false;
2376 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2377 if ( bIsMerged || pInfo->bMerged )
2379 // if merged, add widths of all cells
2380 SCCOL nNextX = nX + 1;
2381 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2383 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2384 ++nNextX;
2387 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2388 mpDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) );
2391 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2394 nPosY += pThisRowInfo->nHeight;
2398 void ScOutputData::AddPDFNotes()
2400 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
2401 if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2402 return;
2404 long nInitPosX = nScrX;
2405 if ( bLayoutRTL )
2407 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
2408 long nOneX = aOnePixel.Width();
2409 nInitPosX += nMirrorW - nOneX;
2411 long nLayoutSign = bLayoutRTL ? -1 : 1;
2413 long nPosY = nScrY;
2414 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2416 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2417 if ( pThisRowInfo->bChanged )
2419 long nPosX = nInitPosX;
2420 for (SCCOL nX=nX1; nX<=nX2; nX++)
2422 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2423 bool bIsMerged = false;
2424 SCROW nY = pRowInfo[nArrY].nRowNo;
2425 SCCOL nMergeX = nX;
2426 SCROW nMergeY = nY;
2428 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2430 // find start of merged cell
2431 bIsMerged = true;
2432 mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2433 // use origin's pCell for NotePtr test below
2436 if ( mpDoc->GetNote(nMergeX, nMergeY, nTab) && ( bIsMerged ||
2437 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2439 long nNoteWidth = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2440 long nNoteHeight = (long)( SC_CLIPMARK_SIZE * mnPPTY );
2442 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign;
2443 if ( bIsMerged || pInfo->bMerged )
2445 // if merged, add widths of all cells
2446 SCCOL nNextX = nX + 1;
2447 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2449 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2450 ++nNextX;
2453 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2455 Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2456 const ScPostIt* pNote = mpDoc->GetNote(nMergeX, nMergeY, nTab);
2458 // Note title is the cell address (as on printed note pages)
2459 ScAddress aAddress( nMergeX, nMergeY, nTab );
2460 OUString aTitle(aAddress.Format(SCA_VALID, mpDoc, mpDoc->GetAddressConvention()));
2462 // Content has to be a simple string without line breaks
2463 OUString aContent = pNote->GetText();
2464 aContent = aContent.replaceAll("\n", " ");
2466 vcl::PDFNote aNote;
2467 aNote.Title = aTitle;
2468 aNote.Contents = aContent;
2469 pPDFData->CreateNote( aNoteRect, aNote );
2473 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2476 nPosY += pThisRowInfo->nHeight;
2480 void ScOutputData::DrawClipMarks()
2482 if (!bAnyClipped)
2483 return;
2485 Color aArrowFillCol( COL_LIGHTRED );
2487 sal_uLong nOldDrawMode = mpDev->GetDrawMode();
2488 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2489 if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2491 // use DrawMode to change the arrow's outline color
2492 mpDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2493 // use text color also for the fill color
2494 aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2497 long nInitPosX = nScrX;
2498 if ( bLayoutRTL )
2499 nInitPosX += nMirrorW - 1; // always in pixels
2500 long nLayoutSign = bLayoutRTL ? -1 : 1;
2502 Rectangle aCellRect;
2503 long nPosY = nScrY;
2504 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2506 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2507 if ( pThisRowInfo->bChanged )
2509 SCROW nY = pThisRowInfo->nRowNo;
2510 long nPosX = nInitPosX;
2511 for (SCCOL nX=nX1; nX<=nX2; nX++)
2513 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2514 if (pInfo->nClipMark)
2516 if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2518 // merge origin may be outside of visible area - use document functions
2520 SCCOL nOverX = nX;
2521 SCROW nOverY = nY;
2522 long nStartPosX = nPosX;
2523 long nStartPosY = nPosY;
2525 while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2526 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2528 --nOverX;
2529 nStartPosX -= nLayoutSign * (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2532 while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2533 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2535 --nOverY;
2536 nStartPosY -= nLayoutSign * (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2539 long nOutWidth = (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2540 long nOutHeight = (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2542 const ScMergeAttr* pMerge = (const ScMergeAttr*)
2543 mpDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2544 SCCOL nCountX = pMerge->GetColMerge();
2545 for (SCCOL i=1; i<nCountX; i++)
2546 nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2547 SCROW nCountY = pMerge->GetRowMerge();
2548 nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2550 if ( bLayoutRTL )
2551 nStartPosX -= nOutWidth - 1;
2552 aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2554 else
2556 long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2557 long nOutHeight = pThisRowInfo->nHeight;
2559 if ( pInfo->bMerged && pInfo->pPatternAttr )
2561 SCCOL nOverX = nX;
2562 SCROW nOverY = nY;
2563 const ScMergeAttr* pMerge =
2564 (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2565 SCCOL nCountX = pMerge->GetColMerge();
2566 for (SCCOL i=1; i<nCountX; i++)
2567 nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2568 SCROW nCountY = pMerge->GetRowMerge();
2569 nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2572 long nStartPosX = nPosX;
2573 if ( bLayoutRTL )
2574 nStartPosX -= nOutWidth - 1;
2575 // #i80447# create aCellRect from two points in case nOutWidth is 0
2576 aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2577 Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2580 aCellRect.Bottom() -= 1; // don't paint over the cell grid
2581 if ( bLayoutRTL )
2582 aCellRect.Left() += 1;
2583 else
2584 aCellRect.Right() -= 1;
2586 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2587 Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2589 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2591 // visually left
2592 Rectangle aMarkRect = aCellRect;
2593 aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2594 SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, true );
2596 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2598 // visually right
2599 Rectangle aMarkRect = aCellRect;
2600 aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2601 SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, false );
2604 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2607 nPosY += pThisRowInfo->nHeight;
2610 mpDev->SetDrawMode(nOldDrawMode);
2615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */