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