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