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