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