1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
55 #include <com/sun/star/frame/XModel.hpp>
56 #include <com/sun/star/embed/XEmbeddedObject.hpp>
58 using namespace ::com::sun::star
;
60 // Global data of the DrawingEngine
61 SdrGlobalData::SdrGlobalData()
63 if (!utl::ConfigManager::IsFuzzing())
65 svx::ExtrusionBar::RegisterInterface();
66 svx::FontworkBar::RegisterInterface();
70 const LocaleDataWrapper
& SdrGlobalData::GetLocaleData()
72 return GetSysLocale().GetLocaleData();
77 struct TheSdrGlobalData
: public rtl::Static
<SdrGlobalData
, TheSdrGlobalData
> {};
81 SdrGlobalData
& GetSdrGlobalData() {
82 return TheSdrGlobalData::get();
85 OLEObjCache::OLEObjCache()
87 if (!utl::ConfigManager::IsFuzzing())
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();
94 nSize
= SAL_MAX_INT32
; // effectively disable the page-out mechanism
99 pTimer
.reset( new AutoTimer( "svx OLEObjCache pTimer UnloadCheck" ) );
100 pTimer
->SetInvokeHandler( LINK(this, OLEObjCache
, UnloadCheckHdl
) );
101 pTimer
->SetTimeout(20000);
105 OLEObjCache::~OLEObjCache()
110 IMPL_LINK_NOARG(OLEObjCache
, UnloadCheckHdl
, Timer
*, void)
112 if (nSize
>= maObjs
.size())
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
)
121 SdrOle2Obj
* pUnloadObj
= maObjs
[nIndex
--];
127 // it is important to get object without reinitialization to avoid reentrance
128 const uno::Reference
< embed::XEmbeddedObject
> & xUnloadObj
= pUnloadObj
->GetObjRef_NoInit();
130 bool bUnload
= !xUnloadObj
|| SdrOle2Obj::CanUnloadRunningObj( xUnloadObj
, pUnloadObj
->GetAspect() );
132 // check whether the object can be unloaded before looking for the parent objects
133 if ( xUnloadObj
.is() && bUnload
)
135 uno::Reference
< frame::XModel
> xUnloadModel( xUnloadObj
->getComponent(), uno::UNO_QUERY
);
136 if ( xUnloadModel
.is() )
138 for (SdrOle2Obj
* pCacheObj
: maObjs
)
140 if ( pCacheObj
&& pCacheObj
!= pUnloadObj
)
142 uno::Reference
< frame::XModel
> xParentModel
= pCacheObj
->GetParentXModel();
143 if ( xUnloadModel
== xParentModel
)
145 bUnload
= false; // the object has running embedded objects
153 if (bUnload
&& UnloadObj(*pUnloadObj
))
155 // object was successfully unloaded
156 RemoveObj(pUnloadObj
);
157 nCount2
= std::min(nCount2
- 1, maObjs
.size());
158 if (nIndex
>= nCount2
)
159 nIndex
= nCount2
- 1;
162 catch( uno::Exception
& )
167 void OLEObjCache::InsertObj(SdrOle2Obj
* pObj
)
171 SdrOle2Obj
* pExistingObj
= maObjs
.front();
172 if ( pObj
== pExistingObj
)
173 // the object is already on the top, nothing has to be changed
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();
183 // insert object into first position
184 maObjs
.insert(maObjs
.begin(), pObj
);
186 // if a new object was inserted, recalculate the cache
190 if (!bFound
|| !pTimer
->IsActive())
194 void OLEObjCache::RemoveObj(SdrOle2Obj
* pObj
)
196 std::vector
<SdrOle2Obj
*>::iterator it
= std::find(maObjs
.begin(), maObjs
.end(), pObj
);
197 if (it
!= maObjs
.end())
203 size_t OLEObjCache::size() const
205 return maObjs
.size();
208 SdrOle2Obj
* OLEObjCache::operator[](size_t nPos
)
213 const SdrOle2Obj
* OLEObjCache::operator[](size_t nPos
) const
218 bool OLEObjCache::UnloadObj(SdrOle2Obj
& rObj
)
220 bool bUnloaded
= false;
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.
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());
234 bUnloaded
= rObj
.Unload();
240 bool GetDraftFillColor(const SfxItemSet
& rSet
, Color
& rCol
)
242 drawing::FillStyle eFill
=rSet
.Get(XATTR_FILLSTYLE
).GetValue();
243 bool bRetval
= false;
247 case drawing::FillStyle_SOLID
:
249 rCol
= rSet
.Get(XATTR_FILLCOLOR
).GetColorValue();
254 case drawing::FillStyle_HATCH
:
256 Color
aCol1(rSet
.Get(XATTR_FILLHATCH
).GetHatchValue().GetColor());
257 Color
aCol2(COL_WHITE
);
259 // when hatched background is activated, use object fill color as hatch color
260 bool bFillHatchBackground
= rSet
.Get(XATTR_FILLBACKGROUND
).GetValue();
261 if(bFillHatchBackground
)
263 aCol2
= rSet
.Get(XATTR_FILLCOLOR
).GetColorValue();
266 const basegfx::BColor
aAverageColor(basegfx::average(aCol1
.getBColor(), aCol2
.getBColor()));
267 rCol
= Color(aAverageColor
);
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
);
282 case drawing::FillStyle_BITMAP
:
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)
291 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
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);
303 for(sal_uInt32
nY(0); nY
< nHeight
; nY
+= nYStep
)
305 for(sal_uInt32
nX(0); nX
< nWidth
; nX
+= nXStep
)
307 const BitmapColor
& rCol2
= pAccess
->GetColor(nY
, nX
);
309 nRt
+= rCol2
.GetRed();
310 nGn
+= rCol2
.GetGreen();
311 nBl
+= rCol2
.GetBlue();
320 rCol
= Color(sal_uInt8(nRt
), sal_uInt8(nGn
), sal_uInt8(nBl
));
332 std::unique_ptr
<SdrOutliner
> SdrMakeOutliner(OutlinerMode nOutlinerMode
, SdrModel
& rModel
)
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());
346 std::vector
<Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>>>& ImpGetUserMakeObjHdl()
348 SdrGlobalData
& rGlobalData
=GetSdrGlobalData();
349 return rGlobalData
.aUserMakeObjHdl
;
352 bool SearchOutlinerItems(const SfxItemSet
& rSet
, bool bInklDefaults
, bool* pbOnlyEE
)
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;
368 nWhich
=aIter
.NextWhich();
370 if (!bHas
) bOnly
=false;
371 if (pbOnlyEE
!=nullptr) *pbOnlyEE
=bOnly
;
375 WhichRangesContainer
RemoveWhichRange(const WhichRangesContainer
& pOldWhichTable
, sal_uInt16 nRangeBeg
, sal_uInt16 nRangeEnd
)
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
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
});
395 buf
.push_back({begin
, nRangeBeg
- 1});
396 buf
.push_back({nRangeEnd
+ 1, end
});
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());
405 SvdProgressInfo::SvdProgressInfo( const Link
<void*,bool>&_rLink
)
420 void SvdProgressInfo::Init( size_t nObjCount
)
422 m_nObjCount
= nObjCount
;
425 bool SvdProgressInfo::ReportActions( size_t nActionCount
)
427 m_nSumCurAction
+= nActionCount
;
428 m_nCurAction
+= nActionCount
;
429 if(m_nCurAction
> m_nActionCount
)
430 m_nCurAction
= m_nActionCount
;
432 return maLink
.Call(nullptr);
435 void SvdProgressInfo::ReportInserts( size_t nInsertCount
)
437 m_nSumCurAction
+= nInsertCount
;
438 m_nCurInsert
+= nInsertCount
;
440 maLink
.Call(nullptr);
443 void SvdProgressInfo::ReportRescales( size_t nRescaleCount
)
445 m_nSumCurAction
+= nRescaleCount
;
446 maLink
.Call(nullptr);
449 void SvdProgressInfo::SetActionCount( size_t nActionCount
)
451 m_nActionCount
= nActionCount
;
454 void SvdProgressInfo::SetInsertCount( size_t nInsertCount
)
456 m_nInsertCount
= nInsertCount
;
459 void SvdProgressInfo::SetNextObject()
471 // #i101872# isolate GetTextEditBackgroundColor to tooling; it will anyways only be used as long
472 // as text edit is not running on overlay
476 bool impGetSdrObjListFillColor(
477 const SdrObjList
& rList
,
479 const SdrPageView
& rTextEditPV
,
480 const SdrLayerIDSet
& rVisLayers
,
484 bool bMaster(rList
.getSdrPageFromSdrObjList() && rList
.getSdrPageFromSdrObjList()->IsMasterPage());
486 for(size_t no(rList
.GetObjCount()); !bRet
&& no
> 0; )
489 SdrObject
* pObj
= rList
.GetObj(no
);
490 SdrObjList
* pOL
= pObj
->GetSubList();
495 bRet
= impGetSdrObjListFillColor(*pOL
, rPnt
, rTextEditPV
, rVisLayers
, rCol
);
499 SdrTextObj
* pText
= DynCastSdrTextObj(pObj
);
501 // Exclude zero master page object (i.e. background shape) from color query
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))
509 bRet
= GetDraftFillColor(pObj
->GetMergedItemSet(), rCol
);
517 bool impGetSdrPageFillColor(
518 const SdrPage
& rPage
,
520 const SdrPageView
& rTextEditPV
,
521 const SdrLayerIDSet
& rVisLayers
,
523 bool bSkipBackgroundShape
)
525 bool bRet(impGetSdrObjListFillColor(rPage
, rPnt
, rTextEditPV
, rVisLayers
, rCol
));
527 if(!bRet
&& !rPage
.IsMasterPage())
529 if(rPage
.TRG_HasMasterPage())
531 SdrLayerIDSet
aSet(rVisLayers
);
532 aSet
&= rPage
.TRG_GetMasterPageVisibleLayers();
533 SdrPage
& rMasterPage
= rPage
.TRG_GetMasterPage();
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
541 bRet
= impGetSdrPageFillColor(rMasterPage
, rPnt
, rTextEditPV
, aSet
, rCol
, true);
545 // Only now determine background color from background shapes
546 if(!bRet
&& !bSkipBackgroundShape
)
548 rCol
= rPage
.GetPageBackgroundColor();
555 Color
impCalcBackgroundColor(
556 const tools::Rectangle
& rArea
,
557 const SdrPageView
& rTextEditPV
,
558 const SdrPage
& rPage
)
560 svtools::ColorConfig aColorConfig
;
561 Color
aBackground(aColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
);
562 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
564 if(!rStyleSettings
.GetHighContrastMode())
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;
578 for ( i
= 0; i
< SPOTCOUNT
; i
++ )
580 // five spots are used
586 aSpotPos
[i
] = rArea
.Center();
593 aSpotPos
[i
] = rArea
.TopLeft();
594 aSpotPos
[i
].AdjustX(nWidth14
);
595 aSpotPos
[i
].AdjustY(nHeight14
);
602 aSpotPos
[i
] = rArea
.TopLeft();
603 aSpotPos
[i
].AdjustX(nWidth34
);
604 aSpotPos
[i
].AdjustY(nHeight14
);
611 aSpotPos
[i
] = rArea
.TopLeft();
612 aSpotPos
[i
].AdjustX(nWidth14
);
613 aSpotPos
[i
].AdjustY(nHeight34
);
620 aSpotPos
[i
] = rArea
.TopLeft();
621 aSpotPos
[i
].AdjustX(nWidth34
);
622 aSpotPos
[i
].AdjustY(nHeight34
);
628 aSpotColor
[i
] = COL_WHITE
;
629 impGetSdrPageFillColor(rPage
, aSpotPos
[i
], rTextEditPV
, rTextEditPV
.GetVisibleLayers(), aSpotColor
[i
], false);
632 sal_uInt16 aMatch
[SPOTCOUNT
];
634 for ( i
= 0; i
< SPOTCOUNT
; i
++ )
636 // were same spot colors found?
639 for ( sal_uInt16 j
= 0; j
< SPOTCOUNT
; j
++ )
643 if( aSpotColor
[i
] == aSpotColor
[j
] )
651 // highest weight to center spot
652 aBackground
= aSpotColor
[0];
654 for ( sal_uInt16 nMatchCount
= SPOTCOUNT
- 1; nMatchCount
> 1; nMatchCount
-- )
656 // which spot color was found most?
657 for ( i
= 0; i
< SPOTCOUNT
; i
++ )
659 if( aMatch
[i
] == nMatchCount
)
661 aBackground
= aSpotColor
[i
];
662 nMatchCount
= 1; // break outer for-loop
671 } // end of anonymous namespace
673 Color
GetTextEditBackgroundColor(const SdrObjEditView
& rView
)
675 svtools::ColorConfig aColorConfig
;
676 Color
aBackground(aColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
);
677 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
679 if(!rStyleSettings
.GetHighContrastMode())
682 SdrTextObj
* pText
= rView
.GetTextEditObject();
684 if(pText
&& pText
->IsClosedObj())
686 sdr::table::SdrTableObj
* pTable
= dynamic_cast< sdr::table::SdrTableObj
* >( pText
);
689 bFound
= GetDraftFillColor(pTable
->GetActiveCellItemSet(), aBackground
);
692 bFound
=GetDraftFillColor(pText
->GetMergedItemSet(), aBackground
);
697 SdrPageView
* pTextEditPV
= rView
.GetTextEditPageView();
701 Point
aPvOfs(pText
->GetTextEditOffset());
702 const SdrPage
* pPg
= pTextEditPV
->GetPage();
706 tools::Rectangle
aSnapRect( pText
->GetSnapRect() );
707 aSnapRect
.Move(aPvOfs
.X(), aPvOfs
.Y());
709 return impCalcBackgroundColor(aSnapRect
, *pTextEditPV
, *pPg
);
718 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */