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