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