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