Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <com/sun/star/embed/EmbedMisc.hpp>
21 :
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>
44 :
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"
64 :
65 : #include "scresid.hxx"
66 : #include "colorscale.hxx"
67 :
68 : #include <math.h>
69 : #include <map>
70 : #include <utility>
71 : #include <iostream>
72 : #include <boost/scoped_ptr.hpp>
73 :
74 : using namespace com::sun::star;
75 :
76 : // Static Data
77 :
78 : // color for ChangeTracking "by author" as in the writer (swmodul1.cxx)
79 :
80 : #define SC_AUTHORCOLORCOUNT 9
81 :
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 };
86 :
87 : // Helper class for color assignment to avoid repeated lookups for the same user
88 :
89 0 : ScActionColorChanger::ScActionColorChanger( const ScChangeTrack& rTrack ) :
90 0 : rOpt( SC_MOD()->GetAppOptions() ),
91 0 : rUsers( rTrack.GetUserCollection() ),
92 : nLastUserIndex( 0 ),
93 0 : nColor( COL_BLACK )
94 : {
95 0 : }
96 :
97 0 : void ScActionColorChanger::Update( const ScChangeAction& rAction )
98 : {
99 : ColorData nSetColor;
100 0 : switch (rAction.GetType())
101 : {
102 : case SC_CAT_INSERT_COLS:
103 : case SC_CAT_INSERT_ROWS:
104 : case SC_CAT_INSERT_TABS:
105 0 : nSetColor = rOpt.GetTrackInsertColor();
106 0 : break;
107 : case SC_CAT_DELETE_COLS:
108 : case SC_CAT_DELETE_ROWS:
109 : case SC_CAT_DELETE_TABS:
110 0 : nSetColor = rOpt.GetTrackDeleteColor();
111 0 : break;
112 : case SC_CAT_MOVE:
113 0 : nSetColor = rOpt.GetTrackMoveColor();
114 0 : break;
115 : default:
116 0 : nSetColor = rOpt.GetTrackContentColor();
117 0 : break;
118 : }
119 0 : if ( nSetColor != COL_TRANSPARENT ) // color assigned
120 0 : nColor = nSetColor;
121 : else // by author
122 : {
123 0 : if (!aLastUserName.equals(rAction.GetUser()))
124 : {
125 0 : aLastUserName = rAction.GetUser();
126 0 : std::set<OUString>::const_iterator it = rUsers.find(aLastUserName);
127 0 : if (it == rUsers.end())
128 : {
129 : // empty string is possible if a name wasn't found while saving a 5.0 file
130 : SAL_INFO_IF( aLastUserName.isEmpty(), "sc.ui", "Author not found" );
131 0 : nLastUserIndex = 0;
132 : }
133 : else
134 : {
135 0 : size_t nPos = std::distance(rUsers.begin(), it);
136 0 : nLastUserIndex = nPos % SC_AUTHORCOLORCOUNT;
137 : }
138 : }
139 0 : nColor = nAuthorColor[nLastUserIndex];
140 : }
141 0 : }
142 :
143 16360 : ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
144 : ScTableInfo& rTabInfo, ScDocument* pNewDoc,
145 : SCTAB nNewTab, long nNewScrX, long nNewScrY,
146 : SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2,
147 : double nPixelPerTwipsX, double nPixelPerTwipsY,
148 : const Fraction* pZoomX, const Fraction* pZoomY ) :
149 : mpDev( pNewDev ),
150 : mpRefDevice( pNewDev ), // default is output device
151 : pFmtDevice( pNewDev ), // default is output device
152 : mrTabInfo( rTabInfo ),
153 : pRowInfo( rTabInfo.mpRowInfo ),
154 : nArrCount( rTabInfo.mnArrCount ),
155 : mpDoc( pNewDoc ),
156 : nTab( nNewTab ),
157 : nScrX( nNewScrX ),
158 : nScrY( nNewScrY ),
159 : nX1( nNewX1 ),
160 : nY1( nNewY1 ),
161 : nX2( nNewX2 ),
162 : nY2( nNewY2 ),
163 : eType( eNewType ),
164 : mnPPTX( nPixelPerTwipsX ),
165 : mnPPTY( nPixelPerTwipsY ),
166 : pEditObj( NULL ),
167 : pViewShell( NULL ),
168 : pDrawView( NULL ), // #114135#
169 : bEditMode( false ),
170 : nEditCol( 0 ),
171 : nEditRow( 0 ),
172 : bMetaFile( false ),
173 : bSingleGrid( false ),
174 : bPagebreakMode( false ),
175 : bSolidBackground( false ),
176 : mbUseStyleColor( false ),
177 16360 : mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
178 : mbSyntaxMode( false ),
179 : pValueColor( NULL ),
180 : pTextColor( NULL ),
181 : pFormulaColor( NULL ),
182 : aGridColor( COL_BLACK ),
183 : mbShowNullValues( true ),
184 : mbShowFormulas( false ),
185 : bShowSpellErrors( false ),
186 : bMarkClipped( false ), // sal_False for printer/metafile etc.
187 : bSnapPixel( false ),
188 : bAnyRotated( false ),
189 : bAnyClipped( false ),
190 : mpTargetPaintWindow(NULL), // #i74769# use SdrPaintWindow direct
191 32720 : mpSpellCheckCxt(NULL)
192 : {
193 16360 : if (pZoomX)
194 16282 : aZoomX = *pZoomX;
195 : else
196 78 : aZoomX = Fraction(1,1);
197 16360 : if (pZoomY)
198 16282 : aZoomY = *pZoomY;
199 : else
200 78 : aZoomY = Fraction(1,1);
201 :
202 16360 : nVisX1 = nX1;
203 16360 : nVisY1 = nY1;
204 16360 : nVisX2 = nX2;
205 16360 : nVisY2 = nY2;
206 16360 : mpDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
207 :
208 16360 : nScrW = 0;
209 191168 : for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
210 174808 : nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
211 :
212 16360 : nMirrorW = nScrW;
213 :
214 16360 : nScrH = 0;
215 414520 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
216 398160 : nScrH += pRowInfo[nArrY].nHeight;
217 :
218 16360 : bTabProtected = mpDoc->IsTabProtected( nTab );
219 16360 : nTabTextDirection = mpDoc->GetEditTextDirection( nTab );
220 16360 : bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
221 16360 : }
222 :
223 16360 : ScOutputData::~ScOutputData()
224 : {
225 16360 : delete pValueColor;
226 16360 : delete pTextColor;
227 16360 : delete pFormulaColor;
228 16360 : }
229 :
230 1474 : void ScOutputData::SetSpellCheckContext( const sc::SpellCheckContext* pCxt )
231 : {
232 1474 : mpSpellCheckCxt = pCxt;
233 1474 : }
234 :
235 1474 : void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
236 : {
237 : // use pContentDev instead of pDev where used
238 :
239 1474 : if ( mpRefDevice == mpDev )
240 1474 : mpRefDevice = pContentDev;
241 1474 : if ( pFmtDevice == mpDev )
242 1391 : pFmtDevice = pContentDev;
243 1474 : mpDev = pContentDev;
244 1474 : }
245 :
246 16282 : void ScOutputData::SetMirrorWidth( long nNew )
247 : {
248 16282 : nMirrorW = nNew;
249 16282 : }
250 :
251 1540 : void ScOutputData::SetGridColor( const Color& rColor )
252 : {
253 1540 : aGridColor = rColor;
254 1540 : }
255 :
256 1474 : void ScOutputData::SetMarkClipped( bool bSet )
257 : {
258 1474 : bMarkClipped = bSet;
259 1474 : }
260 :
261 1552 : void ScOutputData::SetShowNullValues( bool bSet )
262 : {
263 1552 : mbShowNullValues = bSet;
264 1552 : }
265 :
266 1552 : void ScOutputData::SetShowFormulas( bool bSet )
267 : {
268 1552 : mbShowFormulas = bSet;
269 1552 : }
270 :
271 1474 : void ScOutputData::SetShowSpellErrors( bool bSet )
272 : {
273 1474 : bShowSpellErrors = bSet;
274 1474 : }
275 :
276 12 : void ScOutputData::SetSnapPixel( bool bSet )
277 : {
278 12 : bSnapPixel = bSet;
279 12 : }
280 :
281 0 : void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow )
282 : {
283 0 : nEditCol = nCol;
284 0 : nEditRow = nRow;
285 0 : bEditMode = true;
286 0 : }
287 :
288 12 : void ScOutputData::SetMetaFileMode( bool bNewMode )
289 : {
290 12 : bMetaFile = bNewMode;
291 12 : }
292 :
293 0 : void ScOutputData::SetSingleGrid( bool bNewMode )
294 : {
295 0 : bSingleGrid = bNewMode;
296 0 : }
297 :
298 1474 : void ScOutputData::SetSyntaxMode( bool bNewMode )
299 : {
300 1474 : mbSyntaxMode = bNewMode;
301 1474 : if (bNewMode)
302 0 : if (!pValueColor)
303 : {
304 0 : pValueColor = new Color( COL_LIGHTBLUE );
305 0 : pTextColor = new Color( COL_BLACK );
306 0 : pFormulaColor = new Color( COL_GREEN );
307 : }
308 1474 : }
309 :
310 1474 : void ScOutputData::DrawGrid( bool bGrid, bool bPage )
311 : {
312 : SCCOL nX;
313 : SCROW nY;
314 : long nPosX;
315 : long nPosY;
316 : SCSIZE nArrY;
317 1474 : ScBreakType nBreak = BREAK_NONE;
318 1474 : ScBreakType nBreakOld = BREAK_NONE;
319 :
320 : bool bSingle;
321 1474 : Color aPageColor;
322 1474 : Color aManualColor;
323 :
324 1474 : if (bPagebreakMode)
325 0 : bPage = false; // no "normal" breaks over the whole width/height
326 :
327 : //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
328 : //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
329 :
330 1474 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
331 1474 : long nOneX = aOnePixel.Width();
332 1474 : long nOneY = aOnePixel.Height();
333 1474 : if (bMetaFile)
334 0 : nOneX = nOneY = 1;
335 :
336 1474 : long nLayoutSign = bLayoutRTL ? -1 : 1;
337 1474 : long nSignedOneX = nOneX * nLayoutSign;
338 :
339 1474 : if ( eType == OUTTYPE_WINDOW )
340 : {
341 1474 : const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
342 1474 : aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
343 1474 : aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
344 : }
345 : else
346 : {
347 0 : aPageColor = aGridColor;
348 0 : aManualColor = aGridColor;
349 : }
350 :
351 1474 : mpDev->SetLineColor( aGridColor );
352 1474 : ScGridMerger aGrid( mpDev, nOneX, nOneY );
353 :
354 : // vertical lines
355 :
356 1474 : nPosX = nScrX;
357 1474 : if ( bLayoutRTL )
358 1 : nPosX += nMirrorW - nOneX;
359 :
360 15992 : for (nX=nX1; nX<=nX2; nX++)
361 : {
362 14518 : SCCOL nXplus1 = nX+1;
363 14518 : SCCOL nXplus2 = nX+2;
364 14518 : sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
365 14518 : if (nWidth)
366 : {
367 14516 : nPosX += nWidth * nLayoutSign;
368 :
369 14516 : if ( bPage )
370 : {
371 : // Seitenumbrueche auch in ausgeblendeten suchen
372 14516 : SCCOL nCol = nXplus1;
373 29034 : while (nCol <= MAXCOL)
374 : {
375 14516 : nBreak = mpDoc->HasColBreak(nCol, nTab);
376 14516 : bool bHidden = mpDoc->ColHidden(nCol, nTab);
377 :
378 14516 : if ( nBreak || !bHidden )
379 : break;
380 2 : ++nCol;
381 : }
382 :
383 14516 : if (nBreak != nBreakOld)
384 : {
385 6 : aGrid.Flush();
386 6 : mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
387 6 : nBreak ? aPageColor : aGridColor );
388 6 : nBreakOld = nBreak;
389 : }
390 : }
391 :
392 14516 : bool bDraw = bGrid || nBreakOld; // simple grid only if set that way
393 :
394 14516 : sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
395 14516 : bSingle = bSingleGrid; //! get into Fillinfo !!!!!
396 14516 : if ( nX<MAXCOL && !bSingle )
397 : {
398 14514 : bSingle = ( nWidthXplus2 == 0 );
399 243938 : for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
400 : {
401 229424 : if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
402 35 : bSingle = true;
403 229424 : if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
404 0 : bSingle = true;
405 : }
406 : }
407 :
408 14516 : if (bDraw)
409 : {
410 14480 : if ( nX<MAXCOL && bSingle )
411 : {
412 36 : SCCOL nVisX = nXplus1;
413 74 : while ( nVisX < MAXCOL && !mpDoc->GetColWidth(nVisX,nTab) )
414 2 : ++nVisX;
415 :
416 36 : nPosY = nScrY;
417 : long nNextY;
418 858 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
419 : {
420 822 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
421 822 : nNextY = nPosY + pThisRowInfo->nHeight;
422 :
423 822 : bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
424 822 : if (!bHOver)
425 : {
426 822 : if (nWidthXplus2)
427 798 : bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped;
428 : else
429 : {
430 24 : if (nVisX <= nX2)
431 24 : bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped;
432 : else
433 : bHOver = static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
434 0 : nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
435 0 : ->IsHorOverlapped();
436 24 : if (bHOver)
437 : bHOver = static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
438 0 : nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
439 0 : ->IsHorOverlapped();
440 : }
441 : }
442 :
443 822 : if (pThisRowInfo->bChanged && !bHOver)
444 : {
445 717 : aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
446 : }
447 822 : nPosY = nNextY;
448 36 : }
449 : }
450 : else
451 : {
452 14444 : aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
453 : }
454 : }
455 : }
456 : }
457 :
458 : // horizontal lines
459 :
460 1474 : bool bHiddenRow = true;
461 1474 : SCROW nHiddenEndRow = -1;
462 1474 : nPosY = nScrY;
463 24040 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
464 : {
465 22566 : SCSIZE nArrYplus1 = nArrY+1;
466 22566 : nY = pRowInfo[nArrY].nRowNo;
467 22566 : SCROW nYplus1 = nY+1;
468 22566 : nPosY += pRowInfo[nArrY].nHeight;
469 :
470 22566 : if (pRowInfo[nArrY].bChanged)
471 : {
472 22566 : if ( bPage )
473 : {
474 22616 : for (SCROW i = nYplus1; i <= MAXROW; ++i)
475 : {
476 22616 : if (i > nHiddenEndRow)
477 1506 : bHiddenRow = mpDoc->RowHidden(i, nTab, NULL, &nHiddenEndRow);
478 : /* TODO: optimize the row break thing for large hidden
479 : * segments where HasRowBreak() has to be called
480 : * nevertheless for each row, as a row break is drawn also
481 : * for hidden rows, above them. This needed to be done only
482 : * once per hidden segment, maybe giving manual breaks
483 : * priority. Something like GetNextRowBreak() and
484 : * GetNextManualRowBreak(). */
485 22616 : nBreak = mpDoc->HasRowBreak(i, nTab);
486 22616 : if (!bHiddenRow || nBreak)
487 : break;
488 : }
489 :
490 22566 : if (nBreakOld != nBreak)
491 : {
492 2 : aGrid.Flush();
493 2 : mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
494 2 : (nBreak) ? aPageColor : aGridColor );
495 2 : nBreakOld = nBreak;
496 : }
497 : }
498 :
499 22566 : bool bDraw = bGrid || nBreakOld; // simple grid only if set so
500 :
501 22566 : bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
502 22566 : bSingle = !bNextYisNextRow; // Hidden
503 252423 : for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
504 : {
505 229857 : if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
506 64 : bSingle = true;
507 : }
508 :
509 22566 : if (bDraw)
510 : {
511 22462 : if ( bSingle && nY<MAXROW )
512 : {
513 85 : SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
514 :
515 85 : nPosX = nScrX;
516 85 : if ( bLayoutRTL )
517 0 : nPosX += nMirrorW - nOneX;
518 :
519 : long nNextX;
520 1261 : for (SCCOL i=nX1; i<=nX2; i++)
521 : {
522 1176 : nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
523 1176 : if (nNextX != nPosX) // visible
524 : {
525 : bool bVOver;
526 1172 : if ( bNextYisNextRow )
527 936 : bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
528 : else
529 : {
530 : bVOver = static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
531 236 : i,nYplus1,nTab,ATTR_MERGE_FLAG))
532 236 : ->IsVerOverlapped()
533 236 : && static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
534 0 : i,nVisY,nTab,ATTR_MERGE_FLAG))
535 236 : ->IsVerOverlapped();
536 : //! nVisY from Array ??
537 : }
538 1172 : if (!bVOver)
539 : {
540 1040 : aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
541 : }
542 : }
543 1176 : nPosX = nNextX;
544 85 : }
545 : }
546 : else
547 : {
548 22377 : aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
549 : }
550 : }
551 : }
552 1474 : }
553 1474 : }
554 :
555 0 : void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
556 : {
557 0 : bPagebreakMode = true;
558 0 : if (!pPageData)
559 0 : return; // not yet initialized -> everything "not printed"
560 :
561 : // mark printed range
562 : // (everything in FillInfo is already initialized to sal_False)
563 :
564 0 : sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount());
565 0 : for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++)
566 : {
567 0 : ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
568 :
569 0 : SCCOL nStartX = std::max( aRange.aStart.Col(), nX1 );
570 0 : SCCOL nEndX = std::min( aRange.aEnd.Col(), nX2 );
571 0 : SCROW nStartY = std::max( aRange.aStart.Row(), nY1 );
572 0 : SCROW nEndY = std::min( aRange.aEnd.Row(), nY2 );
573 :
574 0 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
575 : {
576 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
577 0 : if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
578 0 : pThisRowInfo->nRowNo <= nEndY )
579 : {
580 0 : for (SCCOL nX=nStartX; nX<=nEndX; nX++)
581 0 : pThisRowInfo->pCellInfo[nX+1].bPrinted = true;
582 : }
583 : }
584 : }
585 : }
586 :
587 1552 : void ScOutputData::FindRotated()
588 : {
589 : //! save nRotMax
590 1552 : SCCOL nRotMax = nX2;
591 27614 : for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
592 26062 : if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
593 0 : nRotMax = pRowInfo[nRotY].nRotMaxCol;
594 :
595 26062 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
596 : {
597 24510 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
598 24510 : if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
599 0 : ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
600 0 : ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
601 : {
602 135 : SCROW nY = pThisRowInfo->nRowNo;
603 :
604 1485 : for (SCCOL nX=0; nX<=nRotMax; nX++)
605 : {
606 1350 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
607 1350 : const ScPatternAttr* pPattern = pInfo->pPatternAttr;
608 1350 : const SfxItemSet* pCondSet = pInfo->pConditionSet;
609 :
610 1350 : if ( !pPattern && !mpDoc->ColHidden(nX, nTab) )
611 : {
612 0 : pPattern = mpDoc->GetPattern( nX, nY, nTab );
613 0 : pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
614 : }
615 :
616 1350 : if ( pPattern ) // column isn't hidden
617 : {
618 1350 : sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet );
619 1350 : if (nDir != SC_ROTDIR_NONE)
620 : {
621 534 : pInfo->nRotateDir = nDir;
622 534 : bAnyRotated = true;
623 : }
624 : }
625 : }
626 : }
627 : }
628 1552 : }
629 :
630 0 : static sal_uInt16 lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
631 : {
632 0 : const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
633 0 : const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
634 :
635 0 : sal_uInt16 nRet = SC_ROTDIR_NONE;
636 :
637 0 : long nAttrRotate = pPattern->GetRotateVal( pCondSet );
638 0 : if ( nAttrRotate )
639 : {
640 : SvxRotateMode eRotMode = (SvxRotateMode)static_cast<const SvxRotateModeItem&>(
641 0 : pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
642 :
643 0 : if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
644 0 : nRet = SC_ROTDIR_STANDARD;
645 0 : else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
646 0 : nRet = SC_ROTDIR_CENTER;
647 0 : else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
648 : {
649 0 : long nRot180 = nAttrRotate % 18000; // 1/100 degree
650 0 : if ( nRot180 == 9000 )
651 0 : nRet = SC_ROTDIR_CENTER;
652 0 : else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
653 0 : ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
654 0 : nRet = SC_ROTDIR_LEFT;
655 : else
656 0 : nRet = SC_ROTDIR_RIGHT;
657 : }
658 : }
659 :
660 0 : return nRet;
661 : }
662 :
663 0 : static const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
664 : {
665 0 : const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
666 0 : const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
667 : const SvxBrushItem* pBackground = static_cast<const SvxBrushItem*>(
668 0 : &pPattern->GetItem( ATTR_BACKGROUND, pCondSet ));
669 :
670 0 : sal_uInt16 nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
671 :
672 : // treat CENTER like RIGHT
673 0 : if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER )
674 : {
675 : // text goes to the right -> take background from the left
676 0 : while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
677 0 : pBackground->GetColor().GetTransparency() != 255 )
678 : {
679 0 : --nCol;
680 0 : pPattern = pDoc->GetPattern( nCol, nRow, nTab );
681 0 : pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
682 0 : pBackground = static_cast<const SvxBrushItem*>(&pPattern->GetItem( ATTR_BACKGROUND, pCondSet ));
683 : }
684 : }
685 0 : else if ( nDir == SC_ROTDIR_LEFT )
686 : {
687 : // text goes to the left -> take background from the right
688 0 : while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
689 0 : pBackground->GetColor().GetTransparency() != 255 )
690 : {
691 0 : ++nCol;
692 0 : pPattern = pDoc->GetPattern( nCol, nRow, nTab );
693 0 : pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
694 0 : pBackground = static_cast<const SvxBrushItem*>(&pPattern->GetItem( ATTR_BACKGROUND, pCondSet ));
695 : }
696 : }
697 :
698 0 : return pBackground;
699 : }
700 :
701 21092 : static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
702 : SCCOL nX1, SCCOL nX2, bool bShowProt, bool bPagebreakMode )
703 : {
704 42184 : if ( rFirst.bChanged != rOther.bChanged ||
705 21092 : rFirst.bEmptyBack != rOther.bEmptyBack )
706 400 : return false;
707 :
708 : SCCOL nX;
709 20692 : if ( bShowProt )
710 : {
711 0 : for ( nX=nX1; nX<=nX2; nX++ )
712 : {
713 0 : const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr;
714 0 : const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr;
715 0 : if ( !pPat1 || !pPat2 ||
716 0 : &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
717 0 : return false;
718 : }
719 : }
720 : else
721 : {
722 232613 : for ( nX=nX1; nX<=nX2; nX++ )
723 211943 : if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
724 22 : return false;
725 : }
726 :
727 20670 : if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
728 913 : for ( nX=nX1; nX<=nX2; nX++ )
729 830 : if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
730 0 : return false;
731 :
732 20670 : if ( bPagebreakMode )
733 0 : for ( nX=nX1; nX<=nX2; nX++ )
734 0 : if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
735 0 : return false;
736 :
737 232576 : for ( nX=nX1; nX<=nX2; nX++ )
738 : {
739 211906 : const Color* pCol1 = rFirst.pCellInfo[nX+1].pColorScale.get();
740 211906 : const Color* pCol2 = rOther.pCellInfo[nX+1].pColorScale.get();
741 211906 : if( (pCol1 && !pCol2) || (!pCol1 && pCol2) )
742 0 : return false;
743 :
744 211906 : if (pCol1 && (*pCol1 != *pCol2))
745 0 : return false;
746 :
747 211906 : const ScDataBarInfo* pInfo1 = rFirst.pCellInfo[nX+1].pDataBar.get();
748 211906 : const ScDataBarInfo* pInfo2 = rOther.pCellInfo[nX+1].pDataBar.get();
749 :
750 211906 : if( (pInfo1 && !pInfo2) || (!pInfo1 && pInfo2) )
751 0 : return false;
752 :
753 211906 : if (pInfo1 && (*pInfo1 != *pInfo2))
754 0 : return false;
755 :
756 : // each cell with an icon set should be painted the same way
757 211906 : const ScIconSetInfo* pIconSet1 = rFirst.pCellInfo[nX+1].pIconSet.get();
758 211906 : const ScIconSetInfo* pIconSet2 = rOther.pCellInfo[nX+1].pIconSet.get();
759 :
760 211906 : if(pIconSet1 || pIconSet2)
761 0 : return false;
762 : }
763 :
764 20670 : return true;
765 : }
766 :
767 1474 : void ScOutputData::DrawDocumentBackground()
768 : {
769 1474 : if ( !bSolidBackground )
770 1474 : return;
771 :
772 1474 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
773 1474 : long nOneX = aOnePixel.Width();
774 1474 : long nOneY = aOnePixel.Height();
775 1474 : Rectangle aRect(nScrX - nOneX, nScrY - nOneY, nScrX + nScrW, nScrY + nScrH);
776 1474 : Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
777 1474 : mpDev->SetFillColor(aBgColor);
778 1474 : mpDev->DrawRect(aRect);
779 : }
780 :
781 : namespace {
782 :
783 : static const double lclCornerRectTransparency = 40.0;
784 :
785 0 : void drawDataBars( const ScDataBarInfo* pOldDataBarInfo, OutputDevice* pDev, const Rectangle& rRect)
786 : {
787 0 : long nPosZero = 0;
788 0 : Rectangle aPaintRect = rRect;
789 0 : aPaintRect.Top() += 2;
790 0 : aPaintRect.Bottom() -= 2;
791 0 : aPaintRect.Left() += 2;
792 0 : aPaintRect.Right() -= 2;
793 0 : if(pOldDataBarInfo->mnZero)
794 : {
795 : // need to calculate null point in cell
796 0 : long nLength = aPaintRect.Right() - aPaintRect.Left();
797 0 : nPosZero = static_cast<long>(aPaintRect.Left() + nLength*pOldDataBarInfo->mnZero/100.0);
798 : }
799 : else
800 : {
801 0 : nPosZero = aPaintRect.Left();
802 : }
803 :
804 0 : if(pOldDataBarInfo->mnLength < 0)
805 : {
806 0 : aPaintRect.Right() = nPosZero;
807 0 : long nLength = nPosZero - aPaintRect.Left();
808 0 : aPaintRect.Left() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
809 : }
810 0 : else if(pOldDataBarInfo->mnLength > 0)
811 : {
812 0 : aPaintRect.Left() = nPosZero;
813 0 : long nLength = aPaintRect.Right() - nPosZero;
814 0 : aPaintRect.Right() = nPosZero + static_cast<long>(nLength * pOldDataBarInfo->mnLength/100.0);
815 : }
816 : else
817 0 : return;
818 :
819 0 : if(pOldDataBarInfo->mbGradient)
820 : {
821 0 : pDev->SetLineColor(pOldDataBarInfo->maColor);
822 0 : Gradient aGradient(GradientStyle_LINEAR, pOldDataBarInfo->maColor, COL_TRANSPARENT);
823 :
824 0 : if(pOldDataBarInfo->mnLength < 0)
825 0 : aGradient.SetAngle(2700);
826 : else
827 0 : aGradient.SetAngle(900);
828 :
829 0 : pDev->DrawGradient(aPaintRect, aGradient);
830 :
831 0 : pDev->SetLineColor();
832 : }
833 : else
834 : {
835 0 : pDev->SetFillColor(pOldDataBarInfo->maColor);
836 0 : pDev->DrawRect(aPaintRect);
837 : }
838 :
839 : //draw axis
840 0 : if(pOldDataBarInfo->mnZero && pOldDataBarInfo->mnZero != 100)
841 : {
842 0 : Point aPoint1(nPosZero, rRect.Top());
843 0 : Point aPoint2(nPosZero, rRect.Bottom());
844 0 : LineInfo aLineInfo(LINE_DASH, 1);
845 0 : aLineInfo.SetDashCount( 4 );
846 0 : aLineInfo.SetDistance( 3 );
847 0 : aLineInfo.SetDashLen( 3 );
848 0 : pDev->SetFillColor(pOldDataBarInfo->maAxisColor);
849 0 : pDev->SetLineColor(pOldDataBarInfo->maAxisColor);
850 0 : pDev->DrawLine(aPoint1, aPoint2, aLineInfo);
851 0 : pDev->SetLineColor();
852 0 : pDev->SetFillColor();
853 : }
854 : }
855 :
856 0 : BitmapEx& getIcon( ScIconSetType eType, sal_Int32 nIndex )
857 : {
858 0 : return ScIconSetFormat::getBitmap( eType, nIndex );
859 : }
860 :
861 0 : void drawIconSets( const ScIconSetInfo* pOldIconSetInfo, OutputDevice* pDev, const Rectangle& rRect )
862 : {
863 : //long nSize = 16;
864 0 : ScIconSetType eType = pOldIconSetInfo->eIconSetType;
865 0 : sal_Int32 nIndex = pOldIconSetInfo->nIconIndex;
866 0 : BitmapEx& rIcon = getIcon( eType, nIndex );
867 0 : long aOrigSize = std::max<long>(0,std::min(rRect.GetSize().getWidth() - 4, rRect.GetSize().getHeight() -4));
868 0 : pDev->DrawBitmapEx( Point( rRect.Left() +2, rRect.Top() + 2 ), Size(aOrigSize, aOrigSize), rIcon );
869 0 : }
870 :
871 20291 : void drawCells(const Color* pColor, const SvxBrushItem* pBackground, const Color*& pOldColor, const SvxBrushItem*& pOldBackground,
872 : Rectangle& rRect, long nPosX, long nSignedOneX, OutputDevice* pDev, const ScDataBarInfo* pDataBarInfo, const ScDataBarInfo*& pOldDataBarInfo,
873 : const ScIconSetInfo* pIconSetInfo, const ScIconSetInfo*& pOldIconSetInfo)
874 : {
875 :
876 : // need to paint if old color scale has been used and now
877 : // we have a different color or a style based background
878 : // we can here fall back to pointer comparison
879 20291 : if (pOldColor && (pBackground || pOldColor != pColor || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo))
880 : {
881 0 : rRect.Right() = nPosX-nSignedOneX;
882 0 : if( !pOldColor->GetTransparency() )
883 : {
884 0 : pDev->SetFillColor( *pOldColor );
885 0 : pDev->DrawRect( rRect );
886 : }
887 0 : if( pOldDataBarInfo )
888 0 : drawDataBars( pOldDataBarInfo, pDev, rRect );
889 0 : if( pOldIconSetInfo )
890 0 : drawIconSets( pOldIconSetInfo, pDev, rRect );
891 :
892 0 : rRect.Left() = nPosX - nSignedOneX;
893 : }
894 :
895 20291 : if ( pOldBackground && (pColor ||pBackground != pOldBackground || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo) )
896 : {
897 2210 : rRect.Right() = nPosX-nSignedOneX;
898 2210 : if (pOldBackground) // ==0 if hidden
899 : {
900 2210 : Color aBackCol = pOldBackground->GetColor();
901 2210 : if ( !aBackCol.GetTransparency() ) //! partial transparency?
902 : {
903 221 : pDev->SetFillColor( aBackCol );
904 221 : pDev->DrawRect( rRect );
905 : }
906 : }
907 2210 : if( pOldDataBarInfo )
908 0 : drawDataBars( pOldDataBarInfo, pDev, rRect );
909 2210 : if( pOldIconSetInfo )
910 0 : drawIconSets( pOldIconSetInfo, pDev, rRect );
911 :
912 2210 : rRect.Left() = nPosX - nSignedOneX;
913 : }
914 :
915 20291 : if (!pOldBackground && !pOldColor && (pDataBarInfo || pIconSetInfo))
916 : {
917 0 : rRect.Right() = nPosX -nSignedOneX;
918 0 : rRect.Left() = nPosX - nSignedOneX;
919 : }
920 :
921 20291 : if(pColor)
922 : {
923 : // only update pOldColor if the colors changed
924 0 : if (!pOldColor || *pOldColor != *pColor)
925 0 : pOldColor = pColor;
926 :
927 0 : pOldBackground = NULL;
928 : }
929 20291 : else if(pBackground)
930 : {
931 18393 : pOldBackground = pBackground;
932 18393 : pOldColor = NULL;
933 : }
934 :
935 20291 : if(pDataBarInfo)
936 0 : pOldDataBarInfo = pDataBarInfo;
937 : else
938 20291 : pOldDataBarInfo = NULL;
939 :
940 20291 : if(pIconSetInfo)
941 0 : pOldIconSetInfo = pIconSetInfo;
942 : else
943 20291 : pOldIconSetInfo = NULL;
944 20291 : }
945 :
946 : }
947 :
948 1552 : void ScOutputData::DrawBackground()
949 : {
950 1552 : FindRotated(); //! from the outside?
951 :
952 1552 : Rectangle aRect;
953 1552 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
954 1552 : long nOneX = aOnePixel.Width();
955 1552 : long nOneY = aOnePixel.Height();
956 :
957 1552 : if (bMetaFile)
958 12 : nOneX = nOneY = 0;
959 :
960 1552 : long nLayoutSign = bLayoutRTL ? -1 : 1;
961 1552 : long nSignedOneX = nOneX * nLayoutSign;
962 :
963 1552 : mpDev->SetLineColor();
964 :
965 1552 : bool bShowProt = mbSyntaxMode && mpDoc->IsTabProtected(nTab);
966 1552 : bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
967 :
968 3092 : bool bCellContrast = mbUseStyleColor &&
969 3092 : Application::GetSettings().GetStyleSettings().GetHighContrastMode();
970 :
971 1552 : long nPosY = nScrY;
972 3840 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
973 : {
974 2288 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
975 2288 : long nRowHeight = pThisRowInfo->nHeight;
976 :
977 2288 : if ( pThisRowInfo->bChanged )
978 : {
979 2288 : if ( ( ( pThisRowInfo->bEmptyBack ) || mbSyntaxMode ) && !bDoAll )
980 : {
981 : // nothing
982 : }
983 : else
984 : {
985 : // scan for rows with the same background:
986 1896 : SCSIZE nSkip = 0;
987 45554 : while ( nArrY+nSkip+2<nArrCount &&
988 42184 : lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
989 63276 : nX1, nX2, bShowProt, bPagebreakMode ) )
990 : {
991 20670 : ++nSkip;
992 20670 : nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
993 : }
994 :
995 1896 : long nPosX = nScrX;
996 1896 : if ( bLayoutRTL )
997 1 : nPosX += nMirrorW - nOneX;
998 1896 : aRect = Rectangle( nPosX, nPosY-nOneY, nPosX, nPosY+nRowHeight-nOneY );
999 :
1000 1896 : const SvxBrushItem* pOldBackground = NULL;
1001 : const SvxBrushItem* pBackground;
1002 1896 : const Color* pOldColor = NULL;
1003 1896 : const Color* pColor = NULL;
1004 1896 : const ScDataBarInfo* pOldDataBarInfo = NULL;
1005 1896 : const ScIconSetInfo* pOldIconSetInfo = NULL;
1006 20291 : for (SCCOL nX=nX1; nX<=nX2; nX++)
1007 : {
1008 18395 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1009 :
1010 18395 : if (bCellContrast)
1011 : {
1012 : // high contrast for cell borders and backgrounds -> empty background
1013 0 : pBackground = ScGlobal::GetEmptyBrushItem();
1014 : }
1015 18395 : else if (bShowProt) // show cell protection in syntax mode
1016 : {
1017 0 : const ScPatternAttr* pP = pInfo->pPatternAttr;
1018 0 : if (pP)
1019 : {
1020 : const ScProtectionAttr& rProt = static_cast<const ScProtectionAttr&>(
1021 0 : pP->GetItem(ATTR_PROTECTION));
1022 0 : if (rProt.GetProtection() || rProt.GetHideCell())
1023 0 : pBackground = ScGlobal::GetProtectedBrushItem();
1024 : else
1025 0 : pBackground = ScGlobal::GetEmptyBrushItem();
1026 : }
1027 : else
1028 0 : pBackground = NULL;
1029 : }
1030 : else
1031 18395 : pBackground = pInfo->pBackground;
1032 :
1033 18395 : if ( bPagebreakMode && !pInfo->bPrinted )
1034 0 : pBackground = ScGlobal::GetProtectedBrushItem();
1035 :
1036 36790 : if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1037 18395 : pBackground->GetColor().GetTransparency() != 255 &&
1038 0 : !bCellContrast )
1039 : {
1040 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
1041 0 : pBackground = lcl_FindBackground( mpDoc, nX, nY, nTab );
1042 : }
1043 :
1044 18395 : pColor = pInfo->pColorScale.get();
1045 18395 : const ScDataBarInfo* pDataBarInfo = pInfo->pDataBar.get();
1046 18395 : const ScIconSetInfo* pIconSetInfo = pInfo->pIconSet.get();
1047 18395 : drawCells( pColor, pBackground, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo );
1048 :
1049 18395 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1050 : }
1051 1896 : drawCells( NULL, NULL, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, NULL, pOldDataBarInfo, NULL, pOldIconSetInfo );
1052 :
1053 1896 : nArrY += nSkip;
1054 : }
1055 : }
1056 2288 : nPosY += nRowHeight;
1057 : }
1058 1552 : }
1059 :
1060 1486 : void ScOutputData::DrawShadow()
1061 : {
1062 1486 : DrawExtraShadow( false, false, false, false );
1063 1486 : }
1064 :
1065 1552 : void ScOutputData::DrawExtraShadow(bool bLeft, bool bTop, bool bRight, bool bBottom)
1066 : {
1067 1552 : mpDev->SetLineColor();
1068 :
1069 1552 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1070 1552 : bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1071 1552 : Color aAutoTextColor;
1072 1552 : if ( bCellContrast )
1073 0 : aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1074 :
1075 1552 : long nInitPosX = nScrX;
1076 1552 : if ( bLayoutRTL )
1077 : {
1078 1 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1079 1 : long nOneX = aOnePixel.Width();
1080 1 : nInitPosX += nMirrorW - nOneX;
1081 : }
1082 1552 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1083 :
1084 1552 : long nPosY = nScrY - pRowInfo[0].nHeight;
1085 27614 : for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
1086 : {
1087 26062 : bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
1088 26062 : bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
1089 :
1090 26062 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1091 26062 : long nRowHeight = pThisRowInfo->nHeight;
1092 :
1093 26062 : if ( pThisRowInfo->bChanged && !bSkipY )
1094 : {
1095 23090 : long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
1096 301103 : for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
1097 : {
1098 278013 : bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
1099 278013 : bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
1100 :
1101 834039 : for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertical
1102 : {
1103 : const SvxShadowItem* pAttr = nPass ?
1104 278013 : pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
1105 834039 : pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
1106 556026 : if ( pAttr && !bSkipX )
1107 : {
1108 : ScShadowPart ePart = nPass ?
1109 0 : pThisRowInfo->pCellInfo[nArrX].eVShadowPart :
1110 0 : pThisRowInfo->pCellInfo[nArrX].eHShadowPart;
1111 :
1112 0 : bool bDo = true;
1113 0 : if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
1114 0 : if ( ePart != SC_SHADOW_CORNER )
1115 0 : bDo = false;
1116 :
1117 0 : if (bDo)
1118 : {
1119 0 : long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1120 0 : long nMaxWidth = nThisWidth;
1121 0 : if (!nMaxWidth)
1122 : {
1123 : //! direction must depend on shadow location
1124 0 : SCCOL nWx = nArrX; // nX+1
1125 0 : while (nWx<nX2 && !pRowInfo[0].pCellInfo[nWx+1].nWidth)
1126 0 : ++nWx;
1127 0 : nMaxWidth = pRowInfo[0].pCellInfo[nWx+1].nWidth;
1128 : }
1129 :
1130 : // rectangle is in logical orientation
1131 : Rectangle aRect( nPosX, nPosY,
1132 0 : nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1133 0 : nPosY + pRowInfo[nArrY].nHeight - 1 );
1134 :
1135 0 : long nSize = pAttr->GetWidth();
1136 0 : long nSizeX = (long)(nSize*mnPPTX);
1137 0 : if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1;
1138 0 : long nSizeY = (long)(nSize*mnPPTY);
1139 0 : if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1;
1140 :
1141 0 : nSizeX *= nLayoutSign; // used only to add to rectangle values
1142 :
1143 0 : SvxShadowLocation eLoc = pAttr->GetLocation();
1144 0 : if ( bLayoutRTL )
1145 : {
1146 : // Shadow location is specified as "visual" (right is always right),
1147 : // so the attribute's location value is mirrored here and in FillInfo.
1148 0 : switch (eLoc)
1149 : {
1150 0 : case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
1151 0 : case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
1152 0 : case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
1153 0 : case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
1154 : default:
1155 : {
1156 : // added to avoid warnings
1157 : }
1158 : }
1159 : }
1160 :
1161 0 : if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1162 : ePart == SC_SHADOW_CORNER)
1163 : {
1164 0 : if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1165 0 : aRect.Top() = aRect.Bottom() - nSizeY;
1166 : else
1167 0 : aRect.Bottom() = aRect.Top() + nSizeY;
1168 : }
1169 0 : if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1170 : ePart == SC_SHADOW_CORNER)
1171 : {
1172 0 : if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1173 0 : aRect.Left() = aRect.Right() - nSizeX;
1174 : else
1175 0 : aRect.Right() = aRect.Left() + nSizeX;
1176 : }
1177 0 : if (ePart == SC_SHADOW_HSTART)
1178 : {
1179 0 : if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1180 0 : aRect.Right() -= nSizeX;
1181 : else
1182 0 : aRect.Left() += nSizeX;
1183 : }
1184 0 : if (ePart == SC_SHADOW_VSTART)
1185 : {
1186 0 : if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1187 0 : aRect.Bottom() -= nSizeY;
1188 : else
1189 0 : aRect.Top() += nSizeY;
1190 : }
1191 :
1192 : //! merge rectangles?
1193 0 : mpDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1194 0 : mpDev->DrawRect( aRect );
1195 : }
1196 : }
1197 : }
1198 :
1199 278013 : nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1200 : }
1201 : }
1202 26062 : nPosY += nRowHeight;
1203 : }
1204 1552 : }
1205 :
1206 0 : void ScOutputData::DrawClear()
1207 : {
1208 0 : Rectangle aRect;
1209 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1210 0 : long nOneX = aOnePixel.Width();
1211 0 : long nOneY = aOnePixel.Height();
1212 :
1213 : // (called only for ScGridWindow)
1214 0 : Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1215 :
1216 0 : if (bMetaFile)
1217 0 : nOneX = nOneY = 0;
1218 :
1219 0 : mpDev->SetLineColor();
1220 :
1221 0 : mpDev->SetFillColor( aBgColor );
1222 :
1223 0 : long nPosY = nScrY;
1224 0 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1225 : {
1226 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1227 0 : long nRowHeight = pThisRowInfo->nHeight;
1228 :
1229 0 : if ( pThisRowInfo->bChanged )
1230 : {
1231 : // scan for more rows which must be painted:
1232 0 : SCSIZE nSkip = 0;
1233 0 : while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1234 : {
1235 0 : ++nSkip;
1236 0 : nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1237 : }
1238 :
1239 : aRect = Rectangle( Point( nScrX, nPosY ),
1240 0 : Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1241 0 : mpDev->DrawRect( aRect );
1242 :
1243 0 : nArrY += nSkip;
1244 : }
1245 0 : nPosY += nRowHeight;
1246 : }
1247 0 : }
1248 :
1249 : // Lines
1250 :
1251 19298 : long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1252 : {
1253 19298 : return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1254 : }
1255 :
1256 27614 : long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1257 : {
1258 27614 : return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1259 : }
1260 :
1261 17746 : size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL )
1262 : {
1263 17746 : return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) );
1264 : }
1265 :
1266 1552 : void ScOutputData::DrawFrame()
1267 : {
1268 1552 : sal_uLong nOldDrawMode = mpDev->GetDrawMode();
1269 :
1270 1552 : Color aSingleColor;
1271 1552 : bool bUseSingleColor = false;
1272 1552 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1273 1552 : bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1274 :
1275 : // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1276 : // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1277 : // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1278 : // must be reset and the border colors handled here.
1279 :
1280 1552 : if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) )
1281 : {
1282 0 : mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) );
1283 0 : aSingleColor.SetColor( COL_BLACK );
1284 0 : bUseSingleColor = true;
1285 : }
1286 1552 : else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) )
1287 : {
1288 0 : mpDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) );
1289 0 : aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE
1290 0 : bUseSingleColor = true;
1291 : }
1292 1552 : else if ( bCellContrast )
1293 : {
1294 0 : aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1295 0 : bUseSingleColor = true;
1296 : }
1297 :
1298 1552 : const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1299 :
1300 1552 : if (bAnyRotated)
1301 29 : DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here
1302 :
1303 1552 : long nInitPosX = nScrX;
1304 1552 : if ( bLayoutRTL )
1305 : {
1306 1 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1307 1 : long nOneX = aOnePixel.Width();
1308 1 : nInitPosX += nMirrorW - nOneX;
1309 : }
1310 1552 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1311 :
1312 : // *** set column and row sizes of the frame border array ***
1313 :
1314 1552 : svx::frame::Array& rArray = mrTabInfo.maArray;
1315 1552 : size_t nColCount = rArray.GetColCount();
1316 1552 : size_t nRowCount = rArray.GetRowCount();
1317 :
1318 : // row heights
1319 :
1320 : // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1321 : // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1322 1552 : long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1323 1552 : long nOldSnapY = lclGetSnappedY( *mpDev, nOldPosY, bSnapPixel );
1324 1552 : rArray.SetYOffset( nOldSnapY );
1325 27614 : for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1326 : {
1327 26062 : long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1328 26062 : long nNewSnapY = lclGetSnappedY( *mpDev, nNewPosY, bSnapPixel );
1329 26062 : rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1330 26062 : nOldPosY = nNewPosY;
1331 26062 : nOldSnapY = nNewSnapY;
1332 : }
1333 :
1334 : // column widths
1335 :
1336 : // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1337 : // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1338 1552 : long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth);
1339 1552 : long nOldSnapX = lclGetSnappedX( *mpDev, nOldPosX, bSnapPixel );
1340 : // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1341 1552 : if( !bLayoutRTL )
1342 1551 : rArray.SetXOffset( nOldSnapX );
1343 19298 : for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
1344 : {
1345 17746 : size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL );
1346 17746 : long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign;
1347 17746 : long nNewSnapX = lclGetSnappedX( *mpDev, nNewPosX, bSnapPixel );
1348 17746 : rArray.SetColWidth( nCol, std::abs( nNewSnapX - nOldSnapX ) );
1349 17746 : nOldPosX = nNewPosX;
1350 17746 : nOldSnapX = nNewSnapX;
1351 : }
1352 1552 : if( bLayoutRTL )
1353 1 : rArray.SetXOffset( nOldSnapX );
1354 :
1355 : // *** draw the array ***
1356 :
1357 1552 : size_t nFirstCol = 1;
1358 1552 : size_t nFirstRow = 1;
1359 1552 : size_t nLastCol = nColCount - 2;
1360 1552 : size_t nLastRow = nRowCount - 2;
1361 :
1362 1552 : if( mrTabInfo.mbPageMode )
1363 66 : rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1364 :
1365 : // draw only rows with set RowInfo::bChanged flag
1366 1552 : size_t nRow1 = nFirstRow;
1367 1552 : boost::scoped_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D());
1368 1552 : if (!pProcessor)
1369 1552 : return;
1370 :
1371 4656 : while( nRow1 <= nLastRow )
1372 : {
1373 1552 : while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1374 1552 : if( nRow1 <= nLastRow )
1375 : {
1376 1552 : size_t nRow2 = nRow1;
1377 1552 : while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1378 1552 : rArray.DrawRange( pProcessor.get(), nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
1379 1552 : nRow1 = nRow2 + 1;
1380 : }
1381 : }
1382 1552 : pProcessor.reset();
1383 :
1384 1552 : mpDev->SetDrawMode(nOldDrawMode);
1385 : }
1386 :
1387 : // Line below the cell
1388 :
1389 0 : static const ::editeng::SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc,
1390 : SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nRotDir,
1391 : bool bTopLine )
1392 : {
1393 0 : if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT )
1394 0 : return NULL;
1395 :
1396 0 : bool bFound = false;
1397 0 : while (!bFound)
1398 : {
1399 0 : if ( nRotDir == SC_ROTDIR_LEFT )
1400 : {
1401 : // text to the left -> line from the right
1402 0 : if ( nCol < MAXCOL )
1403 0 : ++nCol;
1404 : else
1405 0 : return NULL; // couldn't find it
1406 : }
1407 : else
1408 : {
1409 : // text to the right -> line from the left
1410 0 : if ( nCol > 0 )
1411 0 : --nCol;
1412 : else
1413 0 : return NULL; // couldn't find it
1414 : }
1415 0 : const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
1416 0 : const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
1417 0 : if ( !pPattern->GetRotateVal( pCondSet ) ||
1418 : static_cast<const SvxRotateModeItem&>(pPattern->GetItem(
1419 0 : ATTR_ROTATE_MODE, pCondSet)).GetValue() == SVX_ROTATE_MODE_STANDARD )
1420 0 : bFound = true;
1421 : }
1422 :
1423 0 : if (bTopLine)
1424 0 : --nRow;
1425 : const ::editeng::SvxBorderLine* pThisBottom;
1426 0 : if ( ValidRow(nRow) )
1427 0 : pThisBottom = static_cast<const SvxBoxItem*>(pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ))->GetBottom();
1428 : else
1429 0 : pThisBottom = NULL;
1430 : const ::editeng::SvxBorderLine* pNextTop;
1431 0 : if ( nRow < MAXROW )
1432 0 : pNextTop = static_cast<const SvxBoxItem*>(pDoc->GetAttr( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
1433 : else
1434 0 : pNextTop = NULL;
1435 :
1436 0 : if ( ScHasPriority( pThisBottom, pNextTop ) )
1437 0 : return pThisBottom;
1438 : else
1439 0 : return pNextTop;
1440 : }
1441 :
1442 0 : static long lcl_getRotate( ScDocument* pDoc, SCTAB nTab, SCCOL nX, SCROW nY )
1443 : {
1444 0 : long nRotate = 0;
1445 :
1446 0 : const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1447 0 : const SfxItemSet* pCondSet = pDoc->GetCondResult( nX, nY, nTab );
1448 :
1449 0 : nRotate = pPattern->GetRotateVal( pCondSet );
1450 :
1451 0 : return nRotate;
1452 : }
1453 :
1454 29 : void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
1455 : {
1456 : //! save nRotMax
1457 29 : SCCOL nRotMax = nX2;
1458 229 : for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1459 200 : if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
1460 0 : nRotMax = pRowInfo[nRotY].nRotMaxCol;
1461 :
1462 : const ScPatternAttr* pPattern;
1463 : const SfxItemSet* pCondSet;
1464 :
1465 29 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1466 29 : bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1467 :
1468 : // color (pForceColor) is determined externally, including DrawMode changes
1469 :
1470 29 : long nInitPosX = nScrX;
1471 29 : if ( bLayoutRTL )
1472 : {
1473 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1474 0 : long nOneX = aOnePixel.Width();
1475 0 : nInitPosX += nMirrorW - nOneX;
1476 : }
1477 29 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1478 :
1479 29 : Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1480 29 : if (bMetaFile)
1481 : {
1482 0 : mpDev->Push();
1483 0 : mpDev->IntersectClipRegion( aClipRect );
1484 : }
1485 : else
1486 29 : mpDev->SetClipRegion( vcl::Region( aClipRect ) );
1487 :
1488 29 : svx::frame::Array& rArray = mrTabInfo.maArray;
1489 29 : boost::scoped_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D( ));
1490 :
1491 29 : long nPosY = nScrY;
1492 200 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1493 : {
1494 : // Rotated is also drawn one line above/below Changed if parts extend into the cell
1495 :
1496 171 : RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1497 171 : RowInfo& rThisRowInfo = pRowInfo[nArrY];
1498 171 : RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1499 :
1500 171 : size_t nRow = static_cast< size_t >( nArrY );
1501 :
1502 171 : long nRowHeight = rThisRowInfo.nHeight;
1503 171 : if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1504 0 : ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1505 0 : ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1506 : {
1507 135 : SCROW nY = rThisRowInfo.nRowNo;
1508 135 : long nPosX = 0;
1509 : SCCOL nX;
1510 1485 : for (nX=0; nX<=nRotMax; nX++)
1511 : {
1512 1350 : if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1513 :
1514 1350 : sal_uInt16 nArrX = nX + 1;
1515 :
1516 1350 : CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX];
1517 1350 : long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1518 1350 : if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1519 0 : !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1520 : {
1521 0 : pPattern = pInfo->pPatternAttr;
1522 0 : pCondSet = pInfo->pConditionSet;
1523 0 : if (!pPattern)
1524 : {
1525 0 : pPattern = mpDoc->GetPattern( nX, nY, nTab );
1526 0 : pInfo->pPatternAttr = pPattern;
1527 0 : pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
1528 0 : pInfo->pConditionSet = pCondSet;
1529 : }
1530 :
1531 : //! LastPattern etc.
1532 :
1533 0 : long nAttrRotate = pPattern->GetRotateVal( pCondSet );
1534 : SvxRotateMode eRotMode = (SvxRotateMode)static_cast<const SvxRotateModeItem&>(
1535 0 : pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1536 :
1537 0 : if ( nAttrRotate )
1538 : {
1539 0 : if (nX<nX1) // compute negative position
1540 : {
1541 0 : nPosX = nInitPosX;
1542 0 : SCCOL nCol = nX1;
1543 0 : while (nCol > nX)
1544 : {
1545 0 : --nCol;
1546 0 : nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
1547 : }
1548 : }
1549 :
1550 : // start position minus 1 so rotated backgrounds suit the border
1551 : // (border is on the grid)
1552 :
1553 0 : long nTop = nPosY - 1;
1554 0 : long nBottom = nPosY + nRowHeight - 1;
1555 0 : long nTopLeft = nPosX - nLayoutSign;
1556 0 : long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign;
1557 0 : long nBotLeft = nTopLeft;
1558 0 : long nBotRight = nTopRight;
1559 :
1560 : // inclusion of the sign here hasn't been decided yet
1561 : // (if not, the extension of the non-rotated background must also be changed)
1562 0 : double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000; // 1/100th degrees
1563 0 : double nCos = cos( nRealOrient );
1564 0 : double nSin = sin( nRealOrient );
1565 : //! restrict !!!
1566 0 : long nSkew = (long) ( nRowHeight * nCos / nSin );
1567 :
1568 0 : switch (eRotMode)
1569 : {
1570 : case SVX_ROTATE_MODE_BOTTOM:
1571 0 : nTopLeft += nSkew;
1572 0 : nTopRight += nSkew;
1573 0 : break;
1574 : case SVX_ROTATE_MODE_CENTER:
1575 0 : nSkew /= 2;
1576 0 : nTopLeft += nSkew;
1577 0 : nTopRight += nSkew;
1578 0 : nBotLeft -= nSkew;
1579 0 : nBotRight -= nSkew;
1580 0 : break;
1581 : case SVX_ROTATE_MODE_TOP:
1582 0 : nBotLeft -= nSkew;
1583 0 : nBotRight -= nSkew;
1584 0 : break;
1585 : default:
1586 : {
1587 : // added to avoid warnings
1588 : }
1589 : }
1590 :
1591 0 : Point aPoints[4];
1592 0 : aPoints[0] = Point( nTopLeft, nTop );
1593 0 : aPoints[1] = Point( nTopRight, nTop );
1594 0 : aPoints[2] = Point( nBotRight, nBottom );
1595 0 : aPoints[3] = Point( nBotLeft, nBottom );
1596 :
1597 0 : const SvxBrushItem* pBackground = pInfo->pBackground;
1598 0 : if (!pBackground)
1599 : pBackground = static_cast<const SvxBrushItem*>( &pPattern->GetItem(
1600 0 : ATTR_BACKGROUND, pCondSet ));
1601 0 : if (bCellContrast)
1602 : {
1603 : // high contrast for cell borders and backgrounds -> empty background
1604 0 : pBackground = ScGlobal::GetEmptyBrushItem();
1605 : }
1606 0 : if(!pInfo->pColorScale)
1607 : {
1608 0 : const Color& rColor = pBackground->GetColor();
1609 0 : if ( rColor.GetTransparency() != 255 )
1610 : {
1611 : // draw background only for the changed row itself
1612 : // (background doesn't extend into other cells).
1613 : // For the borders (rotated and normal), clipping should be
1614 : // set if the row isn't changed, but at least the borders
1615 : // don't cover the cell contents.
1616 0 : if ( rThisRowInfo.bChanged )
1617 : {
1618 0 : Polygon aPoly( 4, aPoints );
1619 :
1620 : // ohne Pen wird bei DrawPolygon rechts und unten
1621 : // ein Pixel weggelassen...
1622 0 : if ( rColor.GetTransparency() == 0 )
1623 0 : mpDev->SetLineColor(rColor);
1624 : else
1625 0 : mpDev->SetLineColor();
1626 0 : mpDev->SetFillColor(rColor);
1627 0 : mpDev->DrawPolygon( aPoly );
1628 : }
1629 : }
1630 : }
1631 : else
1632 : {
1633 0 : Polygon aPoly( 4, aPoints );
1634 0 : const Color* pColor = pInfo->pColorScale.get();
1635 :
1636 : // ohne Pen wird bei DrawPolygon rechts und unten
1637 : // ein Pixel weggelassen...
1638 0 : if ( pColor->GetTransparency() == 0 )
1639 0 : mpDev->SetLineColor(*pColor);
1640 : else
1641 0 : mpDev->SetLineColor();
1642 0 : mpDev->SetFillColor(*pColor);
1643 0 : mpDev->DrawPolygon( aPoly );
1644 :
1645 : }
1646 :
1647 0 : svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
1648 :
1649 0 : if ( nX < nX1 || nX > nX2 ) // Attribute in FillInfo nicht gesetzt
1650 : {
1651 : //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
1652 : const ::editeng::SvxBorderLine* pLeftLine;
1653 : const ::editeng::SvxBorderLine* pTopLine;
1654 : const ::editeng::SvxBorderLine* pRightLine;
1655 : const ::editeng::SvxBorderLine* pBottomLine;
1656 : mpDoc->GetBorderLines( nX, nY, nTab,
1657 0 : &pLeftLine, &pTopLine, &pRightLine, &pBottomLine );
1658 0 : aTopLine.Set( pTopLine, mnPPTY );
1659 0 : aBottomLine.Set( pBottomLine, mnPPTY );
1660 0 : aLeftLine.Set( pLeftLine, mnPPTX );
1661 0 : aRightLine.Set( pRightLine, mnPPTX );
1662 : }
1663 : else
1664 : {
1665 0 : size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1666 0 : aTopLine = rArray.GetCellStyleTop( nCol, nRow );
1667 0 : aBottomLine = rArray.GetCellStyleBottom( nCol, nRow );
1668 0 : aLeftLine = rArray.GetCellStyleLeft( nCol, nRow );
1669 0 : aRightLine = rArray.GetCellStyleRight( nCol, nRow );
1670 : // in RTL mode the array is already mirrored -> swap back left/right borders
1671 0 : if( bLayoutRTL )
1672 0 : std::swap( aLeftLine, aRightLine );
1673 : }
1674 :
1675 0 : const svx::frame::Style noStyle;
1676 : // Horizontal lines
1677 0 : if (aTopLine.Prim() || aTopLine.Secn())
1678 : {
1679 0 : long nUpperRotate = lcl_getRotate( mpDoc, nTab, nX, nY - 1 );
1680 0 : pProcessor->process( svx::frame::CreateBorderPrimitives(
1681 0 : aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine,
1682 : svx::frame::Style(),
1683 : svx::frame::Style(),
1684 : aLeftLine,
1685 : svx::frame::Style(),
1686 : svx::frame::Style(),
1687 : aRightLine,
1688 0 : pForceColor, nUpperRotate, nAttrRotate ) );
1689 : }
1690 :
1691 0 : if (aBottomLine.Prim() || aBottomLine.Secn())
1692 : {
1693 0 : long nLowerRotate = lcl_getRotate( mpDoc, nTab, nX, nY + 1 );
1694 0 : pProcessor->process( svx::frame::CreateBorderPrimitives(
1695 0 : aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine,
1696 : aLeftLine,
1697 : svx::frame::Style(),
1698 : svx::frame::Style(),
1699 : aRightLine,
1700 : svx::frame::Style(),
1701 : svx::frame::Style(),
1702 0 : pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate ) );
1703 : }
1704 :
1705 : // Vertical slanted lines
1706 0 : if (aLeftLine.Prim() || aLeftLine.Secn())
1707 : {
1708 0 : long nLeftRotate = lcl_getRotate( mpDoc, nTab, nX - 1, nY );
1709 0 : pProcessor->process( svx::frame::CreateBorderPrimitives(
1710 : aPoints[0], aPoints[3], aLeftLine,
1711 : aTopLine,
1712 : svx::frame::Style(),
1713 : svx::frame::Style(),
1714 : aBottomLine,
1715 : svx::frame::Style(),
1716 : svx::frame::Style(),
1717 0 : pForceColor, nAttrRotate, nLeftRotate ) );
1718 : }
1719 :
1720 0 : if (aRightLine.Prim() || aRightLine.Secn())
1721 : {
1722 0 : long nRightRotate = lcl_getRotate( mpDoc, nTab, nX + 1, nY );
1723 0 : pProcessor->process( svx::frame::CreateBorderPrimitives(
1724 : aPoints[1], aPoints[2], aRightLine,
1725 : svx::frame::Style(),
1726 : svx::frame::Style(),
1727 : aTopLine,
1728 : svx::frame::Style(),
1729 : svx::frame::Style(),
1730 : aBottomLine,
1731 0 : pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate ) );
1732 : }
1733 : }
1734 : }
1735 1350 : nPosX += nColWidth * nLayoutSign;
1736 : }
1737 :
1738 : // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1739 :
1740 135 : nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1741 1620 : for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1
1742 : {
1743 1485 : sal_uInt16 nArrX = nX + 1;
1744 1485 : CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1745 1485 : if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD &&
1746 0 : !rInfo.bHOverlapped && !rInfo.bVOverlapped )
1747 : {
1748 0 : size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1749 :
1750 : // horizontal: angrenzende Linie verlaengern
1751 : // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1752 0 : sal_uInt16 nDir = rInfo.nRotateDir;
1753 0 : if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() )
1754 : {
1755 0 : svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, true ), mnPPTY );
1756 0 : rArray.SetCellStyleTop( nCol, nRow, aStyle );
1757 0 : if( nRow > 0 )
1758 0 : rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
1759 : }
1760 0 : if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() )
1761 : {
1762 0 : svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, false ), mnPPTY );
1763 0 : rArray.SetCellStyleBottom( nCol, nRow, aStyle );
1764 0 : if( nRow + 1 < rArray.GetRowCount() )
1765 0 : rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
1766 : }
1767 :
1768 : // always remove vertical borders
1769 0 : if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
1770 : {
1771 0 : rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
1772 0 : if( nCol > 0 )
1773 0 : rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
1774 : }
1775 0 : if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
1776 : {
1777 0 : rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
1778 0 : if( nCol + 1 < rArray.GetColCount() )
1779 0 : rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
1780 : }
1781 :
1782 : // remove diagonal borders
1783 0 : rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
1784 0 : rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
1785 : }
1786 : }
1787 : }
1788 171 : nPosY += nRowHeight;
1789 : }
1790 :
1791 29 : pProcessor.reset();
1792 :
1793 29 : if (bMetaFile)
1794 0 : mpDev->Pop();
1795 : else
1796 29 : mpDev->SetClipRegion();
1797 29 : }
1798 :
1799 1581 : drawinglayer::processor2d::BaseProcessor2D* ScOutputData::CreateProcessor2D( )
1800 : {
1801 1581 : mpDoc->InitDrawLayer(mpDoc->GetDocumentShell());
1802 1581 : ScDrawLayer* pDrawLayer = mpDoc->GetDrawLayer();
1803 1581 : if (!pDrawLayer)
1804 0 : return NULL;
1805 :
1806 1581 : basegfx::B2DRange aViewRange;
1807 1581 : SdrPage *pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
1808 : const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
1809 : basegfx::B2DHomMatrix( ),
1810 : mpDev->GetViewTransformation(),
1811 : aViewRange,
1812 : GetXDrawPageForSdrPage( pDrawPage ),
1813 : 0.0,
1814 1581 : uno::Sequence< beans::PropertyValue >() );
1815 :
1816 : return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1817 1581 : *mpDev, aNewViewInfos );
1818 : }
1819 :
1820 : // Printer
1821 :
1822 14808 : vcl::Region ScOutputData::GetChangedAreaRegion()
1823 : {
1824 14808 : vcl::Region aRegion;
1825 14808 : Rectangle aDrawingRect;
1826 14808 : bool bHad(false);
1827 14808 : long nPosY = nScrY;
1828 : SCSIZE nArrY;
1829 :
1830 14808 : aDrawingRect.Left() = nScrX;
1831 14808 : aDrawingRect.Right() = nScrX+nScrW-1;
1832 :
1833 390010 : for(nArrY=1; nArrY+1<nArrCount; nArrY++)
1834 : {
1835 375202 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1836 :
1837 375202 : if(pThisRowInfo->bChanged)
1838 : {
1839 343 : if(!bHad)
1840 : {
1841 244 : aDrawingRect.Top() = nPosY;
1842 244 : bHad = true;
1843 : }
1844 :
1845 343 : aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1846 : }
1847 374859 : else if(bHad)
1848 : {
1849 244 : aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1850 244 : bHad = false;
1851 : }
1852 :
1853 375202 : nPosY += pRowInfo[nArrY].nHeight;
1854 : }
1855 :
1856 14808 : if(bHad)
1857 : {
1858 0 : aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1859 : }
1860 :
1861 14808 : return aRegion;
1862 : }
1863 :
1864 0 : bool ScOutputData::SetChangedClip()
1865 : {
1866 0 : tools::PolyPolygon aPoly;
1867 :
1868 0 : Rectangle aDrawingRect;
1869 0 : aDrawingRect.Left() = nScrX;
1870 0 : aDrawingRect.Right() = nScrX+nScrW-1;
1871 :
1872 0 : bool bHad = false;
1873 0 : long nPosY = nScrY;
1874 : SCSIZE nArrY;
1875 0 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1876 : {
1877 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1878 :
1879 0 : if ( pThisRowInfo->bChanged )
1880 : {
1881 0 : if (!bHad)
1882 : {
1883 0 : aDrawingRect.Top() = nPosY;
1884 0 : bHad = true;
1885 : }
1886 0 : aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1887 : }
1888 0 : else if (bHad)
1889 : {
1890 0 : aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1891 0 : bHad = false;
1892 : }
1893 0 : nPosY += pRowInfo[nArrY].nHeight;
1894 : }
1895 :
1896 0 : if (bHad)
1897 0 : aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1898 :
1899 0 : bool bRet = (aPoly.Count() != 0);
1900 0 : if (bRet)
1901 0 : mpDev->SetClipRegion(vcl::Region(aPoly));
1902 0 : return bRet;
1903 : }
1904 :
1905 14808 : void ScOutputData::FindChanged()
1906 : {
1907 : SCCOL nX;
1908 : SCSIZE nArrY;
1909 :
1910 14808 : bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
1911 14808 : mpDoc->EnableIdle(false);
1912 419626 : for (nArrY=0; nArrY<nArrCount; nArrY++)
1913 404818 : pRowInfo[nArrY].bChanged = false;
1914 :
1915 14808 : bool bProgress = false;
1916 419626 : for (nArrY=0; nArrY<nArrCount; nArrY++)
1917 : {
1918 404818 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1919 4813466 : for (nX=nX1; nX<=nX2; nX++)
1920 : {
1921 4408648 : const ScRefCellValue& rCell = pThisRowInfo->pCellInfo[nX+1].maCell;
1922 :
1923 4408648 : if (rCell.meType != CELLTYPE_FORMULA)
1924 4400676 : continue;
1925 :
1926 7972 : ScFormulaCell* pFCell = rCell.mpFormula;
1927 7972 : if ( !bProgress && pFCell->GetDirty() )
1928 : {
1929 126 : ScProgress::CreateInterpretProgress(mpDoc, true);
1930 126 : bProgress = true;
1931 : }
1932 7972 : if (pFCell->IsRunning())
1933 : // still being interpreted. Skip it.
1934 0 : continue;
1935 :
1936 7972 : (void)pFCell->GetValue();
1937 7972 : if (!pFCell->IsChanged())
1938 : // the result hasn't changed. Skip it.
1939 7385 : continue;
1940 :
1941 587 : pThisRowInfo->bChanged = true;
1942 587 : if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1943 : {
1944 0 : SCSIZE nOverY = nArrY + 1;
1945 0 : while ( nOverY<nArrCount &&
1946 0 : pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
1947 : {
1948 0 : pRowInfo[nOverY].bChanged = true;
1949 0 : ++nOverY;
1950 : }
1951 : }
1952 : }
1953 : }
1954 14808 : if ( bProgress )
1955 126 : ScProgress::DeleteInterpretProgress();
1956 14808 : mpDoc->EnableIdle(bWasIdleEnabled);
1957 14808 : }
1958 :
1959 0 : void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
1960 : SCCOL nRefEndX, SCROW nRefEndY,
1961 : const Color& rColor, bool bHandle )
1962 : {
1963 0 : PutInOrder( nRefStartX, nRefEndX );
1964 0 : PutInOrder( nRefStartY, nRefEndY );
1965 :
1966 0 : if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1967 0 : mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1968 :
1969 0 : if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
1970 0 : nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
1971 : {
1972 0 : long nMinX = nScrX;
1973 0 : long nMinY = nScrY;
1974 0 : long nMaxX = nScrX + nScrW - 1;
1975 0 : long nMaxY = nScrY + nScrH - 1;
1976 0 : if ( bLayoutRTL )
1977 : {
1978 0 : long nTemp = nMinX;
1979 0 : nMinX = nMaxX;
1980 0 : nMaxX = nTemp;
1981 : }
1982 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1983 :
1984 0 : bool bTop = false;
1985 0 : bool bBottom = false;
1986 0 : bool bLeft = false;
1987 0 : bool bRight = false;
1988 :
1989 0 : long nPosY = nScrY;
1990 0 : bool bNoStartY = ( nY1 < nRefStartY );
1991 0 : bool bNoEndY = false;
1992 0 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
1993 : {
1994 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
1995 :
1996 0 : if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
1997 : {
1998 0 : nMinY = nPosY;
1999 0 : bTop = true;
2000 : }
2001 0 : if ( nY==nRefEndY )
2002 : {
2003 0 : nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
2004 0 : bBottom = true;
2005 : }
2006 0 : if ( nY>nRefEndY && bNoEndY )
2007 : {
2008 0 : nMaxY = nPosY-2;
2009 0 : bBottom = true;
2010 : }
2011 0 : bNoStartY = ( nY < nRefStartY );
2012 0 : bNoEndY = ( nY < nRefEndY );
2013 0 : nPosY += pRowInfo[nArrY].nHeight;
2014 : }
2015 :
2016 0 : long nPosX = nScrX;
2017 0 : if ( bLayoutRTL )
2018 0 : nPosX += nMirrorW - 1; // always in pixels
2019 :
2020 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2021 : {
2022 0 : if ( nX==nRefStartX )
2023 : {
2024 0 : nMinX = nPosX;
2025 0 : bLeft = true;
2026 : }
2027 0 : if ( nX==nRefEndX )
2028 : {
2029 0 : nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
2030 0 : bRight = true;
2031 : }
2032 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2033 : }
2034 :
2035 0 : if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2036 : nMaxY >= nMinY )
2037 : {
2038 0 : mpDev->SetLineColor( rColor );
2039 0 : if (bTop && bBottom && bLeft && bRight)
2040 : {
2041 0 : mpDev->SetFillColor();
2042 0 : mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2043 : }
2044 : else
2045 : {
2046 0 : if (bTop)
2047 0 : mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMaxX, nMinY ) );
2048 0 : if (bBottom)
2049 0 : mpDev->DrawLine( Point( nMinX, nMaxY ), Point( nMaxX, nMaxY ) );
2050 0 : if (bLeft)
2051 0 : mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMinX, nMaxY ) );
2052 0 : if (bRight)
2053 0 : mpDev->DrawLine( Point( nMaxX, nMinY ), Point( nMaxX, nMaxY ) );
2054 : }
2055 0 : if ( bHandle && bRight && bBottom )
2056 : {
2057 0 : mpDev->SetLineColor( rColor );
2058 0 : mpDev->SetFillColor( rColor );
2059 :
2060 0 : const sal_Int32 aRadius = 4;
2061 :
2062 0 : sal_Int32 aRectMaxX1 = nMaxX - nLayoutSign * aRadius;
2063 0 : sal_Int32 aRectMaxX2 = nMaxX + nLayoutSign;
2064 0 : sal_Int32 aRectMinX1 = nMinX - nLayoutSign;
2065 0 : sal_Int32 aRectMinX2 = nMinX + nLayoutSign * aRadius;
2066 :
2067 0 : sal_Int32 aRectMaxY1 = nMaxY - aRadius;
2068 0 : sal_Int32 aRectMaxY2 = nMaxY + 1;
2069 0 : sal_Int32 aRectMinY1 = nMinY - 1;
2070 0 : sal_Int32 aRectMinY2 = nMinY + aRadius;
2071 :
2072 : // Draw corner rectangles
2073 0 : Rectangle aLowerRight( aRectMaxX1, aRectMaxY1, aRectMaxX2, aRectMaxY2 );
2074 0 : Rectangle aUpperLeft ( aRectMinX1, aRectMinY1, aRectMinX2, aRectMinY2 );
2075 0 : Rectangle aLowerLeft ( aRectMinX1, aRectMaxY1, aRectMinX2, aRectMaxY2 );
2076 0 : Rectangle aUpperRight( aRectMaxX1, aRectMinY1, aRectMaxX2, aRectMinY2 );
2077 :
2078 0 : mpDev->DrawTransparent( tools::PolyPolygon( Polygon( aLowerRight ) ), lclCornerRectTransparency );
2079 0 : mpDev->DrawTransparent( tools::PolyPolygon( Polygon( aUpperLeft ) ), lclCornerRectTransparency );
2080 0 : mpDev->DrawTransparent( tools::PolyPolygon( Polygon( aLowerLeft ) ), lclCornerRectTransparency );
2081 0 : mpDev->DrawTransparent( tools::PolyPolygon( Polygon( aUpperRight ) ), lclCornerRectTransparency );
2082 : }
2083 : }
2084 : }
2085 0 : }
2086 :
2087 0 : void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
2088 : SCCOL nRefEndX, SCROW nRefEndY,
2089 : const Color& rColor, sal_uInt16 nType )
2090 : {
2091 0 : PutInOrder( nRefStartX, nRefEndX );
2092 0 : PutInOrder( nRefStartY, nRefEndY );
2093 :
2094 0 : if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2095 0 : mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2096 :
2097 0 : if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
2098 0 : nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top
2099 : {
2100 0 : long nMinX = nScrX;
2101 0 : long nMinY = nScrY;
2102 0 : long nMaxX = nScrX+nScrW-1;
2103 0 : long nMaxY = nScrY+nScrH-1;
2104 0 : if ( bLayoutRTL )
2105 : {
2106 0 : long nTemp = nMinX;
2107 0 : nMinX = nMaxX;
2108 0 : nMaxX = nTemp;
2109 : }
2110 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2111 :
2112 0 : bool bTop = false;
2113 0 : bool bBottom = false;
2114 0 : bool bLeft = false;
2115 0 : bool bRight = false;
2116 :
2117 0 : long nPosY = nScrY;
2118 0 : bool bNoStartY = ( nY1 < nRefStartY );
2119 0 : bool bNoEndY = false;
2120 0 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2121 : {
2122 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
2123 :
2124 0 : if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2125 : {
2126 0 : nMinY = nPosY - 1;
2127 0 : bTop = true;
2128 : }
2129 0 : if ( nY==nRefEndY )
2130 : {
2131 0 : nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2132 0 : bBottom = true;
2133 : }
2134 0 : if ( nY>nRefEndY && bNoEndY )
2135 : {
2136 0 : nMaxY = nPosY - 1;
2137 0 : bBottom = true;
2138 : }
2139 0 : bNoStartY = ( nY < nRefStartY );
2140 0 : bNoEndY = ( nY < nRefEndY );
2141 0 : nPosY += pRowInfo[nArrY].nHeight;
2142 : }
2143 :
2144 0 : long nPosX = nScrX;
2145 0 : if ( bLayoutRTL )
2146 0 : nPosX += nMirrorW - 1; // always in pixels
2147 :
2148 0 : for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2149 : {
2150 0 : if ( nX==nRefStartX )
2151 : {
2152 0 : nMinX = nPosX - nLayoutSign;
2153 0 : bLeft = true;
2154 : }
2155 0 : if ( nX==nRefEndX )
2156 : {
2157 0 : nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2158 0 : bRight = true;
2159 : }
2160 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2161 : }
2162 :
2163 0 : if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2164 : nMaxY >= nMinY )
2165 : {
2166 0 : if ( nType == SC_CAT_DELETE_ROWS )
2167 0 : bLeft = bRight = bBottom = false; //! thick lines???
2168 0 : else if ( nType == SC_CAT_DELETE_COLS )
2169 0 : bTop = bBottom = bRight = false; //! thick lines???
2170 :
2171 0 : mpDev->SetLineColor( rColor );
2172 0 : if (bTop && bBottom && bLeft && bRight)
2173 : {
2174 0 : mpDev->SetFillColor();
2175 0 : mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2176 : }
2177 : else
2178 : {
2179 0 : if (bTop)
2180 : {
2181 0 : mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2182 0 : if ( nType == SC_CAT_DELETE_ROWS )
2183 0 : mpDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2184 : }
2185 0 : if (bBottom)
2186 0 : mpDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2187 0 : if (bLeft)
2188 : {
2189 0 : mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2190 0 : if ( nType == SC_CAT_DELETE_COLS )
2191 0 : mpDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2192 : }
2193 0 : if (bRight)
2194 0 : mpDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2195 : }
2196 0 : if ( bLeft && bTop )
2197 : {
2198 0 : mpDev->SetLineColor();
2199 0 : mpDev->SetFillColor( rColor );
2200 0 : mpDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2201 : }
2202 : }
2203 : }
2204 0 : }
2205 :
2206 0 : void ScOutputData::DrawChangeTrack()
2207 : {
2208 0 : ScChangeTrack* pTrack = mpDoc->GetChangeTrack();
2209 0 : ScChangeViewSettings* pSettings = mpDoc->GetChangeViewSettings();
2210 0 : if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2211 0 : return; // nix da oder abgeschaltet
2212 :
2213 0 : ScActionColorChanger aColorChanger(*pTrack);
2214 :
2215 : // Clipping passiert von aussen
2216 : //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2217 :
2218 0 : SCCOL nEndX = nX2;
2219 0 : SCROW nEndY = nY2;
2220 0 : if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung
2221 0 : if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt
2222 0 : ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2223 0 : const ScChangeAction* pAction = pTrack->GetFirst();
2224 0 : while (pAction)
2225 : {
2226 : ScChangeActionType eActionType;
2227 0 : if ( pAction->IsVisible() )
2228 : {
2229 0 : eActionType = pAction->GetType();
2230 0 : const ScBigRange& rBig = pAction->GetBigRange();
2231 0 : if ( rBig.aStart.Tab() == nTab )
2232 : {
2233 0 : ScRange aRange = rBig.MakeRange();
2234 :
2235 0 : if ( eActionType == SC_CAT_DELETE_ROWS )
2236 0 : aRange.aEnd.SetRow( aRange.aStart.Row() );
2237 0 : else if ( eActionType == SC_CAT_DELETE_COLS )
2238 0 : aRange.aEnd.SetCol( aRange.aStart.Col() );
2239 :
2240 0 : if ( aRange.Intersects( aViewRange ) &&
2241 0 : ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2242 : {
2243 0 : aColorChanger.Update( *pAction );
2244 0 : Color aColor( aColorChanger.GetColor() );
2245 0 : DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2246 0 : aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2247 :
2248 : }
2249 : }
2250 0 : if ( eActionType == SC_CAT_MOVE &&
2251 : static_cast<const ScChangeActionMove*>(pAction)->
2252 0 : GetFromRange().aStart.Tab() == nTab )
2253 : {
2254 : ScRange aRange = static_cast<const ScChangeActionMove*>(pAction)->
2255 0 : GetFromRange().MakeRange();
2256 0 : if ( aRange.Intersects( aViewRange ) &&
2257 0 : ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2258 : {
2259 0 : aColorChanger.Update( *pAction );
2260 0 : Color aColor( aColorChanger.GetColor() );
2261 0 : DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2262 0 : aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2263 : }
2264 : }
2265 : }
2266 :
2267 0 : pAction = pAction->GetNext();
2268 0 : }
2269 : }
2270 :
2271 : //TODO: moggi Need to check if this can't be written simpler
2272 1474 : void ScOutputData::DrawNoteMarks()
2273 : {
2274 :
2275 1474 : bool bFirst = true;
2276 :
2277 1474 : long nInitPosX = nScrX;
2278 1474 : if ( bLayoutRTL )
2279 1 : nInitPosX += nMirrorW - 1; // always in pixels
2280 1474 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2281 :
2282 1474 : long nPosY = nScrY;
2283 24040 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2284 : {
2285 22566 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2286 22566 : if ( pThisRowInfo->bChanged )
2287 : {
2288 22566 : long nPosX = nInitPosX;
2289 252867 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2290 : {
2291 230301 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2292 230301 : bool bIsMerged = false;
2293 :
2294 230301 : if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2295 : {
2296 : // find start of merged cell
2297 0 : bIsMerged = true;
2298 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
2299 0 : SCCOL nMergeX = nX;
2300 0 : SCROW nMergeY = nY;
2301 0 : mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2302 : // use origin's pCell for NotePtr test below
2303 : }
2304 :
2305 230315 : if ( mpDoc->GetNote(nX, pRowInfo[nArrY].nRowNo, nTab) && ( bIsMerged ||
2306 14 : ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2307 : {
2308 7 : if (bFirst)
2309 : {
2310 6 : mpDev->SetLineColor(COL_WHITE);
2311 :
2312 6 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2313 6 : if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2314 0 : mpDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2315 : else
2316 6 : mpDev->SetFillColor(COL_LIGHTRED);
2317 :
2318 6 : bFirst = false;
2319 : }
2320 :
2321 7 : long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2322 7 : if ( bIsMerged || pInfo->bMerged )
2323 : {
2324 : // if merged, add widths of all cells
2325 0 : SCCOL nNextX = nX + 1;
2326 0 : while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2327 : {
2328 0 : nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2329 0 : ++nNextX;
2330 : }
2331 : }
2332 7 : if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2333 7 : mpDev->DrawRect( Rectangle( nMarkX-5*nLayoutSign,nPosY,nMarkX+1*nLayoutSign,nPosY+6 ) );
2334 : }
2335 :
2336 230301 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2337 : }
2338 : }
2339 22566 : nPosY += pThisRowInfo->nHeight;
2340 : }
2341 1474 : }
2342 :
2343 66 : void ScOutputData::AddPDFNotes()
2344 : {
2345 66 : vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
2346 66 : if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2347 132 : return;
2348 :
2349 0 : long nInitPosX = nScrX;
2350 0 : if ( bLayoutRTL )
2351 : {
2352 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
2353 0 : long nOneX = aOnePixel.Width();
2354 0 : nInitPosX += nMirrorW - nOneX;
2355 : }
2356 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2357 :
2358 0 : long nPosY = nScrY;
2359 0 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2360 : {
2361 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2362 0 : if ( pThisRowInfo->bChanged )
2363 : {
2364 0 : long nPosX = nInitPosX;
2365 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2366 : {
2367 0 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2368 0 : bool bIsMerged = false;
2369 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
2370 0 : SCCOL nMergeX = nX;
2371 0 : SCROW nMergeY = nY;
2372 :
2373 0 : if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2374 : {
2375 : // find start of merged cell
2376 0 : bIsMerged = true;
2377 0 : mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2378 : // use origin's pCell for NotePtr test below
2379 : }
2380 :
2381 0 : if ( mpDoc->GetNote(nMergeX, nMergeY, nTab) && ( bIsMerged ||
2382 0 : ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2383 : {
2384 0 : long nNoteWidth = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2385 0 : long nNoteHeight = (long)( SC_CLIPMARK_SIZE * mnPPTY );
2386 :
2387 0 : long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign;
2388 0 : if ( bIsMerged || pInfo->bMerged )
2389 : {
2390 : // if merged, add widths of all cells
2391 0 : SCCOL nNextX = nX + 1;
2392 0 : while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2393 : {
2394 0 : nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2395 0 : ++nNextX;
2396 : }
2397 : }
2398 0 : if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2399 : {
2400 0 : Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2401 0 : const ScPostIt* pNote = mpDoc->GetNote(nMergeX, nMergeY, nTab);
2402 :
2403 : // Note title is the cell address (as on printed note pages)
2404 0 : ScAddress aAddress( nMergeX, nMergeY, nTab );
2405 0 : OUString aTitle(aAddress.Format(SCA_VALID, mpDoc, mpDoc->GetAddressConvention()));
2406 :
2407 : // Content has to be a simple string without line breaks
2408 0 : OUString aContent = pNote->GetText();
2409 0 : aContent = aContent.replaceAll("\n", " ");
2410 :
2411 0 : vcl::PDFNote aNote;
2412 0 : aNote.Title = aTitle;
2413 0 : aNote.Contents = aContent;
2414 0 : pPDFData->CreateNote( aNoteRect, aNote );
2415 : }
2416 : }
2417 :
2418 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2419 : }
2420 : }
2421 0 : nPosY += pThisRowInfo->nHeight;
2422 : }
2423 : }
2424 :
2425 1474 : void ScOutputData::DrawClipMarks()
2426 : {
2427 1474 : if (!bAnyClipped)
2428 2895 : return;
2429 :
2430 53 : Color aArrowFillCol( COL_LIGHTRED );
2431 :
2432 53 : sal_uLong nOldDrawMode = mpDev->GetDrawMode();
2433 53 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2434 53 : if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2435 : {
2436 : // use DrawMode to change the arrow's outline color
2437 0 : mpDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2438 : // use text color also for the fill color
2439 0 : aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2440 : }
2441 :
2442 53 : long nInitPosX = nScrX;
2443 53 : if ( bLayoutRTL )
2444 0 : nInitPosX += nMirrorW - 1; // always in pixels
2445 53 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2446 :
2447 53 : Rectangle aCellRect;
2448 53 : long nPosY = nScrY;
2449 652 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2450 : {
2451 599 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2452 599 : if ( pThisRowInfo->bChanged )
2453 : {
2454 599 : SCROW nY = pThisRowInfo->nRowNo;
2455 599 : long nPosX = nInitPosX;
2456 7457 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2457 : {
2458 6858 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2459 6858 : if (pInfo->nClipMark)
2460 : {
2461 437 : if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2462 : {
2463 : // merge origin may be outside of visible area - use document functions
2464 :
2465 0 : SCCOL nOverX = nX;
2466 0 : SCROW nOverY = nY;
2467 0 : long nStartPosX = nPosX;
2468 0 : long nStartPosY = nPosY;
2469 :
2470 0 : while ( nOverX > 0 && ( static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
2471 0 : nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2472 : {
2473 0 : --nOverX;
2474 0 : nStartPosX -= nLayoutSign * (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2475 : }
2476 :
2477 0 : while ( nOverY > 0 && ( static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr(
2478 0 : nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2479 : {
2480 0 : --nOverY;
2481 0 : nStartPosY -= nLayoutSign * (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2482 : }
2483 :
2484 0 : long nOutWidth = (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2485 0 : long nOutHeight = (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2486 :
2487 : const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(
2488 0 : mpDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE ));
2489 0 : SCCOL nCountX = pMerge->GetColMerge();
2490 0 : for (SCCOL i=1; i<nCountX; i++)
2491 0 : nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2492 0 : SCROW nCountY = pMerge->GetRowMerge();
2493 0 : nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2494 :
2495 0 : if ( bLayoutRTL )
2496 0 : nStartPosX -= nOutWidth - 1;
2497 0 : aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2498 : }
2499 : else
2500 : {
2501 437 : long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2502 437 : long nOutHeight = pThisRowInfo->nHeight;
2503 :
2504 437 : if ( pInfo->bMerged && pInfo->pPatternAttr )
2505 : {
2506 0 : SCCOL nOverX = nX;
2507 0 : SCROW nOverY = nY;
2508 : const ScMergeAttr* pMerge =
2509 0 : static_cast<const ScMergeAttr*>(&pInfo->pPatternAttr->GetItem(ATTR_MERGE));
2510 0 : SCCOL nCountX = pMerge->GetColMerge();
2511 0 : for (SCCOL i=1; i<nCountX; i++)
2512 0 : nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2513 0 : SCROW nCountY = pMerge->GetRowMerge();
2514 0 : nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2515 : }
2516 :
2517 437 : long nStartPosX = nPosX;
2518 437 : if ( bLayoutRTL )
2519 0 : nStartPosX -= nOutWidth - 1;
2520 : // #i80447# create aCellRect from two points in case nOutWidth is 0
2521 : aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2522 437 : Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2523 : }
2524 :
2525 437 : aCellRect.Bottom() -= 1; // don't paint over the cell grid
2526 437 : if ( bLayoutRTL )
2527 0 : aCellRect.Left() += 1;
2528 : else
2529 437 : aCellRect.Right() -= 1;
2530 :
2531 437 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2532 437 : Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2533 :
2534 437 : if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2535 : {
2536 : // visually left
2537 52 : Rectangle aMarkRect = aCellRect;
2538 52 : aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2539 52 : SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, true );
2540 : }
2541 437 : if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2542 : {
2543 : // visually right
2544 386 : Rectangle aMarkRect = aCellRect;
2545 386 : aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2546 386 : SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, false );
2547 : }
2548 : }
2549 6858 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2550 : }
2551 : }
2552 599 : nPosY += pThisRowInfo->nHeight;
2553 : }
2554 :
2555 53 : mpDev->SetDrawMode(nOldDrawMode);
2556 228 : }
2557 :
2558 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|