LibreOffice Module sc (master)  1
output.cxx
Go to the documentation of this file.
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 <scitems.hxx>
21 #include <editeng/brushitem.hxx>
22 #include <svtools/colorcfg.hxx>
23 #include <svx/rotmodit.hxx>
24 #include <editeng/shaditem.hxx>
25 #include <editeng/svxfont.hxx>
26 #include <tools/poly.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/pdfextoutdevdata.hxx>
30 #include <svx/framelinkarray.hxx>
34 #include <vcl/lineinfo.hxx>
35 #include <vcl/gradient.hxx>
36 #include <vcl/settings.hxx>
37 #include <svx/unoapi.hxx>
38 #include <sal/log.hxx>
39 #include <comphelper/lok.hxx>
40 #include <o3tl/unit_conversion.hxx>
45 
46 #include <output.hxx>
47 #include <document.hxx>
48 #include <drwlayer.hxx>
49 #include <formulacell.hxx>
50 #include <attrib.hxx>
51 #include <patattr.hxx>
52 #include <progress.hxx>
53 #include <pagedata.hxx>
54 #include <chgtrack.hxx>
55 #include <chgviset.hxx>
56 #include <viewutil.hxx>
57 #include <gridmerg.hxx>
58 #include <fillinfo.hxx>
59 #include <scmod.hxx>
60 #include <appoptio.hxx>
61 #include <postit.hxx>
62 #include <validat.hxx>
63 #include <detfunc.hxx>
64 
65 #include <SparklineRenderer.hxx>
66 #include <colorscale.hxx>
67 
68 #include <math.h>
69 #include <memory>
70 
71 using namespace com::sun::star;
72 
73 // Static Data
74 
75 // color for ChangeTracking "by author" as in the writer (swmodul1.cxx)
76 
77 #define SC_AUTHORCOLORCOUNT 9
78 
83 
84 // Helper class for color assignment to avoid repeated lookups for the same user
85 
87  rOpt( SC_MOD()->GetAppOptions() ),
88  rUsers( rTrack.GetUserCollection() ),
89  nLastUserIndex( 0 ),
90  nColor( COL_BLACK )
91 {
92 }
93 
95 {
96  Color nSetColor;
97  switch (rAction.GetType())
98  {
99  case SC_CAT_INSERT_COLS:
100  case SC_CAT_INSERT_ROWS:
101  case SC_CAT_INSERT_TABS:
102  nSetColor = rOpt.GetTrackInsertColor();
103  break;
104  case SC_CAT_DELETE_COLS:
105  case SC_CAT_DELETE_ROWS:
106  case SC_CAT_DELETE_TABS:
107  nSetColor = rOpt.GetTrackDeleteColor();
108  break;
109  case SC_CAT_MOVE:
110  nSetColor = rOpt.GetTrackMoveColor();
111  break;
112  default:
113  nSetColor = rOpt.GetTrackContentColor();
114  break;
115  }
116  if ( nSetColor != COL_TRANSPARENT ) // color assigned
117  nColor = nSetColor;
118  else // by author
119  {
120  if (aLastUserName != rAction.GetUser())
121  {
122  aLastUserName = rAction.GetUser();
123  std::set<OUString>::const_iterator it = rUsers.find(aLastUserName);
124  if (it == rUsers.end())
125  {
126  // empty string is possible if a name wasn't found while saving a 5.0 file
127  SAL_INFO_IF( aLastUserName.isEmpty(), "sc.ui", "Author not found" );
128  nLastUserIndex = 0;
129  }
130  else
131  {
132  size_t nPos = std::distance(rUsers.begin(), it);
134  }
135  }
136  nColor = nAuthorColor[nLastUserIndex];
137  }
138 }
139 
141  ScTableInfo& rTabInfo, ScDocument* pNewDoc,
142  SCTAB nNewTab, tools::Long nNewScrX, tools::Long nNewScrY,
143  SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2,
144  double nPixelPerTwipsX, double nPixelPerTwipsY,
145  const Fraction* pZoomX, const Fraction* pZoomY ) :
146  mpDev( pNewDev ),
147  mpRefDevice( pNewDev ), // default is output device
148  pFmtDevice( pNewDev ), // default is output device
149  mrTabInfo( rTabInfo ),
150  pRowInfo( rTabInfo.mpRowInfo.get() ),
151  nArrCount( rTabInfo.mnArrCount ),
152  mpDoc( pNewDoc ),
153  nTab( nNewTab ),
154  nScrX( nNewScrX ),
155  nScrY( nNewScrY ),
156  nX1( nNewX1 ),
157  nY1( nNewY1 ),
158  nX2( nNewX2 ),
159  nY2( nNewY2 ),
160  eType( eNewType ),
161  mnPPTX( nPixelPerTwipsX ),
162  mnPPTY( nPixelPerTwipsY ),
163  pViewShell( nullptr ),
164  pDrawView( nullptr ),
165  bEditMode( false ),
166  nEditCol( 0 ),
167  nEditRow( 0 ),
168  bMetaFile( false ),
169  bPagebreakMode( false ),
170  bSolidBackground( false ),
171  mbUseStyleColor( false ),
172  mbForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
173  mbSyntaxMode( false ),
174  aGridColor( COL_BLACK ),
175  mbShowNullValues( true ),
176  mbShowFormulas( false ),
177  bShowSpellErrors( false ),
178  bMarkClipped( false ), // sal_False for printer/metafile etc.
179  bSnapPixel( false ),
180  bAnyClipped( false ),
181  bVertical(false),
182  mpTargetPaintWindow(nullptr), // #i74769# use SdrPaintWindow direct
183  mpSpellCheckCxt(nullptr)
184 {
185  if (pZoomX)
186  aZoomX = *pZoomX;
187  else
188  aZoomX = Fraction(1,1);
189  if (pZoomY)
190  aZoomY = *pZoomY;
191  else
192  aZoomY = Fraction(1,1);
193 
194  nVisX1 = nX1;
195  nVisY1 = nY1;
196  nVisX2 = nX2;
197  nVisY2 = nY2;
199 
200  nScrW = 0;
201  for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
202  nScrW += pRowInfo[0].basicCellInfo(nX).nWidth;
203 
204  nMirrorW = nScrW;
205 
206  nScrH = 0;
207  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
208  nScrH += pRowInfo[nArrY].nHeight;
209 
212 
213  // always needed, so call at the end of the constructor
215 }
216 
218 {
219 }
220 
222 {
223  mpSpellCheckCxt = pCxt;
224 }
225 
227 {
228  // use pContentDev instead of pDev where used
229 
230  if ( mpRefDevice == mpDev )
231  mpRefDevice = pContentDev;
232  if ( pFmtDevice == mpDev )
233  pFmtDevice = pContentDev;
234  mpDev = pContentDev;
235 }
236 
238 {
239  nMirrorW = nNew;
240 }
241 
242 void ScOutputData::SetGridColor( const Color& rColor )
243 {
244  aGridColor = rColor;
245 }
246 
248 {
249  bMarkClipped = bSet;
250 }
251 
253 {
254  mbShowNullValues = bSet;
255 }
256 
258 {
259  mbShowFormulas = bSet;
260 }
261 
263 {
264  bShowSpellErrors = bSet;
265 }
266 
268 {
269  bSnapPixel = true;
270 }
271 
273 {
274  nEditCol = nCol;
275  nEditRow = nRow;
276  bEditMode = true;
277 }
278 
279 void ScOutputData::SetMetaFileMode( bool bNewMode )
280 {
281  bMetaFile = bNewMode;
282 }
283 
284 void ScOutputData::SetSyntaxMode( bool bNewMode )
285 {
286  mbSyntaxMode = bNewMode;
287  if ( bNewMode && !mxValueColor )
288  {
289  const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
293  }
294 }
295 
296 void ScOutputData::DrawGrid(vcl::RenderContext& rRenderContext, bool bGrid, bool bPage, bool bMergeCover)
297 {
298  // bMergeCover : Draw lines in sheet bgcolor to cover lok client grid lines in merged cell areas.
299  // When scNoGridBackground is set in lok mode, bMergeCover is set to true and bGrid to false.
300 
301  SCCOL nX;
302  SCROW nY;
303  tools::Long nPosX;
304  tools::Long nPosY;
305  SCSIZE nArrY;
307  ScBreakType nBreakOld = ScBreakType::NONE;
308 
309  bool bSingle;
310  bool bDashed = false;
311  Color aPageColor;
312  Color aManualColor;
313 
314  if (bPagebreakMode)
315  bPage = false; // no "normal" breaks over the whole width/height
316 
317  // It is a big mess to distinguish when we are using pixels and when logic
318  // units for drawing. Ultimately we want to work only in the logic units,
319  // but until that happens, we need to special-case:
320  //
321  // * metafile
322  // * drawing to the screen - everything is internally counted in pixels there
323  //
324  // 'Internally' in the above means the pCellInfo[...].nWidth and
325  // pRowInfo[...]->nHeight:
326  //
327  // * when bWorksInPixels is true: these are in pixels
328  // * when bWorksInPixels is false: these are in the logic units
329  //
330  // This is where all the confusion comes from, ultimately we want them
331  // always in the logic units (100th of millimeters), but we need to get
332  // there gradually (get rid of setting MapUnit::MapPixel first), otherwise we'd
333  // break all the drawing by one change.
334  // So until that happens, we need to special case.
335  bool bWorksInPixels = bMetaFile;
336  const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
337  Color aSheetBGColor = rColorCfg.GetColorValue(::svtools::DOCCOLOR).nColor;
338 
339  if ( eType == OUTTYPE_WINDOW )
340  {
341  bWorksInPixels = true;
342  aPageColor = rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
343  aManualColor = rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor;
344  }
345  else
346  {
347  aPageColor = aGridColor;
348  aManualColor = aGridColor;
349  }
350 
351  tools::Long nOneX = 1;
352  tools::Long nOneY = 1;
353  if (!bWorksInPixels)
354  {
355  Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
356  nOneX = aOnePixel.Width();
357  nOneY = aOnePixel.Height();
358  }
359 
360  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
361  tools::Long nSignedOneX = nOneX * nLayoutSign;
362 
363  rRenderContext.SetLineColor(bMergeCover ? aSheetBGColor : aGridColor);
364 
365  ScGridMerger aGrid(&rRenderContext, nOneX, nOneY);
366 
367  // vertical lines
368 
369  nPosX = nScrX;
370  if ( bLayoutRTL )
371  nPosX += nMirrorW - nOneX;
372 
373  for (nX=nX1; nX<=nX2; nX++)
374  {
375  sal_uInt16 nWidth = pRowInfo[0].basicCellInfo(nX).nWidth;
376  if (nWidth)
377  {
378  nPosX += nWidth * nLayoutSign;
379 
380  if ( bPage )
381  {
382  // Search also in hidden part for page breaks
383  SCCOL nCol = nX + 1;
384  while (nCol <= mpDoc->MaxCol())
385  {
386  nBreak = mpDoc->HasColBreak(nCol, nTab);
387  bool bHidden = mpDoc->ColHidden(nCol, nTab);
388 
389  if ( nBreak != ScBreakType::NONE || !bHidden )
390  break;
391  ++nCol;
392  }
393 
394  if (nBreak != nBreakOld)
395  {
396  aGrid.Flush();
397 
398  if (static_cast<int>(nBreak))
399  {
400  rRenderContext.SetLineColor( (nBreak & ScBreakType::Manual) ? aManualColor :
401  aPageColor );
402  bDashed = true;
403  }
404  else
405  {
406  rRenderContext.SetLineColor(bMergeCover ? aSheetBGColor : aGridColor);
407  bDashed = false;
408  }
409 
410  nBreakOld = nBreak;
411  }
412  }
413 
414  bool bDraw = bGrid || nBreakOld != ScBreakType::NONE || bMergeCover; // simple grid only if set that way
415 
416  sal_uInt16 nWidthXplus1 = pRowInfo[0].basicCellInfo(nX+1).nWidth;
417  bSingle = false;
418  if ( nX<mpDoc->MaxCol() && !bSingle )
419  {
420  bSingle = ( nWidthXplus1 == 0 );
421  for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
422  {
423  if (pRowInfo[nArrY].cellInfo(nX+1).bHOverlapped)
424  bSingle = true;
425  if (pRowInfo[nArrY].cellInfo(nX).bHideGrid)
426  bSingle = true;
427  }
428  }
429 
430  if (bDraw)
431  {
432  if ( nX<mpDoc->MaxCol() && bSingle )
433  {
434  SCCOL nVisX = nX + 1;
435  while ( nVisX < mpDoc->MaxCol() && !mpDoc->GetColWidth(nVisX,nTab) )
436  ++nVisX;
437 
438  nPosY = nScrY;
439  for (nArrY=1; nArrY+1<nArrCount; nArrY++)
440  {
441  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
442  const tools::Long nNextY = nPosY + pThisRowInfo->nHeight;
443 
444  bool bHOver = pThisRowInfo->cellInfo(nX).bHideGrid;
445  if (!bHOver)
446  {
447  if (nWidthXplus1)
448  bHOver = pThisRowInfo->cellInfo(nX+1).bHOverlapped;
449  else
450  {
451  if (nVisX <= nX2)
452  bHOver = pThisRowInfo->cellInfo(nVisX).bHOverlapped;
453  else
454  bHOver = mpDoc->GetAttr(
455  nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG)
456  ->IsHorOverlapped();
457  if (bHOver)
458  bHOver = mpDoc->GetAttr(
459  nX + 1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG)
460  ->IsHorOverlapped();
461  }
462  }
463 
464  if ((pThisRowInfo->bChanged && !bHOver && !bMergeCover) || (bHOver && bMergeCover))
465  {
466  aGrid.AddVerLine(bWorksInPixels, nPosX-nSignedOneX, nPosY, nNextY-nOneY, bDashed);
467  }
468  nPosY = nNextY;
469  }
470  }
471  else if (!bMergeCover)
472  {
473  aGrid.AddVerLine(bWorksInPixels, nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY, bDashed);
474  }
475  }
476  }
477  }
478 
479  // horizontal lines
480 
481  bool bHiddenRow = true;
482  SCROW nHiddenEndRow = -1;
483  nPosY = nScrY;
484  for (nArrY=1; nArrY+1<nArrCount; nArrY++)
485  {
486  SCSIZE nArrYplus1 = nArrY+1;
487  nY = pRowInfo[nArrY].nRowNo;
488  SCROW nYplus1 = nY+1;
489  nPosY += pRowInfo[nArrY].nHeight;
490 
491  if (pRowInfo[nArrY].bChanged)
492  {
493  if ( bPage )
494  {
495  for (SCROW i = nYplus1; i <= mpDoc->MaxRow(); ++i)
496  {
497  if (i > nHiddenEndRow)
498  bHiddenRow = mpDoc->RowHidden(i, nTab, nullptr, &nHiddenEndRow);
499  /* TODO: optimize the row break thing for large hidden
500  * segments where HasRowBreak() has to be called
501  * nevertheless for each row, as a row break is drawn also
502  * for hidden rows, above them. This needed to be done only
503  * once per hidden segment, maybe giving manual breaks
504  * priority. Something like GetNextRowBreak() and
505  * GetNextManualRowBreak(). */
506  nBreak = mpDoc->HasRowBreak(i, nTab);
507  if (!bHiddenRow || nBreak != ScBreakType::NONE)
508  break;
509  }
510 
511  if (nBreakOld != nBreak)
512  {
513  aGrid.Flush();
514 
515  if (static_cast<int>(nBreak))
516  {
517  rRenderContext.SetLineColor( (nBreak & ScBreakType::Manual) ? aManualColor :
518  aPageColor );
519  bDashed = true;
520  }
521  else
522  {
523  rRenderContext.SetLineColor(bMergeCover ? aSheetBGColor : aGridColor);
524  bDashed = false;
525  }
526 
527  nBreakOld = nBreak;
528  }
529  }
530 
531  bool bDraw = bGrid || nBreakOld != ScBreakType::NONE || bMergeCover; // simple grid only if set so
532 
533  bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
534  bSingle = !bNextYisNextRow; // Hidden
535  for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
536  {
537  if (pRowInfo[nArrYplus1].cellInfo(i).bVOverlapped)
538  bSingle = true;
539  }
540 
541  if (bDraw)
542  {
543  if ( bSingle && nY<mpDoc->MaxRow() )
544  {
545  SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
546 
547  nPosX = nScrX;
548  if ( bLayoutRTL )
549  nPosX += nMirrorW - nOneX;
550 
551  for (SCCOL i=nX1; i<=nX2; i++)
552  {
553  const tools::Long nNextX = nPosX + pRowInfo[0].basicCellInfo(i).nWidth * nLayoutSign;
554  if (nNextX != nPosX) // visible
555  {
556  bool bVOver;
557  if ( bNextYisNextRow )
558  bVOver = pRowInfo[nArrYplus1].cellInfo(i).bVOverlapped;
559  else
560  {
561  bVOver = mpDoc->GetAttr(
562  i,nYplus1,nTab,ATTR_MERGE_FLAG)
563  ->IsVerOverlapped()
564  && mpDoc->GetAttr(
565  i,nVisY,nTab,ATTR_MERGE_FLAG)
566  ->IsVerOverlapped();
568  }
569 
570  if ((!bVOver && !bMergeCover) || (bVOver && bMergeCover))
571  {
572  aGrid.AddHorLine(bWorksInPixels, nPosX, nNextX-nSignedOneX, nPosY-nOneY, bDashed);
573  }
574  }
575  nPosX = nNextX;
576  }
577  }
578  else if (!bMergeCover)
579  {
580  aGrid.AddHorLine(bWorksInPixels, nScrX, nScrX+nScrW-nOneX, nPosY-nOneY, bDashed);
581  }
582  }
583  }
584  }
585 }
586 
588 {
589  bPagebreakMode = true;
590  if (!pPageData)
591  return; // not yet initialized -> everything "not printed"
592 
593  // mark printed range
594  // (everything in FillInfo is already initialized to sal_False)
595 
596  sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount());
597  for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++)
598  {
599  ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
600 
601  SCCOL nStartX = std::max( aRange.aStart.Col(), nX1 );
602  SCCOL nEndX = std::min( aRange.aEnd.Col(), nX2 );
603  SCROW nStartY = std::max( aRange.aStart.Row(), nY1 );
604  SCROW nEndY = std::min( aRange.aEnd.Row(), nY2 );
605 
606  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
607  {
608  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
609  if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
610  pThisRowInfo->nRowNo <= nEndY )
611  {
612  for (SCCOL nX=nStartX; nX<=nEndX; nX++)
613  pThisRowInfo->cellInfo(nX).bPrinted = true;
614  }
615  }
616  }
617 }
618 
620 {
622  SCCOL nRotMax = nX2;
623  for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
624  if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
625  nRotMax = pRowInfo[nRotY].nRotMaxCol;
626 
627  for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
628  {
629  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
630  if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
631  ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
632  ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
633  {
634  SCROW nY = pThisRowInfo->nRowNo;
635 
636  for (SCCOL nX=0; nX<=nRotMax; nX++)
637  {
638  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
639  const ScPatternAttr* pPattern = pInfo->pPatternAttr;
640  const SfxItemSet* pCondSet = pInfo->pConditionSet;
641 
642  if ( !pPattern && !mpDoc->ColHidden(nX, nTab) )
643  {
644  pPattern = mpDoc->GetPattern( nX, nY, nTab );
645  pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
646  }
647 
648  if ( pPattern ) // column isn't hidden
649  {
650  ScRotateDir nDir = pPattern->GetRotateDir( pCondSet );
651  if (nDir != ScRotateDir::NONE)
652  {
653  // Needed for ScCellInfo internal decisions (bg fill, ...)
654  pInfo->nRotateDir = nDir;
655 
656  // create target coordinates
657  const SCCOL nTargetX(nX - nVisX1 + 1);
658  const SCROW nTargetY(nY - nVisY1 + 1);
659 
660  // Check for values - below in SetCellRotation these will
661  // be converted to size_t and thus may not be negative
662  if(nTargetX >= 0 && nTargetY >= 0)
663  {
664  // add rotation info to Array information
665  const Degree100 nAttrRotate(pPattern->GetRotateVal(pCondSet));
666  const SvxRotateMode eRotMode(pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue());
667  const double fOrient((bLayoutRTL ? -1.0 : 1.0) * toRadians(nAttrRotate)); // 1/100th degrees -> [0..2PI]
669 
670  rArray.SetCellRotation(nTargetX, nTargetY, eRotMode, fOrient);
671  }
672  }
673  }
674  }
675  }
676  }
677 }
678 
679 static ScRotateDir lcl_GetRotateDir( const ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
680 {
681  const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
682  const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
683 
685 
686  Degree100 nAttrRotate = pPattern->GetRotateVal( pCondSet );
687  if ( nAttrRotate )
688  {
689  SvxRotateMode eRotMode =
690  pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue();
691 
692  if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
693  nRet = ScRotateDir::Standard;
694  else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
695  nRet = ScRotateDir::Center;
696  else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
697  {
698  tools::Long nRot180 = nAttrRotate.get() % 18000; // 1/100 degree
699  if ( nRot180 == 9000 )
700  nRet = ScRotateDir::Center;
701  else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
702  ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
703  nRet = ScRotateDir::Left;
704  else
705  nRet = ScRotateDir::Right;
706  }
707  }
708 
709  return nRet;
710 }
711 
712 static const SvxBrushItem* lcl_FindBackground( const ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
713 {
714  const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
715  const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
716  const SvxBrushItem* pBackground =
717  &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
718 
719  ScRotateDir nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
720 
721  // treat CENTER like RIGHT
722  if ( nDir == ScRotateDir::Right || nDir == ScRotateDir::Center )
723  {
724  // text goes to the right -> take background from the left
725  while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
726  pBackground->GetColor().GetAlpha() != 0 )
727  {
728  --nCol;
729  pPattern = pDoc->GetPattern( nCol, nRow, nTab );
730  pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
731  pBackground = &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
732  }
733  }
734  else if ( nDir == ScRotateDir::Left )
735  {
736  // text goes to the left -> take background from the right
737  while ( nCol < pDoc->MaxCol() && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
738  pBackground->GetColor().GetAlpha() != 0 )
739  {
740  ++nCol;
741  pPattern = pDoc->GetPattern( nCol, nRow, nTab );
742  pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
743  pBackground = &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
744  }
745  }
746 
747  return pBackground;
748 }
749 
750 static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
751  SCCOL nX1, SCCOL nX2, bool bShowProt, bool bPagebreakMode )
752 {
753  if ( rFirst.bChanged != rOther.bChanged ||
754  rFirst.bEmptyBack != rOther.bEmptyBack )
755  return false;
756 
757  SCCOL nX;
758  if ( bShowProt )
759  {
760  for ( nX=nX1; nX<=nX2; nX++ )
761  {
762  const ScPatternAttr* pPat1 = rFirst.cellInfo(nX).pPatternAttr;
763  const ScPatternAttr* pPat2 = rOther.cellInfo(nX).pPatternAttr;
764  if ( !pPat1 || !pPat2 ||
765  &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
766  return false;
767  }
768  }
769  else
770  {
771  for ( nX=nX1; nX<=nX2; nX++ )
772  if ( rFirst.cellInfo(nX).pBackground != rOther.cellInfo(nX).pBackground )
773  return false;
774  }
775 
776  if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
777  for ( nX=nX1; nX<=nX2; nX++ )
778  if ( rFirst.cellInfo(nX).nRotateDir != rOther.cellInfo(nX).nRotateDir )
779  return false;
780 
781  if ( bPagebreakMode )
782  for ( nX=nX1; nX<=nX2; nX++ )
783  if ( rFirst.cellInfo(nX).bPrinted != rOther.cellInfo(nX).bPrinted )
784  return false;
785 
786  for ( nX=nX1; nX<=nX2; nX++ )
787  {
788  std::optional<Color> const & pCol1 = rFirst.cellInfo(nX).mxColorScale;
789  std::optional<Color> const & pCol2 = rOther.cellInfo(nX).mxColorScale;
790  if( (pCol1 && !pCol2) || (!pCol1 && pCol2) )
791  return false;
792 
793  if (pCol1 && (*pCol1 != *pCol2))
794  return false;
795 
796  const ScDataBarInfo* pInfo1 = rFirst.cellInfo(nX).pDataBar;
797  const ScDataBarInfo* pInfo2 = rOther.cellInfo(nX).pDataBar;
798 
799  if( (pInfo1 && !pInfo2) || (!pInfo1 && pInfo2) )
800  return false;
801 
802  if (pInfo1 && (*pInfo1 != *pInfo2))
803  return false;
804 
805  // each cell with an icon set should be painted the same way
806  const ScIconSetInfo* pIconSet1 = rFirst.cellInfo(nX).pIconSet;
807  const ScIconSetInfo* pIconSet2 = rOther.cellInfo(nX).pIconSet;
808 
809  if(pIconSet1 || pIconSet2)
810  return false;
811  }
812 
813  return true;
814 }
815 
817 {
818  if ( !bSolidBackground )
819  return;
820 
821  Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
822  mpDev->SetLineColor(aBgColor);
823  mpDev->SetFillColor(aBgColor);
824 
825  Point aScreenPos = mpDev->PixelToLogic(Point(nScrX, nScrY));
826  Size aScreenSize = mpDev->PixelToLogic(Size(nScrW - 1,nScrH - 1));
827 
828  mpDev->DrawRect(tools::Rectangle(aScreenPos, aScreenSize));
829 }
830 
831 namespace {
832 
833 const double lclCornerRectTransparency = 40.0;
834 
835 void drawDataBars(vcl::RenderContext& rRenderContext, const ScDataBarInfo* pOldDataBarInfo, const tools::Rectangle& rRect, tools::Long nOneX, tools::Long nOneY)
836 {
837  tools::Long nPosZero = 0;
838  tools::Rectangle aPaintRect = rRect;
839  aPaintRect.AdjustTop(2 * nOneY );
840  aPaintRect.AdjustBottom( -(2 * nOneY) );
841  aPaintRect.AdjustLeft( 2 * nOneX );
842  aPaintRect.AdjustRight( -(2 * nOneX) );
843  if(pOldDataBarInfo->mnZero)
844  {
845  // need to calculate null point in cell
846  tools::Long nLength = aPaintRect.Right() - aPaintRect.Left();
847  nPosZero = static_cast<tools::Long>(aPaintRect.Left() + nLength*pOldDataBarInfo->mnZero/100.0);
848  }
849  else
850  {
851  nPosZero = aPaintRect.Left();
852  }
853 
854  if(pOldDataBarInfo->mnLength < 0)
855  {
856  aPaintRect.SetRight( nPosZero );
857  tools::Long nLength = nPosZero - aPaintRect.Left();
858  aPaintRect.SetLeft( nPosZero + static_cast<tools::Long>(nLength * pOldDataBarInfo->mnLength/100.0) );
859  }
860  else if(pOldDataBarInfo->mnLength > 0)
861  {
862  aPaintRect.SetLeft( nPosZero );
863  tools::Long nLength = aPaintRect.Right() - nPosZero;
864  aPaintRect.SetRight( nPosZero + static_cast<tools::Long>(nLength * pOldDataBarInfo->mnLength/100.0) );
865  }
866  else
867  return;
868 
869  if(pOldDataBarInfo->mbGradient)
870  {
871  rRenderContext.SetLineColor(pOldDataBarInfo->maColor);
872  Gradient aGradient(GradientStyle::Linear, pOldDataBarInfo->maColor, COL_TRANSPARENT);
873  aGradient.SetSteps(255);
874 
875  if(pOldDataBarInfo->mnLength < 0)
876  aGradient.SetAngle(2700_deg10);
877  else
878  aGradient.SetAngle(900_deg10);
879 
880  rRenderContext.DrawGradient(aPaintRect, aGradient);
881 
882  rRenderContext.SetLineColor();
883  }
884  else
885  {
886  rRenderContext.SetFillColor(pOldDataBarInfo->maColor);
887  rRenderContext.DrawRect(aPaintRect);
888  }
889 
890  //draw axis
891  if(!(pOldDataBarInfo->mnZero && pOldDataBarInfo->mnZero != 100))
892  return;
893 
894  Point aPoint1(nPosZero, rRect.Top());
895  Point aPoint2(nPosZero, rRect.Bottom());
896  LineInfo aLineInfo(LineStyle::Dash, 1);
897  aLineInfo.SetDashCount( 4 );
898  aLineInfo.SetDistance( 3 );
899  aLineInfo.SetDashLen( 3 );
900  rRenderContext.SetFillColor(pOldDataBarInfo->maAxisColor);
901  rRenderContext.SetLineColor(pOldDataBarInfo->maAxisColor);
902  rRenderContext.DrawLine(aPoint1, aPoint2, aLineInfo);
903  rRenderContext.SetLineColor();
904  rRenderContext.SetFillColor();
905 }
906 
907 const BitmapEx& getIcon(sc::IconSetBitmapMap & rIconSetBitmapMap, ScIconSetType eType, sal_Int32 nIndex)
908 {
909  return ScIconSetFormat::getBitmap(rIconSetBitmapMap, eType, nIndex);
910 }
911 
912 void drawIconSets(vcl::RenderContext& rRenderContext, const ScIconSetInfo* pOldIconSetInfo, const tools::Rectangle& rRect, tools::Long nOneX, tools::Long nOneY,
913  sc::IconSetBitmapMap & rIconSetBitmapMap)
914 {
915  ScIconSetType eType = pOldIconSetInfo->eIconSetType;
916  sal_Int32 nIndex = pOldIconSetInfo->nIconIndex;
917  const BitmapEx& rIcon = getIcon(rIconSetBitmapMap, eType, nIndex);
918 
920 
921  if (pOldIconSetInfo->mnHeight)
922  {
924  {
925  aHeight = rRenderContext.LogicToPixel(Size(0, pOldIconSetInfo->mnHeight), MapMode(MapUnit::MapTwip)).Height();
927  }
928  else
929  {
930  aHeight = o3tl::convert(pOldIconSetInfo->mnHeight, o3tl::Length::twip, o3tl::Length::mm100);
931  }
932  }
933 
934  Size aSize = rIcon.GetSizePixel();
935  double fRatio = static_cast<double>(aSize.Width()) / aSize.Height();
936  tools::Long aWidth = fRatio * aHeight;
937 
938  rRenderContext.Push();
939  rRenderContext.SetClipRegion(vcl::Region(rRect));
940  rRenderContext.DrawBitmapEx(Point(rRect.Left() + 2 * nOneX, rRect.Bottom() - 2 * nOneY - aHeight), Size(aWidth, aHeight), rIcon);
941  rRenderContext.Pop();
942 }
943 
944 void drawCells(vcl::RenderContext& rRenderContext, std::optional<Color> const & pColor, const SvxBrushItem* pBackground, std::optional<Color>& pOldColor, const SvxBrushItem*& pOldBackground,
945  tools::Rectangle& rRect, tools::Long nPosX, tools::Long nLayoutSign, tools::Long nOneX, tools::Long nOneY, const ScDataBarInfo* pDataBarInfo, const ScDataBarInfo*& pOldDataBarInfo,
946  const ScIconSetInfo* pIconSetInfo, const ScIconSetInfo*& pOldIconSetInfo,
947  sc::IconSetBitmapMap & rIconSetBitmapMap)
948 {
949  tools::Long nSignedOneX = nOneX * nLayoutSign;
950  // need to paint if old color scale has been used and now
951  // we have a different color or a style based background
952  // we can here fall back to pointer comparison
953  if (pOldColor && (pBackground || pOldColor != pColor || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo))
954  {
955  rRect.SetRight( nPosX-nSignedOneX );
956  if( !pOldColor->IsTransparent() )
957  {
958  rRenderContext.SetFillColor( *pOldColor );
959  rRenderContext.DrawRect( rRect );
960  }
961  if( pOldDataBarInfo )
962  drawDataBars(rRenderContext, pOldDataBarInfo, rRect, nOneX, nOneY);
963  if( pOldIconSetInfo )
964  drawIconSets(rRenderContext, pOldIconSetInfo, rRect, nOneX, nOneY, rIconSetBitmapMap);
965 
966  rRect.SetLeft( nPosX - nSignedOneX );
967  }
968 
969  if ( pOldBackground && (pColor ||pBackground != pOldBackground || pOldDataBarInfo || pDataBarInfo || pIconSetInfo || pOldIconSetInfo) )
970  {
971  rRect.SetRight( nPosX-nSignedOneX );
972  if (pOldBackground) // ==0 if hidden
973  {
974  Color aBackCol = pOldBackground->GetColor();
975  if ( !aBackCol.IsTransparent() )
976  {
977  rRenderContext.SetFillColor( aBackCol );
978  rRenderContext.DrawRect( rRect );
979  }
980  }
981  if( pOldDataBarInfo )
982  drawDataBars(rRenderContext, pOldDataBarInfo, rRect, nOneX, nOneY);
983  if( pOldIconSetInfo )
984  drawIconSets(rRenderContext, pOldIconSetInfo, rRect, nOneX, nOneY, rIconSetBitmapMap);
985 
986  rRect.SetLeft( nPosX - nSignedOneX );
987  }
988 
989  if (!pOldBackground && !pOldColor && (pDataBarInfo || pIconSetInfo))
990  {
991  rRect.SetRight( nPosX -nSignedOneX );
992  rRect.SetLeft( nPosX - nSignedOneX );
993  }
994 
995  if(pColor)
996  {
997  // only update pOldColor if the colors changed
998  if (!pOldColor || *pOldColor != *pColor)
999  pOldColor = pColor;
1000 
1001  pOldBackground = nullptr;
1002  }
1003  else if(pBackground)
1004  {
1005  pOldBackground = pBackground;
1006  pOldColor.reset();
1007  }
1008 
1009  if(pDataBarInfo)
1010  pOldDataBarInfo = pDataBarInfo;
1011  else
1012  pOldDataBarInfo = nullptr;
1013 
1014  if(pIconSetInfo)
1015  pOldIconSetInfo = pIconSetInfo;
1016  else
1017  pOldIconSetInfo = nullptr;
1018 }
1019 
1020 }
1021 
1023 {
1024  Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
1025  tools::Long nOneXLogic = aOnePixel.Width();
1026  tools::Long nOneYLogic = aOnePixel.Height();
1027 
1028  // See more about bWorksInPixels in ScOutputData::DrawGrid
1029  bool bWorksInPixels = false;
1030  if (eType == OUTTYPE_WINDOW)
1031  bWorksInPixels = true;
1032 
1033  tools::Long nOneX = 1;
1034  tools::Long nOneY = 1;
1035  if (!bWorksInPixels)
1036  {
1037  nOneX = nOneXLogic;
1038  nOneY = nOneYLogic;
1039  }
1040 
1041  tools::Rectangle aRect;
1042 
1043  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1044 
1045  rRenderContext.SetLineColor();
1046 
1047  bool bShowProt = mbSyntaxMode && mpDoc->IsTabProtected(nTab);
1048  bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
1049 
1050  bool bCellContrast = mbUseStyleColor &&
1052 
1053  tools::Long nPosY = nScrY;
1054 
1055  const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1056  Color aProtectedColor( rColorCfg.GetColorValue( svtools::CALCPROTECTEDBACKGROUND ).nColor );
1057  auto pProtectedBackground = std::make_shared<SvxBrushItem>( aProtectedColor, ATTR_BACKGROUND );
1058 
1059  // iterate through the rows to show
1060  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1061  {
1062  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1063  tools::Long nRowHeight = pThisRowInfo->nHeight;
1064 
1065  if ( pThisRowInfo->bChanged )
1066  {
1067  if ( ( ( pThisRowInfo->bEmptyBack ) || mbSyntaxMode ) && !bDoAll )
1068  {
1069  // nothing
1070  }
1071  else
1072  {
1073  // scan for rows with the same background:
1074  SCSIZE nSkip = 0;
1075  while ( nArrY+nSkip+2<nArrCount &&
1076  lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
1077  nX1, nX2, bShowProt, bPagebreakMode ) )
1078  {
1079  ++nSkip;
1080  nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1081  }
1082 
1083  tools::Long nPosX = nScrX;
1084 
1085  if ( bLayoutRTL )
1086  nPosX += nMirrorW - nOneX;
1087 
1088  aRect = tools::Rectangle(nPosX, nPosY - nOneY, nPosX, nPosY - nOneY + nRowHeight);
1089  if (bWorksInPixels)
1090  aRect = rRenderContext.PixelToLogic(aRect); // internal data in pixels, but we'll be drawing in logic units
1091 
1092  const SvxBrushItem* pOldBackground = nullptr;
1093  const SvxBrushItem* pBackground = nullptr;
1094  std::optional<Color> pOldColor;
1095  const ScDataBarInfo* pOldDataBarInfo = nullptr;
1096  const ScIconSetInfo* pOldIconSetInfo = nullptr;
1097  SCCOL nMergedCols = 1;
1098  SCCOL nOldMerged = 0;
1099 
1100  for (SCCOL nX=nX1; nX + nMergedCols <= nX2 + 1; nX += nOldMerged)
1101  {
1102  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX-1+nMergedCols);
1103 
1104  nOldMerged = nMergedCols;
1105 
1106  tools::Long nNewPosX = nPosX;
1107  // extend for all merged cells
1108  nMergedCols = 1;
1109  if (pInfo->bMerged && pInfo->pPatternAttr)
1110  {
1111  const ScMergeAttr* pMerge =
1112  &pInfo->pPatternAttr->GetItem(ATTR_MERGE);
1113  nMergedCols = std::max<SCCOL>(1, pMerge->GetColMerge());
1114  }
1115 
1116  for (SCCOL nMerged = 0; nMerged < nMergedCols; ++nMerged)
1117  {
1118  SCCOL nCol = nX+nOldMerged+nMerged;
1119  if (nCol > nX2+2)
1120  break;
1121  nNewPosX += pRowInfo[0].basicCellInfo(nCol-1).nWidth * nLayoutSign;
1122  }
1123 
1124  if (nNewPosX == nPosX)
1125  continue; // Zero width, no need to draw.
1126 
1127  if (bCellContrast)
1128  {
1129  // high contrast for cell borders and backgrounds -> empty background
1130  pBackground = ScGlobal::GetEmptyBrushItem();
1131  }
1132  else if (bShowProt) // show cell protection in syntax mode
1133  {
1134  const ScPatternAttr* pP = pInfo->pPatternAttr;
1135  if (pP)
1136  {
1137  const ScProtectionAttr& rProt = pP->GetItem(ATTR_PROTECTION);
1138  if (rProt.GetProtection() || rProt.GetHideCell())
1139  pBackground = pProtectedBackground.get();
1140  else
1141  pBackground = ScGlobal::GetEmptyBrushItem();
1142  }
1143  else
1144  pBackground = nullptr;
1145  }
1146  else
1147  pBackground = pInfo->pBackground;
1148 
1149  if ( bPagebreakMode && !pInfo->bPrinted )
1150  pBackground = pProtectedBackground.get();
1151 
1152  if ( pInfo->nRotateDir > ScRotateDir::Standard &&
1153  !pBackground->GetColor().IsFullyTransparent() &&
1154  !bCellContrast )
1155  {
1156  SCROW nY = pRowInfo[nArrY].nRowNo;
1157  pBackground = lcl_FindBackground( mpDoc, nX, nY, nTab );
1158  }
1159 
1160  std::optional<Color> const & pColor = pInfo->mxColorScale;
1161  const ScDataBarInfo* pDataBarInfo = pInfo->pDataBar;
1162  const ScIconSetInfo* pIconSetInfo = pInfo->pIconSet;
1163 
1164  tools::Long nPosXLogic = nPosX;
1165  if (bWorksInPixels)
1166  nPosXLogic = rRenderContext.PixelToLogic(Point(nPosX, 0)).X();
1167 
1168  drawCells(rRenderContext, pColor, pBackground, pOldColor, pOldBackground, aRect, nPosXLogic, nLayoutSign, nOneXLogic, nOneYLogic, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap());
1169 
1170  nPosX = nNewPosX;
1171  }
1172 
1173  tools::Long nPosXLogic = nPosX;
1174  if (bWorksInPixels)
1175  nPosXLogic = rRenderContext.PixelToLogic(Point(nPosX, 0)).X();
1176 
1177  drawCells(rRenderContext, std::optional<Color>(), nullptr, pOldColor, pOldBackground, aRect, nPosXLogic, nLayoutSign, nOneXLogic, nOneYLogic, nullptr, pOldDataBarInfo, nullptr, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap());
1178 
1179  nArrY += nSkip;
1180  }
1181  }
1182  nPosY += nRowHeight;
1183  }
1184 }
1185 
1187 {
1188  DrawExtraShadow( false, false, false, false );
1189 }
1190 
1191 void ScOutputData::DrawExtraShadow(bool bLeft, bool bTop, bool bRight, bool bBottom)
1192 {
1193  mpDev->SetLineColor();
1194 
1195  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1196  bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1197  Color aAutoTextColor;
1198  if ( bCellContrast )
1199  aAutoTextColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
1200 
1201  tools::Long nInitPosX = nScrX;
1202  if ( bLayoutRTL )
1203  {
1204  Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1205  tools::Long nOneX = aOnePixel.Width();
1206  nInitPosX += nMirrorW - nOneX;
1207  }
1208  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1209 
1210  tools::Long nPosY = nScrY - pRowInfo[0].nHeight;
1211  for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
1212  {
1213  bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
1214  bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
1215 
1216  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1217  tools::Long nRowHeight = pThisRowInfo->nHeight;
1218 
1219  if ( pThisRowInfo->bChanged && !bSkipY )
1220  {
1221  tools::Long nPosX = nInitPosX - pRowInfo[0].basicCellInfo(nX1-1).nWidth * nLayoutSign;
1222  for (SCCOL nCol=nX1-1; nCol<=nX2+1; nCol++)
1223  {
1224  bool bCornerX = ( nCol==nX1-1 || nCol==nX2+1 );
1225  bool bSkipX = ( nCol==nX1-1 && !bLeft ) || ( nCol==nX2+1 && !bRight );
1226 
1227  for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertical
1228  {
1229  const SvxShadowItem* pAttr = nPass ?
1230  pThisRowInfo->cellInfo(nCol).pVShadowOrigin :
1231  pThisRowInfo->cellInfo(nCol).pHShadowOrigin;
1232  if ( pAttr && !bSkipX )
1233  {
1234  ScShadowPart ePart = nPass ?
1235  pThisRowInfo->cellInfo(nCol).eVShadowPart :
1236  pThisRowInfo->cellInfo(nCol).eHShadowPart;
1237 
1238  bool bDo = true;
1239  if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
1240  if ( ePart != SC_SHADOW_CORNER )
1241  bDo = false;
1242 
1243  if (bDo)
1244  {
1245  tools::Long nThisWidth = pRowInfo[0].basicCellInfo(nCol).nWidth;
1246  tools::Long nMaxWidth = nThisWidth;
1247  if (!nMaxWidth)
1248  {
1250  SCCOL nWx = nCol+1;
1251  while (nWx<nX2 && !pRowInfo[0].basicCellInfo(nWx).nWidth)
1252  ++nWx;
1253  nMaxWidth = pRowInfo[0].basicCellInfo(nWx).nWidth;
1254  }
1255 
1256  // rectangle is in logical orientation
1257  tools::Rectangle aRect( nPosX, nPosY,
1258  nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1259  nPosY + pRowInfo[nArrY].nHeight - 1 );
1260 
1261  tools::Long nSize = pAttr->GetWidth();
1262  tools::Long nSizeX = static_cast<tools::Long>(nSize*mnPPTX);
1263  if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1;
1264  tools::Long nSizeY = static_cast<tools::Long>(nSize*mnPPTY);
1265  if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1;
1266 
1267  nSizeX *= nLayoutSign; // used only to add to rectangle values
1268 
1269  SvxShadowLocation eLoc = pAttr->GetLocation();
1270  if ( bLayoutRTL )
1271  {
1272  // Shadow location is specified as "visual" (right is always right),
1273  // so the attribute's location value is mirrored here and in FillInfo.
1274  switch (eLoc)
1275  {
1276  case SvxShadowLocation::BottomRight: eLoc = SvxShadowLocation::BottomLeft; break;
1277  case SvxShadowLocation::BottomLeft: eLoc = SvxShadowLocation::BottomRight; break;
1278  case SvxShadowLocation::TopRight: eLoc = SvxShadowLocation::TopLeft; break;
1279  case SvxShadowLocation::TopLeft: eLoc = SvxShadowLocation::TopRight; break;
1280  default:
1281  {
1282  // added to avoid warnings
1283  }
1284  }
1285  }
1286 
1287  if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1288  ePart == SC_SHADOW_CORNER)
1289  {
1290  if (eLoc == SvxShadowLocation::TopLeft || eLoc == SvxShadowLocation::TopRight)
1291  aRect.SetTop( aRect.Bottom() - nSizeY );
1292  else
1293  aRect.SetBottom( aRect.Top() + nSizeY );
1294  }
1295  if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1296  ePart == SC_SHADOW_CORNER)
1297  {
1298  if (eLoc == SvxShadowLocation::TopLeft || eLoc == SvxShadowLocation::BottomLeft)
1299  aRect.SetLeft( aRect.Right() - nSizeX );
1300  else
1301  aRect.SetRight( aRect.Left() + nSizeX );
1302  }
1303  if (ePart == SC_SHADOW_HSTART)
1304  {
1305  if (eLoc == SvxShadowLocation::TopLeft || eLoc == SvxShadowLocation::BottomLeft)
1306  aRect.AdjustRight( -nSizeX );
1307  else
1308  aRect.AdjustLeft(nSizeX );
1309  }
1310  if (ePart == SC_SHADOW_VSTART)
1311  {
1312  if (eLoc == SvxShadowLocation::TopLeft || eLoc == SvxShadowLocation::TopRight)
1313  aRect.AdjustBottom( -nSizeY );
1314  else
1315  aRect.AdjustTop(nSizeY );
1316  }
1317 
1319  mpDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1320  mpDev->DrawRect( aRect );
1321  }
1322  }
1323  }
1324 
1325  nPosX += pRowInfo[0].basicCellInfo(nCol).nWidth * nLayoutSign;
1326  }
1327  }
1328  nPosY += nRowHeight;
1329  }
1330 }
1331 
1333 {
1334  tools::Rectangle aRect;
1335  Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
1336  tools::Long nOneX = aOnePixel.Width();
1337  tools::Long nOneY = aOnePixel.Height();
1338 
1339  // (called only for ScGridWindow)
1340  Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1341 
1342  if (bMetaFile)
1343  nOneX = nOneY = 0;
1344 
1345  mpDev->SetLineColor();
1346 
1347  mpDev->SetFillColor( aBgColor );
1348 
1349  tools::Long nPosY = nScrY;
1350  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1351  {
1352  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1353  tools::Long nRowHeight = pThisRowInfo->nHeight;
1354 
1355  if ( pThisRowInfo->bChanged )
1356  {
1357  // scan for more rows which must be painted:
1358  SCSIZE nSkip = 0;
1359  while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1360  {
1361  ++nSkip;
1362  nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1363  }
1364 
1365  aRect = tools::Rectangle( Point( nScrX, nPosY ),
1366  Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1367  mpDev->DrawRect( aRect );
1368 
1369  nArrY += nSkip;
1370  }
1371  nPosY += nRowHeight;
1372  }
1373 }
1374 
1375 // Lines
1376 
1377 static tools::Long lclGetSnappedX( const OutputDevice& rDev, tools::Long nPosX, bool bSnapPixel )
1378 {
1379  return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1380 }
1381 
1382 static tools::Long lclGetSnappedY( const OutputDevice& rDev, tools::Long nPosY, bool bSnapPixel )
1383 {
1384  return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1385 }
1386 
1388 {
1389  DrawModeFlags nOldDrawMode = rRenderContext.GetDrawMode();
1390 
1391  Color aSingleColor;
1392  bool bUseSingleColor = false;
1393  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1394  bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1395 
1396  // if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1397  // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1398  // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1399  // must be reset and the border colors handled here.
1400 
1401  if ( ( nOldDrawMode & DrawModeFlags::WhiteFill ) && ( nOldDrawMode & DrawModeFlags::BlackLine ) )
1402  {
1403  rRenderContext.SetDrawMode( nOldDrawMode & (~DrawModeFlags::WhiteFill) );
1404  aSingleColor = COL_BLACK;
1405  bUseSingleColor = true;
1406  }
1407  else if ( ( nOldDrawMode & DrawModeFlags::SettingsFill ) && ( nOldDrawMode & DrawModeFlags::SettingsLine ) )
1408  {
1409  rRenderContext.SetDrawMode( nOldDrawMode & (~DrawModeFlags::SettingsFill) );
1410  aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DrawModeFlags::SettingsLine
1411  bUseSingleColor = true;
1412  }
1413  else if ( bCellContrast )
1414  {
1415  aSingleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
1416  bUseSingleColor = true;
1417  }
1418 
1419  const Color* pForceColor = bUseSingleColor ? &aSingleColor : nullptr;
1420 
1422  {
1423  DrawRotatedFrame(rRenderContext); // removes the lines that must not be painted here
1424  }
1425 
1426  tools::Long nInitPosX = nScrX;
1427  if ( bLayoutRTL )
1428  {
1429  Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
1430  tools::Long nOneX = aOnePixel.Width();
1431  nInitPosX += nMirrorW - nOneX;
1432  }
1433  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1434 
1435  // *** set column and row sizes of the frame border array ***
1436 
1438  size_t nColCount = rArray.GetColCount();
1439  size_t nRowCount = rArray.GetRowCount();
1440 
1441  // row heights
1442 
1443  // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1444  // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1445  tools::Long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1446  tools::Long nOldSnapY = lclGetSnappedY( rRenderContext, nOldPosY, bSnapPixel );
1447  rArray.SetYOffset( nOldSnapY );
1448  for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1449  {
1450  tools::Long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1451  tools::Long nNewSnapY = lclGetSnappedY( rRenderContext, nNewPosY, bSnapPixel );
1452  rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1453  nOldPosY = nNewPosY;
1454  nOldSnapY = nNewSnapY;
1455  }
1456 
1457  // column widths
1458 
1459  // column nX1-1 is not visible (dummy for borders from left) - subtract its width from initial position
1460  // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1461  tools::Long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].basicCellInfo( nX1 - 1 ).nWidth);
1462  tools::Long nOldSnapX = lclGetSnappedX( rRenderContext, nOldPosX, bSnapPixel );
1463  // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1464  if( !bLayoutRTL )
1465  rArray.SetXOffset( nOldSnapX );
1466  for( SCCOL nCol = nX1 - 1; nCol <= nX2 + 1; ++nCol )
1467  {
1468  size_t nArrCol = bLayoutRTL ? nX2 + 1 - nCol : nCol - (nX1 - 1);
1469  tools::Long nNewPosX = nOldPosX + pRowInfo[ 0 ].basicCellInfo( nCol ).nWidth * nLayoutSign;
1470  tools::Long nNewSnapX = lclGetSnappedX( rRenderContext, nNewPosX, bSnapPixel );
1471  rArray.SetColWidth( nArrCol, std::abs( nNewSnapX - nOldSnapX ) );
1472  nOldPosX = nNewPosX;
1473  nOldSnapX = nNewSnapX;
1474  }
1475  if( bLayoutRTL )
1476  rArray.SetXOffset( nOldSnapX );
1477 
1478  // *** draw the array ***
1479 
1480  size_t nFirstCol = 1;
1481  size_t nFirstRow = 1;
1482  size_t nLastCol = nColCount - 2;
1483  size_t nLastRow = nRowCount - 2;
1484 
1485  if( mrTabInfo.mbPageMode )
1486  rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1487 
1488  // draw only rows with set RowInfo::bChanged flag
1489  size_t nRow1 = nFirstRow;
1490  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D());
1491  if (!pProcessor)
1492  return;
1494  while( nRow1 <= nLastRow )
1495  {
1496  while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1497  if( nRow1 <= nLastRow )
1498  {
1499  size_t nRow2 = nRow1;
1500  while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1501  aPrimitives.append(
1502  rArray.CreateB2DPrimitiveRange(
1503  nFirstCol, nRow1, nLastCol, nRow2, pForceColor ));
1504  nRow1 = nRow2 + 1;
1505  }
1506  }
1507  pProcessor->process(aPrimitives);
1508  pProcessor.reset();
1509 
1510  rRenderContext.SetDrawMode(nOldDrawMode);
1511 }
1512 
1514 {
1516  SCCOL nRotMax = nX2;
1517  for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1518  if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
1519  nRotMax = pRowInfo[nRotY].nRotMaxCol;
1520 
1521  const ScPatternAttr* pPattern;
1522  const SfxItemSet* pCondSet;
1523 
1524  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1525  bool bCellContrast = mbUseStyleColor && rStyleSettings.GetHighContrastMode();
1526 
1527  tools::Long nInitPosX = nScrX;
1528  if ( bLayoutRTL )
1529  {
1530  Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
1531  tools::Long nOneX = aOnePixel.Width();
1532  nInitPosX += nMirrorW - nOneX;
1533  }
1534  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1535 
1536  tools::Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1537  if (bMetaFile)
1538  {
1539  rRenderContext.Push();
1540  rRenderContext.IntersectClipRegion( aClipRect );
1541  }
1542  else
1543  rRenderContext.SetClipRegion( vcl::Region( aClipRect ) );
1544 
1545  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D( ));
1546  tools::Long nPosY = nScrY;
1547  for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1548  {
1549  // Rotated is also drawn one line above/below Changed if parts extend into the cell
1550 
1551  RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1552  RowInfo& rThisRowInfo = pRowInfo[nArrY];
1553  RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1554 
1555  tools::Long nRowHeight = rThisRowInfo.nHeight;
1556  if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1557  ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1558  ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1559  {
1560  SCROW nY = rThisRowInfo.nRowNo;
1561  tools::Long nPosX = 0;
1562  SCCOL nX;
1563  for (nX=0; nX<=nRotMax; nX++)
1564  {
1565  if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1566 
1567  ScCellInfo* pInfo = &rThisRowInfo.cellInfo(nX);
1568  tools::Long nColWidth = pRowInfo[0].basicCellInfo(nX).nWidth;
1569  if ( pInfo->nRotateDir > ScRotateDir::Standard &&
1570  !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1571  {
1572  pPattern = pInfo->pPatternAttr;
1573  pCondSet = pInfo->pConditionSet;
1574  if (!pPattern)
1575  {
1576  pPattern = mpDoc->GetPattern( nX, nY, nTab );
1577  pInfo->pPatternAttr = pPattern;
1578  pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
1579  pInfo->pConditionSet = pCondSet;
1580  }
1581 
1583 
1584  Degree100 nAttrRotate = pPattern->GetRotateVal( pCondSet );
1585  SvxRotateMode eRotMode =
1586  pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue();
1587 
1588  if (nAttrRotate)
1589  {
1590  if (nX < nX1) // compute negative position
1591  {
1592  nPosX = nInitPosX;
1593  SCCOL nCol = nX1;
1594  while (nCol > nX)
1595  {
1596  --nCol;
1597  nPosX -= nLayoutSign * static_cast<tools::Long>(pRowInfo[0].basicCellInfo(nCol).nWidth);
1598  }
1599  }
1600 
1601  // start position minus 1 so rotated backgrounds suit the border
1602  // (border is on the grid)
1603 
1604  tools::Long nTop = nPosY - 1;
1605  tools::Long nBottom = nPosY + nRowHeight - 1;
1606  tools::Long nTopLeft = nPosX - nLayoutSign;
1607  tools::Long nTopRight = nPosX + (nColWidth - 1) * nLayoutSign;
1608  tools::Long nBotLeft = nTopLeft;
1609  tools::Long nBotRight = nTopRight;
1610 
1611  // inclusion of the sign here hasn't been decided yet
1612  // (if not, the extension of the non-rotated background must also be changed)
1613  double nRealOrient = nLayoutSign * toRadians(nAttrRotate); // 1/100th degrees
1614  double nCos = cos(nRealOrient);
1615  double nSin = sin(nRealOrient);
1617  tools::Long nSkew = static_cast<tools::Long>(nRowHeight * nCos / nSin);
1618 
1619  switch (eRotMode)
1620  {
1622  nTopLeft += nSkew;
1623  nTopRight += nSkew;
1624  break;
1626  nSkew /= 2;
1627  nTopLeft += nSkew;
1628  nTopRight += nSkew;
1629  nBotLeft -= nSkew;
1630  nBotRight -= nSkew;
1631  break;
1632  case SVX_ROTATE_MODE_TOP:
1633  nBotLeft -= nSkew;
1634  nBotRight -= nSkew;
1635  break;
1636  default:
1637  {
1638  // added to avoid warnings
1639  }
1640  }
1641 
1642  Point aPoints[4];
1643  aPoints[0] = Point(nTopLeft, nTop);
1644  aPoints[1] = Point(nTopRight, nTop);
1645  aPoints[2] = Point(nBotRight, nBottom);
1646  aPoints[3] = Point(nBotLeft, nBottom);
1647 
1648  const SvxBrushItem* pBackground = pInfo->pBackground;
1649  if (!pBackground)
1650  pBackground = &pPattern->GetItem(ATTR_BACKGROUND, pCondSet);
1651  if (bCellContrast)
1652  {
1653  // high contrast for cell borders and backgrounds -> empty background
1654  pBackground = ScGlobal::GetEmptyBrushItem();
1655  }
1656  if (!pInfo->mxColorScale)
1657  {
1658  const Color& rColor = pBackground->GetColor();
1659  if (rColor.GetAlpha() != 0)
1660  {
1661  // draw background only for the changed row itself
1662  // (background doesn't extend into other cells).
1663  // For the borders (rotated and normal), clipping should be
1664  // set if the row isn't changed, but at least the borders
1665  // don't cover the cell contents.
1666  if (rThisRowInfo.bChanged)
1667  {
1668  tools::Polygon aPoly(4, aPoints);
1669 
1670  // for DrawPolygon, without Pen one pixel is left out
1671  // to the right and below...
1672  if (!rColor.IsTransparent())
1673  rRenderContext.SetLineColor(rColor);
1674  else
1675  rRenderContext.SetLineColor();
1676  rRenderContext.SetFillColor(rColor);
1677  rRenderContext.DrawPolygon(aPoly);
1678  }
1679  }
1680  }
1681  else
1682  {
1683  tools::Polygon aPoly(4, aPoints);
1684  std::optional<Color> const & pColor = pInfo->mxColorScale;
1685 
1686  // for DrawPolygon, without Pen one pixel is left out
1687  // to the right and below...
1688  if (!pColor->IsTransparent())
1689  rRenderContext.SetLineColor(*pColor);
1690  else
1691  rRenderContext.SetLineColor();
1692  rRenderContext.SetFillColor(*pColor);
1693  rRenderContext.DrawPolygon(aPoly);
1694 
1695  }
1696  }
1697  }
1698  nPosX += nColWidth * nLayoutSign;
1699  }
1700  }
1701  nPosY += nRowHeight;
1702  }
1703 
1704  pProcessor.reset();
1705 
1706  if (bMetaFile)
1707  rRenderContext.Pop();
1708  else
1709  rRenderContext.SetClipRegion();
1710 }
1711 
1712 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> ScOutputData::CreateProcessor2D( )
1713 {
1715  ScDrawLayer* pDrawLayer = mpDoc->GetDrawLayer();
1716  if (!pDrawLayer)
1717  return nullptr;
1718 
1719  basegfx::B2DRange aViewRange;
1720  SdrPage *pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
1721  const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
1724  aViewRange,
1725  GetXDrawPageForSdrPage( pDrawPage ),
1726  0.0);
1727 
1729  *mpDev, aNewViewInfos );
1730 }
1731 
1732 // Printer
1733 
1735 {
1736  vcl::Region aRegion;
1737  tools::Rectangle aDrawingRect;
1738  bool bHad(false);
1739  tools::Long nPosY = nScrY;
1740  SCSIZE nArrY;
1741 
1742  aDrawingRect.SetLeft( nScrX );
1743  aDrawingRect.SetRight( nScrX+nScrW-1 );
1744 
1745  for(nArrY=1; nArrY+1<nArrCount; nArrY++)
1746  {
1747  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1748 
1749  if(pThisRowInfo->bChanged)
1750  {
1751  if(!bHad)
1752  {
1753  aDrawingRect.SetTop( nPosY );
1754  bHad = true;
1755  }
1756 
1757  aDrawingRect.SetBottom( nPosY + pRowInfo[nArrY].nHeight - 1 );
1758  }
1759  else if(bHad)
1760  {
1761  aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1762  bHad = false;
1763  }
1764 
1765  nPosY += pRowInfo[nArrY].nHeight;
1766  }
1767 
1768  if(bHad)
1769  {
1770  aRegion.Union(mpDev->PixelToLogic(aDrawingRect));
1771  }
1772 
1773  return aRegion;
1774 }
1775 
1777 {
1778  tools::PolyPolygon aPoly;
1779 
1780  tools::Rectangle aDrawingRect;
1781  aDrawingRect.SetLeft( nScrX );
1782  aDrawingRect.SetRight( nScrX+nScrW-1 );
1783 
1784  bool bHad = false;
1785  tools::Long nPosY = nScrY;
1786  SCSIZE nArrY;
1787  for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1788  {
1789  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1790 
1791  if ( pThisRowInfo->bChanged )
1792  {
1793  if (!bHad)
1794  {
1795  aDrawingRect.SetTop( nPosY );
1796  bHad = true;
1797  }
1798  aDrawingRect.SetBottom( nPosY + pRowInfo[nArrY].nHeight - 1 );
1799  }
1800  else if (bHad)
1801  {
1802  aPoly.Insert( tools::Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1803  bHad = false;
1804  }
1805  nPosY += pRowInfo[nArrY].nHeight;
1806  }
1807 
1808  if (bHad)
1809  aPoly.Insert( tools::Polygon( mpDev->PixelToLogic(aDrawingRect) ) );
1810 
1811  bool bRet = (aPoly.Count() != 0);
1812  if (bRet)
1813  mpDev->SetClipRegion(vcl::Region(aPoly));
1814  return bRet;
1815 }
1816 
1818 {
1819  SCCOL nX;
1820  SCSIZE nArrY;
1821 
1822  bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
1823  mpDoc->EnableIdle(false);
1824  for (nArrY=0; nArrY<nArrCount; nArrY++)
1825  pRowInfo[nArrY].bChanged = false;
1826 
1827  SCCOL nCol1 = mpDoc->MaxCol(), nCol2 = 0;
1828  SCROW nRow1 = mpDoc->MaxRow(), nRow2 = 0;
1829  bool bAnyDirty = false;
1830  bool bAnyChanged = false;
1831 
1832  for (nArrY=0; nArrY<nArrCount; nArrY++)
1833  {
1834  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1835  for (nX=nX1; nX<=nX2; nX++)
1836  {
1837  const ScRefCellValue& rCell = pThisRowInfo->cellInfo(nX).maCell;
1838 
1839  if (rCell.meType != CELLTYPE_FORMULA)
1840  continue;
1841 
1842  ScFormulaCell* pFCell = rCell.mpFormula;
1843  if (pFCell->IsRunning())
1844  // still being interpreted. Skip it.
1845  continue;
1846 
1847  bool bDirty = pFCell->GetDirty();
1848  bAnyChanged = bAnyChanged || pFCell->IsChanged();
1849 
1850  if (bDirty)
1851  {
1852  if (!bAnyDirty)
1853  {
1855  bAnyDirty = true;
1856  }
1857 
1858  ScAddress& rPos(pFCell->aPos);
1859  nCol1 = std::min(rPos.Col(), nCol1);
1860  nCol2 = std::max(rPos.Col(), nCol2);
1861  nRow1 = std::min(rPos.Row(), nRow1);
1862  nRow2 = std::max(rPos.Row(), nRow2);
1863 
1864  const SfxUInt32Item* pItem = mpDoc->GetAttr(rPos, ATTR_VALIDDATA);
1865  const ScValidationData* pData = mpDoc->GetValidationEntry(pItem->GetValue());
1866  if (pData)
1867  {
1868  ScRefCellValue aCell(*mpDoc, rPos);
1869  if (pData->IsDataValid(aCell, rPos))
1870  ScDetectiveFunc(*mpDoc, rPos.Tab()).DeleteCirclesAt(rPos.Col(), rPos.Row());
1871  }
1872  }
1873  }
1874  }
1875 
1876  if (bAnyDirty || bAnyChanged)
1877  {
1878  if (bAnyDirty)
1879  mpDoc->EnsureFormulaCellResults(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab), true);
1880 
1881  for (nArrY=0; nArrY<nArrCount; nArrY++)
1882  {
1883  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1884  for (nX=nX1; nX<=nX2; nX++)
1885  {
1886  const ScRefCellValue& rCell = pThisRowInfo->cellInfo(nX).maCell;
1887 
1888  if (rCell.meType != CELLTYPE_FORMULA)
1889  continue;
1890 
1891  ScFormulaCell* pFCell = rCell.mpFormula;
1892  if (pFCell->IsRunning())
1893  // still being interpreted. Skip it.
1894  continue;
1895 
1896  if (!pFCell->IsChanged())
1897  // the result hasn't changed. Skip it.
1898  continue;
1899 
1900  pThisRowInfo->bChanged = true;
1901  if ( pThisRowInfo->cellInfo(nX).bMerged )
1902  {
1903  SCSIZE nOverY = nArrY + 1;
1904  while ( nOverY<nArrCount &&
1905  pRowInfo[nOverY].cellInfo(nX).bVOverlapped )
1906  {
1907  pRowInfo[nOverY].bChanged = true;
1908  ++nOverY;
1909  }
1910  }
1911  }
1912  }
1913 
1914  if (bAnyDirty)
1916  }
1917 
1918  mpDoc->EnableIdle(bWasIdleEnabled);
1919 }
1920 
1922  SCCOL nRefEndX, SCROW nRefEndY, const Color& rColor)
1923 {
1924  ReferenceMark aResult;
1925 
1926  PutInOrder( nRefStartX, nRefEndX );
1927  PutInOrder( nRefStartY, nRefEndY );
1928 
1929  if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1930  mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1931 
1932  if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
1933  nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
1934  {
1935  tools::Long nMinX = nScrX;
1936  tools::Long nMinY = nScrY;
1937  tools::Long nMaxX = nScrX + nScrW - 1;
1938  tools::Long nMaxY = nScrY + nScrH - 1;
1939  if ( bLayoutRTL )
1940  {
1941  tools::Long nTemp = nMinX;
1942  nMinX = nMaxX;
1943  nMaxX = nTemp;
1944  }
1945  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1946 
1947  bool bTop = false;
1948  bool bBottom = false;
1949  bool bLeft = false;
1950  bool bRight = false;
1951 
1952  tools::Long nPosY = nScrY;
1953  bool bNoStartY = ( nY1 < nRefStartY );
1954  bool bNoEndY = false;
1955  for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
1956  {
1957  SCROW nY = pRowInfo[nArrY].nRowNo;
1958 
1959  if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
1960  {
1961  nMinY = nPosY;
1962  bTop = true;
1963  }
1964  if ( nY==nRefEndY )
1965  {
1966  nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
1967  bBottom = true;
1968  }
1969  if ( nY>nRefEndY && bNoEndY )
1970  {
1971  nMaxY = nPosY-2;
1972  bBottom = true;
1973  }
1974  bNoStartY = ( nY < nRefStartY );
1975  bNoEndY = ( nY < nRefEndY );
1976  nPosY += pRowInfo[nArrY].nHeight;
1977  }
1978 
1979  tools::Long nPosX = nScrX;
1980  if ( bLayoutRTL )
1981  nPosX += nMirrorW - 1; // always in pixels
1982 
1983  for (SCCOL nX=nX1; nX<=nX2; nX++)
1984  {
1985  if ( nX==nRefStartX )
1986  {
1987  nMinX = nPosX;
1988  bLeft = true;
1989  }
1990  if ( nX==nRefEndX )
1991  {
1992  nMaxX = nPosX + ( pRowInfo[0].basicCellInfo(nX).nWidth - 2 ) * nLayoutSign;
1993  bRight = true;
1994  }
1995  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
1996  }
1997 
1998  if (bTop && bBottom && bLeft && bRight)
1999  {
2000  // mnPPT[XY] already has the factor aZoom[XY] in it.
2001  aResult = ReferenceMark( nMinX / mnPPTX,
2002  nMinY / mnPPTY,
2003  ( nMaxX - nMinX ) / mnPPTX,
2004  ( nMaxY - nMinY ) / mnPPTY,
2005  nTab,
2006  rColor );
2007  }
2008  }
2009 
2010  return aResult;
2011 }
2012 
2013 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
2014  SCCOL nRefEndX, SCROW nRefEndY,
2015  const Color& rColor, bool bHandle )
2016 {
2017  PutInOrder( nRefStartX, nRefEndX );
2018  PutInOrder( nRefStartY, nRefEndY );
2019 
2020  if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2021  mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2022 
2023  if ( !(nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
2024  nRefStartY <= nVisY2 && nRefEndY >= nVisY1) )
2025  return;
2026 
2027  tools::Long nMinX = nScrX;
2028  tools::Long nMinY = nScrY;
2029  tools::Long nMaxX = nScrX + nScrW - 1;
2030  tools::Long nMaxY = nScrY + nScrH - 1;
2031  if ( bLayoutRTL )
2032  {
2033  tools::Long nTemp = nMinX;
2034  nMinX = nMaxX;
2035  nMaxX = nTemp;
2036  }
2037  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2038 
2039  bool bTop = false;
2040  bool bBottom = false;
2041  bool bLeft = false;
2042  bool bRight = false;
2043 
2044  tools::Long nPosY = nScrY;
2045  bool bNoStartY = ( nY1 < nRefStartY );
2046  bool bNoEndY = false;
2047  for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2048  {
2049  SCROW nY = pRowInfo[nArrY].nRowNo;
2050 
2051  if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2052  {
2053  nMinY = nPosY;
2054  bTop = true;
2055  }
2056  if ( nY==nRefEndY )
2057  {
2058  nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
2059  bBottom = true;
2060  }
2061  if ( nY>nRefEndY && bNoEndY )
2062  {
2063  nMaxY = nPosY-2;
2064  bBottom = true;
2065  }
2066  bNoStartY = ( nY < nRefStartY );
2067  bNoEndY = ( nY < nRefEndY );
2068  nPosY += pRowInfo[nArrY].nHeight;
2069  }
2070 
2071  tools::Long nPosX = nScrX;
2072  if ( bLayoutRTL )
2073  nPosX += nMirrorW - 1; // always in pixels
2074 
2075  for (SCCOL nX=nX1; nX<=nX2; nX++)
2076  {
2077  if ( nX==nRefStartX )
2078  {
2079  nMinX = nPosX;
2080  bLeft = true;
2081  }
2082  if ( nX==nRefEndX )
2083  {
2084  nMaxX = nPosX + ( pRowInfo[0].basicCellInfo(nX).nWidth - 2 ) * nLayoutSign;
2085  bRight = true;
2086  }
2087  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2088  }
2089 
2090  if ( nMaxX * nLayoutSign < nMinX * nLayoutSign || nMaxY < nMinY )
2091  return;
2092 
2093  mpDev->SetLineColor( rColor );
2094  if (bTop && bBottom && bLeft && bRight && !comphelper::LibreOfficeKit::isActive() )
2095  {
2096  mpDev->SetFillColor();
2097  mpDev->DrawRect( tools::Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2098  }
2100  {
2101  if (bTop)
2102  mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMaxX, nMinY ) );
2103  if (bBottom)
2104  mpDev->DrawLine( Point( nMinX, nMaxY ), Point( nMaxX, nMaxY ) );
2105  if (bLeft)
2106  mpDev->DrawLine( Point( nMinX, nMinY ), Point( nMinX, nMaxY ) );
2107  if (bRight)
2108  mpDev->DrawLine( Point( nMaxX, nMinY ), Point( nMaxX, nMaxY ) );
2109  }
2110  if ( !bHandle || !bRight || !bBottom || comphelper::LibreOfficeKit::isActive() )
2111  return;
2112 
2113  mpDev->SetLineColor( rColor );
2114  mpDev->SetFillColor( rColor );
2115 
2116  const sal_Int32 aRadius = 4;
2117 
2118  sal_Int32 aRectMaxX1 = nMaxX - nLayoutSign * aRadius;
2119  sal_Int32 aRectMaxX2 = nMaxX + nLayoutSign;
2120  sal_Int32 aRectMinX1 = nMinX - nLayoutSign;
2121  sal_Int32 aRectMinX2 = nMinX + nLayoutSign * aRadius;
2122 
2123  sal_Int32 aRectMaxY1 = nMaxY - aRadius;
2124  sal_Int32 aRectMaxY2 = nMaxY + 1;
2125  sal_Int32 aRectMinY1 = nMinY - 1;
2126  sal_Int32 aRectMinY2 = nMinY + aRadius;
2127 
2128  // Draw corner rectangles
2129  tools::Rectangle aLowerRight( aRectMaxX1, aRectMaxY1, aRectMaxX2, aRectMaxY2 );
2130  tools::Rectangle aUpperLeft ( aRectMinX1, aRectMinY1, aRectMinX2, aRectMinY2 );
2131  tools::Rectangle aLowerLeft ( aRectMinX1, aRectMaxY1, aRectMinX2, aRectMaxY2 );
2132  tools::Rectangle aUpperRight( aRectMaxX1, aRectMinY1, aRectMaxX2, aRectMinY2 );
2133 
2134  mpDev->DrawTransparent( tools::PolyPolygon( tools::Polygon( aLowerRight ) ), lclCornerRectTransparency );
2135  mpDev->DrawTransparent( tools::PolyPolygon( tools::Polygon( aUpperLeft ) ), lclCornerRectTransparency );
2136  mpDev->DrawTransparent( tools::PolyPolygon( tools::Polygon( aLowerLeft ) ), lclCornerRectTransparency );
2137  mpDev->DrawTransparent( tools::PolyPolygon( tools::Polygon( aUpperRight ) ), lclCornerRectTransparency );
2138 }
2139 
2140 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
2141  SCCOL nRefEndX, SCROW nRefEndY,
2142  const Color& rColor, sal_uInt16 nType )
2143 {
2144  PutInOrder( nRefStartX, nRefEndX );
2145  PutInOrder( nRefStartY, nRefEndY );
2146 
2147  if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
2148  mpDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
2149 
2150  if ( !(nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
2151  nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1) ) // +1 because it touches next cells left/top
2152  return;
2153 
2154  tools::Long nMinX = nScrX;
2155  tools::Long nMinY = nScrY;
2156  tools::Long nMaxX = nScrX+nScrW-1;
2157  tools::Long nMaxY = nScrY+nScrH-1;
2158  if ( bLayoutRTL )
2159  {
2160  tools::Long nTemp = nMinX;
2161  nMinX = nMaxX;
2162  nMaxX = nTemp;
2163  }
2164  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2165 
2166  bool bTop = false;
2167  bool bBottom = false;
2168  bool bLeft = false;
2169  bool bRight = false;
2170 
2171  tools::Long nPosY = nScrY;
2172  bool bNoStartY = ( nY1 < nRefStartY );
2173  bool bNoEndY = false;
2174  for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2175  {
2176  SCROW nY = pRowInfo[nArrY].nRowNo;
2177 
2178  if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2179  {
2180  nMinY = nPosY - 1;
2181  bTop = true;
2182  }
2183  if ( nY==nRefEndY )
2184  {
2185  nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2186  bBottom = true;
2187  }
2188  if ( nY>nRefEndY && bNoEndY )
2189  {
2190  nMaxY = nPosY - 1;
2191  bBottom = true;
2192  }
2193  bNoStartY = ( nY < nRefStartY );
2194  bNoEndY = ( nY < nRefEndY );
2195  nPosY += pRowInfo[nArrY].nHeight;
2196  }
2197 
2198  tools::Long nPosX = nScrX;
2199  if ( bLayoutRTL )
2200  nPosX += nMirrorW - 1; // always in pixels
2201 
2202  for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2203  {
2204  if ( nX==nRefStartX )
2205  {
2206  nMinX = nPosX - nLayoutSign;
2207  bLeft = true;
2208  }
2209  if ( nX==nRefEndX )
2210  {
2211  nMaxX = nPosX + ( pRowInfo[0].basicCellInfo(nX).nWidth - 1 ) * nLayoutSign;
2212  bRight = true;
2213  }
2214  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2215  }
2216 
2217  if ( nMaxX * nLayoutSign < nMinX * nLayoutSign || nMaxY < nMinY )
2218  return;
2219 
2220  if ( nType == SC_CAT_DELETE_ROWS )
2221  bLeft = bRight = bBottom = false;
2222  else if ( nType == SC_CAT_DELETE_COLS )
2223  bTop = bBottom = bRight = false;
2224 
2225  mpDev->SetLineColor( rColor );
2226  if (bTop && bBottom && bLeft && bRight)
2227  {
2228  mpDev->SetFillColor();
2229  mpDev->DrawRect( tools::Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2230  }
2231  else
2232  {
2233  if (bTop)
2234  {
2235  mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2236  if ( nType == SC_CAT_DELETE_ROWS )
2237  mpDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2238  }
2239  if (bBottom)
2240  mpDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2241  if (bLeft)
2242  {
2243  mpDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2244  if ( nType == SC_CAT_DELETE_COLS )
2245  mpDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2246  }
2247  if (bRight)
2248  mpDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2249  }
2250  if ( bLeft && bTop )
2251  {
2252  mpDev->SetLineColor();
2253  mpDev->SetFillColor( rColor );
2254  mpDev->DrawRect( tools::Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2255  }
2256 }
2257 
2259 {
2260  ScChangeTrack* pTrack = mpDoc->GetChangeTrack();
2262  if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2263  return; // nothing there or hidden
2264 
2265  ScActionColorChanger aColorChanger(*pTrack);
2266 
2267  // clipping happens from the outside
2269 
2270  SCCOL nEndX = nX2;
2271  SCROW nEndY = nY2;
2272  if ( nEndX < mpDoc->MaxCol() ) ++nEndX; // also from the next cell since the mark
2273  if ( nEndY < mpDoc->MaxRow() ) ++nEndY; // protrudes from the preceding cell
2274  ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2275  const ScChangeAction* pAction = pTrack->GetFirst();
2276  while (pAction)
2277  {
2278  if ( pAction->IsVisible() )
2279  {
2280  ScChangeActionType eActionType = pAction->GetType();
2281  const ScBigRange& rBig = pAction->GetBigRange();
2282  if ( rBig.aStart.Tab() == nTab )
2283  {
2284  ScRange aRange = rBig.MakeRange( *mpDoc );
2285 
2286  if ( eActionType == SC_CAT_DELETE_ROWS )
2287  aRange.aEnd.SetRow( aRange.aStart.Row() );
2288  else if ( eActionType == SC_CAT_DELETE_COLS )
2289  aRange.aEnd.SetCol( aRange.aStart.Col() );
2290 
2291  if ( aRange.Intersects( aViewRange ) &&
2292  ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2293  {
2294  aColorChanger.Update( *pAction );
2295  Color aColor( aColorChanger.GetColor() );
2296  DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2297  aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2298 
2299  }
2300  }
2301  if ( eActionType == SC_CAT_MOVE &&
2302  static_cast<const ScChangeActionMove*>(pAction)->
2303  GetFromRange().aStart.Tab() == nTab )
2304  {
2305  ScRange aRange = static_cast<const ScChangeActionMove*>(pAction)->
2306  GetFromRange().MakeRange( *mpDoc );
2307  if ( aRange.Intersects( aViewRange ) &&
2308  ScViewUtil::IsActionShown( *pAction, *pSettings, *mpDoc ) )
2309  {
2310  aColorChanger.Update( *pAction );
2311  Color aColor( aColorChanger.GetColor() );
2312  DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2313  aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2314  }
2315  }
2316  }
2317 
2318  pAction = pAction->GetNext();
2319  }
2320 }
2321 
2323 {
2324  Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
2325  tools::Long nOneXLogic = aOnePixel.Width();
2326  tools::Long nOneYLogic = aOnePixel.Height();
2327 
2328  // See more about bWorksInPixels in ScOutputData::DrawGrid
2329  bool bWorksInPixels = false;
2330  if (eType == OUTTYPE_WINDOW)
2331  bWorksInPixels = true;
2332 
2333  tools::Long nOneX = 1;
2334  tools::Long nOneY = 1;
2335  if (!bWorksInPixels)
2336  {
2337  nOneX = nOneXLogic;
2338  nOneY = nOneYLogic;
2339  }
2340 
2341  tools::Long nInitPosX = nScrX;
2342  if ( bLayoutRTL )
2343  nInitPosX += nMirrorW - 1; // always in pixels
2344  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2345 
2346  tools::Long nPosY = nScrY;
2347  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2348  {
2349  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2350  if ( pThisRowInfo->bChanged )
2351  {
2352  tools::Long nPosX = nInitPosX;
2353  for (SCCOL nX=nX1; nX<=nX2; nX++)
2354  {
2355  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
2356  bool bIsMerged = false;
2357 
2358  if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2359  {
2360  // find start of merged cell
2361  bIsMerged = true;
2362  SCROW nY = pRowInfo[nArrY].nRowNo;
2363  SCCOL nMergeX = nX;
2364  SCROW nMergeY = nY;
2365  mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2366  }
2367 
2368  std::shared_ptr<sc::Sparkline> pSparkline;
2369  ScAddress aCurrentAddress(nX, pRowInfo[nArrY].nRowNo, nTab);
2370 
2371  if (!mpDoc->ColHidden(nX, nTab) && (pSparkline = mpDoc->GetSparkline(aCurrentAddress))
2372  && (bIsMerged || (!pInfo->bHOverlapped && !pInfo->bVOverlapped)))
2373  {
2374  const tools::Long nWidth = pRowInfo[0].basicCellInfo(nX).nWidth;
2375  const tools::Long nHeight = pThisRowInfo->nHeight;
2376 
2377  Point aPoint(nPosX, nPosY);
2378  Size aSize(nWidth, nHeight);
2379 
2380  sc::SparklineRenderer renderer(*mpDoc);
2381  renderer.render(pSparkline, rRenderContext, tools::Rectangle(aPoint, aSize), nOneX, nOneY, double(aZoomX), double(aZoomY));
2382  }
2383 
2384  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2385  }
2386  }
2387  nPosY += pThisRowInfo->nHeight;
2388  }
2389 
2390 }
2391 
2392 //TODO: moggi Need to check if this can't be written simpler
2394 {
2395 
2396  bool bFirst = true;
2397 
2398  tools::Long nInitPosX = nScrX;
2399  if ( bLayoutRTL )
2400  nInitPosX += nMirrorW - 1; // always in pixels
2401  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2402 
2403  tools::Long nPosY = nScrY;
2404  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2405  {
2406  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2407  if ( pThisRowInfo->bChanged )
2408  {
2409  tools::Long nPosX = nInitPosX;
2410  for (SCCOL nX=nX1; nX<=nX2; nX++)
2411  {
2412  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
2413  bool bIsMerged = false;
2414 
2415  if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2416  {
2417  // find start of merged cell
2418  bIsMerged = true;
2419  SCROW nY = pRowInfo[nArrY].nRowNo;
2420  SCCOL nMergeX = nX;
2421  SCROW nMergeY = nY;
2422  mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2423  }
2424 
2425  if (!mpDoc->ColHidden(nX, nTab) && mpDoc->GetNote(nX, pRowInfo[nArrY].nRowNo, nTab)
2426  && (bIsMerged || (!pInfo->bHOverlapped && !pInfo->bVOverlapped)))
2427  {
2428  if (bFirst)
2429  {
2430  rRenderContext.SetLineColor(COL_WHITE);
2431 
2432  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2433  if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2434  rRenderContext.SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2435  else
2436  rRenderContext.SetFillColor(COL_LIGHTRED);
2437 
2438  bFirst = false;
2439  }
2440 
2441  tools::Long nMarkX = nPosX + ( pRowInfo[0].basicCellInfo(nX).nWidth - 4 ) * nLayoutSign;
2442  if ( bIsMerged || pInfo->bMerged )
2443  {
2444  // if merged, add widths of all cells
2445  SCCOL nNextX = nX + 1;
2446  while ( nNextX <= nX2 + 1 && pThisRowInfo->cellInfo(nNextX).bHOverlapped )
2447  {
2448  nMarkX += pRowInfo[0].basicCellInfo(nNextX).nWidth * nLayoutSign;
2449  ++nNextX;
2450  }
2451  }
2452  if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2453  rRenderContext.DrawRect( tools::Rectangle( nMarkX-5*nLayoutSign,nPosY,nMarkX+1*nLayoutSign,nPosY+6 ) );
2454  }
2455 
2456  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2457  }
2458  }
2459  nPosY += pThisRowInfo->nHeight;
2460  }
2461 }
2462 
2464 {
2465  vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >( mpDev->GetExtOutDevData() );
2466  if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2467  return;
2468 
2469  tools::Long nInitPosX = nScrX;
2470  if ( bLayoutRTL )
2471  {
2472  Size aOnePixel = mpDev->PixelToLogic(Size(1,1));
2473  tools::Long nOneX = aOnePixel.Width();
2474  nInitPosX += nMirrorW - nOneX;
2475  }
2476  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2477 
2478  tools::Long nPosY = nScrY;
2479  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2480  {
2481  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2482  if ( pThisRowInfo->bChanged )
2483  {
2484  tools::Long nPosX = nInitPosX;
2485  for (SCCOL nX=nX1; nX<=nX2; nX++)
2486  {
2487  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
2488  bool bIsMerged = false;
2489  SCROW nY = pRowInfo[nArrY].nRowNo;
2490  SCCOL nMergeX = nX;
2491  SCROW nMergeY = nY;
2492 
2493  if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2494  {
2495  // find start of merged cell
2496  bIsMerged = true;
2497  mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2498  // use origin's pCell for NotePtr test below
2499  }
2500 
2501  if ( mpDoc->GetNote(nMergeX, nMergeY, nTab) && ( bIsMerged ||
2502  ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2503  {
2504  tools::Long nNoteWidth = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTX );
2505  tools::Long nNoteHeight = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTY );
2506 
2507  tools::Long nMarkX = nPosX + ( pRowInfo[0].basicCellInfo(nX).nWidth - nNoteWidth ) * nLayoutSign;
2508  if ( bIsMerged || pInfo->bMerged )
2509  {
2510  // if merged, add widths of all cells
2511  SCCOL nNextX = nX + 1;
2512  while ( nNextX <= nX2 + 1 && pThisRowInfo->cellInfo(nNextX).bHOverlapped )
2513  {
2514  nMarkX += pRowInfo[0].basicCellInfo(nNextX).nWidth * nLayoutSign;
2515  ++nNextX;
2516  }
2517  }
2518  if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2519  {
2520  tools::Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2521  const ScPostIt* pNote = mpDoc->GetNote(nMergeX, nMergeY, nTab);
2522 
2523  // Note title is the cell address (as on printed note pages)
2524  ScAddress aAddress( nMergeX, nMergeY, nTab );
2525  OUString aTitle(aAddress.Format(ScRefFlags::VALID, mpDoc, mpDoc->GetAddressConvention()));
2526 
2527  // Content has to be a simple string without line breaks
2528  OUString aContent = pNote->GetText();
2529  aContent = aContent.replaceAll("\n", " ");
2530 
2531  vcl::PDFNote aNote;
2532  aNote.Title = aTitle;
2533  aNote.Contents = aContent;
2534  pPDFData->CreateNote( aNoteRect, aNote );
2535  }
2536  }
2537 
2538  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2539  }
2540  }
2541  nPosY += pThisRowInfo->nHeight;
2542  }
2543 }
2544 
2546 {
2547  if (!bAnyClipped)
2548  return;
2549 
2550  Color aArrowFillCol( COL_LIGHTRED );
2551 
2552  DrawModeFlags nOldDrawMode = mpDev->GetDrawMode();
2553  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2554  if ( mbUseStyleColor && rStyleSettings.GetHighContrastMode() )
2555  {
2556  // use DrawMode to change the arrow's outline color
2557  mpDev->SetDrawMode( nOldDrawMode | DrawModeFlags::SettingsLine );
2558  // use text color also for the fill color
2559  aArrowFillCol = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
2560  }
2561 
2562  tools::Long nInitPosX = nScrX;
2563  if ( bLayoutRTL )
2564  nInitPosX += nMirrorW - 1; // always in pixels
2565  tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2566 
2567  tools::Rectangle aCellRect;
2568  tools::Long nPosY = nScrY;
2569  for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2570  {
2571  RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2572  if ( pThisRowInfo->bChanged )
2573  {
2574  SCROW nY = pThisRowInfo->nRowNo;
2575  tools::Long nPosX = nInitPosX;
2576  for (SCCOL nX=nX1; nX<=nX2; nX++)
2577  {
2578  ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
2579  if (pInfo->nClipMark != ScClipMark::NONE)
2580  {
2581  if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2582  {
2583  // merge origin may be outside of visible area - use document functions
2584 
2585  SCCOL nOverX = nX;
2586  SCROW nOverY = nY;
2587  tools::Long nStartPosX = nPosX;
2588  tools::Long nStartPosY = nPosY;
2589 
2590  while ( nOverX > 0 && ( mpDoc->GetAttr(
2591  nOverX, nOverY, nTab, ATTR_MERGE_FLAG )->GetValue() & ScMF::Hor ) )
2592  {
2593  --nOverX;
2594  nStartPosX -= nLayoutSign * static_cast<tools::Long>( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2595  }
2596 
2597  while ( nOverY > 0 && ( mpDoc->GetAttr(
2598  nOverX, nOverY, nTab, ATTR_MERGE_FLAG )->GetValue() & ScMF::Ver ) )
2599  {
2600  --nOverY;
2601  nStartPosY -= nLayoutSign * static_cast<tools::Long>( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2602  }
2603 
2604  tools::Long nOutWidth = static_cast<tools::Long>( mpDoc->GetColWidth(nOverX,nTab) * mnPPTX );
2605  tools::Long nOutHeight = static_cast<tools::Long>( mpDoc->GetRowHeight(nOverY,nTab) * mnPPTY );
2606 
2607  const ScMergeAttr* pMerge = mpDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2608  SCCOL nCountX = pMerge->GetColMerge();
2609  for (SCCOL i=1; i<nCountX; i++)
2610  nOutWidth += mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX;
2611  SCROW nCountY = pMerge->GetRowMerge();
2612  nOutHeight += mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2613 
2614  if ( bLayoutRTL )
2615  nStartPosX -= nOutWidth - 1;
2616  aCellRect = tools::Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2617  }
2618  else
2619  {
2620  tools::Long nOutWidth = pRowInfo[0].basicCellInfo(nX).nWidth;
2621  tools::Long nOutHeight = pThisRowInfo->nHeight;
2622 
2623  if ( pInfo->bMerged && pInfo->pPatternAttr )
2624  {
2625  SCCOL nOverX = nX;
2626  SCROW nOverY = nY;
2627  const ScMergeAttr* pMerge =
2628  &pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2629  SCCOL nCountX = pMerge->GetColMerge();
2630  for (SCCOL i=1; i<nCountX; i++)
2631  nOutWidth += mpDoc->GetColWidth(nOverX+i,nTab) * mnPPTX;
2632  SCROW nCountY = pMerge->GetRowMerge();
2633  nOutHeight += mpDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, mnPPTY);
2634  }
2635 
2636  tools::Long nStartPosX = nPosX;
2637  if ( bLayoutRTL )
2638  nStartPosX -= nOutWidth - 1;
2639  // #i80447# create aCellRect from two points in case nOutWidth is 0
2640  aCellRect = tools::Rectangle( Point( nStartPosX, nPosY ),
2641  Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2642  }
2643 
2644  aCellRect.AdjustBottom( -1 ); // don't paint over the cell grid
2645  if ( bLayoutRTL )
2646  aCellRect.AdjustLeft(1 );
2647  else
2648  aCellRect.AdjustRight( -1 );
2649 
2650  tools::Long nMarkPixel = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTX );
2651  Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2652 
2653  if (bVertical)
2654  {
2656  {
2657  // visually top
2658  tools::Rectangle aMarkRect = aCellRect;
2659  aMarkRect.SetBottom(aCellRect.Top() + nMarkPixel - 1);
2660  SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, true, true);
2661  }
2662  if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Top : ScClipMark::Bottom))
2663  {
2664  // visually bottom
2665  tools::Rectangle aMarkRect = aCellRect;
2666  aMarkRect.SetTop(aCellRect.Bottom() + nMarkPixel + 1);
2667  SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, false,
2668  true);
2669  }
2670  }
2671  else
2672  {
2674  {
2675  // visually left
2676  tools::Rectangle aMarkRect = aCellRect;
2677  aMarkRect.SetRight(aCellRect.Left() + nMarkPixel - 1);
2678  SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, true,
2679  false);
2680  }
2681  if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Left : ScClipMark::Right))
2682  {
2683  // visually right
2684  tools::Rectangle aMarkRect = aCellRect;
2685  aMarkRect.SetLeft(aCellRect.Right() - nMarkPixel + 1);
2686  SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, false,
2687  false);
2688  }
2689  }
2690  }
2691  nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
2692  }
2693  }
2694  nPosY += pThisRowInfo->nHeight;
2695  }
2696 
2697  mpDev->SetDrawMode(nOldDrawMode);
2698 }
2699 
2700 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tools::Long nScrY
Definition: output.hxx:185
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
sal_uInt16 Count() const
void SetClipRegion()
ScRotateDir nRotateDir
Definition: fillinfo.hxx:170
std::optional< Color > mxColorScale
Definition: fillinfo.hxx:152
SVXCORE_DLLPUBLIC css::uno::Reference< css::drawing::XDrawPage > GetXDrawPageForSdrPage(SdrPage *pPage) noexcept
void SetSyntaxMode(bool bNewMode)
Definition: output.cxx:284
bool mbGradient
Definition: fillinfo.hxx:67
void EnableIdle(bool bDo)
Definition: document.hxx:2201
SCCOL GetColMerge() const
Definition: attrib.hxx:68
bool IsDataValid(const OUString &rTest, const ScPatternAttr &rPattern, const ScAddress &rPos) const
Definition: validat.cxx:518
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
const SCCOL SC_ROTMAX_NONE
Definition: fillinfo.hxx:183
std::optional< Color > mxTextColor
Definition: output.hxx:221
void StripHidden(SCCOL &rX1, SCROW &rY1, SCCOL &rX2, SCROW &rY2, SCTAB nTab)
Definition: document.cxx:4750
SCROW nEditRow
Definition: output.hxx:209
bool mbPageMode
Definition: fillinfo.hxx:262
sal_Int32 nIndex
ScRotateDir GetRotateDir(const SfxItemSet *pCondSet) const
Definition: patattr.cxx:1371
ScAddress aStart
Definition: address.hxx:497
OUString Title
void DrawFrame(vcl::RenderContext &rRenderContext)
Definition: output.cxx:1387
ScRotateDir
Definition: fillinfo.hxx:40
sal_uInt8 GetAlpha() const
SC_DLLPUBLIC bool IsTabProtected(SCTAB nTab) const
Definition: documen3.cxx:1913
ScChangeActionType GetType() const
Definition: chgtrack.hxx:317
static tools::Polygon DrawArrow(OutputDevice &rOut, const tools::Rectangle &rRect, const Size &rSize, const Color &rCol, bool bLeftOrTop, bool bVertical)
void SetShowNullValues(bool bSet)
Definition: output.cxx:252
OUString Contents
static bool IsActionShown(const ScChangeAction &rAction, const ScChangeViewSettings &rSettings, ScDocument &rDocument)
Definition: viewutil.cxx:135
OUString aLastUserName
Definition: chgtrack.hxx:52
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTMAGENTA
SCROW Row() const
Definition: address.hxx:274
ScChangeAction * GetNext() const
Definition: chgtrack.hxx:322
Class shared between grid windows to cache spelling results.
SvxRotateMode
void DrawClipMarks()
Definition: output.cxx:2545
bool bLayoutRTL
Definition: output.hxx:236
bool IsTransparent() const
bool mbUseStyleColor
Definition: output.hxx:216
constexpr tools::Long Left() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
void AddVerLine(bool bWorksInPixels, tools::Long nX, tools::Long nY1, tools::Long nY2, bool bDashed=false)
Definition: gridmerg.cxx:140
bool bSnapPixel
Definition: output.hxx:231
void Union(const tools::Rectangle &rRegion)
constexpr::Color COL_RED(0x80, 0x00, 0x00)
std::unique_ptr< sal_Int32[]> pData
SCCOL nX1
Definition: output.hxx:189
bool Intersects(const ScRange &rRange) const
Definition: address.hxx:734
sc::IconSetBitmapMap & GetIconSetBitmapMap()
Definition: documen2.cxx:1452
bool GetDirty() const
SCCOL nEditCol
Definition: output.hxx:208
#define SAL_INFO_IF(condition, area, stream)
long Long
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
const sc::SpellCheckContext * mpSpellCheckCxt
Definition: output.hxx:240
constexpr TypedWhichId< SvxRotateModeItem > ATTR_ROTATE_MODE(136)
bool bVOverlapped
Definition: fillinfo.hxx:174
void DrawRefMark(SCCOL nRefStartX, SCROW nRefStartY, SCCOL nRefEndX, SCROW nRefEndY, const Color &rColor, bool bHandle)
Draws reference mark and returns its properties.
Definition: output.cxx:2013
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
void DrawPolygon(const tools::Polygon &rPoly)
sal_Int32 nIconIndex
Definition: fillinfo.hxx:93
void SetSnapPixel()
Definition: output.cxx:267
bool mbShowFormulas
Definition: output.hxx:227
void DrawChangeTrack()
Definition: output.cxx:2258
ScPrintRangeData & GetData(size_t i)
Definition: pagedata.cxx:60
SVX_ROTATE_MODE_STANDARD
static BitmapEx & getBitmap(sc::IconSetBitmapMap &rBitmapMap, ScIconSetType eType, sal_Int32 nIndex)
bool bVertical
Definition: output.hxx:234
const sal_uInt8 SC_CLIPMARK_SIZE
Definition: fillinfo.hxx:51
ScOutputType eType
Definition: output.hxx:197
ScChangeActionType
Definition: chgtrack.hxx:62
const SvxShadowItem * pVShadowOrigin
Definition: fillinfo.hxx:165
ScAddress aEnd
Definition: address.hxx:498
void IntersectClipRegion(const tools::Rectangle &rRect)
double mnZero
Definition: fillinfo.hxx:64
void SetShowFormulas(bool bSet)
Definition: output.cxx:257
bool bPagebreakMode
Definition: output.hxx:213
Fraction aZoomX
Definition: output.hxx:200
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
void SetMarkClipped(bool bSet)
Definition: output.cxx:247
constexpr TypedWhichId< ScProtectionAttr > ATTR_PROTECTION(149)
const ScAppOptions & rOpt
Definition: chgtrack.hxx:50
SVX_ROTATE_MODE_TOP
bool bMetaFile
Definition: output.hxx:211
sal_Int64 Tab() const
Definition: bigrange.hxx:46
ScRefCellValue maCell
Definition: fillinfo.hxx:148
double mnLength
Definition: fillinfo.hxx:66
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
CALCPAGEBREAKAUTOMATIC
drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveRange(sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow, const Color *pForceColor) const
SCROW nRowNo
Definition: fillinfo.hxx:233
ReferenceMark FillReferenceMark(SCCOL nRefStartX, SCROW nRefStartY, SCCOL nRefEndX, SCROW nRefEndY, const Color &rColor)
Definition: output.cxx:1921
const SvxShadowItem * pHShadowOrigin
Definition: fillinfo.hxx:164
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
SC_DLLPUBLIC ScBreakType HasRowBreak(SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4409
Color maColor
Definition: fillinfo.hxx:65
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4211
void SetContentDevice(OutputDevice *pContentDev)
Definition: output.cxx:226
SCROW nY2
Definition: output.hxx:192
SCCOL nVisX1
Definition: output.hxx:193
void SetDrawMode(DrawModeFlags nDrawMode)
constexpr::Color COL_MAGENTA(0x80, 0x00, 0x80)
SC_DLLPUBLIC const ScValidationData * GetValidationEntry(sal_uLong nIndex) const
Definition: documen4.cxx:888
Color GetTrackContentColor() const
Definition: appoptio.hxx:59
constexpr tools::Long Width() const
Color GetTrackMoveColor() const
Definition: appoptio.hxx:65
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Definition: document.cxx:6716
bool ShowChanges() const
Definition: chgviset.hxx:77
SvxShadowLocation GetLocation() const
SCROW nVisY2
Definition: output.hxx:196
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:891
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
ScCellInfo & cellInfo(SCCOL nCol)
Definition: fillinfo.hxx:191
Additional class containing cell annotation data.
Definition: postit.hxx:160
constexpr::Color COL_CYAN(0x00, 0x80, 0x80)
void DrawExtraShadow(bool bLeft, bool bTop, bool bRight, bool bBottom)
Definition: output.cxx:1191
bool mbShowNullValues
Definition: output.hxx:226
static ScRotateDir lcl_GetRotateDir(const ScDocument *pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: output.cxx:679
ScActionColorChanger(const ScChangeTrack &rTrack)
Definition: output.cxx:86
bool GetHighContrastMode() const
const Color nAuthorColor[SC_AUTHORCOLORCOUNT]
Definition: output.cxx:79
bool bPrinted
Definition: fillinfo.hxx:179
ScChangeAction * GetFirst() const
Definition: chgtrack.hxx:953
std::map< OUString, BitmapEx > IconSetBitmapMap
Definition: document.hxx:216
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
SCTAB Tab() const
Definition: address.hxx:283
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
std::unique_ptr< drawinglayer::processor2d::BaseProcessor2D > CreateProcessor2D()
Definition: output.cxx:1712
void SetRow(SCROW nRowP)
Definition: address.hxx:287
ScClipMark nClipMark
Definition: fillinfo.hxx:169
sal_uInt16 nHeight
Definition: fillinfo.hxx:232
ScAddress aPos
size_t GetCount() const
Definition: pagedata.hxx:73
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
void DrawLine(const Point &rStartPt, const Point &rEndPt)
SC_DLLPUBLIC const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4799
void SetCol(SCCOL nColP)
Definition: address.hxx:291
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTRED
bool IsChanged() const
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2485
SVX_ROTATE_MODE_CENTER
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4764
void DrawRect(const tools::Rectangle &rRect)
bool bSolidBackground
Definition: output.hxx:214
static bool lcl_EqualBack(const RowInfo &rFirst, const RowInfo &rOther, SCCOL nX1, SCCOL nX2, bool bShowProt, bool bPagebreakMode)
Definition: output.cxx:750
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:72
void AddHorLine(bool bWorksInPixels, tools::Long nX1, tools::Long nX2, tools::Long nY, bool bDashed=false)
Definition: gridmerg.cxx:96
void PutInOrder(T &nStart, T &nEnd)
Definition: address.hxx:150
double mnPPTY
Definition: output.hxx:199
constexpr void SetLeft(tools::Long v)
ScShadowPart
Definition: fillinfo.hxx:53
void render(std::shared_ptr< sc::Sparkline > const &pSparkline, vcl::RenderContext &rRenderContext, tools::Rectangle const &rRectangle, tools::Long nOneX, tools::Long nOneY, double fScaleX, double fScaleY)
DocumentType eType
void SetEditCell(SCCOL nCol, SCROW nRow)
Definition: output.cxx:272
bool GetHideCell() const
Definition: attrib.hxx:147
const Color & GetColor() const
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALIDDATA(153)
void SetRowHeight(sal_Int32 nRow, sal_Int32 nHeight)
Color GetTrackInsertColor() const
Definition: appoptio.hxx:61
const Color & GetColor() const
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1081
void SetCellRotations()
Definition: output.cxx:619
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:890
void SetClipRange(sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow)
void SetLineColor()
void DrawRotatedFrame(vcl::RenderContext &rRenderContext)
Definition: output.cxx:1513
void SetColWidth(sal_Int32 nCol, sal_Int32 nWidth)
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4495
UNDERLYING_TYPE get() const
SC_DLLPUBLIC void InitDrawLayer(SfxObjectShell *pDocShell=nullptr)
Definition: documen9.cxx:98
SCCOL nRotMaxCol
Definition: fillinfo.hxx:234
bool bShowSpellErrors
Definition: output.hxx:228
ScDocument * mpDoc
Definition: output.hxx:182
Render a provided sparkline into the input rectangle.
SCCOL nX2
Definition: output.hxx:191
void SetCellRotation(sal_Int32 nCol, sal_Int32 nRow, SvxRotateMode eRotMode, double fOrientation)
void append(const Primitive2DReference &)
double mnPPTX
Definition: output.hxx:198
Fraction aZoomY
Definition: output.hxx:201
int i
VclPtr< OutputDevice > pFmtDevice
Definition: output.hxx:178
bool bChanged
Definition: fillinfo.hxx:239
bool bMarkClipped
Definition: output.hxx:229
RowInfo * pRowInfo
Definition: output.hxx:180
ScIconSetType eIconSetType
Definition: fillinfo.hxx:94
Color GetColor() const
Definition: chgtrack.hxx:59
sal_Int16 SCCOL
Definition: types.hxx:21
svx::frame::Array maArray
Definition: fillinfo.hxx:257
ScShadowPart eVShadowPart
Definition: fillinfo.hxx:168
Describes reference mark to be drawn, position & size in TWIPs.
Definition: output.hxx:63
#define SC_MOD()
Definition: scmod.hxx:249
void DrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
const ScPatternAttr * pPatternAttr
Definition: fillinfo.hxx:150
bool SetChangedClip()
Definition: output.cxx:1776
const SdrPage * GetPage(sal_uInt16 nPgNum) const
const ScRange & GetPrintRange() const
Definition: pagedata.hxx:44
constexpr tools::Long Right() const
void SetFillColor()
bool mbSyntaxMode
Definition: output.hxx:219
void DrawBackground(vcl::RenderContext &rRenderContext)
Definition: output.cxx:1022
void DrawDocumentBackground()
Definition: output.cxx:816
OUString GetText() const
Returns the caption text of this note.
Definition: postit.cxx:916
const SfxItemSet * pConditionSet
Definition: fillinfo.hxx:151
bool GetIsExportNotes() const
constexpr tools::Long Top() const
static void DeleteInterpretProgress()
Definition: progress.cxx:154
ScBigRange & GetBigRange()
Definition: chgtrack.hxx:231
bool bEmptyBack
Definition: fillinfo.hxx:236
SCROW nY1
Definition: output.hxx:190
VclPtr< OutputDevice > mpRefDevice
Definition: output.hxx:177
double toRadians(D x)
bool IsFullyTransparent() const
constexpr void SetRight(tools::Long v)
ScBasicCellInfo & basicCellInfo(SCCOL nCol)
Definition: fillinfo.hxx:204
bool IsRunning() const
SCSIZE nArrCount
Definition: output.hxx:181
sal_Int32 GetRowCount() const
static void CreateInterpretProgress(ScDocument *pDoc, bool bWait=true)
Definition: progress.cxx:134
SCROW nVisY1
Definition: output.hxx:194
constexpr void SetBottom(tools::Long v)
SVX_ROTATE_MODE_BOTTOM
ScOutputData(OutputDevice *pNewDev, ScOutputType eNewType, ScTableInfo &rTabInfo, ScDocument *pNewDoc, SCTAB nNewTab, tools::Long nNewScrX, tools::Long nNewScrY, SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2, double nPixelPerTwipsX, double nPixelPerTwipsY, const Fraction *pZoomX=nullptr, const Fraction *pZoomY=nullptr)
Definition: output.cxx:140
void Update(const ScChangeAction &rAction)
Definition: output.cxx:94
DrawModeFlags GetDrawMode() const
SC_DLLPUBLIC const SfxItemSet * GetCondResult(SCCOL nCol, SCROW nRow, SCTAB nTab, ScRefCellValue *pCell=nullptr) const
Definition: documen4.cxx:805
SC_DLLPUBLIC bool ExtendMerge(SCCOL nStartCol, SCROW nStartRow, SCCOL &rEndCol, SCROW &rEndRow, SCTAB nTab, bool bRefresh=false)
Definition: document.cxx:5662
tools::Long nScrX
Definition: output.hxx:184
ScShadowPart eHShadowPart
Definition: fillinfo.hxx:167
constexpr void SetTop(tools::Long v)
void DrawClear()
Definition: output.cxx:1332
void SetGridColor(const Color &rColor)
Definition: output.cxx:242
ScOutputType
Definition: output.hxx:57
Degree100 GetRotateVal(const SfxItemSet *pCondSet) const
Definition: patattr.cxx:1357
SCCOL Col() const
Definition: address.hxx:279
void DrawOneChange(SCCOL nRefStartX, SCROW nRefStartY, SCCOL nRefEndX, SCROW nRefEndY, const Color &rColor, sal_uInt16 nType)
Definition: output.cxx:2140
SCTAB nTab
Definition: output.hxx:183
Color aGridColor
Definition: output.hxx:224
tools::Long AdjustTop(tools::Long nVertMoveDelta)
#define SC_AUTHORCOLORCOUNT
Definition: output.cxx:77
tools::Long nScrH
Definition: output.hxx:187
constexpr tools::Long Bottom() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
ScBreakType
Definition: global.hxx:138
SC_DLLPUBLIC std::shared_ptr< sc::Sparkline > GetSparkline(ScAddress const &rPosition)
Returns sparkline at the address if it exists.
Definition: document.cxx:6611
std::unique_ptr< drawinglayer::processor2d::BaseProcessor2D > createBaseProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
constexpr TypedWhichId< SvxBrushItem > ATTR_BACKGROUND(148)
static SvxBrushItem * GetEmptyBrushItem()
Definition: global.hxx:591
static tools::Long lclGetSnappedY(const OutputDevice &rDev, tools::Long nPosY, bool bSnapPixel)
Definition: output.cxx:1382
static tools::Long lclGetSnappedX(const OutputDevice &rDev, tools::Long nPosX, bool bSnapPixel)
Definition: output.cxx:1377
CellType meType
Definition: cellvalue.hxx:105
Color GetTrackDeleteColor() const
Definition: appoptio.hxx:63
SC_DLLPUBLIC bool EnsureFormulaCellResults(const ScRange &rRange, bool bSkipRunning=false)
Make sure all of the formula cells in the specified range have been fully calculated.
void DrawGrid(vcl::RenderContext &rRenderContext, bool bGrid, bool bPage, bool bMergeCover=false)
Definition: output.cxx:296
constexpr TypedWhichId< ScMergeFlagAttr > ATTR_MERGE_FLAG(145)
void CreateNote(const tools::Rectangle &rRect, const PDFNote &rNote, sal_Int32 nPageNr=-1)
sal_Int32 SCROW
Definition: types.hxx:17
ScBigAddress aStart
Definition: bigrange.hxx:108
bool bAnyClipped
Definition: output.hxx:233
void SetShowSpellErrors(bool bSet)
Definition: output.cxx:262
bool HasCellRotation() const
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
bool bHOverlapped
Definition: fillinfo.hxx:173
constexpr tools::Long Height() const
Color maAxisColor
Definition: fillinfo.hxx:69
constexpr::Color COL_GREEN(0x00, 0x80, 0x00)
std::optional< Color > mxValueColor
Definition: output.hxx:220
const ScIconSetInfo * pIconSet
Definition: fillinfo.hxx:154
bool GetProtection() const
Definition: attrib.hxx:143
void SetXOffset(sal_Int32 nXOffset)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
SC_DLLPUBLIC ScBreakType HasColBreak(SCCOL nCol, SCTAB nTab) const
Definition: document.cxx:4424
SCCOL nVisX2
Definition: output.hxx:195
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BROWN
bool IsVisible() const
Definition: chgtrack.cxx:141
ScChangeViewSettings * GetChangeViewSettings() const
Definition: document.hxx:2236
void DrawSparklines(vcl::RenderContext &rRenderContext)
Definition: output.cxx:2322
void SetSpellCheckContext(const sc::SpellCheckContext *pCxt)
Definition: output.cxx:221
tools::Long mnHeight
Definition: fillinfo.hxx:95
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
bool bTabProtected
Definition: output.hxx:235
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
bool bHideGrid
Definition: fillinfo.hxx:180
const std::set< OUString > & rUsers
Definition: chgtrack.hxx:51
void DrawNoteMarks(vcl::RenderContext &rRenderContext)
Definition: output.cxx:2393
CALCPAGEBREAKMANUAL
std::optional< Color > mxFormulaColor
Definition: output.hxx:222
SC_DLLPUBLIC bool IsLayoutRTL(SCTAB nTab) const
Definition: document.cxx:989
SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4479
const OUString & GetUser() const
Definition: chgtrack.hxx:349
sal_uInt16 nLastUserIndex
Definition: chgtrack.hxx:53
ScIconSetType
Definition: colorscale.hxx:188
VclPtr< OutputDevice > mpDev
Definition: output.hxx:176
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTBLUE
sal_Int32 GetColCount() const
void SetMirrorWidth(tools::Long nNew)
Definition: output.cxx:237
CALCPROTECTEDBACKGROUND
ScRange MakeRange(const ScDocument &rDoc) const
Definition: bigrange.hxx:134
void Flush()
Definition: gridmerg.cxx:184
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1080
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
vcl::Region GetChangedAreaRegion()
Definition: output.cxx:1734
vcl::ExtOutDevData * GetExtOutDevData() const
constexpr::Color COL_BLUE(0x00, 0x00, 0x80)
void SetMetaFileMode(bool bNewMode)
Definition: output.cxx:279
SCROW GetRowMerge() const
Definition: attrib.hxx:69
const SvxBrushItem * pBackground
Definition: fillinfo.hxx:156
sal_Int32 nLength
tools::Long nScrW
Definition: output.hxx:186
void DrawShadow()
Definition: output.cxx:1186
void AddPDFNotes()
Definition: output.cxx:2463
static const SvxBrushItem * lcl_FindBackground(const ScDocument *pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: output.cxx:712
SC_DLLPUBLIC void ExtendOverlapped(SCCOL &rStartCol, SCROW &rStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:5572
const Size & GetSizePixel() const
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4170
void DrawGradient(const tools::Rectangle &rRect, const Gradient &rGradient)
basegfx::B2DHomMatrix GetViewTransformation() const
void FindChanged()
Definition: output.cxx:1817
bool IsIdleEnabled() const
Definition: document.hxx:2200
tools::Long GetScaledRowHeight(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, double fScale, const tools::Long *pnMaxHeight=nullptr) const
Definition: document.cxx:4248
ScTableInfo & mrTabInfo
Definition: output.hxx:179
DrawModeFlags
const Color & GetWindowTextColor() const
bool bEditMode
Definition: output.hxx:207
bool bMerged
Definition: fillinfo.hxx:172
void SetYOffset(sal_Int32 nYOffset)
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
void SetPagebreakMode(ScPageBreakData *pPageData)
Definition: output.cxx:587
const ScDataBarInfo * pDataBar
Definition: fillinfo.hxx:153
bool m_bDetectedRangeSegmentation false
sal_uInt16 GetWidth() const
SvxShadowLocation
sal_uInt16 nWidth
Definition: fillinfo.hxx:110
tools::Long nMirrorW
Definition: output.hxx:188