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 Region ScOutputData::GetChangedAreaRegion() 1689 { 1690 Region aRegion; 1691 Rectangle aDrawingRect; 1692 bool bHad(false); 1693 long nPosY = nScrY; 1694 SCSIZE nArrY; 1695 1696 aDrawingRect.Left() = nScrX; 1697 aDrawingRect.Right() = nScrX+nScrW-1; 1698 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 = true; 1709 } 1710 1711 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; 1712 } 1713 else if(bHad) 1714 { 1715 aRegion.Union(pDev->PixelToLogic(aDrawingRect)); 1716 bHad = false; 1717 } 1718 1719 nPosY += pRowInfo[nArrY].nHeight; 1720 } 1721 1722 if(bHad) 1723 { 1724 aRegion.Union(pDev->PixelToLogic(aDrawingRect)); 1725 } 1726 1727 return aRegion; 1728 } 1729 1730 sal_Bool ScOutputData::SetChangedClip() 1731 { 1732 PolyPolygon aPoly; 1733 1734 Rectangle aDrawingRect; 1735 aDrawingRect.Left() = nScrX; 1736 aDrawingRect.Right() = nScrX+nScrW-1; 1737 1738 sal_Bool bHad = sal_False; 1739 long nPosY = nScrY; 1740 SCSIZE nArrY; 1741 for (nArrY=1; nArrY+1<nArrCount; nArrY++) 1742 { 1743 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 1744 1745 if ( pThisRowInfo->bChanged ) 1746 { 1747 if (!bHad) 1748 { 1749 aDrawingRect.Top() = nPosY; 1750 bHad = sal_True; 1751 } 1752 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; 1753 } 1754 else if (bHad) 1755 { 1756 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); 1757 bHad = sal_False; 1758 } 1759 nPosY += pRowInfo[nArrY].nHeight; 1760 } 1761 1762 if (bHad) 1763 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); 1764 1765 sal_Bool bRet = (aPoly.Count() != 0); 1766 if (bRet) 1767 pDev->SetClipRegion(Region(aPoly)); 1768 return bRet; 1769 } 1770 1771 void ScOutputData::FindChanged() 1772 { 1773 SCCOL nX; 1774 SCSIZE nArrY; 1775 1776 sal_Bool bWasIdleDisabled = pDoc->IsIdleDisabled(); 1777 pDoc->DisableIdle( sal_True ); 1778 for (nArrY=0; nArrY<nArrCount; nArrY++) 1779 pRowInfo[nArrY].bChanged = sal_False; 1780 1781 sal_Bool bProgress = sal_False; 1782 for (nArrY=0; nArrY<nArrCount; nArrY++) 1783 { 1784 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 1785 for (nX=nX1; nX<=nX2; nX++) 1786 { 1787 ScBaseCell* pCell = pThisRowInfo->pCellInfo[nX+1].pCell; 1788 if (pCell) 1789 if (pCell->GetCellType() == CELLTYPE_FORMULA) 1790 { 1791 ScFormulaCell* pFCell = (ScFormulaCell*)pCell; 1792 if ( !bProgress && pFCell->GetDirty() ) 1793 { 1794 ScProgress::CreateInterpretProgress( pDoc, sal_True ); 1795 bProgress = sal_True; 1796 } 1797 if (!pFCell->IsRunning()) 1798 { 1799 (void)pFCell->GetValue(); 1800 if (pFCell->IsChanged()) 1801 { 1802 pThisRowInfo->bChanged = sal_True; 1803 if ( pThisRowInfo->pCellInfo[nX+1].bMerged ) 1804 { 1805 SCSIZE nOverY = nArrY + 1; 1806 while ( nOverY<nArrCount && 1807 pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped ) 1808 { 1809 pRowInfo[nOverY].bChanged = sal_True; 1810 ++nOverY; 1811 } 1812 } 1813 } 1814 } 1815 } 1816 } 1817 } 1818 if ( bProgress ) 1819 ScProgress::DeleteInterpretProgress(); 1820 pDoc->DisableIdle( bWasIdleDisabled ); 1821 } 1822 1823 #ifdef OLD_SELECTION_PAINT 1824 void ScOutputData::DrawMark( Window* pWin ) 1825 { 1826 Rectangle aRect; 1827 ScInvertMerger aInvert( pWin ); 1828 //! additional method AddLineRect for ScInvertMerger? 1829 1830 long nPosY = nScrY; 1831 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) 1832 { 1833 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 1834 if (pThisRowInfo->bChanged) 1835 { 1836 long nPosX = nScrX; 1837 if (bLayoutRTL) 1838 nPosX += nMirrorW - 1; // always in pixels 1839 1840 aRect = Rectangle( Point( nPosX,nPosY ), Size(1, pThisRowInfo->nHeight) ); 1841 if (bLayoutRTL) 1842 aRect.Left() = aRect.Right() + 1; 1843 else 1844 aRect.Right() = aRect.Left() - 1; 1845 1846 sal_Bool bOldMarked = sal_False; 1847 for (SCCOL nX=nX1; nX<=nX2; nX++) 1848 { 1849 if (pThisRowInfo->pCellInfo[nX+1].bMarked != bOldMarked) 1850 { 1851 if (bOldMarked && aRect.Right() >= aRect.Left()) 1852 aInvert.AddRect( aRect ); 1853 1854 if (bLayoutRTL) 1855 aRect.Right() = nPosX; 1856 else 1857 aRect.Left() = nPosX; 1858 1859 bOldMarked = pThisRowInfo->pCellInfo[nX+1].bMarked; 1860 } 1861 1862 if (bLayoutRTL) 1863 { 1864 nPosX -= pRowInfo[0].pCellInfo[nX+1].nWidth; 1865 aRect.Left() = nPosX+1; 1866 } 1867 else 1868 { 1869 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth; 1870 aRect.Right() = nPosX-1; 1871 } 1872 } 1873 if (bOldMarked && aRect.Right() >= aRect.Left()) 1874 aInvert.AddRect( aRect ); 1875 } 1876 nPosY += pThisRowInfo->nHeight; 1877 } 1878 } 1879 #endif 1880 1881 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY, 1882 SCCOL nRefEndX, SCROW nRefEndY, 1883 const Color& rColor, sal_Bool bHandle ) 1884 { 1885 PutInOrder( nRefStartX, nRefEndX ); 1886 PutInOrder( nRefStartY, nRefEndY ); 1887 1888 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY ) 1889 pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab ); 1890 1891 if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 && 1892 nRefStartY <= nVisY2 && nRefEndY >= nVisY1 ) 1893 { 1894 long nMinX = nScrX; 1895 long nMinY = nScrY; 1896 long nMaxX = nScrX+nScrW-1; 1897 long nMaxY = nScrY+nScrH-1; 1898 if ( bLayoutRTL ) 1899 { 1900 long nTemp = nMinX; 1901 nMinX = nMaxX; 1902 nMaxX = nTemp; 1903 } 1904 long nLayoutSign = bLayoutRTL ? -1 : 1; 1905 1906 sal_Bool bTop = sal_False; 1907 sal_Bool bBottom = sal_False; 1908 sal_Bool bLeft = sal_False; 1909 sal_Bool bRight = sal_False; 1910 1911 long nPosY = nScrY; 1912 sal_Bool bNoStartY = ( nY1 < nRefStartY ); 1913 sal_Bool bNoEndY = sal_False; 1914 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check 1915 { 1916 SCROW nY = pRowInfo[nArrY].nRowNo; 1917 1918 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) ) 1919 { 1920 nMinY = nPosY; 1921 bTop = sal_True; 1922 } 1923 if ( nY==nRefEndY ) 1924 { 1925 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2; 1926 bBottom = sal_True; 1927 } 1928 if ( nY>nRefEndY && bNoEndY ) 1929 { 1930 nMaxY = nPosY-2; 1931 bBottom = sal_True; 1932 } 1933 bNoStartY = ( nY < nRefStartY ); 1934 bNoEndY = ( nY < nRefEndY ); 1935 nPosY += pRowInfo[nArrY].nHeight; 1936 } 1937 1938 long nPosX = nScrX; 1939 if ( bLayoutRTL ) 1940 nPosX += nMirrorW - 1; // always in pixels 1941 1942 for (SCCOL nX=nX1; nX<=nX2; nX++) 1943 { 1944 if ( nX==nRefStartX ) 1945 { 1946 nMinX = nPosX; 1947 bLeft = sal_True; 1948 } 1949 if ( nX==nRefEndX ) 1950 { 1951 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign; 1952 bRight = sal_True; 1953 } 1954 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; 1955 } 1956 1957 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign && 1958 nMaxY >= nMinY ) 1959 { 1960 pDev->SetLineColor( rColor ); 1961 if (bTop && bBottom && bLeft && bRight) 1962 { 1963 pDev->SetFillColor(); 1964 pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) ); 1965 } 1966 else 1967 { 1968 if (bTop) 1969 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) ); 1970 if (bBottom) 1971 pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) ); 1972 if (bLeft) 1973 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) ); 1974 if (bRight) 1975 pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) ); 1976 } 1977 if ( bHandle && bRight && bBottom ) 1978 { 1979 pDev->SetLineColor(); 1980 pDev->SetFillColor( rColor ); 1981 pDev->DrawRect( Rectangle( nMaxX-3*nLayoutSign, nMaxY-3, nMaxX+nLayoutSign, nMaxY+1 ) ); 1982 } 1983 } 1984 } 1985 } 1986 1987 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY, 1988 SCCOL nRefEndX, SCROW nRefEndY, 1989 const Color& rColor, sal_uInt16 nType ) 1990 { 1991 PutInOrder( nRefStartX, nRefEndX ); 1992 PutInOrder( nRefStartY, nRefEndY ); 1993 1994 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY ) 1995 pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab ); 1996 1997 if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 && 1998 nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top 1999 { 2000 long nMinX = nScrX; 2001 long nMinY = nScrY; 2002 long nMaxX = nScrX+nScrW-1; 2003 long nMaxY = nScrY+nScrH-1; 2004 if ( bLayoutRTL ) 2005 { 2006 long nTemp = nMinX; 2007 nMinX = nMaxX; 2008 nMaxX = nTemp; 2009 } 2010 long nLayoutSign = bLayoutRTL ? -1 : 1; 2011 2012 sal_Bool bTop = sal_False; 2013 sal_Bool bBottom = sal_False; 2014 sal_Bool bLeft = sal_False; 2015 sal_Bool bRight = sal_False; 2016 2017 long nPosY = nScrY; 2018 sal_Bool bNoStartY = ( nY1 < nRefStartY ); 2019 sal_Bool bNoEndY = sal_False; 2020 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check 2021 { 2022 SCROW nY = pRowInfo[nArrY].nRowNo; 2023 2024 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) ) 2025 { 2026 nMinY = nPosY - 1; 2027 bTop = sal_True; 2028 } 2029 if ( nY==nRefEndY ) 2030 { 2031 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1; 2032 bBottom = sal_True; 2033 } 2034 if ( nY>nRefEndY && bNoEndY ) 2035 { 2036 nMaxY = nPosY - 1; 2037 bBottom = sal_True; 2038 } 2039 bNoStartY = ( nY < nRefStartY ); 2040 bNoEndY = ( nY < nRefEndY ); 2041 nPosY += pRowInfo[nArrY].nHeight; 2042 } 2043 2044 long nPosX = nScrX; 2045 if ( bLayoutRTL ) 2046 nPosX += nMirrorW - 1; // always in pixels 2047 2048 for (SCCOL nX=nX1; nX<=nX2+1; nX++) 2049 { 2050 if ( nX==nRefStartX ) 2051 { 2052 nMinX = nPosX - nLayoutSign; 2053 bLeft = sal_True; 2054 } 2055 if ( nX==nRefEndX ) 2056 { 2057 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign; 2058 bRight = sal_True; 2059 } 2060 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; 2061 } 2062 2063 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign && 2064 nMaxY >= nMinY ) 2065 { 2066 if ( nType == SC_CAT_DELETE_ROWS ) 2067 bLeft = bRight = bBottom = sal_False; //! dicke Linie ??? 2068 else if ( nType == SC_CAT_DELETE_COLS ) 2069 bTop = bBottom = bRight = sal_False; //! dicke Linie ??? 2070 2071 pDev->SetLineColor( rColor ); 2072 if (bTop && bBottom && bLeft && bRight) 2073 { 2074 pDev->SetFillColor(); 2075 pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) ); 2076 } 2077 else 2078 { 2079 if (bTop) 2080 { 2081 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) ); 2082 if ( nType == SC_CAT_DELETE_ROWS ) 2083 pDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) ); 2084 } 2085 if (bBottom) 2086 pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) ); 2087 if (bLeft) 2088 { 2089 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) ); 2090 if ( nType == SC_CAT_DELETE_COLS ) 2091 pDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) ); 2092 } 2093 if (bRight) 2094 pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) ); 2095 } 2096 if ( bLeft && bTop ) 2097 { 2098 pDev->SetLineColor(); 2099 pDev->SetFillColor( rColor ); 2100 pDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) ); 2101 } 2102 } 2103 } 2104 } 2105 2106 void ScOutputData::DrawChangeTrack() 2107 { 2108 ScChangeTrack* pTrack = pDoc->GetChangeTrack(); 2109 ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings(); 2110 if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() ) 2111 return; // nix da oder abgeschaltet 2112 2113 ScActionColorChanger aColorChanger(*pTrack); 2114 2115 // Clipping passiert von aussen 2116 //! ohne Clipping, nur betroffene Zeilen painten ??!??!? 2117 2118 SCCOL nEndX = nX2; 2119 SCROW nEndY = nY2; 2120 if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung 2121 if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt 2122 ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab ); 2123 const ScChangeAction* pAction = pTrack->GetFirst(); 2124 while (pAction) 2125 { 2126 ScChangeActionType eActionType; 2127 if ( pAction->IsVisible() ) 2128 { 2129 eActionType = pAction->GetType(); 2130 const ScBigRange& rBig = pAction->GetBigRange(); 2131 if ( rBig.aStart.Tab() == nTab ) 2132 { 2133 ScRange aRange = rBig.MakeRange(); 2134 2135 if ( eActionType == SC_CAT_DELETE_ROWS ) 2136 aRange.aEnd.SetRow( aRange.aStart.Row() ); 2137 else if ( eActionType == SC_CAT_DELETE_COLS ) 2138 aRange.aEnd.SetCol( aRange.aStart.Col() ); 2139 2140 if ( aRange.Intersects( aViewRange ) && 2141 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) 2142 { 2143 aColorChanger.Update( *pAction ); 2144 Color aColor( aColorChanger.GetColor() ); 2145 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(), 2146 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) ); 2147 2148 } 2149 } 2150 if ( eActionType == SC_CAT_MOVE && 2151 ((const ScChangeActionMove*)pAction)-> 2152 GetFromRange().aStart.Tab() == nTab ) 2153 { 2154 ScRange aRange = ((const ScChangeActionMove*)pAction)-> 2155 GetFromRange().MakeRange(); 2156 if ( aRange.Intersects( aViewRange ) && 2157 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) 2158 { 2159 aColorChanger.Update( *pAction ); 2160 Color aColor( aColorChanger.GetColor() ); 2161 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(), 2162 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) ); 2163 } 2164 } 2165 } 2166 2167 pAction = pAction->GetNext(); 2168 } 2169 } 2170 2171 void ScOutputData::DrawNoteMarks() 2172 { 2173 sal_Bool bFirst = sal_True; 2174 2175 long nInitPosX = nScrX; 2176 if ( bLayoutRTL ) 2177 nInitPosX += nMirrorW - 1; // always in pixels 2178 long nLayoutSign = bLayoutRTL ? -1 : 1; 2179 2180 long nPosY = nScrY; 2181 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) 2182 { 2183 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 2184 if ( pThisRowInfo->bChanged ) 2185 { 2186 long nPosX = nInitPosX; 2187 for (SCCOL nX=nX1; nX<=nX2; nX++) 2188 { 2189 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; 2190 ScBaseCell* pCell = pInfo->pCell; 2191 sal_Bool bIsMerged = sal_False; 2192 2193 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped ) 2194 { 2195 // find start of merged cell 2196 bIsMerged = sal_True; 2197 SCROW nY = pRowInfo[nArrY].nRowNo; 2198 SCCOL nMergeX = nX; 2199 SCROW nMergeY = nY; 2200 pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab ); 2201 pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) ); 2202 // use origin's pCell for NotePtr test below 2203 } 2204 2205 if ( pCell && pCell->HasNote() && ( bIsMerged || 2206 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) ) 2207 { 2208 if (bFirst) 2209 { 2210 pDev->SetLineColor(); 2211 2212 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 2213 if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() ) 2214 pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 2215 else 2216 pDev->SetFillColor(COL_LIGHTRED); 2217 2218 bFirst = sal_False; 2219 } 2220 2221 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign; 2222 if ( bIsMerged || pInfo->bMerged ) 2223 { 2224 // if merged, add widths of all cells 2225 SCCOL nNextX = nX + 1; 2226 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped ) 2227 { 2228 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign; 2229 ++nNextX; 2230 } 2231 } 2232 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) ) 2233 pDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) ); 2234 } 2235 2236 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; 2237 } 2238 } 2239 nPosY += pThisRowInfo->nHeight; 2240 } 2241 } 2242 2243 void ScOutputData::AddPDFNotes() 2244 { 2245 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); 2246 if ( !pPDFData || !pPDFData->GetIsExportNotes() ) 2247 return; 2248 2249 long nInitPosX = nScrX; 2250 if ( bLayoutRTL ) 2251 { 2252 Size aOnePixel = pDev->PixelToLogic(Size(1,1)); 2253 long nOneX = aOnePixel.Width(); 2254 nInitPosX += nMirrorW - nOneX; 2255 } 2256 long nLayoutSign = bLayoutRTL ? -1 : 1; 2257 2258 long nPosY = nScrY; 2259 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) 2260 { 2261 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 2262 if ( pThisRowInfo->bChanged ) 2263 { 2264 long nPosX = nInitPosX; 2265 for (SCCOL nX=nX1; nX<=nX2; nX++) 2266 { 2267 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; 2268 ScBaseCell* pCell = pInfo->pCell; 2269 sal_Bool bIsMerged = sal_False; 2270 SCROW nY = pRowInfo[nArrY].nRowNo; 2271 SCCOL nMergeX = nX; 2272 SCROW nMergeY = nY; 2273 2274 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped ) 2275 { 2276 // find start of merged cell 2277 bIsMerged = sal_True; 2278 pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab ); 2279 pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) ); 2280 // use origin's pCell for NotePtr test below 2281 } 2282 2283 if ( pCell && pCell->HasNote() && ( bIsMerged || 2284 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) ) 2285 { 2286 long nNoteWidth = (long)( SC_CLIPMARK_SIZE * nPPTX ); 2287 long nNoteHeight = (long)( SC_CLIPMARK_SIZE * nPPTY ); 2288 2289 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign; 2290 if ( bIsMerged || pInfo->bMerged ) 2291 { 2292 // if merged, add widths of all cells 2293 SCCOL nNextX = nX + 1; 2294 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped ) 2295 { 2296 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign; 2297 ++nNextX; 2298 } 2299 } 2300 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) ) 2301 { 2302 Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight ); 2303 const ScPostIt* pNote = pCell->GetNote(); 2304 2305 // Note title is the cell address (as on printed note pages) 2306 String aTitle; 2307 ScAddress aAddress( nMergeX, nMergeY, nTab ); 2308 aAddress.Format( aTitle, SCA_VALID, pDoc, pDoc->GetAddressConvention() ); 2309 2310 // Content has to be a simple string without line breaks 2311 String aContent = pNote->GetText(); 2312 xub_StrLen nPos; 2313 while ( (nPos=aContent.Search('\n')) != STRING_NOTFOUND ) 2314 aContent.SetChar( nPos, ' ' ); 2315 2316 vcl::PDFNote aNote; 2317 aNote.Title = aTitle; 2318 aNote.Contents = aContent; 2319 pPDFData->CreateNote( aNoteRect, aNote ); 2320 } 2321 } 2322 2323 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; 2324 } 2325 } 2326 nPosY += pThisRowInfo->nHeight; 2327 } 2328 } 2329 2330 void ScOutputData::DrawClipMarks() 2331 { 2332 if (!bAnyClipped) 2333 return; 2334 2335 Color aArrowFillCol( COL_LIGHTRED ); 2336 2337 sal_uLong nOldDrawMode = pDev->GetDrawMode(); 2338 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 2339 if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() ) 2340 { 2341 // use DrawMode to change the arrow's outline color 2342 pDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE ); 2343 // use text color also for the fill color 2344 aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 2345 } 2346 2347 long nInitPosX = nScrX; 2348 if ( bLayoutRTL ) 2349 nInitPosX += nMirrorW - 1; // always in pixels 2350 long nLayoutSign = bLayoutRTL ? -1 : 1; 2351 2352 Rectangle aCellRect; 2353 long nPosY = nScrY; 2354 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) 2355 { 2356 RowInfo* pThisRowInfo = &pRowInfo[nArrY]; 2357 if ( pThisRowInfo->bChanged ) 2358 { 2359 SCROW nY = pThisRowInfo->nRowNo; 2360 long nPosX = nInitPosX; 2361 for (SCCOL nX=nX1; nX<=nX2; nX++) 2362 { 2363 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; 2364 if (pInfo->nClipMark) 2365 { 2366 if (pInfo->bHOverlapped || pInfo->bVOverlapped) 2367 { 2368 // merge origin may be outside of visible area - use document functions 2369 2370 SCCOL nOverX = nX; 2371 SCROW nOverY = nY; 2372 long nStartPosX = nPosX; 2373 long nStartPosY = nPosY; 2374 2375 while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr( 2376 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) ) 2377 { 2378 --nOverX; 2379 nStartPosX -= nLayoutSign * (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX ); 2380 } 2381 2382 while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr( 2383 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) ) 2384 { 2385 --nOverY; 2386 nStartPosY -= nLayoutSign * (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY ); 2387 } 2388 2389 long nOutWidth = (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX ); 2390 long nOutHeight = (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY ); 2391 2392 const ScMergeAttr* pMerge = (const ScMergeAttr*) 2393 pDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE ); 2394 SCCOL nCountX = pMerge->GetColMerge(); 2395 for (SCCOL i=1; i<nCountX; i++) 2396 nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX ); 2397 SCROW nCountY = pMerge->GetRowMerge(); 2398 nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY); 2399 2400 if ( bLayoutRTL ) 2401 nStartPosX -= nOutWidth - 1; 2402 aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) ); 2403 } 2404 else 2405 { 2406 long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth; 2407 long nOutHeight = pThisRowInfo->nHeight; 2408 2409 if ( pInfo->bMerged && pInfo->pPatternAttr ) 2410 { 2411 SCCOL nOverX = nX; 2412 SCROW nOverY = nY; 2413 const ScMergeAttr* pMerge = 2414 (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE); 2415 SCCOL nCountX = pMerge->GetColMerge(); 2416 for (SCCOL i=1; i<nCountX; i++) 2417 nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX ); 2418 SCROW nCountY = pMerge->GetRowMerge(); 2419 nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY); 2420 } 2421 2422 long nStartPosX = nPosX; 2423 if ( bLayoutRTL ) 2424 nStartPosX -= nOutWidth - 1; 2425 // #i80447# create aCellRect from two points in case nOutWidth is 0 2426 aCellRect = Rectangle( Point( nStartPosX, nPosY ), 2427 Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) ); 2428 } 2429 2430 aCellRect.Bottom() -= 1; // don't paint over the cell grid 2431 if ( bLayoutRTL ) 2432 aCellRect.Left() += 1; 2433 else 2434 aCellRect.Right() -= 1; 2435 2436 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); 2437 Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 ); 2438 2439 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) ) 2440 { 2441 // visually left 2442 Rectangle aMarkRect = aCellRect; 2443 aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1; 2444 #if 0 2445 //! Test 2446 pDev->SetLineColor(); pDev->SetFillColor(COL_YELLOW); 2447 pDev->DrawRect(aMarkRect); 2448 //! Test 2449 #endif 2450 SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_True ); 2451 } 2452 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) ) 2453 { 2454 // visually right 2455 Rectangle aMarkRect = aCellRect; 2456 aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1; 2457 #if 0 2458 //! Test 2459 pDev->SetLineColor(); pDev->SetFillColor(COL_LIGHTGREEN); 2460 pDev->DrawRect(aMarkRect); 2461 //! Test 2462 #endif 2463 SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_False ); 2464 } 2465 } 2466 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; 2467 } 2468 } 2469 nPosY += pThisRowInfo->nHeight; 2470 } 2471 2472 pDev->SetDrawMode(nOldDrawMode); 2473 } 2474 2475 2476 2477