1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 22 #include <algorithm> 23 24 #include <officecfg/Office/Common.hxx> 25 #include <svtools/colorcfg.hxx> 26 #include <svx/svdetc.hxx> 27 #include <svx/svdedxv.hxx> 28 #include <svx/svdmodel.hxx> 29 #include <svx/svdoutl.hxx> 30 #include <vcl/BitmapReadAccess.hxx> 31 #include <editeng/eeitem.hxx> 32 #include <svl/itemset.hxx> 33 #include <svl/whiter.hxx> 34 #include <svx/xfillit0.hxx> 35 #include <svx/xflclit.hxx> 36 #include <svx/xflhtit.hxx> 37 #include <svx/xbtmpit.hxx> 38 #include <svx/xflgrit.hxx> 39 #include <svx/svdoole2.hxx> 40 #include <svl/itempool.hxx> 41 #include <unotools/configmgr.hxx> 42 #include <unotools/localedatawrapper.hxx> 43 #include <unotools/syslocale.hxx> 44 #include <svx/xflbckit.hxx> 45 #include <svx/extrusionbar.hxx> 46 #include <svx/fontworkbar.hxx> 47 #include <vcl/svapp.hxx> 48 #include <vcl/settings.hxx> 49 #include <svx/sdr/contact/viewcontact.hxx> 50 #include <svx/svdpage.hxx> 51 #include <svx/svdpagv.hxx> 52 #include <svx/svdotable.hxx> 53 #include <svx/sdrhittesthelper.hxx> 54 55 #include <com/sun/star/frame/XModel.hpp> 56 #include <com/sun/star/embed/XEmbeddedObject.hpp> 57 58 using namespace ::com::sun::star; 59 60 // Global data of the DrawingEngine 61 SdrGlobalData::SdrGlobalData() 62 { 63 if (!utl::ConfigManager::IsFuzzing()) 64 { 65 svx::ExtrusionBar::RegisterInterface(); 66 svx::FontworkBar::RegisterInterface(); 67 } 68 } 69 70 const LocaleDataWrapper& SdrGlobalData::GetLocaleData() 71 { 72 return GetSysLocale().GetLocaleData(); 73 } 74 75 namespace { 76 77 struct TheSdrGlobalData: public rtl::Static<SdrGlobalData, TheSdrGlobalData> {}; 78 79 } 80 81 SdrGlobalData & GetSdrGlobalData() { 82 return TheSdrGlobalData::get(); 83 } 84 85 OLEObjCache::OLEObjCache() 86 { 87 if (!utl::ConfigManager::IsFuzzing()) 88 { 89 // This limit is only useful on 32-bit windows, where we can run out of virtual memory (see tdf#95579) 90 // For everything else, we are better off keeping it in main memory rather than using our hacky page-out thing 91 #if defined _WIN32 && !defined _WIN64 92 nSize = officecfg::Office::Common::Cache::DrawingEngine::OLE_Objects::get(); 93 #else 94 nSize = SAL_MAX_INT32; // effectively disable the page-out mechanism 95 #endif 96 } 97 else 98 nSize = 100; 99 pTimer.reset( new AutoTimer( "svx OLEObjCache pTimer UnloadCheck" ) ); 100 pTimer->SetInvokeHandler( LINK(this, OLEObjCache, UnloadCheckHdl) ); 101 pTimer->SetTimeout(20000); 102 pTimer->SetStatic(); 103 } 104 105 OLEObjCache::~OLEObjCache() 106 { 107 pTimer->Stop(); 108 } 109 110 IMPL_LINK_NOARG(OLEObjCache, UnloadCheckHdl, Timer*, void) 111 { 112 if (nSize >= maObjs.size()) 113 return; 114 115 // more objects than configured cache size try to remove objects 116 // of course not the freshly inserted one at nIndex=0 117 size_t nCount2 = maObjs.size(); 118 size_t nIndex = nCount2-1; 119 while( nIndex && nCount2 > nSize ) 120 { 121 SdrOle2Obj* pUnloadObj = maObjs[nIndex--]; 122 if (!pUnloadObj) 123 continue; 124 125 try 126 { 127 // it is important to get object without reinitialization to avoid reentrance 128 const uno::Reference< embed::XEmbeddedObject > & xUnloadObj = pUnloadObj->GetObjRef_NoInit(); 129 130 bool bUnload = !xUnloadObj || SdrOle2Obj::CanUnloadRunningObj( xUnloadObj, pUnloadObj->GetAspect() ); 131 132 // check whether the object can be unloaded before looking for the parent objects 133 if ( xUnloadObj.is() && bUnload ) 134 { 135 uno::Reference< frame::XModel > xUnloadModel( xUnloadObj->getComponent(), uno::UNO_QUERY ); 136 if ( xUnloadModel.is() ) 137 { 138 for (SdrOle2Obj* pCacheObj : maObjs) 139 { 140 if ( pCacheObj && pCacheObj != pUnloadObj ) 141 { 142 uno::Reference< frame::XModel > xParentModel = pCacheObj->GetParentXModel(); 143 if ( xUnloadModel == xParentModel ) 144 { 145 bUnload = false; // the object has running embedded objects 146 break; 147 } 148 } 149 } 150 } 151 } 152 153 if (bUnload && UnloadObj(*pUnloadObj)) 154 { 155 // object was successfully unloaded 156 RemoveObj(pUnloadObj); 157 nCount2 = std::min(nCount2 - 1, maObjs.size()); 158 if (nIndex >= nCount2) 159 nIndex = nCount2 - 1; 160 } 161 } 162 catch( uno::Exception& ) 163 {} 164 } 165 } 166 167 void OLEObjCache::InsertObj(SdrOle2Obj* pObj) 168 { 169 if (!maObjs.empty()) 170 { 171 SdrOle2Obj* pExistingObj = maObjs.front(); 172 if ( pObj == pExistingObj ) 173 // the object is already on the top, nothing has to be changed 174 return; 175 } 176 177 // get the old position of the object to know whether it is already in container 178 std::vector<SdrOle2Obj*>::iterator it = std::find(maObjs.begin(), maObjs.end(), pObj); 179 bool bFound = it != maObjs.end(); 180 181 if (bFound) 182 maObjs.erase(it); 183 // insert object into first position 184 maObjs.insert(maObjs.begin(), pObj); 185 186 // if a new object was inserted, recalculate the cache 187 if (!bFound) 188 pTimer->Invoke(); 189 190 if (!bFound || !pTimer->IsActive()) 191 pTimer->Start(); 192 } 193 194 void OLEObjCache::RemoveObj(SdrOle2Obj* pObj) 195 { 196 std::vector<SdrOle2Obj*>::iterator it = std::find(maObjs.begin(), maObjs.end(), pObj); 197 if (it != maObjs.end()) 198 maObjs.erase(it); 199 if (maObjs.empty()) 200 pTimer->Stop(); 201 } 202 203 size_t OLEObjCache::size() const 204 { 205 return maObjs.size(); 206 } 207 208 SdrOle2Obj* OLEObjCache::operator[](size_t nPos) 209 { 210 return maObjs[nPos]; 211 } 212 213 const SdrOle2Obj* OLEObjCache::operator[](size_t nPos) const 214 { 215 return maObjs[nPos]; 216 } 217 218 bool OLEObjCache::UnloadObj(SdrOle2Obj& rObj) 219 { 220 bool bUnloaded = false; 221 222 //#i80528# The old mechanism is completely useless, only taking into account if 223 // in all views the GrafDraft feature is used. This will nearly never have been the 224 // case since no one ever used this option. 225 226 // A much better (and working) criteria would be the VOC contact count. 227 // The question is what will happen when i make it work now suddenly? I 228 // will try it for 2.4. 229 const sdr::contact::ViewContact& rViewContact = rObj.GetViewContact(); 230 const bool bVisible(rViewContact.HasViewObjectContacts()); 231 232 if(!bVisible) 233 { 234 bUnloaded = rObj.Unload(); 235 } 236 237 return bUnloaded; 238 } 239 240 bool GetDraftFillColor(const SfxItemSet& rSet, Color& rCol) 241 { 242 drawing::FillStyle eFill=rSet.Get(XATTR_FILLSTYLE).GetValue(); 243 bool bRetval = false; 244 245 switch(eFill) 246 { 247 case drawing::FillStyle_SOLID: 248 { 249 rCol = rSet.Get(XATTR_FILLCOLOR).GetColorValue(); 250 bRetval = true; 251 252 break; 253 } 254 case drawing::FillStyle_HATCH: 255 { 256 Color aCol1(rSet.Get(XATTR_FILLHATCH).GetHatchValue().GetColor()); 257 Color aCol2(COL_WHITE); 258 259 // when hatched background is activated, use object fill color as hatch color 260 bool bFillHatchBackground = rSet.Get(XATTR_FILLBACKGROUND).GetValue(); 261 if(bFillHatchBackground) 262 { 263 aCol2 = rSet.Get(XATTR_FILLCOLOR).GetColorValue(); 264 } 265 266 const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor())); 267 rCol = Color(aAverageColor); 268 bRetval = true; 269 270 break; 271 } 272 case drawing::FillStyle_GRADIENT: { 273 const basegfx::BGradient& rGrad=rSet.Get(XATTR_FILLGRADIENT).GetGradientValue(); 274 Color aCol1(Color(rGrad.GetColorStops().front().getStopColor())); 275 Color aCol2(Color(rGrad.GetColorStops().back().getStopColor())); 276 const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor())); 277 rCol = Color(aAverageColor); 278 bRetval = true; 279 280 break; 281 } 282 case drawing::FillStyle_BITMAP: 283 { 284 Bitmap aBitmap(rSet.Get(XATTR_FILLBITMAP).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap()); 285 const Size aSize(aBitmap.GetSizePixel()); 286 const sal_uInt32 nWidth = aSize.Width(); 287 const sal_uInt32 nHeight = aSize.Height(); 288 if (nWidth <= 0 || nHeight <= 0) 289 return bRetval; 290 291 Bitmap::ScopedReadAccess pAccess(aBitmap); 292 293 if (pAccess) 294 { 295 sal_uInt32 nRt(0); 296 sal_uInt32 nGn(0); 297 sal_uInt32 nBl(0); 298 const sal_uInt32 nMaxSteps(8); 299 const sal_uInt32 nXStep((nWidth > nMaxSteps) ? nWidth / nMaxSteps : 1); 300 const sal_uInt32 nYStep((nHeight > nMaxSteps) ? nHeight / nMaxSteps : 1); 301 sal_uInt32 nCount(0); 302 303 for(sal_uInt32 nY(0); nY < nHeight; nY += nYStep) 304 { 305 for(sal_uInt32 nX(0); nX < nWidth; nX += nXStep) 306 { 307 const BitmapColor& rCol2 = pAccess->GetColor(nY, nX); 308 309 nRt += rCol2.GetRed(); 310 nGn += rCol2.GetGreen(); 311 nBl += rCol2.GetBlue(); 312 nCount++; 313 } 314 } 315 316 nRt /= nCount; 317 nGn /= nCount; 318 nBl /= nCount; 319 320 rCol = Color(sal_uInt8(nRt), sal_uInt8(nGn), sal_uInt8(nBl)); 321 322 bRetval = true; 323 } 324 break; 325 } 326 default: break; 327 } 328 329 return bRetval; 330 } 331 332 std::unique_ptr<SdrOutliner> SdrMakeOutliner(OutlinerMode nOutlinerMode, SdrModel& rModel) 333 { 334 SfxItemPool* pPool = &rModel.GetItemPool(); 335 std::unique_ptr<SdrOutliner> pOutl(new SdrOutliner( pPool, nOutlinerMode )); 336 pOutl->SetEditTextObjectPool( pPool ); 337 pOutl->SetStyleSheetPool( static_cast<SfxStyleSheetPool*>(rModel.GetStyleSheetPool())); 338 pOutl->SetDefTab(rModel.GetDefaultTabulator()); 339 Outliner::SetForbiddenCharsTable(rModel.GetForbiddenCharsTable()); 340 pOutl->SetAsianCompressionMode(rModel.GetCharCompressType()); 341 pOutl->SetKernAsianPunctuation(rModel.IsKernAsianPunctuation()); 342 pOutl->SetAddExtLeading(rModel.IsAddExtLeading()); 343 return pOutl; 344 } 345 346 std::vector<Link<SdrObjCreatorParams, rtl::Reference<SdrObject>>>& ImpGetUserMakeObjHdl() 347 { 348 SdrGlobalData& rGlobalData=GetSdrGlobalData(); 349 return rGlobalData.aUserMakeObjHdl; 350 } 351 352 bool SearchOutlinerItems(const SfxItemSet& rSet, bool bInklDefaults, bool* pbOnlyEE) 353 { 354 bool bHas=false; 355 bool bOnly=true; 356 bool bLookOnly=pbOnlyEE!=nullptr; 357 SfxWhichIter aIter(rSet); 358 sal_uInt16 nWhich=aIter.FirstWhich(); 359 while (((bLookOnly && bOnly) || !bHas) && nWhich!=0) { 360 // For bInklDefaults, the entire Which range is decisive, 361 // in other cases only the set items are. 362 // Disabled and DontCare are regarded as holes in the Which range. 363 SfxItemState eState=aIter.GetItemState(); 364 if ((eState==SfxItemState::DEFAULT && bInklDefaults) || eState==SfxItemState::SET) { 365 if (nWhich<EE_ITEMS_START || nWhich>EE_ITEMS_END) bOnly=false; 366 else bHas=true; 367 } 368 nWhich=aIter.NextWhich(); 369 } 370 if (!bHas) bOnly=false; 371 if (pbOnlyEE!=nullptr) *pbOnlyEE=bOnly; 372 return bHas; 373 } 374 375 WhichRangesContainer RemoveWhichRange(const WhichRangesContainer& pOldWhichTable, sal_uInt16 nRangeBeg, sal_uInt16 nRangeEnd) 376 { 377 // Six possible cases (per range): 378 // [Beg..End] [nRangeBeg, nRangeEnd], to delete 379 // [b..e] [b..e] [b..e] Cases 1,3,2: doesn't matter, delete, doesn't matter + Ranges 380 // [b........e] [b........e] Cases 4,5 : shrink range | in 381 // [b......................e] Case 6 : splitting + pOldWhichTable 382 std::vector<WhichPair> buf; 383 for (const auto & rPair : pOldWhichTable) { 384 auto const begin = rPair.first; 385 auto const end = rPair.second; 386 if (end < nRangeBeg || begin > nRangeEnd) { // cases 1, 2 387 buf.push_back({begin, end}); 388 } else if (begin >= nRangeBeg && end <= nRangeEnd) { // case 3 389 // drop 390 } else if (end <= nRangeEnd) { // case 4 391 buf.push_back({begin, nRangeBeg - 1}); 392 } else if (begin >= nRangeBeg) { // case 5 393 buf.push_back({nRangeEnd + 1, end}); 394 } else { // case 6 395 buf.push_back({begin, nRangeBeg - 1}); 396 buf.push_back({nRangeEnd + 1, end}); 397 } 398 } 399 std::unique_ptr<WhichPair[]> pNewWhichTable(new WhichPair[buf.size()]); 400 std::copy(buf.begin(), buf.end(), pNewWhichTable.get()); 401 return WhichRangesContainer(std::move(pNewWhichTable), buf.size()); 402 } 403 404 405 SvdProgressInfo::SvdProgressInfo( const Link<void*,bool>&_rLink ) 406 { 407 maLink = _rLink; 408 m_nSumCurAction = 0; 409 410 m_nObjCount = 0; 411 m_nCurObj = 0; 412 413 m_nActionCount = 0; 414 m_nCurAction = 0; 415 416 m_nInsertCount = 0; 417 m_nCurInsert = 0; 418 } 419 420 void SvdProgressInfo::Init( size_t nObjCount ) 421 { 422 m_nObjCount = nObjCount; 423 } 424 425 bool SvdProgressInfo::ReportActions( size_t nActionCount ) 426 { 427 m_nSumCurAction += nActionCount; 428 m_nCurAction += nActionCount; 429 if(m_nCurAction > m_nActionCount) 430 m_nCurAction = m_nActionCount; 431 432 return maLink.Call(nullptr); 433 } 434 435 void SvdProgressInfo::ReportInserts( size_t nInsertCount ) 436 { 437 m_nSumCurAction += nInsertCount; 438 m_nCurInsert += nInsertCount; 439 440 maLink.Call(nullptr); 441 } 442 443 void SvdProgressInfo::ReportRescales( size_t nRescaleCount ) 444 { 445 m_nSumCurAction += nRescaleCount; 446 maLink.Call(nullptr); 447 } 448 449 void SvdProgressInfo::SetActionCount( size_t nActionCount ) 450 { 451 m_nActionCount = nActionCount; 452 } 453 454 void SvdProgressInfo::SetInsertCount( size_t nInsertCount ) 455 { 456 m_nInsertCount = nInsertCount; 457 } 458 459 void SvdProgressInfo::SetNextObject() 460 { 461 m_nActionCount = 0; 462 m_nCurAction = 0; 463 464 m_nInsertCount = 0; 465 m_nCurInsert = 0; 466 467 m_nCurObj++; 468 ReportActions(0); 469 } 470 471 // #i101872# isolate GetTextEditBackgroundColor to tooling; it will anyways only be used as long 472 // as text edit is not running on overlay 473 474 namespace 475 { 476 bool impGetSdrObjListFillColor( 477 const SdrObjList& rList, 478 const Point& rPnt, 479 const SdrPageView& rTextEditPV, 480 const SdrLayerIDSet& rVisLayers, 481 Color& rCol) 482 { 483 bool bRet(false); 484 bool bMaster(rList.getSdrPageFromSdrObjList() && rList.getSdrPageFromSdrObjList()->IsMasterPage()); 485 486 for(size_t no(rList.GetObjCount()); !bRet && no > 0; ) 487 { 488 no--; 489 SdrObject* pObj = rList.GetObj(no); 490 SdrObjList* pOL = pObj->GetSubList(); 491 492 if(pOL) 493 { 494 // group object 495 bRet = impGetSdrObjListFillColor(*pOL, rPnt, rTextEditPV, rVisLayers, rCol); 496 } 497 else 498 { 499 SdrTextObj* pText = DynCastSdrTextObj(pObj); 500 501 // Exclude zero master page object (i.e. background shape) from color query 502 if(pText 503 && pObj->IsClosedObj() 504 && (!bMaster || (!pObj->IsNotVisibleAsMaster() && 0 != no)) 505 && pObj->GetCurrentBoundRect().Contains(rPnt) 506 && !pText->IsHideContour() 507 && SdrObjectPrimitiveHit(*pObj, rPnt, {0, 0}, rTextEditPV, &rVisLayers, false)) 508 { 509 bRet = GetDraftFillColor(pObj->GetMergedItemSet(), rCol); 510 } 511 } 512 } 513 514 return bRet; 515 } 516 517 bool impGetSdrPageFillColor( 518 const SdrPage& rPage, 519 const Point& rPnt, 520 const SdrPageView& rTextEditPV, 521 const SdrLayerIDSet& rVisLayers, 522 Color& rCol, 523 bool bSkipBackgroundShape) 524 { 525 bool bRet(impGetSdrObjListFillColor(rPage, rPnt, rTextEditPV, rVisLayers, rCol)); 526 527 if(!bRet && !rPage.IsMasterPage()) 528 { 529 if(rPage.TRG_HasMasterPage()) 530 { 531 SdrLayerIDSet aSet(rVisLayers); 532 aSet &= rPage.TRG_GetMasterPageVisibleLayers(); 533 SdrPage& rMasterPage = rPage.TRG_GetMasterPage(); 534 535 // Don't fall back to background shape on 536 // master pages. This is later handled by 537 // GetBackgroundColor, and is necessary to cater for 538 // the silly ordering: 1. shapes, 2. master page 539 // shapes, 3. page background, 4. master page 540 // background. 541 bRet = impGetSdrPageFillColor(rMasterPage, rPnt, rTextEditPV, aSet, rCol, true); 542 } 543 } 544 545 // Only now determine background color from background shapes 546 if(!bRet && !bSkipBackgroundShape) 547 { 548 rCol = rPage.GetPageBackgroundColor(); 549 return true; 550 } 551 552 return bRet; 553 } 554 555 Color impCalcBackgroundColor( 556 const tools::Rectangle& rArea, 557 const SdrPageView& rTextEditPV, 558 const SdrPage& rPage) 559 { 560 svtools::ColorConfig aColorConfig; 561 Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); 562 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 563 564 if(!rStyleSettings.GetHighContrastMode()) 565 { 566 // search in page 567 const sal_uInt16 SPOTCOUNT(5); 568 Point aSpotPos[SPOTCOUNT]; 569 Color aSpotColor[SPOTCOUNT]; 570 sal_uInt32 nHeight( rArea.GetSize().Height() ); 571 sal_uInt32 nWidth( rArea.GetSize().Width() ); 572 sal_uInt32 nWidth14 = nWidth / 4; 573 sal_uInt32 nHeight14 = nHeight / 4; 574 sal_uInt32 nWidth34 = ( 3 * nWidth ) / 4; 575 sal_uInt32 nHeight34 = ( 3 * nHeight ) / 4; 576 577 sal_uInt16 i; 578 for ( i = 0; i < SPOTCOUNT; i++ ) 579 { 580 // five spots are used 581 switch ( i ) 582 { 583 case 0 : 584 { 585 // Center-Spot 586 aSpotPos[i] = rArea.Center(); 587 } 588 break; 589 590 case 1 : 591 { 592 // TopLeft-Spot 593 aSpotPos[i] = rArea.TopLeft(); 594 aSpotPos[i].AdjustX(nWidth14 ); 595 aSpotPos[i].AdjustY(nHeight14 ); 596 } 597 break; 598 599 case 2 : 600 { 601 // TopRight-Spot 602 aSpotPos[i] = rArea.TopLeft(); 603 aSpotPos[i].AdjustX(nWidth34 ); 604 aSpotPos[i].AdjustY(nHeight14 ); 605 } 606 break; 607 608 case 3 : 609 { 610 // BottomLeft-Spot 611 aSpotPos[i] = rArea.TopLeft(); 612 aSpotPos[i].AdjustX(nWidth14 ); 613 aSpotPos[i].AdjustY(nHeight34 ); 614 } 615 break; 616 617 case 4 : 618 { 619 // BottomRight-Spot 620 aSpotPos[i] = rArea.TopLeft(); 621 aSpotPos[i].AdjustX(nWidth34 ); 622 aSpotPos[i].AdjustY(nHeight34 ); 623 } 624 break; 625 626 } 627 628 aSpotColor[i] = COL_WHITE; 629 impGetSdrPageFillColor(rPage, aSpotPos[i], rTextEditPV, rTextEditPV.GetVisibleLayers(), aSpotColor[i], false); 630 } 631 632 sal_uInt16 aMatch[SPOTCOUNT]; 633 634 for ( i = 0; i < SPOTCOUNT; i++ ) 635 { 636 // were same spot colors found? 637 aMatch[i] = 0; 638 639 for ( sal_uInt16 j = 0; j < SPOTCOUNT; j++ ) 640 { 641 if( j != i ) 642 { 643 if( aSpotColor[i] == aSpotColor[j] ) 644 { 645 aMatch[i]++; 646 } 647 } 648 } 649 } 650 651 // highest weight to center spot 652 aBackground = aSpotColor[0]; 653 654 for ( sal_uInt16 nMatchCount = SPOTCOUNT - 1; nMatchCount > 1; nMatchCount-- ) 655 { 656 // which spot color was found most? 657 for ( i = 0; i < SPOTCOUNT; i++ ) 658 { 659 if( aMatch[i] == nMatchCount ) 660 { 661 aBackground = aSpotColor[i]; 662 nMatchCount = 1; // break outer for-loop 663 break; 664 } 665 } 666 } 667 } 668 669 return aBackground; 670 } 671 } // end of anonymous namespace 672 673 Color GetTextEditBackgroundColor(const SdrObjEditView& rView) 674 { 675 svtools::ColorConfig aColorConfig; 676 Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); 677 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 678 679 if(!rStyleSettings.GetHighContrastMode()) 680 { 681 bool bFound(false); 682 SdrTextObj* pText = rView.GetTextEditObject(); 683 684 if(pText && pText->IsClosedObj()) 685 { 686 sdr::table::SdrTableObj* pTable = dynamic_cast< sdr::table::SdrTableObj * >( pText ); 687 688 if( pTable ) 689 bFound = GetDraftFillColor(pTable->GetActiveCellItemSet(), aBackground ); 690 691 if( !bFound ) 692 bFound=GetDraftFillColor(pText->GetMergedItemSet(), aBackground); 693 } 694 695 if(!bFound && pText) 696 { 697 SdrPageView* pTextEditPV = rView.GetTextEditPageView(); 698 699 if(pTextEditPV) 700 { 701 Point aPvOfs(pText->GetTextEditOffset()); 702 const SdrPage* pPg = pTextEditPV->GetPage(); 703 704 if(pPg) 705 { 706 tools::Rectangle aSnapRect( pText->GetSnapRect() ); 707 aSnapRect.Move(aPvOfs.X(), aPvOfs.Y()); 708 709 return impCalcBackgroundColor(aSnapRect, *pTextEditPV, *pPg); 710 } 711 } 712 } 713 } 714 715 return aBackground; 716 } 717 718 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 719
