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/brshitem.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 "cell.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<rtl::OUString>& rUsers;
95 : rtl::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<rtl::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 1 : 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 1 : 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 2 : mpTargetPaintWindow(0) // #i74769# use SdrPaintWindow direct
211 : {
212 1 : if (pZoomX)
213 0 : aZoomX = *pZoomX;
214 : else
215 1 : aZoomX = Fraction(1,1);
216 1 : if (pZoomY)
217 0 : aZoomY = *pZoomY;
218 : else
219 1 : aZoomY = Fraction(1,1);
220 :
221 1 : nVisX1 = nX1;
222 1 : nVisY1 = nY1;
223 1 : nVisX2 = nX2;
224 1 : nVisY2 = nY2;
225 1 : mpDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
226 :
227 1 : nScrW = 0;
228 5 : for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
229 4 : nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
230 :
231 1 : nMirrorW = nScrW;
232 :
233 1 : nScrH = 0;
234 28 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
235 27 : nScrH += pRowInfo[nArrY].nHeight;
236 :
237 1 : bTabProtected = mpDoc->IsTabProtected( nTab );
238 1 : nTabTextDirection = mpDoc->GetEditTextDirection( nTab );
239 1 : bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
240 1 : }
241 :
242 1 : ScOutputData::~ScOutputData()
243 : {
244 1 : delete pValueColor;
245 1 : delete pTextColor;
246 1 : delete pFormulaColor;
247 1 : }
248 :
249 0 : void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
250 : {
251 : // use pContentDev instead of pDev where used
252 :
253 0 : if ( mpRefDevice == mpDev )
254 0 : mpRefDevice = pContentDev;
255 0 : if ( pFmtDevice == mpDev )
256 0 : pFmtDevice = pContentDev;
257 0 : mpDev = pContentDev;
258 0 : }
259 :
260 0 : void ScOutputData::SetMirrorWidth( long nNew )
261 : {
262 0 : nMirrorW = nNew;
263 0 : }
264 :
265 0 : void ScOutputData::SetGridColor( const Color& rColor )
266 : {
267 0 : aGridColor = rColor;
268 0 : }
269 :
270 0 : void ScOutputData::SetMarkClipped( sal_Bool bSet )
271 : {
272 0 : bMarkClipped = bSet;
273 0 : }
274 :
275 1 : void ScOutputData::SetShowNullValues( sal_Bool bSet )
276 : {
277 1 : mbShowNullValues = bSet;
278 1 : }
279 :
280 1 : void ScOutputData::SetShowFormulas( sal_Bool bSet )
281 : {
282 1 : mbShowFormulas = bSet;
283 1 : }
284 :
285 0 : void ScOutputData::SetShowSpellErrors( sal_Bool bSet )
286 : {
287 0 : bShowSpellErrors = bSet;
288 0 : }
289 :
290 1 : void ScOutputData::SetSnapPixel( sal_Bool bSet )
291 : {
292 1 : bSnapPixel = bSet;
293 1 : }
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 1 : void ScOutputData::SetMetaFileMode( sal_Bool bNewMode )
303 : {
304 1 : bMetaFile = bNewMode;
305 1 : }
306 :
307 0 : void ScOutputData::SetSingleGrid( sal_Bool bNewMode )
308 : {
309 0 : bSingleGrid = bNewMode;
310 0 : }
311 :
312 0 : void ScOutputData::SetSyntaxMode( sal_Bool bNewMode )
313 : {
314 0 : mbSyntaxMode = bNewMode;
315 0 : 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 0 : }
323 :
324 0 : 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 0 : ScBreakType nBreak = BREAK_NONE;
332 0 : ScBreakType nBreakOld = BREAK_NONE;
333 :
334 : sal_Bool bSingle;
335 0 : Color aPageColor;
336 0 : Color aManualColor;
337 :
338 0 : if (bPagebreakMode)
339 0 : 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 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
345 0 : long nOneX = aOnePixel.Width();
346 0 : long nOneY = aOnePixel.Height();
347 0 : if (bMetaFile)
348 0 : nOneX = nOneY = 1;
349 :
350 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
351 0 : long nSignedOneX = nOneX * nLayoutSign;
352 :
353 0 : if ( eType == OUTTYPE_WINDOW )
354 : {
355 0 : const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
356 0 : aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
357 0 : aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
358 : }
359 : else
360 : {
361 0 : aPageColor = aGridColor;
362 0 : aManualColor = aGridColor;
363 : }
364 :
365 0 : mpDev->SetLineColor( aGridColor );
366 0 : ScGridMerger aGrid( mpDev, nOneX, nOneY );
367 :
368 : //
369 : // Vertikale Linien
370 : //
371 :
372 0 : nPosX = nScrX;
373 0 : if ( bLayoutRTL )
374 0 : nPosX += nMirrorW - nOneX;
375 :
376 0 : for (nX=nX1; nX<=nX2; nX++)
377 : {
378 0 : SCCOL nXplus1 = nX+1;
379 0 : SCCOL nXplus2 = nX+2;
380 0 : sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
381 0 : if (nWidth)
382 : {
383 0 : nPosX += nWidth * nLayoutSign;
384 :
385 0 : if ( bPage )
386 : {
387 : // Seitenumbrueche auch in ausgeblendeten suchen
388 0 : SCCOL nCol = nXplus1;
389 0 : while (nCol <= MAXCOL)
390 : {
391 0 : nBreak = mpDoc->HasColBreak(nCol, nTab);
392 0 : bool bHidden = mpDoc->ColHidden(nCol, nTab);
393 :
394 0 : if ( nBreak || !bHidden )
395 0 : break;
396 0 : ++nCol;
397 : }
398 :
399 0 : if (nBreak != nBreakOld)
400 : {
401 0 : aGrid.Flush();
402 : mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
403 0 : nBreak ? aPageColor : aGridColor );
404 0 : nBreakOld = nBreak;
405 : }
406 : }
407 :
408 0 : sal_Bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
409 :
410 0 : sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
411 0 : bSingle = bSingleGrid; //! in Fillinfo holen !!!!!
412 0 : if ( nX<MAXCOL && !bSingle )
413 : {
414 0 : bSingle = ( nWidthXplus2 == 0 );
415 0 : for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
416 : {
417 0 : if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
418 0 : bSingle = sal_True;
419 0 : if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
420 0 : bSingle = sal_True;
421 : }
422 : }
423 :
424 0 : if (bDraw)
425 : {
426 0 : if ( nX<MAXCOL && bSingle )
427 : {
428 0 : SCCOL nVisX = nXplus1;
429 0 : while ( nVisX < MAXCOL && !mpDoc->GetColWidth(nVisX,nTab) )
430 0 : ++nVisX;
431 :
432 0 : nPosY = nScrY;
433 : long nNextY;
434 0 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
435 : {
436 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
437 0 : nNextY = nPosY + pThisRowInfo->nHeight;
438 :
439 0 : sal_Bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
440 0 : if (!bHOver)
441 : {
442 0 : if (nWidthXplus2)
443 0 : 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 0 : if (pThisRowInfo->bChanged && !bHOver)
460 : {
461 0 : aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
462 : }
463 0 : nPosY = nNextY;
464 0 : }
465 : }
466 : else
467 : {
468 0 : aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
469 : }
470 : }
471 : }
472 : }
473 :
474 : //
475 : // Horizontale Linien
476 : //
477 :
478 0 : bool bHiddenRow = true;
479 0 : SCROW nHiddenEndRow = -1;
480 0 : nPosY = nScrY;
481 0 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
482 : {
483 0 : SCSIZE nArrYplus1 = nArrY+1;
484 0 : nY = pRowInfo[nArrY].nRowNo;
485 0 : SCROW nYplus1 = nY+1;
486 0 : nPosY += pRowInfo[nArrY].nHeight;
487 :
488 0 : if (pRowInfo[nArrY].bChanged)
489 : {
490 0 : if ( bPage )
491 : {
492 0 : for (SCROW i = nYplus1; i <= MAXROW; ++i)
493 : {
494 0 : if (i > nHiddenEndRow)
495 0 : 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 0 : nBreak = mpDoc->HasRowBreak(i, nTab);
504 0 : if (!bHiddenRow || nBreak)
505 0 : break;
506 : }
507 :
508 0 : if (nBreakOld != nBreak)
509 : {
510 0 : aGrid.Flush();
511 : mpDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
512 0 : (nBreak) ? aPageColor : aGridColor );
513 0 : nBreakOld = nBreak;
514 : }
515 : }
516 :
517 0 : sal_Bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
518 :
519 0 : sal_Bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
520 0 : bSingle = !bNextYisNextRow; // Hidden
521 0 : for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
522 : {
523 0 : if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
524 0 : bSingle = sal_True;
525 : }
526 :
527 0 : if (bDraw)
528 : {
529 0 : if ( bSingle && nY<MAXROW )
530 : {
531 0 : SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
532 :
533 0 : nPosX = nScrX;
534 0 : if ( bLayoutRTL )
535 0 : nPosX += nMirrorW - nOneX;
536 :
537 : long nNextX;
538 0 : for (SCCOL i=nX1; i<=nX2; i++)
539 : {
540 0 : nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
541 0 : if (nNextX != nPosX) // sichtbar
542 : {
543 : sal_Bool bVOver;
544 0 : if ( bNextYisNextRow )
545 0 : bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
546 : else
547 : {
548 : bVOver = ((ScMergeFlagAttr*)mpDoc->GetAttr(
549 0 : i,nYplus1,nTab,ATTR_MERGE_FLAG))
550 0 : ->IsVerOverlapped()
551 : && ((ScMergeFlagAttr*)mpDoc->GetAttr(
552 0 : i,nVisY,nTab,ATTR_MERGE_FLAG))
553 0 : ->IsVerOverlapped();
554 : //! nVisY aus Array ??
555 : }
556 0 : if (!bVOver)
557 : {
558 0 : aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
559 : }
560 : }
561 0 : nPosX = nNextX;
562 0 : }
563 : }
564 : else
565 : {
566 0 : aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
567 : }
568 : }
569 : }
570 0 : }
571 0 : }
572 :
573 : // ----------------------------------------------------------------------------
574 :
575 0 : void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
576 : {
577 0 : bPagebreakMode = sal_True;
578 0 : if (!pPageData)
579 0 : 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 = Max( aRange.aStart.Col(), nX1 );
590 0 : SCCOL nEndX = Min( aRange.aEnd.Col(), nX2 );
591 0 : SCROW nStartY = Max( aRange.aStart.Row(), nY1 );
592 0 : SCROW nEndY = 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 : 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 1 : void ScOutputData::FindRotated()
608 : {
609 : //! nRotMax speichern
610 1 : SCCOL nRotMax = nX2;
611 30 : for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
612 29 : if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
613 0 : nRotMax = pRowInfo[nRotY].nRotMaxCol;
614 :
615 29 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
616 : {
617 28 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
618 28 : 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 0 : SCROW nY = pThisRowInfo->nRowNo;
623 :
624 0 : for (SCCOL nX=0; nX<=nRotMax; nX++)
625 : {
626 0 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
627 0 : const ScPatternAttr* pPattern = pInfo->pPatternAttr;
628 0 : const SfxItemSet* pCondSet = pInfo->pConditionSet;
629 :
630 0 : 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 0 : if ( pPattern ) // Spalte nicht ausgeblendet
637 : {
638 0 : sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet );
639 0 : if (nDir != SC_ROTDIR_NONE)
640 : {
641 0 : pInfo->nRotateDir = nDir;
642 0 : bAnyRotated = sal_True;
643 : }
644 : }
645 : }
646 : }
647 : }
648 1 : }
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 : ( 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 0 : static sal_Bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
726 : SCCOL nX1, SCCOL nX2, sal_Bool bShowProt, sal_Bool bPagebreakMode )
727 : {
728 0 : if ( rFirst.bChanged != rOther.bChanged ||
729 : rFirst.bEmptyBack != rOther.bEmptyBack )
730 0 : return false;
731 :
732 : SCCOL nX;
733 0 : 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 0 : for ( nX=nX1; nX<=nX2; nX++ )
747 0 : if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
748 0 : return false;
749 : }
750 :
751 0 : if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
752 0 : for ( nX=nX1; nX<=nX2; nX++ )
753 0 : if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
754 0 : return false;
755 :
756 0 : if ( bPagebreakMode )
757 0 : for ( nX=nX1; nX<=nX2; nX++ )
758 0 : if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
759 0 : return false;
760 :
761 0 : for ( nX=nX1; nX<=nX2; nX++ )
762 : {
763 0 : const Color* pCol1 = rFirst.pCellInfo[nX+1].pColorScale;
764 0 : const Color* pCol2 = rOther.pCellInfo[nX+1].pColorScale;
765 0 : if( (pCol1 && !pCol2) || (!pCol1 && pCol2) )
766 0 : return false;
767 :
768 0 : if (pCol1 && (*pCol1 != *pCol2))
769 0 : return false;
770 :
771 0 : const ScDataBarInfo* pInfo1 = rFirst.pCellInfo[nX+1].pDataBar;
772 0 : const ScDataBarInfo* pInfo2 = rOther.pCellInfo[nX+1].pDataBar;
773 :
774 0 : if( (pInfo1 && !pInfo2) || (!pInfo1 && pInfo2) )
775 0 : return false;
776 :
777 0 : if (pInfo1 && (*pInfo1 != *pInfo2))
778 0 : return false;
779 :
780 : // each cell with an icon set should be painted the same way
781 0 : const ScIconSetInfo* pIconSet1 = rFirst.pCellInfo[nX+1].pIconSet;
782 0 : const ScIconSetInfo* pIconSet2 = rOther.pCellInfo[nX+1].pIconSet;
783 :
784 0 : if(pIconSet1 || pIconSet2)
785 0 : return false;
786 : }
787 :
788 0 : return sal_True;
789 : }
790 :
791 0 : void ScOutputData::DrawDocumentBackground()
792 : {
793 0 : if ( !bSolidBackground )
794 0 : return;
795 :
796 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
797 0 : long nOneX = aOnePixel.Width();
798 0 : long nOneY = aOnePixel.Height();
799 0 : Rectangle aRect(nScrX - nOneX, nScrY - nOneY, nScrX + nScrW, nScrY + nScrH);
800 0 : Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
801 0 : mpDev->SetFillColor(aBgColor);
802 0 : 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 0 : 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 0 : 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 0 : if ( pOldBackground && (pColor ||pBackground != pOldBackground || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo) )
917 : {
918 0 : rRect.Right() = nPosX-nSignedOneX;
919 0 : if (pOldBackground) // ==0 if hidden
920 : {
921 0 : Color aBackCol = pOldBackground->GetColor();
922 0 : if ( !aBackCol.GetTransparency() ) //! partial transparency?
923 : {
924 0 : pDev->SetFillColor( aBackCol );
925 0 : pDev->DrawRect( rRect );
926 : }
927 : }
928 0 : if( pOldDataBarInfo )
929 0 : drawDataBars( pOldDataBarInfo, pDev, rRect );
930 0 : if( pOldIconSetInfo )
931 0 : drawIconSets( pOldIconSetInfo, pDev, rRect );
932 :
933 0 : rRect.Left() = nPosX - nSignedOneX;
934 : }
935 :
936 0 : if (!pOldBackground && !pOldColor && (pDataBarInfo || pIconSetInfo))
937 : {
938 0 : rRect.Right() = nPosX -nSignedOneX;
939 0 : rRect.Left() = nPosX - nSignedOneX;
940 : }
941 :
942 0 : 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 0 : else if(pBackground)
951 : {
952 0 : pOldBackground = pBackground;
953 0 : pOldColor = NULL;
954 : }
955 :
956 0 : if(pDataBarInfo)
957 0 : pOldDataBarInfo = pDataBarInfo;
958 : else
959 0 : pOldDataBarInfo = NULL;
960 :
961 0 : if(pIconSetInfo)
962 0 : pOldIconSetInfo = pIconSetInfo;
963 : else
964 0 : pOldIconSetInfo = NULL;
965 0 : }
966 :
967 : }
968 :
969 1 : void ScOutputData::DrawBackground()
970 : {
971 1 : FindRotated(); //! von aussen ?
972 :
973 1 : Rectangle aRect;
974 1 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
975 1 : long nOneX = aOnePixel.Width();
976 1 : long nOneY = aOnePixel.Height();
977 :
978 1 : if (bMetaFile)
979 1 : nOneX = nOneY = 0;
980 :
981 1 : long nLayoutSign = bLayoutRTL ? -1 : 1;
982 1 : long nSignedOneX = nOneX * nLayoutSign;
983 :
984 1 : mpDev->SetLineColor();
985 :
986 1 : sal_Bool bShowProt = mbSyntaxMode && mpDoc->IsTabProtected(nTab);
987 1 : sal_Bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
988 :
989 : sal_Bool bCellContrast = mbUseStyleColor &&
990 1 : Application::GetSettings().GetStyleSettings().GetHighContrastMode();
991 :
992 1 : long nPosY = nScrY;
993 28 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
994 : {
995 27 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
996 27 : long nRowHeight = pThisRowInfo->nHeight;
997 :
998 27 : if ( pThisRowInfo->bChanged )
999 : {
1000 27 : if ( ( ( pThisRowInfo->bEmptyBack ) || mbSyntaxMode ) && !bDoAll )
1001 : {
1002 : // nichts
1003 : }
1004 : else
1005 : {
1006 : // scan for rows with the same background:
1007 0 : SCSIZE nSkip = 0;
1008 0 : while ( nArrY+nSkip+2<nArrCount &&
1009 0 : lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
1010 0 : nX1, nX2, bShowProt, bPagebreakMode ) )
1011 : {
1012 0 : ++nSkip;
1013 0 : nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1014 : }
1015 :
1016 0 : long nPosX = nScrX;
1017 0 : if ( bLayoutRTL )
1018 0 : nPosX += nMirrorW - nOneX;
1019 0 : aRect = Rectangle( nPosX, nPosY-nOneY, nPosX, nPosY+nRowHeight-nOneY );
1020 :
1021 0 : const SvxBrushItem* pOldBackground = NULL;
1022 : const SvxBrushItem* pBackground;
1023 0 : const Color* pOldColor = NULL;
1024 0 : const Color* pColor = NULL;
1025 0 : const ScDataBarInfo* pOldDataBarInfo = NULL;
1026 0 : const ScIconSetInfo* pOldIconSetInfo = NULL;
1027 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
1028 : {
1029 0 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1030 :
1031 0 : if (bCellContrast)
1032 : {
1033 : // high contrast for cell borders and backgrounds -> empty background
1034 0 : pBackground = ScGlobal::GetEmptyBrushItem();
1035 : }
1036 0 : 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 0 : pBackground = pInfo->pBackground;
1053 :
1054 0 : if ( bPagebreakMode && !pInfo->bPrinted )
1055 0 : pBackground = ScGlobal::GetProtectedBrushItem();
1056 :
1057 0 : if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1058 0 : 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 0 : pColor = pInfo->pColorScale;
1066 0 : const ScDataBarInfo* pDataBarInfo = pInfo->pDataBar;
1067 0 : const ScIconSetInfo* pIconSetInfo = pInfo->pIconSet;
1068 0 : drawCells( pColor, pBackground, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo );
1069 :
1070 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1071 : }
1072 0 : drawCells( NULL, NULL, pOldColor, pOldBackground, aRect, nPosX, nSignedOneX, mpDev, NULL, pOldDataBarInfo, NULL, pOldIconSetInfo );
1073 :
1074 0 : nArrY += nSkip;
1075 : }
1076 : }
1077 27 : nPosY += nRowHeight;
1078 : }
1079 1 : }
1080 :
1081 1 : void ScOutputData::DrawShadow()
1082 : {
1083 1 : DrawExtraShadow( false, false, false, false );
1084 1 : }
1085 :
1086 1 : void ScOutputData::DrawExtraShadow(sal_Bool bLeft, sal_Bool bTop, sal_Bool bRight, sal_Bool bBottom)
1087 : {
1088 1 : mpDev->SetLineColor();
1089 :
1090 1 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1091 1 : sal_Bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1092 1 : Color aAutoTextColor;
1093 1 : if ( bCellContrast )
1094 0 : aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1095 :
1096 1 : long nInitPosX = nScrX;
1097 1 : if ( bLayoutRTL )
1098 : {
1099 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1100 0 : long nOneX = aOnePixel.Width();
1101 0 : nInitPosX += nMirrorW - nOneX;
1102 : }
1103 1 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1104 :
1105 1 : long nPosY = nScrY - pRowInfo[0].nHeight;
1106 30 : for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
1107 : {
1108 29 : sal_Bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
1109 29 : sal_Bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
1110 :
1111 29 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1112 29 : long nRowHeight = pThisRowInfo->nHeight;
1113 :
1114 29 : if ( pThisRowInfo->bChanged && !bSkipY )
1115 : {
1116 27 : long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
1117 189 : for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
1118 : {
1119 162 : sal_Bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
1120 162 : sal_Bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
1121 :
1122 486 : for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertikal
1123 : {
1124 : const SvxShadowItem* pAttr = nPass ?
1125 162 : pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
1126 486 : pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
1127 324 : 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 : 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 162 : nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1221 : }
1222 : }
1223 29 : nPosY += nRowHeight;
1224 : }
1225 1 : }
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 7 : long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1277 : {
1278 7 : return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1279 : }
1280 :
1281 30 : long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1282 : {
1283 30 : return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1284 : }
1285 :
1286 6 : size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL )
1287 : {
1288 6 : 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 1 : AntiAliasingSwitch(bool bOn) : mbOldSetting(maDrawOpt.IsAntiAliasing())
1300 : {
1301 1 : maDrawOpt.SetAntiAliasing(bOn);
1302 1 : }
1303 :
1304 1 : ~AntiAliasingSwitch()
1305 1 : {
1306 1 : maDrawOpt.SetAntiAliasing(mbOldSetting);
1307 1 : }
1308 : };
1309 :
1310 : }
1311 :
1312 1 : void ScOutputData::DrawFrame()
1313 : {
1314 : // No anti-aliasing for drawing cell borders.
1315 1 : AntiAliasingSwitch aAASwitch(false);
1316 :
1317 1 : sal_uLong nOldDrawMode = mpDev->GetDrawMode();
1318 :
1319 1 : Color aSingleColor;
1320 1 : sal_Bool bUseSingleColor = false;
1321 1 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1322 1 : 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 1 : 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 1 : 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 1 : else if ( bCellContrast )
1342 : {
1343 0 : aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1344 0 : bUseSingleColor = sal_True;
1345 : }
1346 :
1347 1 : const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1348 :
1349 1 : if (bAnyRotated)
1350 0 : DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here
1351 :
1352 1 : long nInitPosX = nScrX;
1353 1 : if ( bLayoutRTL )
1354 : {
1355 0 : Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1356 0 : long nOneX = aOnePixel.Width();
1357 0 : nInitPosX += nMirrorW - nOneX;
1358 : }
1359 1 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1360 :
1361 :
1362 : // *** set column and row sizes of the frame border array ***
1363 :
1364 1 : svx::frame::Array& rArray = mrTabInfo.maArray;
1365 1 : size_t nColCount = rArray.GetColCount();
1366 1 : 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 1 : long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1373 1 : long nOldSnapY = lclGetSnappedY( *mpDev, nOldPosY, bSnapPixel );
1374 1 : rArray.SetYOffset( nOldSnapY );
1375 30 : for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1376 : {
1377 29 : long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1378 29 : long nNewSnapY = lclGetSnappedY( *mpDev, nNewPosY, bSnapPixel );
1379 29 : rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1380 29 : nOldPosY = nNewPosY;
1381 29 : 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 1 : long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth);
1389 1 : 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 1 : if( !bLayoutRTL )
1392 1 : rArray.SetXOffset( nOldSnapX );
1393 7 : for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
1394 : {
1395 6 : size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL );
1396 6 : long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign;
1397 6 : long nNewSnapX = lclGetSnappedX( *mpDev, nNewPosX, bSnapPixel );
1398 6 : rArray.SetColWidth( nCol, Abs( nNewSnapX - nOldSnapX ) );
1399 6 : nOldPosX = nNewPosX;
1400 6 : nOldSnapX = nNewSnapX;
1401 : }
1402 1 : if( bLayoutRTL )
1403 0 : rArray.SetXOffset( nOldSnapX );
1404 :
1405 : // *** draw the array ***
1406 :
1407 1 : size_t nFirstCol = 1;
1408 1 : size_t nFirstRow = 1;
1409 1 : size_t nLastCol = nColCount - 2;
1410 1 : size_t nLastRow = nRowCount - 2;
1411 :
1412 1 : if( mrTabInfo.mbPageMode )
1413 0 : rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1414 :
1415 : // draw only rows with set RowInfo::bChanged flag
1416 1 : size_t nRow1 = nFirstRow;
1417 1 : drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D();
1418 1 : if (!pProcessor)
1419 1 : return;
1420 :
1421 3 : while( nRow1 <= nLastRow )
1422 : {
1423 1 : while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1424 1 : if( nRow1 <= nLastRow )
1425 : {
1426 1 : size_t nRow2 = nRow1;
1427 1 : while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1428 1 : rArray.DrawRange( pProcessor, nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
1429 1 : nRow1 = nRow2 + 1;
1430 : }
1431 : }
1432 1 : if ( pProcessor )
1433 1 : delete pProcessor;
1434 :
1435 1 : 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 0 : void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
1509 : {
1510 : //! nRotMax speichern
1511 0 : SCCOL nRotMax = nX2;
1512 0 : for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1513 0 : 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 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1520 0 : sal_Bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1521 :
1522 : // color (pForceColor) is determined externally, including DrawMode changes
1523 :
1524 0 : long nInitPosX = nScrX;
1525 0 : 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 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1532 :
1533 0 : Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1534 0 : if (bMetaFile)
1535 : {
1536 0 : mpDev->Push();
1537 0 : mpDev->IntersectClipRegion( aClipRect );
1538 : }
1539 : else
1540 0 : mpDev->SetClipRegion( Region( aClipRect ) );
1541 :
1542 0 : svx::frame::Array& rArray = mrTabInfo.maArray;
1543 0 : drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D( );
1544 :
1545 0 : long nPosY = nScrY;
1546 0 : 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 0 : RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1552 0 : RowInfo& rThisRowInfo = pRowInfo[nArrY];
1553 0 : RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1554 :
1555 0 : size_t nRow = static_cast< size_t >( nArrY );
1556 :
1557 0 : long nRowHeight = rThisRowInfo.nHeight;
1558 0 : if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1559 : ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1560 : ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1561 : {
1562 0 : SCROW nY = rThisRowInfo.nRowNo;
1563 0 : long nPosX = 0;
1564 : SCCOL nX;
1565 0 : for (nX=0; nX<=nRotMax; nX++)
1566 : {
1567 0 : if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1568 :
1569 0 : sal_uInt16 nArrX = nX + 1;
1570 :
1571 0 : CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX];
1572 0 : long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1573 0 : 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 0 : nPosX += nColWidth * nLayoutSign;
1779 : }
1780 :
1781 : // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1782 :
1783 0 : nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1784 0 : for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1
1785 : {
1786 0 : sal_uInt16 nArrX = nX + 1;
1787 0 : CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1788 0 : 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 0 : nPosY += nRowHeight;
1835 : }
1836 :
1837 0 : if ( pProcessor ) delete pProcessor;
1838 :
1839 0 : if (bMetaFile)
1840 0 : mpDev->Pop();
1841 : else
1842 0 : mpDev->SetClipRegion();
1843 0 : }
1844 :
1845 1 : drawinglayer::processor2d::BaseProcessor2D* ScOutputData::CreateProcessor2D( )
1846 : {
1847 1 : mpDoc->InitDrawLayer(mpDoc->GetDocumentShell());
1848 1 : ScDrawLayer* pDrawLayer = mpDoc->GetDrawLayer();
1849 1 : if (!pDrawLayer)
1850 0 : return NULL;
1851 :
1852 1 : basegfx::B2DRange aViewRange;
1853 1 : 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 1 : uno::Sequence< beans::PropertyValue >() );
1861 :
1862 : return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
1863 1 : *mpDev, aNewViewInfos );
1864 : }
1865 :
1866 : // Drucker
1867 :
1868 0 : PolyPolygon ScOutputData::GetChangedArea()
1869 : {
1870 0 : PolyPolygon aPoly;
1871 :
1872 0 : Rectangle aDrawingRect;
1873 0 : aDrawingRect.Left() = nScrX;
1874 0 : aDrawingRect.Right() = nScrX+nScrW-1;
1875 :
1876 0 : sal_Bool bHad = false;
1877 0 : long nPosY = nScrY;
1878 : SCSIZE nArrY;
1879 0 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1880 : {
1881 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1882 :
1883 0 : if ( pThisRowInfo->bChanged )
1884 : {
1885 0 : if (!bHad)
1886 : {
1887 0 : aDrawingRect.Top() = nPosY;
1888 0 : bHad = sal_True;
1889 : }
1890 0 : aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1891 : }
1892 0 : else if (bHad)
1893 : {
1894 0 : aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1895 0 : bHad = false;
1896 : }
1897 0 : nPosY += pRowInfo[nArrY].nHeight;
1898 : }
1899 :
1900 0 : if (bHad)
1901 0 : aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1902 :
1903 0 : return aPoly;
1904 : }
1905 :
1906 0 : sal_Bool ScOutputData::SetChangedClip()
1907 : {
1908 0 : PolyPolygon aPoly;
1909 :
1910 0 : Rectangle aDrawingRect;
1911 0 : aDrawingRect.Left() = nScrX;
1912 0 : aDrawingRect.Right() = nScrX+nScrW-1;
1913 :
1914 0 : sal_Bool bHad = false;
1915 0 : long nPosY = nScrY;
1916 : SCSIZE nArrY;
1917 0 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1918 : {
1919 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1920 :
1921 0 : if ( pThisRowInfo->bChanged )
1922 : {
1923 0 : if (!bHad)
1924 : {
1925 0 : aDrawingRect.Top() = nPosY;
1926 0 : bHad = sal_True;
1927 : }
1928 0 : 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 0 : nPosY += pRowInfo[nArrY].nHeight;
1936 : }
1937 :
1938 0 : if (bHad)
1939 0 : aPoly.Insert( Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1940 :
1941 0 : sal_Bool bRet = (aPoly.Count() != 0);
1942 0 : if (bRet)
1943 0 : mpDev->SetClipRegion(Region(aPoly));
1944 0 : return bRet;
1945 : }
1946 :
1947 0 : void ScOutputData::FindChanged()
1948 : {
1949 : SCCOL nX;
1950 : SCSIZE nArrY;
1951 :
1952 0 : bool bWasIdleDisabled = mpDoc->IsIdleDisabled();
1953 0 : mpDoc->DisableIdle(true);
1954 0 : for (nArrY=0; nArrY<nArrCount; nArrY++)
1955 0 : pRowInfo[nArrY].bChanged = false;
1956 :
1957 0 : bool bProgress = false;
1958 0 : for (nArrY=0; nArrY<nArrCount; nArrY++)
1959 : {
1960 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1961 0 : for (nX=nX1; nX<=nX2; nX++)
1962 : {
1963 0 : ScBaseCell* pCell = pThisRowInfo->pCellInfo[nX+1].pCell;
1964 0 : if (!pCell)
1965 0 : continue;
1966 :
1967 0 : if (pCell->GetCellType() != CELLTYPE_FORMULA)
1968 0 : continue;
1969 :
1970 0 : ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1971 0 : if ( !bProgress && pFCell->GetDirty() )
1972 : {
1973 0 : ScProgress::CreateInterpretProgress(mpDoc, true);
1974 0 : bProgress = true;
1975 : }
1976 0 : if (pFCell->IsRunning())
1977 : // still being interpreted. Skip it.
1978 0 : continue;
1979 :
1980 0 : (void)pFCell->GetValue();
1981 0 : if (!pFCell->IsChanged())
1982 : // the result hasn't changed. Skip it.
1983 0 : continue;
1984 :
1985 0 : pThisRowInfo->bChanged = true;
1986 0 : if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1987 : {
1988 0 : SCSIZE nOverY = nArrY + 1;
1989 0 : while ( nOverY<nArrCount &&
1990 0 : pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
1991 : {
1992 0 : pRowInfo[nOverY].bChanged = true;
1993 0 : ++nOverY;
1994 : }
1995 : }
1996 : }
1997 : }
1998 0 : if ( bProgress )
1999 0 : ScProgress::DeleteInterpretProgress();
2000 0 : mpDoc->DisableIdle( bWasIdleDisabled );
2001 0 : }
2002 :
2003 0 : void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
2004 : SCCOL nRefEndX, SCROW nRefEndY,
2005 : const Color& rColor, sal_Bool bHandle )
2006 : {
2007 0 : PutInOrder( nRefStartX, nRefEndX );
2008 0 : PutInOrder( nRefStartY, nRefEndY );
2009 :
2010 0 : if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2011 0 : mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2012 :
2013 0 : if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
2014 : nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
2015 : {
2016 0 : long nMinX = nScrX;
2017 0 : long nMinY = nScrY;
2018 0 : long nMaxX = nScrX+nScrW-1;
2019 0 : long nMaxY = nScrY+nScrH-1;
2020 0 : if ( bLayoutRTL )
2021 : {
2022 0 : long nTemp = nMinX;
2023 0 : nMinX = nMaxX;
2024 0 : nMaxX = nTemp;
2025 : }
2026 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2027 :
2028 0 : sal_Bool bTop = false;
2029 0 : sal_Bool bBottom = false;
2030 0 : sal_Bool bLeft = false;
2031 0 : sal_Bool bRight = false;
2032 :
2033 0 : long nPosY = nScrY;
2034 0 : sal_Bool bNoStartY = ( nY1 < nRefStartY );
2035 0 : sal_Bool bNoEndY = false;
2036 0 : for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2037 : {
2038 0 : SCROW nY = pRowInfo[nArrY].nRowNo;
2039 :
2040 0 : if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2041 : {
2042 0 : nMinY = nPosY;
2043 0 : bTop = sal_True;
2044 : }
2045 0 : if ( nY==nRefEndY )
2046 : {
2047 0 : nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
2048 0 : bBottom = sal_True;
2049 : }
2050 0 : if ( nY>nRefEndY && bNoEndY )
2051 : {
2052 0 : nMaxY = nPosY-2;
2053 0 : bBottom = sal_True;
2054 : }
2055 0 : bNoStartY = ( nY < nRefStartY );
2056 0 : bNoEndY = ( nY < nRefEndY );
2057 0 : nPosY += pRowInfo[nArrY].nHeight;
2058 : }
2059 :
2060 0 : long nPosX = nScrX;
2061 0 : if ( bLayoutRTL )
2062 0 : nPosX += nMirrorW - 1; // always in pixels
2063 :
2064 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2065 : {
2066 0 : if ( nX==nRefStartX )
2067 : {
2068 0 : nMinX = nPosX;
2069 0 : bLeft = sal_True;
2070 : }
2071 0 : if ( nX==nRefEndX )
2072 : {
2073 0 : nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
2074 0 : bRight = sal_True;
2075 : }
2076 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2077 : }
2078 :
2079 0 : if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2080 : nMaxY >= nMinY )
2081 : {
2082 0 : mpDev->SetLineColor( rColor );
2083 0 : if (bTop && bBottom && bLeft && bRight)
2084 : {
2085 0 : mpDev->SetFillColor();
2086 0 : mpDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2087 : }
2088 : else
2089 : {
2090 0 : if (bTop)
2091 0 : mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2092 0 : if (bBottom)
2093 0 : mpDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2094 0 : if (bLeft)
2095 0 : mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2096 0 : if (bRight)
2097 0 : mpDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2098 : }
2099 0 : if ( bHandle && bRight && bBottom )
2100 : {
2101 0 : mpDev->SetLineColor();
2102 0 : mpDev->SetFillColor( rColor );
2103 0 : mpDev->DrawRect( Rectangle( nMaxX-3*nLayoutSign, nMaxY-3, nMaxX+nLayoutSign, nMaxY+1 ) );
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 : 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 : sal_Bool bTop = false;
2135 0 : sal_Bool bBottom = false;
2136 0 : sal_Bool bLeft = false;
2137 0 : sal_Bool bRight = false;
2138 :
2139 0 : long nPosY = nScrY;
2140 0 : sal_Bool bNoStartY = ( nY1 < nRefStartY );
2141 0 : sal_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 = sal_True;
2150 : }
2151 0 : if ( nY==nRefEndY )
2152 : {
2153 0 : nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2154 0 : bBottom = sal_True;
2155 : }
2156 0 : if ( nY>nRefEndY && bNoEndY )
2157 : {
2158 0 : nMaxY = nPosY - 1;
2159 0 : bBottom = sal_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 = sal_True;
2176 : }
2177 0 : if ( nX==nRefEndX )
2178 : {
2179 0 : nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2180 0 : bRight = sal_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; //! dicke Linie ???
2190 0 : else if ( nType == SC_CAT_DELETE_COLS )
2191 0 : bTop = bBottom = bRight = false; //! dicke Linie ???
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 0 : void ScOutputData::DrawChangeTrack()
2229 : {
2230 0 : ScChangeTrack* pTrack = mpDoc->GetChangeTrack();
2231 0 : ScChangeViewSettings* pSettings = mpDoc->GetChangeViewSettings();
2232 0 : if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2233 0 : 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 : ((const ScChangeActionMove*)pAction)->
2274 0 : GetFromRange().aStart.Tab() == nTab )
2275 : {
2276 : ScRange aRange = ((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 0 : void ScOutputData::DrawNoteMarks()
2295 : {
2296 :
2297 0 : sal_Bool bFirst = sal_True;
2298 :
2299 0 : long nInitPosX = nScrX;
2300 0 : if ( bLayoutRTL )
2301 0 : nInitPosX += nMirrorW - 1; // always in pixels
2302 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2303 :
2304 0 : long nPosY = nScrY;
2305 0 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2306 : {
2307 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2308 0 : if ( pThisRowInfo->bChanged )
2309 : {
2310 0 : long nPosX = nInitPosX;
2311 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2312 : {
2313 0 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2314 0 : sal_Bool bIsMerged = false;
2315 :
2316 0 : if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2317 : {
2318 : // find start of merged cell
2319 0 : bIsMerged = sal_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 0 : if ( mpDoc->GetNotes(nTab)->findByAddress(nX, pRowInfo[nArrY].nRowNo) && ( bIsMerged ||
2328 0 : ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2329 : {
2330 0 : if (bFirst)
2331 : {
2332 0 : mpDev->SetLineColor();
2333 :
2334 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2335 0 : if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2336 0 : mpDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2337 : else
2338 0 : mpDev->SetFillColor(COL_LIGHTRED);
2339 :
2340 0 : bFirst = false;
2341 : }
2342 :
2343 0 : long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2344 0 : 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 0 : if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2355 0 : mpDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) );
2356 : }
2357 :
2358 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2359 : }
2360 : }
2361 0 : nPosY += pThisRowInfo->nHeight;
2362 : }
2363 0 : }
2364 :
2365 0 : void ScOutputData::AddPDFNotes()
2366 : {
2367 0 : vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
2368 0 : if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2369 0 : 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 : sal_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 = sal_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->GetNotes(nTab)->findByAddress(nMergeX, nMergeY) && ( 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->GetNotes(nTab)->findByAddress(nMergeX, nMergeY);
2424 :
2425 : // Note title is the cell address (as on printed note pages)
2426 0 : String aTitle;
2427 0 : ScAddress aAddress( nMergeX, nMergeY, nTab );
2428 0 : aAddress.Format( aTitle, SCA_VALID, mpDoc, mpDoc->GetAddressConvention() );
2429 :
2430 : // Content has to be a simple string without line breaks
2431 0 : String aContent = pNote->GetText();
2432 : xub_StrLen nPos;
2433 0 : while ( (nPos=aContent.Search('\n')) != STRING_NOTFOUND )
2434 0 : aContent.SetChar( nPos, ' ' );
2435 :
2436 0 : vcl::PDFNote aNote;
2437 0 : aNote.Title = aTitle;
2438 0 : aNote.Contents = aContent;
2439 0 : pPDFData->CreateNote( aNoteRect, aNote );
2440 : }
2441 : }
2442 :
2443 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2444 : }
2445 : }
2446 0 : nPosY += pThisRowInfo->nHeight;
2447 : }
2448 : }
2449 :
2450 0 : void ScOutputData::DrawClipMarks()
2451 : {
2452 0 : if (!bAnyClipped)
2453 0 : return;
2454 :
2455 0 : Color aArrowFillCol( COL_LIGHTRED );
2456 :
2457 0 : sal_uLong nOldDrawMode = mpDev->GetDrawMode();
2458 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2459 0 : if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2460 : {
2461 : // use DrawMode to change the arrow's outline color
2462 0 : mpDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2463 : // use text color also for the fill color
2464 0 : aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2465 : }
2466 :
2467 0 : long nInitPosX = nScrX;
2468 0 : if ( bLayoutRTL )
2469 0 : nInitPosX += nMirrorW - 1; // always in pixels
2470 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
2471 :
2472 0 : Rectangle aCellRect;
2473 0 : long nPosY = nScrY;
2474 0 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2475 : {
2476 0 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2477 0 : if ( pThisRowInfo->bChanged )
2478 : {
2479 0 : SCROW nY = pThisRowInfo->nRowNo;
2480 0 : long nPosX = nInitPosX;
2481 0 : for (SCCOL nX=nX1; nX<=nX2; nX++)
2482 : {
2483 0 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2484 0 : if (pInfo->nClipMark)
2485 : {
2486 0 : if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2487 : {
2488 : // merge origin may be outside of visible area - use document functions
2489 :
2490 0 : SCCOL nOverX = nX;
2491 0 : SCROW nOverY = nY;
2492 0 : long nStartPosX = nPosX;
2493 0 : long nStartPosY = nPosY;
2494 :
2495 0 : while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2496 0 : nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2497 : {
2498 0 : --nOverX;
2499 0 : nStartPosX -= nLayoutSign * (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2500 : }
2501 :
2502 0 : while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)mpDoc->GetAttr(
2503 0 : nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2504 : {
2505 0 : --nOverY;
2506 0 : nStartPosY -= nLayoutSign * (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2507 : }
2508 :
2509 0 : long nOutWidth = (long) ( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2510 0 : long nOutHeight = (long) ( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2511 :
2512 : const ScMergeAttr* pMerge = (const ScMergeAttr*)
2513 0 : mpDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2514 0 : SCCOL nCountX = pMerge->GetColMerge();
2515 0 : for (SCCOL i=1; i<nCountX; i++)
2516 0 : nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2517 0 : SCROW nCountY = pMerge->GetRowMerge();
2518 0 : nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2519 :
2520 0 : if ( bLayoutRTL )
2521 0 : nStartPosX -= nOutWidth - 1;
2522 0 : aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2523 : }
2524 : else
2525 : {
2526 0 : long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2527 0 : long nOutHeight = pThisRowInfo->nHeight;
2528 :
2529 0 : if ( pInfo->bMerged && pInfo->pPatternAttr )
2530 : {
2531 0 : SCCOL nOverX = nX;
2532 0 : SCROW nOverY = nY;
2533 : const ScMergeAttr* pMerge =
2534 0 : (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2535 0 : SCCOL nCountX = pMerge->GetColMerge();
2536 0 : for (SCCOL i=1; i<nCountX; i++)
2537 0 : nOutWidth += (long) ( mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX );
2538 0 : SCROW nCountY = pMerge->GetRowMerge();
2539 0 : nOutHeight += (long) mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2540 : }
2541 :
2542 0 : long nStartPosX = nPosX;
2543 0 : if ( bLayoutRTL )
2544 0 : nStartPosX -= nOutWidth - 1;
2545 : // #i80447# create aCellRect from two points in case nOutWidth is 0
2546 : aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2547 0 : Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2548 : }
2549 :
2550 0 : aCellRect.Bottom() -= 1; // don't paint over the cell grid
2551 0 : if ( bLayoutRTL )
2552 0 : aCellRect.Left() += 1;
2553 : else
2554 0 : aCellRect.Right() -= 1;
2555 :
2556 0 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2557 0 : Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2558 :
2559 0 : if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2560 : {
2561 : // visually left
2562 0 : Rectangle aMarkRect = aCellRect;
2563 0 : aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2564 0 : SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, true );
2565 : }
2566 0 : if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2567 : {
2568 : // visually right
2569 0 : Rectangle aMarkRect = aCellRect;
2570 0 : aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2571 0 : SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, false );
2572 : }
2573 : }
2574 0 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2575 : }
2576 : }
2577 0 : nPosY += pThisRowInfo->nHeight;
2578 : }
2579 :
2580 0 : mpDev->SetDrawMode(nOldDrawMode);
2581 15 : }
2582 :
2583 :
2584 :
2585 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|