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