Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / view / output.cxx
blob5fd547f15a197bda66e1dc7c8fdb298f13188ccd
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 <svx/rotmodit.hxx>
28 #include <editeng/shaditem.hxx>
29 #include <editeng/svxfont.hxx>
30 #include <svx/svdoole2.hxx>
31 #include <tools/poly.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/pdfextoutdevdata.hxx>
34 #include <svtools/accessibilityoptions.hxx>
35 #include <svx/framelinkarray.hxx>
36 #include <drawinglayer/geometry/viewinformation2d.hxx>
37 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
38 #include <basegfx/matrix/b2dhommatrix.hxx>
39 #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
40 #include <vcl/lineinfo.hxx>
41 #include <vcl/gradient.hxx>
42 #include <vcl/settings.hxx>
43 #include <svx/unoapi.hxx>
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>
72 #include <boost/scoped_ptr.hpp>
74 using namespace com::sun::star;
76 // Static Data
78 // color for ChangeTracking "by author" as in the writer (swmodul1.cxx)
80 #define SC_AUTHORCOLORCOUNT 9
82 static const ColorData nAuthorColor[ SC_AUTHORCOLORCOUNT ] = {
83 COL_LIGHTRED, COL_LIGHTBLUE, COL_LIGHTMAGENTA,
84 COL_GREEN, COL_RED, COL_BLUE,
85 COL_BROWN, COL_MAGENTA, COL_CYAN };
88 // Helper class for color assignment to avoid repeated lookups for the same user
90 ScActionColorChanger::ScActionColorChanger( const ScChangeTrack& rTrack ) :
91 rOpt( SC_MOD()->GetAppOptions() ),
92 rUsers( rTrack.GetUserCollection() ),
93 nLastUserIndex( 0 ),
94 nColor( COL_BLACK )
98 void ScActionColorChanger::Update( const ScChangeAction& rAction )
100 ColorData nSetColor;
101 switch (rAction.GetType())
103 case SC_CAT_INSERT_COLS:
104 case SC_CAT_INSERT_ROWS:
105 case SC_CAT_INSERT_TABS:
106 nSetColor = rOpt.GetTrackInsertColor();
107 break;
108 case SC_CAT_DELETE_COLS:
109 case SC_CAT_DELETE_ROWS:
110 case SC_CAT_DELETE_TABS:
111 nSetColor = rOpt.GetTrackDeleteColor();
112 break;
113 case SC_CAT_MOVE:
114 nSetColor = rOpt.GetTrackMoveColor();
115 break;
116 default:
117 nSetColor = rOpt.GetTrackContentColor();
118 break;
120 if ( nSetColor != COL_TRANSPARENT ) // color assigned
121 nColor = nSetColor;
122 else // by author
124 if (!aLastUserName.equals(rAction.GetUser()))
126 aLastUserName = rAction.GetUser();
127 std::set<OUString>::const_iterator it = rUsers.find(aLastUserName);
128 if (it == rUsers.end())
130 // empty string is possible if a name wasn't found while saving a 5.0 file
131 SAL_INFO_IF( aLastUserName.isEmpty(), "sc.ui", "Author not found" );
132 nLastUserIndex = 0;
134 else
136 size_t nPos = std::distance(rUsers.begin(), it);
137 nLastUserIndex = nPos % SC_AUTHORCOLORCOUNT;
140 nColor = nAuthorColor[nLastUserIndex];
145 ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
146 ScTableInfo& rTabInfo, ScDocument* pNewDoc,
147 SCTAB nNewTab, long nNewScrX, long nNewScrY,
148 SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2,
149 double nPixelPerTwipsX, double nPixelPerTwipsY,
150 const Fraction* pZoomX, const Fraction* pZoomY ) :
151 mpDev( pNewDev ),
152 mpRefDevice( pNewDev ), // default is output device
153 pFmtDevice( pNewDev ), // default is output device
154 mrTabInfo( rTabInfo ),
155 pRowInfo( rTabInfo.mpRowInfo ),
156 nArrCount( rTabInfo.mnArrCount ),
157 mpDoc( pNewDoc ),
158 nTab( nNewTab ),
159 nScrX( nNewScrX ),
160 nScrY( nNewScrY ),
161 nX1( nNewX1 ),
162 nY1( nNewY1 ),
163 nX2( nNewX2 ),
164 nY2( nNewY2 ),
165 eType( eNewType ),
166 mnPPTX( nPixelPerTwipsX ),
167 mnPPTY( nPixelPerTwipsY ),
168 pEditObj( NULL ),
169 pViewShell( NULL ),
170 pDrawView( NULL ), // #114135#
171 bEditMode( false ),
172 nEditCol( 0 ),
173 nEditRow( 0 ),
174 bMetaFile( false ),
175 bSingleGrid( false ),
176 bPagebreakMode( false ),
177 bSolidBackground( false ),
178 mbUseStyleColor( false ),
179 mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
180 mbSyntaxMode( false ),
181 pValueColor( NULL ),
182 pTextColor( NULL ),
183 pFormulaColor( NULL ),
184 aGridColor( COL_BLACK ),
185 mbShowNullValues( true ),
186 mbShowFormulas( false ),
187 bShowSpellErrors( false ),
188 bMarkClipped( false ), // sal_False for printer/metafile etc.
189 bSnapPixel( false ),
190 bAnyRotated( false ),
191 bAnyClipped( false ),
192 mpTargetPaintWindow(NULL), // #i74769# use SdrPaintWindow direct
193 mpSpellCheckCxt(NULL)
195 if (pZoomX)
196 aZoomX = *pZoomX;
197 else
198 aZoomX = Fraction(1,1);
199 if (pZoomY)
200 aZoomY = *pZoomY;
201 else
202 aZoomY = Fraction(1,1);
204 nVisX1 = nX1;
205 nVisY1 = nY1;
206 nVisX2 = nX2;
207 nVisY2 = nY2;
208 mpDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
210 nScrW = 0;
211 for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
212 nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
214 nMirrorW = nScrW;
216 nScrH = 0;
217 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
218 nScrH += pRowInfo[nArrY].nHeight;
220 bTabProtected = mpDoc->IsTabProtected( nTab );
221 nTabTextDirection = mpDoc->GetEditTextDirection( nTab );
222 bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
225 ScOutputData::~ScOutputData()
227 delete pValueColor;
228 delete pTextColor;
229 delete pFormulaColor;
232 void ScOutputData::SetSpellCheckContext( const sc::SpellCheckContext* pCxt )
234 mpSpellCheckCxt = pCxt;
237 void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
239 // use pContentDev instead of pDev where used
241 if ( mpRefDevice == mpDev )
242 mpRefDevice = pContentDev;
243 if ( pFmtDevice == mpDev )
244 pFmtDevice = pContentDev;
245 mpDev = pContentDev;
248 void ScOutputData::SetMirrorWidth( long nNew )
250 nMirrorW = nNew;
253 void ScOutputData::SetGridColor( const Color& rColor )
255 aGridColor = rColor;
258 void ScOutputData::SetMarkClipped( bool bSet )
260 bMarkClipped = bSet;
263 void ScOutputData::SetShowNullValues( bool bSet )
265 mbShowNullValues = bSet;
268 void ScOutputData::SetShowFormulas( bool bSet )
270 mbShowFormulas = bSet;
273 void ScOutputData::SetShowSpellErrors( bool bSet )
275 bShowSpellErrors = bSet;
278 void ScOutputData::SetSnapPixel( bool bSet )
280 bSnapPixel = bSet;
283 void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow )
285 nEditCol = nCol;
286 nEditRow = nRow;
287 bEditMode = true;
290 void ScOutputData::SetMetaFileMode( bool bNewMode )
292 bMetaFile = bNewMode;
295 void ScOutputData::SetSingleGrid( bool bNewMode )
297 bSingleGrid = bNewMode;
300 void ScOutputData::SetSyntaxMode( bool bNewMode )
302 mbSyntaxMode = bNewMode;
303 if (bNewMode)
304 if (!pValueColor)
306 pValueColor = new Color( COL_LIGHTBLUE );
307 pTextColor = new Color( COL_BLACK );
308 pFormulaColor = new Color( COL_GREEN );
312 void ScOutputData::DrawGrid( bool bGrid, bool bPage )
314 SCCOL nX;
315 SCROW nY;
316 long nPosX;
317 long nPosY;
318 SCSIZE nArrY;
319 ScBreakType nBreak = BREAK_NONE;
320 ScBreakType nBreakOld = BREAK_NONE;
322 bool bSingle;
323 Color aPageColor;
324 Color aManualColor;
326 if (bPagebreakMode)
327 bPage = false; // no "normal" breaks over the whole width/height
329 //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
330 //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
332 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
333 long nOneX = aOnePixel.Width();
334 long nOneY = aOnePixel.Height();
335 if (bMetaFile)
336 nOneX = nOneY = 1;
338 long nLayoutSign = bLayoutRTL ? -1 : 1;
339 long nSignedOneX = nOneX * nLayoutSign;
341 if ( eType == OUTTYPE_WINDOW )
343 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
344 aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
345 aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
347 else
349 aPageColor = aGridColor;
350 aManualColor = aGridColor;
353 mpDev->SetLineColor( aGridColor );
354 ScGridMerger aGrid( mpDev, nOneX, nOneY );
356 // vertical lines
358 nPosX = nScrX;
359 if ( bLayoutRTL )
360 nPosX += nMirrorW - nOneX;
362 for (nX=nX1; nX<=nX2; nX++)
364 SCCOL nXplus1 = nX+1;
365 SCCOL nXplus2 = nX+2;
366 sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
367 if (nWidth)
369 nPosX += nWidth * nLayoutSign;
371 if ( bPage )
373 // Seitenumbrueche auch in ausgeblendeten suchen
374 SCCOL nCol = nXplus1;
375 while (nCol <= MAXCOL)
377 nBreak = mpDoc->HasColBreak(nCol, nTab);
378 bool bHidden = mpDoc->ColHidden(nCol, nTab);
380 if ( nBreak || !bHidden )
381 break;
382 ++nCol;
385 if (nBreak != nBreakOld)
387 aGrid.Flush();
388 mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
389 nBreak ? aPageColor : aGridColor );
390 nBreakOld = nBreak;
394 bool bDraw = bGrid || nBreakOld; // simple grid only if set that way
396 sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
397 bSingle = bSingleGrid; //! get into Fillinfo !!!!!
398 if ( nX<MAXCOL && !bSingle )
400 bSingle = ( nWidthXplus2 == 0 );
401 for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
403 if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
404 bSingle = true;
405 if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
406 bSingle = true;
410 if (bDraw)
412 if ( nX<MAXCOL && bSingle )
414 SCCOL nVisX = nXplus1;
415 while ( nVisX < MAXCOL && !mpDoc->GetColWidth(nVisX,nTab) )
416 ++nVisX;
418 nPosY = nScrY;
419 long nNextY;
420 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
422 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
423 nNextY = nPosY + pThisRowInfo->nHeight;
425 bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
426 if (!bHOver)
428 if (nWidthXplus2)
429 bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped;
430 else
432 if (nVisX <= nX2)
433 bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped;
434 else
435 bHOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
436 nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
437 ->IsHorOverlapped();
438 if (bHOver)
439 bHOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
440 nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
441 ->IsHorOverlapped();
445 if (pThisRowInfo->bChanged && !bHOver)
447 aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
449 nPosY = nNextY;
452 else
454 aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
460 // horizontal lines
462 bool bHiddenRow = true;
463 SCROW nHiddenEndRow = -1;
464 nPosY = nScrY;
465 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
467 SCSIZE nArrYplus1 = nArrY+1;
468 nY = pRowInfo[nArrY].nRowNo;
469 SCROW nYplus1 = nY+1;
470 nPosY += pRowInfo[nArrY].nHeight;
472 if (pRowInfo[nArrY].bChanged)
474 if ( bPage )
476 for (SCROW i = nYplus1; i <= MAXROW; ++i)
478 if (i > nHiddenEndRow)
479 bHiddenRow = mpDoc->RowHidden(i, nTab, NULL, &nHiddenEndRow);
480 /* TODO: optimize the row break thing for large hidden
481 * segments where HasRowBreak() has to be called
482 * nevertheless for each row, as a row break is drawn also
483 * for hidden rows, above them. This needed to be done only
484 * once per hidden segment, maybe giving manual breaks
485 * priority. Something like GetNextRowBreak() and
486 * GetNextManualRowBreak(). */
487 nBreak = mpDoc->HasRowBreak(i, nTab);
488 if (!bHiddenRow || nBreak)
489 break;
492 if (nBreakOld != nBreak)
494 aGrid.Flush();
495 mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
496 (nBreak) ? aPageColor : aGridColor );
497 nBreakOld = nBreak;
501 bool bDraw = bGrid || nBreakOld; // simple grid only if set so
503 bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
504 bSingle = !bNextYisNextRow; // Hidden
505 for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
507 if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
508 bSingle = true;
511 if (bDraw)
513 if ( bSingle && nY<MAXROW )
515 SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
517 nPosX = nScrX;
518 if ( bLayoutRTL )
519 nPosX += nMirrorW - nOneX;
521 long nNextX;
522 for (SCCOL i=nX1; i<=nX2; i++)
524 nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
525 if (nNextX != nPosX) // visible
527 bool bVOver;
528 if ( bNextYisNextRow )
529 bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
530 else
532 bVOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
533 i,nYplus1,nTab,ATTR_MERGE_FLAG))
534 ->IsVerOverlapped()
535 && ((ScMergeFlagAttr*)mpDoc->GetAttr(
536 i,nVisY,nTab,ATTR_MERGE_FLAG))
537 ->IsVerOverlapped();
538 //! nVisY from Array ??
540 if (!bVOver)
542 aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
545 nPosX = nNextX;
548 else
550 aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
557 void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
559 bPagebreakMode = true;
560 if (!pPageData)
561 return; // not yet initialized -> everything "not printed"
563 // mark printed range
564 // (everything in FillInfo is already initialized to sal_False)
566 sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount());
567 for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++)
569 ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
571 SCCOL nStartX = std::max( aRange.aStart.Col(), nX1 );
572 SCCOL nEndX = std::min( aRange.aEnd.Col(), nX2 );
573 SCROW nStartY = std::max( aRange.aStart.Row(), nY1 );
574 SCROW nEndY = std::min( aRange.aEnd.Row(), nY2 );
576 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
578 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
579 if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
580 pThisRowInfo->nRowNo <= nEndY )
582 for (SCCOL nX=nStartX; nX<=nEndX; nX++)
583 pThisRowInfo->pCellInfo[nX+1].bPrinted = true;
589 void ScOutputData::FindRotated()
591 //! save nRotMax
592 SCCOL nRotMax = nX2;
593 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
594 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
595 nRotMax = pRowInfo[nRotY].nRotMaxCol;
597 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
599 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
600 if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
601 ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
602 ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
604 SCROW nY = pThisRowInfo->nRowNo;
606 for (SCCOL nX=0; nX<=nRotMax; nX++)
608 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
609 const ScPatternAttr* pPattern = pInfo->pPatternAttr;
610 const SfxItemSet* pCondSet = pInfo->pConditionSet;
612 if ( !pPattern && !mpDoc->ColHidden(nX, nTab) )
614 pPattern = mpDoc->GetPattern( nX, nY, nTab );
615 pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
618 if ( pPattern ) // column isn't hidden
620 sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet );
621 if (nDir != SC_ROTDIR_NONE)
623 pInfo->nRotateDir = nDir;
624 bAnyRotated = true;
632 static sal_uInt16 lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
634 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
635 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
637 sal_uInt16 nRet = SC_ROTDIR_NONE;
639 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
640 if ( nAttrRotate )
642 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
643 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
645 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
646 nRet = SC_ROTDIR_STANDARD;
647 else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
648 nRet = SC_ROTDIR_CENTER;
649 else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
651 long nRot180 = nAttrRotate % 18000; // 1/100 degree
652 if ( nRot180 == 9000 )
653 nRet = SC_ROTDIR_CENTER;
654 else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
655 ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
656 nRet = SC_ROTDIR_LEFT;
657 else
658 nRet = SC_ROTDIR_RIGHT;
662 return nRet;
665 static const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
667 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
668 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
669 const SvxBrushItem* pBackground = (const SvxBrushItem*)
670 &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
672 sal_uInt16 nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
674 // treat CENTER like RIGHT
675 if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER )
677 // text goes to the right -> take background from the left
678 while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
679 pBackground->GetColor().GetTransparency() != 255 )
681 --nCol;
682 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
683 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
684 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
687 else if ( nDir == SC_ROTDIR_LEFT )
689 // text goes to the left -> take background from the right
690 while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
691 pBackground->GetColor().GetTransparency() != 255 )
693 ++nCol;
694 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
695 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
696 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
700 return pBackground;
704 static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
705 SCCOL nX1, SCCOL nX2, bool bShowProt, bool bPagebreakMode )
707 if ( rFirst.bChanged != rOther.bChanged ||
708 rFirst.bEmptyBack != rOther.bEmptyBack )
709 return false;
711 SCCOL nX;
712 if ( bShowProt )
714 for ( nX=nX1; nX<=nX2; nX++ )
716 const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr;
717 const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr;
718 if ( !pPat1 || !pPat2 ||
719 &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
720 return false;
723 else
725 for ( nX=nX1; nX<=nX2; nX++ )
726 if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
727 return false;
730 if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
731 for ( nX=nX1; nX<=nX2; nX++ )
732 if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
733 return false;
735 if ( bPagebreakMode )
736 for ( nX=nX1; nX<=nX2; nX++ )
737 if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
738 return false;
740 for ( nX=nX1; nX<=nX2; nX++ )
742 const Color* pCol1 = rFirst.pCellInfo[nX+1].pColorScale;
743 const Color* pCol2 = rOther.pCellInfo[nX+1].pColorScale;
744 if( (pCol1 && !pCol2) || (!pCol1 && pCol2) )
745 return false;
747 if (pCol1 && (*pCol1 != *pCol2))
748 return false;
750 const ScDataBarInfo* pInfo1 = rFirst.pCellInfo[nX+1].pDataBar;
751 const ScDataBarInfo* pInfo2 = rOther.pCellInfo[nX+1].pDataBar;
753 if( (pInfo1 && !pInfo2) || (!pInfo1 && pInfo2) )
754 return false;
756 if (pInfo1 && (*pInfo1 != *pInfo2))
757 return false;
759 // each cell with an icon set should be painted the same way
760 const ScIconSetInfo* pIconSet1 = rFirst.pCellInfo[nX+1].pIconSet;
761 const ScIconSetInfo* pIconSet2 = rOther.pCellInfo[nX+1].pIconSet;
763 if(pIconSet1 || pIconSet2)
764 return false;
767 return true;
770 void ScOutputData::DrawDocumentBackground()
772 if ( !bSolidBackground )
773 return;
775 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
776 long nOneX = aOnePixel.Width();
777 long nOneY = aOnePixel.Height();
778 Rectangle aRect(nScrX - nOneX, nScrY - nOneY, nScrX + nScrW, nScrY + nScrH);
779 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
780 mpDev->SetFillColor(aBgColor);
781 mpDev->DrawRect(aRect);
784 namespace {
786 static const double lclCornerRectTransparency = 40.0;
788 void drawDataBars( const ScDataBarInfo* pOldDataBarInfo, OutputDevice* pDev, const Rectangle& rRect)
790 long nPosZero = 0;
791 Rectangle aPaintRect = rRect;
792 aPaintRect.Top() += 2;
793 aPaintRect.Bottom() -= 2;
794 aPaintRect.Left() += 2;
795 aPaintRect.Right() -= 2;
796 if(pOldDataBarInfo->mnZero)
798 // need to calculate null point in cell
799 long nLength = aPaintRect.Right() - aPaintRect.Left();
800 nPosZero = static_cast<long>(aPaintRect.Left() + nLength*pOldDataBarInfo->mnZero/100.0);
802 else
804 nPosZero = aPaintRect.Left();
807 if(pOldDataBarInfo->mnLength < 0)
809 aPaintRect.Right() = nPosZero;
810 long nLength = nPosZero - aPaintRect.Left();
811 aPaintRect.Left() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
813 else if(pOldDataBarInfo->mnLength > 0)
815 aPaintRect.Left() = nPosZero;
816 long nLength = aPaintRect.Right() - nPosZero;
817 aPaintRect.Right() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
819 else
820 return;
822 if(pOldDataBarInfo->mbGradient)
824 pDev->SetLineColor(pOldDataBarInfo->maColor);
825 Gradient aGradient(GradientStyle_LINEAR, pOldDataBarInfo->maColor, COL_TRANSPARENT);
827 if(pOldDataBarInfo->mnLength < 0)
828 aGradient.SetAngle(2700);
829 else
830 aGradient.SetAngle(900);
832 pDev->DrawGradient(aPaintRect, aGradient);
834 pDev->SetLineColor();
836 else
838 pDev->SetFillColor(pOldDataBarInfo->maColor);
839 pDev->DrawRect(aPaintRect);
842 //draw axis
843 if(pOldDataBarInfo->mnZero && pOldDataBarInfo->mnZero != 100)
845 Point aPoint1(nPosZero, rRect.Top());
846 Point aPoint2(nPosZero, rRect.Bottom());
847 LineInfo aLineInfo(LINE_DASH, 1);
848 aLineInfo.SetDashCount( 4 );
849 aLineInfo.SetDistance( 3 );
850 aLineInfo.SetDashLen( 3 );
851 pDev->SetFillColor(pOldDataBarInfo->maAxisColor);
852 pDev->SetLineColor(pOldDataBarInfo->maAxisColor);
853 pDev->DrawLine(aPoint1, aPoint2, aLineInfo);
854 pDev->SetLineColor();
855 pDev->SetFillColor();
859 BitmapEx& getIcon( ScIconSetType eType, sal_Int32 nIndex )
861 return ScIconSetFormat::getBitmap( eType, nIndex );
864 void drawIconSets( const ScIconSetInfo* pOldIconSetInfo, OutputDevice* pDev, const Rectangle& rRect )
866 //long nSize = 16;
867 ScIconSetType eType = pOldIconSetInfo->eIconSetType;
868 sal_Int32 nIndex = pOldIconSetInfo->nIconIndex;
869 BitmapEx& rIcon = getIcon( eType, nIndex );
870 long aOrigSize = std::max<long>(0,std::min(rRect.GetSize().getWidth() - 4, rRect.GetSize().getHeight() -4));
871 pDev->DrawBitmapEx( Point( rRect.Left() +2, rRect.Top() + 2 ), Size(aOrigSize, aOrigSize), rIcon );
874 void drawCells(const Color* pColor, const SvxBrushItem* pBackground, const Color*& pOldColor, const SvxBrushItem*& pOldBackground,
875 Rectangle& rRect, long nPosX, long nSignedOneX, OutputDevice* pDev, const ScDataBarInfo* pDataBarInfo, const ScDataBarInfo*& pOldDataBarInfo,
876 const ScIconSetInfo* pIconSetInfo, const ScIconSetInfo*& pOldIconSetInfo)
879 // need to paint if old color scale has been used and now
880 // we have a different color or a style based background
881 // we can here fall back to pointer comparison
882 if (pOldColor && (pBackground || pOldColor != pColor || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo))
884 rRect.Right() = nPosX-nSignedOneX;
885 if( !pOldColor->GetTransparency() )
887 pDev->SetFillColor( *pOldColor );
888 pDev->DrawRect( rRect );
890 if( pOldDataBarInfo )
891 drawDataBars( pOldDataBarInfo, pDev, rRect );
892 if( pOldIconSetInfo )
893 drawIconSets( pOldIconSetInfo, pDev, rRect );
895 rRect.Left() = nPosX - nSignedOneX;
898 if ( pOldBackground && (pColor ||pBackground != pOldBackground || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo) )
900 rRect.Right() = nPosX-nSignedOneX;
901 if (pOldBackground) // ==0 if hidden
903 Color aBackCol = pOldBackground->GetColor();
904 if ( !aBackCol.GetTransparency() ) //! partial transparency?
906 pDev->SetFillColor( aBackCol );
907 pDev->DrawRect( rRect );
910 if( pOldDataBarInfo )
911 drawDataBars( pOldDataBarInfo, pDev, rRect );
912 if( pOldIconSetInfo )
913 drawIconSets( pOldIconSetInfo, pDev, rRect );
915 rRect.Left() = nPosX - nSignedOneX;
918 if (!pOldBackground && !pOldColor && (pDataBarInfo || pIconSetInfo))
920 rRect.Right() = nPosX -nSignedOneX;
921 rRect.Left() = nPosX - nSignedOneX;
924 if(pColor)
926 // only update pOldColor if the colors changed
927 if (!pOldColor || *pOldColor != *pColor)
928 pOldColor = pColor;
930 pOldBackground = NULL;
932 else if(pBackground)
934 pOldBackground = pBackground;
935 pOldColor = NULL;
938 if(pDataBarInfo)
939 pOldDataBarInfo = pDataBarInfo;
940 else
941 pOldDataBarInfo = NULL;
943 if(pIconSetInfo)
944 pOldIconSetInfo = pIconSetInfo;
945 else
946 pOldIconSetInfo = NULL;
951 void ScOutputData::DrawBackground()
953 FindRotated(); //! from the outside?
955 Rectangle aRect;
956 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
957 long nOneX = aOnePixel.Width();
958 long nOneY = aOnePixel.Height();
960 if (bMetaFile)
961 nOneX = nOneY = 0;
963 long nLayoutSign = bLayoutRTL ? -1 : 1;
964 long nSignedOneX = nOneX * nLayoutSign;
966 mpDev->SetLineColor();
968 bool bShowProt = mbSyntaxMode && mpDoc->IsTabProtected(nTab);
969 bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
971 bool bCellContrast = mbUseStyleColor &&
972 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
974 long nPosY = nScrY;
975 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
977 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
978 long nRowHeight = pThisRowInfo->nHeight;
980 if ( pThisRowInfo->bChanged )
982 if ( ( ( pThisRowInfo->bEmptyBack ) || mbSyntaxMode ) && !bDoAll )
984 // nothing
986 else
988 // scan for rows with the same background:
989 SCSIZE nSkip = 0;
990 while ( nArrY+nSkip+2<nArrCount &&
991 lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
992 nX1, nX2, bShowProt, bPagebreakMode ) )
994 ++nSkip;
995 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
998 long nPosX = nScrX;
999 if ( bLayoutRTL )
1000 nPosX += nMirrorW - nOneX;
1001 aRect = Rectangle( nPosX, nPosY-nOneY, nPosX, nPosY+nRowHeight-nOneY );
1003 const SvxBrushItem* pOldBackground = NULL;
1004 const SvxBrushItem* pBackground;
1005 const Color* pOldColor = NULL;
1006 const Color* pColor = NULL;
1007 const ScDataBarInfo* pOldDataBarInfo = NULL;
1008 const ScIconSetInfo* pOldIconSetInfo = NULL;
1009 for (SCCOL nX=nX1; nX<=nX2; nX++)
1011 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1013 if (bCellContrast)
1015 // high contrast for cell borders and backgrounds -> empty background
1016 pBackground = ScGlobal::GetEmptyBrushItem();
1018 else if (bShowProt) // show cell protection in syntax mode
1020 const ScPatternAttr* pP = pInfo->pPatternAttr;
1021 if (pP)
1023 const ScProtectionAttr& rProt = (const ScProtectionAttr&)
1024 pP->GetItem(ATTR_PROTECTION);
1025 if (rProt.GetProtection() || rProt.GetHideCell())
1026 pBackground = ScGlobal::GetProtectedBrushItem();
1027 else
1028 pBackground = ScGlobal::GetEmptyBrushItem();
1030 else
1031 pBackground = NULL;
1033 else
1034 pBackground = pInfo->pBackground;
1036 if ( bPagebreakMode && !pInfo->bPrinted )
1037 pBackground = ScGlobal::GetProtectedBrushItem();
1039 if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1040 pBackground->GetColor().GetTransparency() != 255 &&
1041 !bCellContrast )
1043 SCROW nY = pRowInfo[nArrY].nRowNo;
1044 pBackground = lcl_FindBackground( mpDoc, nX, nY, nTab );
1047 pColor = pInfo->pColorScale;
1048 const ScDataBarInfo* pDataBarInfo = pInfo->pDataBar;
1049 const ScIconSetInfo* pIconSetInfo = pInfo->pIconSet;
1050 drawCells( pColor, pBackground, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo );
1052 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1054 drawCells( NULL, NULL, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, NULL, pOldDataBarInfo, NULL, pOldIconSetInfo );
1056 nArrY += nSkip;
1059 nPosY += nRowHeight;
1063 void ScOutputData::DrawShadow()
1065 DrawExtraShadow( false, false, false, false );
1068 void ScOutputData::DrawExtraShadow(bool bLeft, bool bTop, bool bRight, bool bBottom)
1070 mpDev->SetLineColor();
1072 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1073 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1074 Color aAutoTextColor;
1075 if ( bCellContrast )
1076 aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1078 long nInitPosX = nScrX;
1079 if ( bLayoutRTL )
1081 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1082 long nOneX = aOnePixel.Width();
1083 nInitPosX += nMirrorW - nOneX;
1085 long nLayoutSign = bLayoutRTL ? -1 : 1;
1087 long nPosY = nScrY - pRowInfo[0].nHeight;
1088 for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
1090 bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
1091 bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
1093 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1094 long nRowHeight = pThisRowInfo->nHeight;
1096 if ( pThisRowInfo->bChanged && !bSkipY )
1098 long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
1099 for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
1101 bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
1102 bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
1104 for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertical
1106 const SvxShadowItem* pAttr = nPass ?
1107 pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
1108 pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
1109 if ( pAttr && !bSkipX )
1111 ScShadowPart ePart = nPass ?
1112 pThisRowInfo->pCellInfo[nArrX].eVShadowPart :
1113 pThisRowInfo->pCellInfo[nArrX].eHShadowPart;
1115 bool bDo = true;
1116 if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
1117 if ( ePart != SC_SHADOW_CORNER )
1118 bDo = false;
1120 if (bDo)
1122 long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1123 long nMaxWidth = nThisWidth;
1124 if (!nMaxWidth)
1126 //! direction must depend on shadow location
1127 SCCOL nWx = nArrX; // nX+1
1128 while (nWx<nX2 && !pRowInfo[0].pCellInfo[nWx+1].nWidth)
1129 ++nWx;
1130 nMaxWidth = pRowInfo[0].pCellInfo[nWx+1].nWidth;
1133 // rectangle is in logical orientation
1134 Rectangle aRect( nPosX, nPosY,
1135 nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1136 nPosY + pRowInfo[nArrY].nHeight - 1 );
1138 long nSize = pAttr->GetWidth();
1139 long nSizeX = (long)(nSize*mnPPTX);
1140 if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1;
1141 long nSizeY = (long)(nSize*mnPPTY);
1142 if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1;
1144 nSizeX *= nLayoutSign; // used only to add to rectangle values
1146 SvxShadowLocation eLoc = pAttr->GetLocation();
1147 if ( bLayoutRTL )
1149 // Shadow location is specified as "visual" (right is always right),
1150 // so the attribute's location value is mirrored here and in FillInfo.
1151 switch (eLoc)
1153 case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
1154 case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
1155 case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
1156 case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
1157 default:
1159 // added to avoid warnings
1164 if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1165 ePart == SC_SHADOW_CORNER)
1167 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1168 aRect.Top() = aRect.Bottom() - nSizeY;
1169 else
1170 aRect.Bottom() = aRect.Top() + nSizeY;
1172 if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1173 ePart == SC_SHADOW_CORNER)
1175 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1176 aRect.Left() = aRect.Right() - nSizeX;
1177 else
1178 aRect.Right() = aRect.Left() + nSizeX;
1180 if (ePart == SC_SHADOW_HSTART)
1182 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1183 aRect.Right() -= nSizeX;
1184 else
1185 aRect.Left() += nSizeX;
1187 if (ePart == SC_SHADOW_VSTART)
1189 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1190 aRect.Bottom() -= nSizeY;
1191 else
1192 aRect.Top() += nSizeY;
1195 //! merge rectangles?
1196 mpDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1197 mpDev->DrawRect( aRect );
1202 nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1205 nPosY += nRowHeight;
1209 void ScOutputData::DrawClear()
1211 Rectangle aRect;
1212 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1213 long nOneX = aOnePixel.Width();
1214 long nOneY = aOnePixel.Height();
1216 // (called only for ScGridWindow)
1217 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1219 if (bMetaFile)
1220 nOneX = nOneY = 0;
1222 mpDev->SetLineColor();
1224 mpDev->SetFillColor( aBgColor );
1226 long nPosY = nScrY;
1227 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1229 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1230 long nRowHeight = pThisRowInfo->nHeight;
1232 if ( pThisRowInfo->bChanged )
1234 // scan for more rows which must be painted:
1235 SCSIZE nSkip = 0;
1236 while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1238 ++nSkip;
1239 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1242 aRect = Rectangle( Point( nScrX, nPosY ),
1243 Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1244 mpDev->DrawRect( aRect );
1246 nArrY += nSkip;
1248 nPosY += nRowHeight;
1253 // Lines
1255 long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1257 return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1260 long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1262 return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1265 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL )
1267 return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) );
1270 void ScOutputData::DrawFrame()
1272 sal_uLong nOldDrawMode = mpDev->GetDrawMode();
1274 Color aSingleColor;
1275 bool bUseSingleColor = false;
1276 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1277 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1279 // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1280 // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1281 // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1282 // must be reset and the border colors handled here.
1284 if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) )
1286 mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) );
1287 aSingleColor.SetColor( COL_BLACK );
1288 bUseSingleColor = true;
1290 else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) )
1292 mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) );
1293 aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE
1294 bUseSingleColor = true;
1296 else if ( bCellContrast )
1298 aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1299 bUseSingleColor = true;
1302 const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1304 if (bAnyRotated)
1305 DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here
1307 long nInitPosX = nScrX;
1308 if ( bLayoutRTL )
1310 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1311 long nOneX = aOnePixel.Width();
1312 nInitPosX += nMirrorW - nOneX;
1314 long nLayoutSign = bLayoutRTL ? -1 : 1;
1317 // *** set column and row sizes of the frame border array ***
1319 svx::frame::Array& rArray = mrTabInfo.maArray;
1320 size_t nColCount = rArray.GetColCount();
1321 size_t nRowCount = rArray.GetRowCount();
1323 // row heights
1325 // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1326 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1327 long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1328 long nOldSnapY = lclGetSnappedY( *mpDev, nOldPosY, bSnapPixel );
1329 rArray.SetYOffset( nOldSnapY );
1330 for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1332 long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1333 long nNewSnapY = lclGetSnappedY( *mpDev, nNewPosY, bSnapPixel );
1334 rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1335 nOldPosY = nNewPosY;
1336 nOldSnapY = nNewSnapY;
1339 // column widths
1341 // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1342 // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1343 long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth);
1344 long nOldSnapX = lclGetSnappedX( *mpDev, nOldPosX, bSnapPixel );
1345 // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1346 if( !bLayoutRTL )
1347 rArray.SetXOffset( nOldSnapX );
1348 for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
1350 size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL );
1351 long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign;
1352 long nNewSnapX = lclGetSnappedX( *mpDev, nNewPosX, bSnapPixel );
1353 rArray.SetColWidth( nCol, std::abs( nNewSnapX - nOldSnapX ) );
1354 nOldPosX = nNewPosX;
1355 nOldSnapX = nNewSnapX;
1357 if( bLayoutRTL )
1358 rArray.SetXOffset( nOldSnapX );
1360 // *** draw the array ***
1362 size_t nFirstCol = 1;
1363 size_t nFirstRow = 1;
1364 size_t nLastCol = nColCount - 2;
1365 size_t nLastRow = nRowCount - 2;
1367 if( mrTabInfo.mbPageMode )
1368 rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1370 // draw only rows with set RowInfo::bChanged flag
1371 size_t nRow1 = nFirstRow;
1372 boost::scoped_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D());
1373 if (!pProcessor)
1374 return;
1376 while( nRow1 <= nLastRow )
1378 while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1379 if( nRow1 <= nLastRow )
1381 size_t nRow2 = nRow1;
1382 while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1383 rArray.DrawRange( pProcessor.get(), nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
1384 nRow1 = nRow2 + 1;
1387 pProcessor.reset();
1389 mpDev->SetDrawMode(nOldDrawMode);
1393 // Line below the cell
1395 static const ::editeng::SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc,
1396 SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nRotDir,
1397 bool bTopLine )
1399 if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT )
1400 return NULL;
1402 bool bFound = false;
1403 while (!bFound)
1405 if ( nRotDir == SC_ROTDIR_LEFT )
1407 // text to the left -> line from the right
1408 if ( nCol < MAXCOL )
1409 ++nCol;
1410 else
1411 return NULL; // couldn't find it
1413 else
1415 // text to the right -> line from the left
1416 if ( nCol > 0 )
1417 --nCol;
1418 else
1419 return NULL; // couldn't find it
1421 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
1422 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
1423 if ( !pPattern->GetRotateVal( pCondSet ) ||
1424 ((const SvxRotateModeItem&)pPattern->GetItem(
1425 ATTR_ROTATE_MODE, pCondSet)).GetValue() == SVX_ROTATE_MODE_STANDARD )
1426 bFound = true;
1429 if (bTopLine)
1430 --nRow;
1431 const ::editeng::SvxBorderLine* pThisBottom;
1432 if ( ValidRow(nRow) )
1433 pThisBottom = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ))->GetBottom();
1434 else
1435 pThisBottom = NULL;
1436 const ::editeng::SvxBorderLine* pNextTop;
1437 if ( nRow < MAXROW )
1438 pNextTop = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
1439 else
1440 pNextTop = NULL;
1442 if ( ScHasPriority( pThisBottom, pNextTop ) )
1443 return pThisBottom;
1444 else
1445 return pNextTop;
1449 static long lcl_getRotate( ScDocument* pDoc, SCTAB nTab, SCCOL nX, SCROW nY )
1451 long nRotate = 0;
1453 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1454 const SfxItemSet* pCondSet = pDoc->GetCondResult( nX, nY, nTab );
1456 nRotate = pPattern->GetRotateVal( pCondSet );
1458 return nRotate;
1461 void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
1463 //! save nRotMax
1464 SCCOL nRotMax = nX2;
1465 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1466 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
1467 nRotMax = pRowInfo[nRotY].nRotMaxCol;
1469 const ScPatternAttr* pPattern;
1470 const SfxItemSet* pCondSet;
1472 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1473 bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1475 // color (pForceColor) is determined externally, including DrawMode changes
1477 long nInitPosX = nScrX;
1478 if ( bLayoutRTL )
1480 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1481 long nOneX = aOnePixel.Width();
1482 nInitPosX += nMirrorW - nOneX;
1484 long nLayoutSign = bLayoutRTL ? -1 : 1;
1486 Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1487 if (bMetaFile)
1489 mpDev->Push();
1490 mpDev->IntersectClipRegion( aClipRect );
1492 else
1493 mpDev->SetClipRegion( Region( aClipRect ) );
1495 svx::frame::Array& rArray = mrTabInfo.maArray;
1496 boost::scoped_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D( ));
1498 long nPosY = nScrY;
1499 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1501 // Rotated is also drawn one line above/below Changed if parts extend into the cell
1503 RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1504 RowInfo& rThisRowInfo = pRowInfo[nArrY];
1505 RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1507 size_t nRow = static_cast< size_t >( nArrY );
1509 long nRowHeight = rThisRowInfo.nHeight;
1510 if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1511 ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1512 ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1514 SCROW nY = rThisRowInfo.nRowNo;
1515 long nPosX = 0;
1516 SCCOL nX;
1517 for (nX=0; nX<=nRotMax; nX++)
1519 if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1521 sal_uInt16 nArrX = nX + 1;
1523 CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX];
1524 long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1525 if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1526 !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1528 pPattern = pInfo->pPatternAttr;
1529 pCondSet = pInfo->pConditionSet;
1530 if (!pPattern)
1532 pPattern = mpDoc->GetPattern( nX, nY, nTab );
1533 pInfo->pPatternAttr = pPattern;
1534 pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
1535 pInfo->pConditionSet = pCondSet;
1538 //! LastPattern etc.
1540 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
1541 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1542 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1544 if ( nAttrRotate )
1546 if (nX<nX1) // compute negative position
1548 nPosX = nInitPosX;
1549 SCCOL nCol = nX1;
1550 while (nCol > nX)
1552 --nCol;
1553 nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
1557 // start position minus 1 so rotated backgrounds suit the border
1558 // (border is on the grid)
1560 long nTop = nPosY - 1;
1561 long nBottom = nPosY + nRowHeight - 1;
1562 long nTopLeft = nPosX - nLayoutSign;
1563 long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign;
1564 long nBotLeft = nTopLeft;
1565 long nBotRight = nTopRight;
1567 // inclusion of the sign here hasn't been decided yet
1568 // (if not, the extension of the non-rotated background must also be changed)
1569 double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000; // 1/100th degrees
1570 double nCos = cos( nRealOrient );
1571 double nSin = sin( nRealOrient );
1572 //! restrict !!!
1573 long nSkew = (long) ( nRowHeight * nCos / nSin );
1575 switch (eRotMode)
1577 case SVX_ROTATE_MODE_BOTTOM:
1578 nTopLeft += nSkew;
1579 nTopRight += nSkew;
1580 break;
1581 case SVX_ROTATE_MODE_CENTER:
1582 nSkew /= 2;
1583 nTopLeft += nSkew;
1584 nTopRight += nSkew;
1585 nBotLeft -= nSkew;
1586 nBotRight -= nSkew;
1587 break;
1588 case SVX_ROTATE_MODE_TOP:
1589 nBotLeft -= nSkew;
1590 nBotRight -= nSkew;
1591 break;
1592 default:
1594 // added to avoid warnings
1598 Point aPoints[4];
1599 aPoints[0] = Point( nTopLeft, nTop );
1600 aPoints[1] = Point( nTopRight, nTop );
1601 aPoints[2] = Point( nBotRight, nBottom );
1602 aPoints[3] = Point( nBotLeft, nBottom );
1604 const SvxBrushItem* pBackground = pInfo->pBackground;
1605 if (!pBackground)
1606 pBackground = (const SvxBrushItem*) &pPattern->GetItem(
1607 ATTR_BACKGROUND, pCondSet );
1608 if (bCellContrast)
1610 // high contrast for cell borders and backgrounds -> empty background
1611 pBackground = ScGlobal::GetEmptyBrushItem();
1613 if(!pInfo->pColorScale)
1615 const Color& rColor = pBackground->GetColor();
1616 if ( rColor.GetTransparency() != 255 )
1618 // draw background only for the changed row itself
1619 // (background doesn't extend into other cells).
1620 // For the borders (rotated and normal), clipping should be
1621 // set if the row isn't changed, but at least the borders
1622 // don't cover the cell contents.
1623 if ( rThisRowInfo.bChanged )
1625 Polygon aPoly( 4, aPoints );
1627 // ohne Pen wird bei DrawPolygon rechts und unten
1628 // ein Pixel weggelassen...
1629 if ( rColor.GetTransparency() == 0 )
1630 mpDev->SetLineColor(rColor);
1631 else
1632 mpDev->SetLineColor();
1633 mpDev->SetFillColor(rColor);
1634 mpDev->DrawPolygon( aPoly );
1638 else
1640 Polygon aPoly( 4, aPoints );
1641 const Color* pColor = pInfo->pColorScale;
1643 // ohne Pen wird bei DrawPolygon rechts und unten
1644 // ein Pixel weggelassen...
1645 if ( pColor->GetTransparency() == 0 )
1646 mpDev->SetLineColor(*pColor);
1647 else
1648 mpDev->SetLineColor();
1649 mpDev->SetFillColor(*pColor);
1650 mpDev->DrawPolygon( aPoly );
1654 svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
1656 if ( nX < nX1 || nX > nX2 ) // Attribute in FillInfo nicht gesetzt
1658 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
1659 const ::editeng::SvxBorderLine* pLeftLine;
1660 const ::editeng::SvxBorderLine* pTopLine;
1661 const ::editeng::SvxBorderLine* pRightLine;
1662 const ::editeng::SvxBorderLine* pBottomLine;
1663 mpDoc->GetBorderLines( nX, nY, nTab,
1664 &pLeftLine, &pTopLine, &pRightLine, &pBottomLine );
1665 aTopLine.Set( pTopLine, mnPPTY );
1666 aBottomLine.Set( pBottomLine, mnPPTY );
1667 aLeftLine.Set( pLeftLine, mnPPTX );
1668 aRightLine.Set( pRightLine, mnPPTX );
1670 else
1672 size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1673 aTopLine = rArray.GetCellStyleTop( nCol, nRow );
1674 aBottomLine = rArray.GetCellStyleBottom( nCol, nRow );
1675 aLeftLine = rArray.GetCellStyleLeft( nCol, nRow );
1676 aRightLine = rArray.GetCellStyleRight( nCol, nRow );
1677 // in RTL mode the array is already mirrored -> swap back left/right borders
1678 if( bLayoutRTL )
1679 std::swap( aLeftLine, aRightLine );
1682 const svx::frame::Style noStyle;
1683 // Horizontal lines
1684 if (aTopLine.Prim() || aTopLine.Secn())
1686 long nUpperRotate = lcl_getRotate( mpDoc, nTab, nX, nY - 1 );
1687 pProcessor->process( svx::frame::CreateBorderPrimitives(
1688 aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine,
1689 svx::frame::Style(),
1690 svx::frame::Style(),
1691 aLeftLine,
1692 svx::frame::Style(),
1693 svx::frame::Style(),
1694 aRightLine,
1695 pForceColor, nUpperRotate, nAttrRotate ) );
1698 if (aBottomLine.Prim() || aBottomLine.Secn())
1700 long nLowerRotate = lcl_getRotate( mpDoc, nTab, nX, nY + 1 );
1701 pProcessor->process( svx::frame::CreateBorderPrimitives(
1702 aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine,
1703 aLeftLine,
1704 svx::frame::Style(),
1705 svx::frame::Style(),
1706 aRightLine,
1707 svx::frame::Style(),
1708 svx::frame::Style(),
1709 pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate ) );
1712 // Vertical slanted lines
1713 if (aLeftLine.Prim() || aLeftLine.Secn())
1715 long nLeftRotate = lcl_getRotate( mpDoc, nTab, nX - 1, nY );
1716 pProcessor->process( svx::frame::CreateBorderPrimitives(
1717 aPoints[0], aPoints[3], aLeftLine,
1718 aTopLine,
1719 svx::frame::Style(),
1720 svx::frame::Style(),
1721 aBottomLine,
1722 svx::frame::Style(),
1723 svx::frame::Style(),
1724 pForceColor, nAttrRotate, nLeftRotate ) );
1727 if (aRightLine.Prim() || aRightLine.Secn())
1729 long nRightRotate = lcl_getRotate( mpDoc, nTab, nX + 1, nY );
1730 pProcessor->process( svx::frame::CreateBorderPrimitives(
1731 aPoints[1], aPoints[2], aRightLine,
1732 svx::frame::Style(),
1733 svx::frame::Style(),
1734 aTopLine,
1735 svx::frame::Style(),
1736 svx::frame::Style(),
1737 aBottomLine,
1738 pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate ) );
1742 nPosX += nColWidth * nLayoutSign;
1745 // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1747 nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1748 for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1
1750 sal_uInt16 nArrX = nX + 1;
1751 CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1752 if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD &&
1753 !rInfo.bHOverlapped && !rInfo.bVOverlapped )
1755 pPattern = rInfo.pPatternAttr;
1756 pCondSet = rInfo.pConditionSet;
1758 size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1760 // horizontal: angrenzende Linie verlaengern
1761 // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1762 sal_uInt16 nDir = rInfo.nRotateDir;
1763 if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() )
1765 svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, true ), mnPPTY );
1766 rArray.SetCellStyleTop( nCol, nRow, aStyle );
1767 if( nRow > 0 )
1768 rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
1770 if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() )
1772 svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, false ), mnPPTY );
1773 rArray.SetCellStyleBottom( nCol, nRow, aStyle );
1774 if( nRow + 1 < rArray.GetRowCount() )
1775 rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
1778 // always remove vertical borders
1779 if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
1781 rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
1782 if( nCol > 0 )
1783 rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
1785 if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
1787 rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
1788 if( nCol + 1 < rArray.GetColCount() )
1789 rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
1792 // remove diagonal borders
1793 rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
1794 rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
1798 nPosY += nRowHeight;
1801 pProcessor.reset();
1803 if (bMetaFile)
1804 mpDev->Pop();
1805 else
1806 mpDev->SetClipRegion();
1809 drawinglayer::processor2d::BaseProcessor2D* ScOutputData::CreateProcessor2D( )
1811 mpDoc->InitDrawLayer(mpDoc->GetDocumentShell());
1812 ScDrawLayer* pDrawLayer = mpDoc->GetDrawLayer();
1813 if (!pDrawLayer)
1814 return NULL;
1816 basegfx::B2DRange aViewRange;
1817 SdrPage *pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
1818 const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
1819 basegfx::B2DHomMatrix( ),
1820 mpDev->GetViewTransformation(),
1821 aViewRange,
1822 GetXDrawPageForSdrPage( pDrawPage ),
1823 0.0,
1824 uno::Sequence< beans::PropertyValue >() );
1826 return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1827 *mpDev, aNewViewInfos );
1830 // Printer
1832 Region ScOutputData::GetChangedAreaRegion()
1834 Region aRegion;
1835 Rectangle aDrawingRect;
1836 bool bHad(false);
1837 long nPosY = nScrY;
1838 SCSIZE nArrY;
1840 aDrawingRect.Left() = nScrX;
1841 aDrawingRect.Right() = nScrX+nScrW-1;
1843 for(nArrY=1; nArrY+1<nArrCount; nArrY++)
1845 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1847 if(pThisRowInfo->bChanged)
1849 if(!bHad)
1851 aDrawingRect.Top() = nPosY;
1852 bHad = true;
1855 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1857 else if(bHad)
1859 aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1860 bHad = false;
1863 nPosY += pRowInfo[nArrY].nHeight;
1866 if(bHad)
1868 aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1871 return aRegion;
1874 bool ScOutputData::SetChangedClip()
1876 PolyPolygon aPoly;
1878 Rectangle aDrawingRect;
1879 aDrawingRect.Left() = nScrX;
1880 aDrawingRect.Right() = nScrX+nScrW-1;
1882 bool bHad = false;
1883 long nPosY = nScrY;
1884 SCSIZE nArrY;
1885 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1887 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1889 if ( pThisRowInfo->bChanged )
1891 if (!bHad)
1893 aDrawingRect.Top() = nPosY;
1894 bHad = true;
1896 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1898 else if (bHad)
1900 aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1901 bHad = false;
1903 nPosY += pRowInfo[nArrY].nHeight;
1906 if (bHad)
1907 aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1909 bool bRet = (aPoly.Count() != 0);
1910 if (bRet)
1911 mpDev->SetClipRegion(Region(aPoly));
1912 return bRet;
1915 void ScOutputData::FindChanged()
1917 SCCOL nX;
1918 SCSIZE nArrY;
1920 bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
1921 mpDoc->EnableIdle(false);
1922 for (nArrY=0; nArrY<nArrCount; nArrY++)
1923 pRowInfo[nArrY].bChanged = false;
1925 bool bProgress = false;
1926 for (nArrY=0; nArrY<nArrCount; nArrY++)
1928 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1929 for (nX=nX1; nX<=nX2; nX++)
1931 const ScRefCellValue& rCell = pThisRowInfo->pCellInfo[nX+1].maCell;
1933 if (rCell.meType != CELLTYPE_FORMULA)
1934 continue;
1936 ScFormulaCell* pFCell = rCell.mpFormula;
1937 if ( !bProgress && pFCell->GetDirty() )
1939 ScProgress::CreateInterpretProgress(mpDoc, true);
1940 bProgress = true;
1942 if (pFCell->IsRunning())
1943 // still being interpreted. Skip it.
1944 continue;
1946 (void)pFCell->GetValue();
1947 if (!pFCell->IsChanged())
1948 // the result hasn't changed. Skip it.
1949 continue;
1951 pThisRowInfo->bChanged = true;
1952 if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1954 SCSIZE nOverY = nArrY + 1;
1955 while ( nOverY<nArrCount &&
1956 pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
1958 pRowInfo[nOverY].bChanged = true;
1959 ++nOverY;
1964 if ( bProgress )
1965 ScProgress::DeleteInterpretProgress();
1966 mpDoc->EnableIdle(bWasIdleEnabled);
1969 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
1970 SCCOL nRefEndX, SCROW nRefEndY,
1971 const Color& rColor, bool bHandle )
1973 PutInOrder( nRefStartX, nRefEndX );
1974 PutInOrder( nRefStartY, nRefEndY );
1976 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1977 mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1979 if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
1980 nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
1982 long nMinX = nScrX;
1983 long nMinY = nScrY;
1984 long nMaxX = nScrX + nScrW - 1;
1985 long nMaxY = nScrY + nScrH - 1;
1986 if ( bLayoutRTL )
1988 long nTemp = nMinX;
1989 nMinX = nMaxX;
1990 nMaxX = nTemp;
1992 long nLayoutSign = bLayoutRTL ? -1 : 1;
1994 bool bTop = false;
1995 bool bBottom = false;
1996 bool bLeft = false;
1997 bool bRight = false;
1999 long nPosY = nScrY;
2000 bool bNoStartY = ( nY1 < nRefStartY );
2001 bool bNoEndY = false;
2002 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2004 SCROW nY = pRowInfo[nArrY].nRowNo;
2006 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2008 nMinY = nPosY;
2009 bTop = true;
2011 if ( nY==nRefEndY )
2013 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
2014 bBottom = true;
2016 if ( nY>nRefEndY && bNoEndY )
2018 nMaxY = nPosY-2;
2019 bBottom = true;
2021 bNoStartY = ( nY < nRefStartY );
2022 bNoEndY = ( nY < nRefEndY );
2023 nPosY += pRowInfo[nArrY].nHeight;
2026 long nPosX = nScrX;
2027 if ( bLayoutRTL )
2028 nPosX += nMirrorW - 1; // always in pixels
2030 for (SCCOL nX=nX1; nX<=nX2; nX++)
2032 if ( nX==nRefStartX )
2034 nMinX = nPosX;
2035 bLeft = true;
2037 if ( nX==nRefEndX )
2039 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
2040 bRight = true;
2042 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2045 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2046 nMaxY >= nMinY )
2048 mpDev->SetLineColor( rColor );
2049 if (bTop && bBottom && bLeft && bRight)
2051 mpDev->SetFillColor();
2052 mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2054 else
2056 if (bTop)
2057 mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMaxX, nMinY ) );
2058 if (bBottom)
2059 mpDev->DrawLine( Point( nMinX, nMaxY ), Point( nMaxX, nMaxY ) );
2060 if (bLeft)
2061 mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMinX, nMaxY ) );
2062 if (bRight)
2063 mpDev->DrawLine( Point( nMaxX, nMinY ), Point( nMaxX, nMaxY ) );
2065 if ( bHandle && bRight && bBottom )
2067 mpDev->SetLineColor( rColor );
2068 mpDev->SetFillColor( rColor );
2070 const sal_Int32 aRadius = 4;
2072 sal_Int32 aRectMaxX1 = nMaxX - nLayoutSign * aRadius;
2073 sal_Int32 aRectMaxX2 = nMaxX + nLayoutSign;
2074 sal_Int32 aRectMinX1 = nMinX - nLayoutSign;
2075 sal_Int32 aRectMinX2 = nMinX + nLayoutSign * aRadius;
2077 sal_Int32 aRectMaxY1 = nMaxY - aRadius;
2078 sal_Int32 aRectMaxY2 = nMaxY + 1;
2079 sal_Int32 aRectMinY1 = nMinY - 1;
2080 sal_Int32 aRectMinY2 = nMinY + aRadius;
2082 // Draw corner rectangles
2083 Rectangle aLowerRight( aRectMaxX1, aRectMaxY1, aRectMaxX2, aRectMaxY2 );
2084 Rectangle aUpperLeft ( aRectMinX1, aRectMinY1, aRectMinX2, aRectMinY2 );
2085 Rectangle aLowerLeft ( aRectMinX1, aRectMaxY1, aRectMinX2, aRectMaxY2 );
2086 Rectangle aUpperRight( aRectMaxX1, aRectMinY1, aRectMaxX2, aRectMinY2 );
2088 mpDev->DrawTransparent( PolyPolygon( Polygon( aLowerRight ) ), lclCornerRectTransparency );
2089 mpDev->DrawTransparent( PolyPolygon( Polygon( aUpperLeft ) ), lclCornerRectTransparency );
2090 mpDev->DrawTransparent( PolyPolygon( Polygon( aLowerLeft ) ), lclCornerRectTransparency );
2091 mpDev->DrawTransparent( PolyPolygon( Polygon( aUpperRight ) ), lclCornerRectTransparency );
2097 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
2098 SCCOL nRefEndX, SCROW nRefEndY,
2099 const Color& rColor, sal_uInt16 nType )
2101 PutInOrder( nRefStartX, nRefEndX );
2102 PutInOrder( nRefStartY, nRefEndY );
2104 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2105 mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2107 if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
2108 nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top
2110 long nMinX = nScrX;
2111 long nMinY = nScrY;
2112 long nMaxX = nScrX+nScrW-1;
2113 long nMaxY = nScrY+nScrH-1;
2114 if ( bLayoutRTL )
2116 long nTemp = nMinX;
2117 nMinX = nMaxX;
2118 nMaxX = nTemp;
2120 long nLayoutSign = bLayoutRTL ? -1 : 1;
2122 bool bTop = false;
2123 bool bBottom = false;
2124 bool bLeft = false;
2125 bool bRight = false;
2127 long nPosY = nScrY;
2128 bool bNoStartY = ( nY1 < nRefStartY );
2129 bool bNoEndY = false;
2130 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2132 SCROW nY = pRowInfo[nArrY].nRowNo;
2134 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2136 nMinY = nPosY - 1;
2137 bTop = true;
2139 if ( nY==nRefEndY )
2141 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2142 bBottom = true;
2144 if ( nY>nRefEndY && bNoEndY )
2146 nMaxY = nPosY - 1;
2147 bBottom = true;
2149 bNoStartY = ( nY < nRefStartY );
2150 bNoEndY = ( nY < nRefEndY );
2151 nPosY += pRowInfo[nArrY].nHeight;
2154 long nPosX = nScrX;
2155 if ( bLayoutRTL )
2156 nPosX += nMirrorW - 1; // always in pixels
2158 for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2160 if ( nX==nRefStartX )
2162 nMinX = nPosX - nLayoutSign;
2163 bLeft = true;
2165 if ( nX==nRefEndX )
2167 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2168 bRight = true;
2170 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2173 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2174 nMaxY >= nMinY )
2176 if ( nType == SC_CAT_DELETE_ROWS )
2177 bLeft = bRight = bBottom = false; //! thick lines???
2178 else if ( nType == SC_CAT_DELETE_COLS )
2179 bTop = bBottom = bRight = false; //! thick lines???
2181 mpDev->SetLineColor( rColor );
2182 if (bTop && bBottom && bLeft && bRight)
2184 mpDev->SetFillColor();
2185 mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2187 else
2189 if (bTop)
2191 mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2192 if ( nType == SC_CAT_DELETE_ROWS )
2193 mpDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2195 if (bBottom)
2196 mpDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2197 if (bLeft)
2199 mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2200 if ( nType == SC_CAT_DELETE_COLS )
2201 mpDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2203 if (bRight)
2204 mpDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2206 if ( bLeft && bTop )
2208 mpDev->SetLineColor();
2209 mpDev->SetFillColor( rColor );
2210 mpDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2216 void ScOutputData::DrawChangeTrack()
2218 ScChangeTrack* pTrack = mpDoc->GetChangeTrack();
2219 ScChangeViewSettings* pSettings = mpDoc->GetChangeViewSettings();
2220 if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2221 return; // nix da oder abgeschaltet
2223 ScActionColorChanger aColorChanger(*pTrack);
2225 // Clipping passiert von aussen
2226 //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2228 SCCOL nEndX = nX2;
2229 SCROW nEndY = nY2;
2230 if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung
2231 if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt
2232 ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2233 const ScChangeAction* pAction = pTrack->GetFirst();
2234 while (pAction)
2236 ScChangeActionType eActionType;
2237 if ( pAction->IsVisible() )
2239 eActionType = pAction->GetType();
2240 const ScBigRange& rBig = pAction->GetBigRange();
2241 if ( rBig.aStart.Tab() == nTab )
2243 ScRange aRange = rBig.MakeRange();
2245 if ( eActionType == SC_CAT_DELETE_ROWS )
2246 aRange.aEnd.SetRow( aRange.aStart.Row() );
2247 else if ( eActionType == SC_CAT_DELETE_COLS )
2248 aRange.aEnd.SetCol( aRange.aStart.Col() );
2250 if ( aRange.Intersects( aViewRange ) &&
2251 ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2253 aColorChanger.Update( *pAction );
2254 Color aColor( aColorChanger.GetColor() );
2255 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2256 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2260 if ( eActionType == SC_CAT_MOVE &&
2261 ((const ScChangeActionMove*)pAction)->
2262 GetFromRange().aStart.Tab() == nTab )
2264 ScRange aRange = ((const ScChangeActionMove*)pAction)->
2265 GetFromRange().MakeRange();
2266 if ( aRange.Intersects( aViewRange ) &&
2267 ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2269 aColorChanger.Update( *pAction );
2270 Color aColor( aColorChanger.GetColor() );
2271 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2272 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2277 pAction = pAction->GetNext();
2281 //TODO: moggi Need to check if this can't be written simpler
2282 void ScOutputData::DrawNoteMarks()
2285 bool bFirst = true;
2287 long nInitPosX = nScrX;
2288 if ( bLayoutRTL )
2289 nInitPosX += nMirrorW - 1; // always in pixels
2290 long nLayoutSign = bLayoutRTL ? -1 : 1;
2292 long nPosY = nScrY;
2293 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2295 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2296 if ( pThisRowInfo->bChanged )
2298 long nPosX = nInitPosX;
2299 for (SCCOL nX=nX1; nX<=nX2; nX++)
2301 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2302 bool bIsMerged = false;
2304 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2306 // find start of merged cell
2307 bIsMerged = true;
2308 SCROW nY = pRowInfo[nArrY].nRowNo;
2309 SCCOL nMergeX = nX;
2310 SCROW nMergeY = nY;
2311 mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2312 // use origin's pCell for NotePtr test below
2315 if ( mpDoc->GetNote(nX, pRowInfo[nArrY].nRowNo, nTab) && ( bIsMerged ||
2316 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2318 if (bFirst)
2320 mpDev->SetLineColor();
2322 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2323 if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2324 mpDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2325 else
2326 mpDev->SetFillColor(COL_LIGHTRED);
2328 bFirst = false;
2331 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2332 if ( bIsMerged || pInfo->bMerged )
2334 // if merged, add widths of all cells
2335 SCCOL nNextX = nX + 1;
2336 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2338 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2339 ++nNextX;
2342 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2343 mpDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) );
2346 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2349 nPosY += pThisRowInfo->nHeight;
2353 void ScOutputData::AddPDFNotes()
2355 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
2356 if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2357 return;
2359 long nInitPosX = nScrX;
2360 if ( bLayoutRTL )
2362 Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
2363 long nOneX = aOnePixel.Width();
2364 nInitPosX += nMirrorW - nOneX;
2366 long nLayoutSign = bLayoutRTL ? -1 : 1;
2368 long nPosY = nScrY;
2369 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2371 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2372 if ( pThisRowInfo->bChanged )
2374 long nPosX = nInitPosX;
2375 for (SCCOL nX=nX1; nX<=nX2; nX++)
2377 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2378 bool bIsMerged = false;
2379 SCROW nY = pRowInfo[nArrY].nRowNo;
2380 SCCOL nMergeX = nX;
2381 SCROW nMergeY = nY;
2383 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2385 // find start of merged cell
2386 bIsMerged = true;
2387 mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2388 // use origin's pCell for NotePtr test below
2391 if ( mpDoc->GetNote(nMergeX, nMergeY, nTab) && ( bIsMerged ||
2392 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2394 long nNoteWidth = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2395 long nNoteHeight = (long)( SC_CLIPMARK_SIZE * mnPPTY );
2397 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign;
2398 if ( bIsMerged || pInfo->bMerged )
2400 // if merged, add widths of all cells
2401 SCCOL nNextX = nX + 1;
2402 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2404 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2405 ++nNextX;
2408 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2410 Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2411 const ScPostIt* pNote = mpDoc->GetNote(nMergeX, nMergeY, nTab);
2413 // Note title is the cell address (as on printed note pages)
2414 ScAddress aAddress( nMergeX, nMergeY, nTab );
2415 OUString aTitle(aAddress.Format(SCA_VALID, mpDoc, mpDoc->GetAddressConvention()));
2417 // Content has to be a simple string without line breaks
2418 OUString aContent = pNote->GetText();
2419 aContent = aContent.replaceAll("\n", " ");
2421 vcl::PDFNote aNote;
2422 aNote.Title = aTitle;
2423 aNote.Contents = aContent;
2424 pPDFData->CreateNote( aNoteRect, aNote );
2428 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2431 nPosY += pThisRowInfo->nHeight;
2435 void ScOutputData::DrawClipMarks()
2437 if (!bAnyClipped)
2438 return;
2440 Color aArrowFillCol( COL_LIGHTRED );
2442 sal_uLong nOldDrawMode = mpDev->GetDrawMode();
2443 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2444 if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2446 // use DrawMode to change the arrow's outline color
2447 mpDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2448 // use text color also for the fill color
2449 aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2452 long nInitPosX = nScrX;
2453 if ( bLayoutRTL )
2454 nInitPosX += nMirrorW - 1; // always in pixels
2455 long nLayoutSign = bLayoutRTL ? -1 : 1;
2457 Rectangle aCellRect;
2458 long nPosY = nScrY;
2459 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2461 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2462 if ( pThisRowInfo->bChanged )
2464 SCROW nY = pThisRowInfo->nRowNo;
2465 long nPosX = nInitPosX;
2466 for (SCCOL nX=nX1; nX<=nX2; nX++)
2468 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2469 if (pInfo->nClipMark)
2471 if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2473 // merge origin may be outside of visible area - use document functions
2475 SCCOL nOverX = nX;
2476 SCROW nOverY = nY;
2477 long nStartPosX = nPosX;
2478 long nStartPosY = nPosY;
2480 while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2481 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2483 --nOverX;
2484 nStartPosX -= nLayoutSign * (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2487 while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2488 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2490 --nOverY;
2491 nStartPosY -= nLayoutSign * (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2494 long nOutWidth = (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2495 long nOutHeight = (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2497 const ScMergeAttr* pMerge = (const ScMergeAttr*)
2498 mpDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2499 SCCOL nCountX = pMerge->GetColMerge();
2500 for (SCCOL i=1; i<nCountX; i++)
2501 nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2502 SCROW nCountY = pMerge->GetRowMerge();
2503 nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2505 if ( bLayoutRTL )
2506 nStartPosX -= nOutWidth - 1;
2507 aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2509 else
2511 long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2512 long nOutHeight = pThisRowInfo->nHeight;
2514 if ( pInfo->bMerged && pInfo->pPatternAttr )
2516 SCCOL nOverX = nX;
2517 SCROW nOverY = nY;
2518 const ScMergeAttr* pMerge =
2519 (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2520 SCCOL nCountX = pMerge->GetColMerge();
2521 for (SCCOL i=1; i<nCountX; i++)
2522 nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2523 SCROW nCountY = pMerge->GetRowMerge();
2524 nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2527 long nStartPosX = nPosX;
2528 if ( bLayoutRTL )
2529 nStartPosX -= nOutWidth - 1;
2530 // #i80447# create aCellRect from two points in case nOutWidth is 0
2531 aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2532 Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2535 aCellRect.Bottom() -= 1; // don't paint over the cell grid
2536 if ( bLayoutRTL )
2537 aCellRect.Left() += 1;
2538 else
2539 aCellRect.Right() -= 1;
2541 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2542 Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2544 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2546 // visually left
2547 Rectangle aMarkRect = aCellRect;
2548 aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2549 SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, true );
2551 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2553 // visually right
2554 Rectangle aMarkRect = aCellRect;
2555 aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2556 SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, false );
2559 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2562 nPosY += pThisRowInfo->nHeight;
2565 mpDev->SetDrawMode(nOldDrawMode);
2568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */