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