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