Line data Source code
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 <tools/vcompat.hxx>
26 : #include <tools/helpers.hxx>
27 : #include <unotools/ucbstreamhelper.hxx>
28 : #include <unotools/localfilehelper.hxx>
29 : #include <unotools/tempfile.hxx>
30 : #include <vcl/svapp.hxx>
31 : #include <vcl/cvtgrf.hxx>
32 : #include <vcl/metaact.hxx>
33 : #include <vcl/virdev.hxx>
34 : #include <svtools/grfmgr.hxx>
35 :
36 : #include <vcl/pdfextoutdevdata.hxx>
37 :
38 : #include <com/sun/star/container/XNameContainer.hpp>
39 : #include <com/sun/star/beans/XPropertySet.hpp>
40 : #include <boost/scoped_ptr.hpp>
41 :
42 : using com::sun::star::uno::Reference;
43 : using com::sun::star::uno::XInterface;
44 : using com::sun::star::uno::UNO_QUERY;
45 : using com::sun::star::uno::Sequence;
46 : using com::sun::star::container::XNameContainer;
47 : using com::sun::star::beans::XPropertySet;
48 :
49 : GraphicManager* GraphicObject::mpGlobalMgr = NULL;
50 :
51 0 : struct GrfSimpleCacheObj
52 : {
53 : Graphic maGraphic;
54 : GraphicAttr maAttr;
55 :
56 0 : GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) :
57 0 : maGraphic( rGraphic ), maAttr( rAttr ) {}
58 : };
59 :
60 0 : TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
61 :
62 : // unique increasing ID for being able to detect the GraphicObject with the
63 : // oldest last data changes
64 : static sal_uLong aIncrementingTimeOfLastDataChange = 1;
65 :
66 2746 : void GraphicObject::ImplAfterDataChange()
67 : {
68 : // set unique timestamp ID of last data change
69 2746 : mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
70 :
71 : // check memory footprint of all GraphicObjects managed and evtl. take action
72 2746 : if (mpMgr)
73 2746 : mpMgr->ImplCheckSizeOfSwappedInGraphics();
74 2746 : }
75 :
76 4398 : GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
77 : maLink (),
78 4398 : maUserData ()
79 : {
80 4398 : ImplConstruct();
81 4398 : ImplAssignGraphicData();
82 4398 : ImplSetGraphicManager( pMgr );
83 4398 : }
84 :
85 9178 : GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) :
86 : maGraphic ( rGraphic ),
87 : maLink (),
88 9178 : maUserData ()
89 : {
90 9178 : ImplConstruct();
91 9178 : ImplAssignGraphicData();
92 9178 : ImplSetGraphicManager( pMgr );
93 9178 : }
94 :
95 14697 : GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) :
96 : SvDataCopyStream(),
97 14697 : maGraphic ( rGraphicObj.GetGraphic() ),
98 : maAttr ( rGraphicObj.maAttr ),
99 : maLink ( rGraphicObj.maLink ),
100 29394 : maUserData ( rGraphicObj.maUserData )
101 : {
102 14697 : ImplConstruct();
103 14697 : ImplAssignGraphicData();
104 14697 : ImplSetGraphicManager( pMgr, NULL, &rGraphicObj );
105 14697 : }
106 :
107 2712 : GraphicObject::GraphicObject( const OString& rUniqueID, const GraphicManager* pMgr ) :
108 : maLink (),
109 2712 : maUserData ()
110 : {
111 2712 : ImplConstruct();
112 :
113 : // assign default properties
114 2712 : ImplAssignGraphicData();
115 :
116 2712 : ImplSetGraphicManager( pMgr, &rUniqueID );
117 :
118 : // update properties
119 2712 : ImplAssignGraphicData();
120 2712 : }
121 :
122 65754 : GraphicObject::~GraphicObject()
123 : {
124 30772 : if( mpMgr )
125 : {
126 30772 : mpMgr->ImplUnregisterObj( *this );
127 :
128 30772 : if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
129 90 : delete mpGlobalMgr, mpGlobalMgr = NULL;
130 : }
131 :
132 30772 : delete mpSwapOutTimer;
133 30772 : delete mpSwapStreamHdl;
134 30772 : delete mpSimpleCache;
135 34982 : }
136 :
137 30985 : void GraphicObject::ImplConstruct()
138 : {
139 30985 : mpMgr = NULL;
140 30985 : mpSwapStreamHdl = NULL;
141 30985 : mpSwapOutTimer = NULL;
142 30985 : mpSimpleCache = NULL;
143 30985 : mnAnimationLoopCount = 0;
144 30985 : mbAutoSwapped = false;
145 30985 : mbIsInSwapIn = false;
146 30985 : mbIsInSwapOut = false;
147 :
148 : // Init with a unique, increasing ID
149 30985 : mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
150 30985 : }
151 :
152 37977 : void GraphicObject::ImplAssignGraphicData()
153 : {
154 37977 : maPrefSize = maGraphic.GetPrefSize();
155 37977 : maPrefMapMode = maGraphic.GetPrefMapMode();
156 37977 : mnSizeBytes = maGraphic.GetSizeBytes();
157 37977 : meType = maGraphic.GetType();
158 37977 : mbTransparent = maGraphic.IsTransparent();
159 37977 : mbAlpha = maGraphic.IsAlpha();
160 37977 : mbAnimated = maGraphic.IsAnimated();
161 37977 : mbEPS = maGraphic.IsEPS();
162 37977 : mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
163 37977 : }
164 :
165 30985 : void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const OString* pID, const GraphicObject* pCopyObj )
166 : {
167 30985 : if( !mpMgr || ( pMgr != mpMgr ) )
168 : {
169 30985 : if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) )
170 30985 : return;
171 : else
172 : {
173 30985 : if( mpMgr )
174 : {
175 0 : mpMgr->ImplUnregisterObj( *this );
176 :
177 0 : if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
178 0 : delete mpGlobalMgr, mpGlobalMgr = NULL;
179 : }
180 :
181 30985 : if( !pMgr )
182 : {
183 30985 : if( !mpGlobalMgr )
184 : {
185 : mpGlobalMgr = new GraphicManager(
186 : (officecfg::Office::Common::Cache::GraphicManager::
187 452 : TotalCacheSize::get()),
188 : (officecfg::Office::Common::Cache::GraphicManager::
189 226 : ObjectCacheSize::get()));
190 : mpGlobalMgr->SetCacheTimeout(
191 : officecfg::Office::Common::Cache::GraphicManager::
192 226 : ObjectReleaseTime::get());
193 : }
194 :
195 30985 : mpMgr = mpGlobalMgr;
196 : }
197 : else
198 0 : mpMgr = (GraphicManager*) pMgr;
199 :
200 30985 : mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj );
201 : }
202 : }
203 : }
204 :
205 968 : void GraphicObject::ImplAutoSwapIn()
206 : {
207 968 : if( IsSwappedOut() )
208 : {
209 84 : if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
210 0 : mbAutoSwapped = false;
211 : else
212 : {
213 84 : mbIsInSwapIn = true;
214 :
215 84 : if( maGraphic.SwapIn() )
216 24 : mbAutoSwapped = false;
217 : else
218 : {
219 60 : SvStream* pStream = GetSwapStream();
220 :
221 60 : if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
222 : {
223 18 : if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
224 : {
225 0 : if( HasLink() )
226 : {
227 0 : OUString aURLStr;
228 :
229 0 : if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) )
230 : {
231 0 : boost::scoped_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ ));
232 :
233 0 : if( pIStm )
234 : {
235 0 : ReadGraphic( *pIStm, maGraphic );
236 0 : mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE );
237 0 : }
238 0 : }
239 : }
240 : }
241 18 : else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
242 0 : mbAutoSwapped = !maGraphic.SwapIn();
243 18 : else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream )
244 18 : mbAutoSwapped = maGraphic.IsSwapOut();
245 : else
246 : {
247 0 : mbAutoSwapped = !maGraphic.SwapIn( pStream );
248 0 : delete pStream;
249 : }
250 : }
251 : else
252 : {
253 : DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ),
254 : "GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" );
255 : }
256 : }
257 :
258 84 : mbIsInSwapIn = false;
259 :
260 84 : if( !mbAutoSwapped && mpMgr )
261 42 : mpMgr->ImplGraphicObjectWasSwappedIn( *this );
262 : }
263 :
264 : // Handle evtl. needed AfterDataChanges
265 84 : ImplAfterDataChange();
266 : }
267 968 : }
268 :
269 4 : bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
270 : tools::PolyPolygon& rClipPolyPoly, bool& bRectClipRegion ) const
271 : {
272 4 : bool bRet = false;
273 :
274 4 : if( GetType() != GRAPHIC_NONE )
275 : {
276 4 : Polygon aClipPoly( Rectangle( rPt, rSz ) );
277 4 : const sal_uInt16 nRot10 = pAttr->GetRotation() % 3600;
278 4 : const Point aOldOrigin( rPt );
279 8 : const MapMode aMap100( MAP_100TH_MM );
280 4 : Size aSize100;
281 : long nTotalWidth, nTotalHeight;
282 :
283 4 : if( nRot10 )
284 : {
285 0 : aClipPoly.Rotate( rPt, nRot10 );
286 0 : bRectClipRegion = false;
287 : }
288 : else
289 4 : bRectClipRegion = true;
290 :
291 4 : rClipPolyPoly = aClipPoly;
292 :
293 4 : if( maGraphic.GetPrefMapMode() == MAP_PIXEL )
294 4 : aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 );
295 : else
296 : {
297 0 : MapMode m(maGraphic.GetPrefMapMode());
298 0 : aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 );
299 : }
300 :
301 4 : nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop();
302 4 : nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop();
303 :
304 4 : if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 )
305 : {
306 0 : double fScale = (double) aSize100.Width() / nTotalWidth;
307 0 : const long nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale );
308 0 : const long nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1;
309 :
310 0 : fScale = (double) rSz.Width() / aSize100.Width();
311 0 : rPt.X() += FRound( nNewLeft * fScale );
312 0 : rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale );
313 :
314 0 : fScale = (double) aSize100.Height() / nTotalHeight;
315 0 : const long nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale );
316 0 : const long nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1;
317 :
318 0 : fScale = (double) rSz.Height() / aSize100.Height();
319 0 : rPt.Y() += FRound( nNewTop * fScale );
320 0 : rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale );
321 :
322 0 : if( nRot10 )
323 : {
324 0 : Polygon aOriginPoly( 1 );
325 :
326 0 : aOriginPoly[ 0 ] = rPt;
327 0 : aOriginPoly.Rotate( aOldOrigin, nRot10 );
328 0 : rPt = aOriginPoly[ 0 ];
329 : }
330 :
331 0 : bRet = true;
332 4 : }
333 : }
334 :
335 4 : return bRet;
336 : }
337 :
338 1618 : GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
339 : {
340 1618 : if( &rGraphicObj != this )
341 : {
342 1618 : mpMgr->ImplUnregisterObj( *this );
343 :
344 1618 : delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
345 1618 : delete mpSimpleCache, mpSimpleCache = NULL;
346 :
347 1618 : maGraphic = rGraphicObj.GetGraphic();
348 1618 : maAttr = rGraphicObj.maAttr;
349 1618 : maLink = rGraphicObj.maLink;
350 1618 : maUserData = rGraphicObj.maUserData;
351 1618 : ImplAssignGraphicData();
352 1618 : mbAutoSwapped = false;
353 1618 : mpMgr = rGraphicObj.mpMgr;
354 :
355 1618 : mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj );
356 : }
357 :
358 1618 : return *this;
359 : }
360 :
361 3663 : bool GraphicObject::operator==( const GraphicObject& rGraphicObj ) const
362 : {
363 7234 : return( ( rGraphicObj.maGraphic == maGraphic ) &&
364 18039 : ( rGraphicObj.maAttr == maAttr ) &&
365 14376 : ( rGraphicObj.GetLink() == GetLink() ) );
366 : }
367 :
368 0 : void GraphicObject::Load( SvStream& rIStm )
369 : {
370 0 : ReadGraphicObject( rIStm, *this );
371 0 : }
372 :
373 0 : void GraphicObject::Save( SvStream& rOStm )
374 : {
375 0 : WriteGraphicObject( rOStm, *this );
376 0 : }
377 :
378 0 : void GraphicObject::Assign( const SvDataCopyStream& rCopyStream )
379 : {
380 0 : *this = static_cast<const GraphicObject&>(rCopyStream);
381 0 : }
382 :
383 3598 : OString GraphicObject::GetUniqueID() const
384 : {
385 3598 : if ( !IsInSwapIn() && IsEPS() )
386 0 : const_cast<GraphicObject*>(this)->FireSwapInRequest();
387 :
388 3598 : OString aRet;
389 :
390 3598 : if( mpMgr )
391 3598 : aRet = mpMgr->ImplGetUniqueID( *this );
392 :
393 3598 : return aRet;
394 : }
395 :
396 236 : SvStream* GraphicObject::GetSwapStream() const
397 : {
398 236 : if( HasSwapStreamHdl() )
399 194 : return reinterpret_cast<SvStream*>( mpSwapStreamHdl->Call( const_cast<void*>(reinterpret_cast<const void*>(this)) ) );
400 : else
401 42 : return GRFMGR_AUTOSWAPSTREAM_NONE;
402 : }
403 :
404 122 : void GraphicObject::SetAttr( const GraphicAttr& rAttr )
405 : {
406 122 : maAttr = rAttr;
407 :
408 122 : if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) )
409 0 : delete mpSimpleCache, mpSimpleCache = NULL;
410 122 : }
411 :
412 0 : void GraphicObject::SetLink()
413 : {
414 0 : maLink = "";
415 0 : }
416 :
417 16 : void GraphicObject::SetLink( const OUString& rLink )
418 : {
419 16 : maLink = rLink;
420 16 : }
421 :
422 1670 : void GraphicObject::SetUserData()
423 : {
424 1670 : maUserData = "";
425 1670 : }
426 :
427 108 : void GraphicObject::SetUserData( const OUString& rUserData )
428 : {
429 108 : maUserData = rUserData;
430 108 : }
431 :
432 0 : void GraphicObject::SetSwapStreamHdl()
433 : {
434 0 : if( mpSwapStreamHdl )
435 : {
436 0 : delete mpSwapOutTimer, mpSwapOutTimer = NULL;
437 0 : delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
438 : }
439 0 : }
440 :
441 : #define SWAPGRAPHIC_TIMEOUT 5000
442 :
443 : // #i122985# it is not correct to set the swap-timeout to a hard-coded 5000ms
444 : // as it was before. Added code and experimented what to do as a good
445 : // compromise, see description.
446 3204 : static sal_uInt32 GetCacheTimeInMs()
447 : {
448 : static bool bSetAtAll(true);
449 :
450 3204 : if (bSetAtAll)
451 : {
452 : static bool bSetToPreferenceTime(true);
453 :
454 3204 : if (bSetToPreferenceTime)
455 : {
456 : const sal_uInt32 nSeconds =
457 : officecfg::Office::Common::Cache::GraphicManager::ObjectReleaseTime::get(
458 3204 : comphelper::getProcessComponentContext());
459 :
460 :
461 : // The default is 10 minutes. The minimum is one minute, thus 60
462 : // seconds. When the minimum should match to the former hard-coded
463 : // 5 seconds, we have a divisor of 12 to use. For the default of 10
464 : // minutes this would mean 50 seconds. Compared to before this is
465 : // ten times more (would allow better navigation by switching
466 : // through pages) and is controllable by the user by setting the
467 : // tools/options/memory/Remove_from_memory_after setting. Seems to
468 : // be a good compromise to me.
469 3204 : return nSeconds * 1000 / 12;
470 : }
471 : else
472 : {
473 0 : return SWAPGRAPHIC_TIMEOUT;
474 : }
475 : }
476 :
477 0 : return 0;
478 : }
479 :
480 3204 : void GraphicObject::SetSwapStreamHdl(const Link& rHdl)
481 : {
482 3204 : delete mpSwapStreamHdl, mpSwapStreamHdl = new Link( rHdl );
483 :
484 3204 : sal_uInt32 const nSwapOutTimeout(GetCacheTimeInMs());
485 3204 : if( nSwapOutTimeout )
486 : {
487 3204 : if( !mpSwapOutTimer )
488 : {
489 2316 : mpSwapOutTimer = new Timer;
490 2316 : mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) );
491 : }
492 :
493 3204 : mpSwapOutTimer->SetTimeout( nSwapOutTimeout );
494 3204 : mpSwapOutTimer->Start();
495 : }
496 : else
497 0 : delete mpSwapOutTimer, mpSwapOutTimer = NULL;
498 3204 : }
499 :
500 910 : void GraphicObject::FireSwapInRequest()
501 : {
502 910 : ImplAutoSwapIn();
503 910 : }
504 :
505 204 : void GraphicObject::FireSwapOutRequest()
506 : {
507 204 : ImplAutoSwapOutHdl( NULL );
508 204 : }
509 :
510 0 : void GraphicObject::GraphicManagerDestroyed()
511 : {
512 : // we're alive, but our manager doesn't live anymore ==> connect to default manager
513 0 : mpMgr = NULL;
514 0 : ImplSetGraphicManager( NULL );
515 0 : }
516 :
517 4 : bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz,
518 : const GraphicAttr* pAttr, sal_uLong nFlags ) const
519 : {
520 : bool bRet;
521 :
522 4 : if( nFlags & GRFMGR_DRAW_CACHED )
523 : {
524 4 : Point aPt( rPt );
525 4 : Size aSz( rSz );
526 4 : if ( pAttr && pAttr->IsCropped() )
527 : {
528 4 : tools::PolyPolygon aClipPolyPoly;
529 : bool bRectClip;
530 4 : ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
531 : }
532 4 : bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
533 : }
534 : else
535 0 : bRet = false;
536 :
537 4 : return bRet;
538 : }
539 :
540 162 : void GraphicObject::ReleaseFromCache()
541 : {
542 :
543 162 : mpMgr->ReleaseFromCache( *this );
544 162 : }
545 :
546 0 : bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
547 : const GraphicAttr* pAttr, sal_uLong nFlags )
548 : {
549 0 : GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
550 0 : Point aPt( rPt );
551 0 : Size aSz( rSz );
552 0 : const sal_uInt32 nOldDrawMode = pOut->GetDrawMode();
553 0 : bool bCropped = aAttr.IsCropped();
554 0 : bool bCached = false;
555 : bool bRet;
556 :
557 : // #i29534# Provide output rects for PDF writer
558 0 : Rectangle aCropRect;
559 :
560 0 : if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) )
561 0 : pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) );
562 :
563 : // mirrored horizontically
564 0 : if( aSz.Width() < 0L )
565 : {
566 0 : aPt.X() += aSz.Width() + 1;
567 0 : aSz.Width() = -aSz.Width();
568 0 : aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ );
569 : }
570 :
571 : // mirrored vertically
572 0 : if( aSz.Height() < 0L )
573 : {
574 0 : aPt.Y() += aSz.Height() + 1;
575 0 : aSz.Height() = -aSz.Height();
576 0 : aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT );
577 : }
578 :
579 0 : if( bCropped )
580 : {
581 0 : tools::PolyPolygon aClipPolyPoly;
582 : bool bRectClip;
583 0 : const bool bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
584 :
585 0 : pOut->Push( PushFlags::CLIPREGION );
586 :
587 0 : if( bCrop )
588 : {
589 0 : if( bRectClip )
590 : {
591 : // #i29534# Store crop rect for later forwarding to
592 : // PDF writer
593 0 : aCropRect = aClipPolyPoly.GetBoundRect();
594 0 : pOut->IntersectClipRegion( aCropRect );
595 : }
596 : else
597 : {
598 0 : pOut->IntersectClipRegion(vcl::Region(aClipPolyPoly));
599 : }
600 0 : }
601 : }
602 :
603 0 : bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached );
604 :
605 0 : if( bCropped )
606 0 : pOut->Pop();
607 :
608 0 : pOut->SetDrawMode( nOldDrawMode );
609 :
610 : // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
611 : // (code above needs to call GetGraphic twice)
612 0 : if( bCached )
613 : {
614 0 : if( mpSwapOutTimer )
615 0 : mpSwapOutTimer->Start();
616 : else
617 0 : FireSwapOutRequest();
618 : }
619 :
620 0 : return bRet;
621 : }
622 :
623 : // #i105243#
624 0 : bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev,
625 : const Point& rPt, const Size& rSz,
626 : const GraphicAttr* pGrfAttr,
627 : const sal_uLong nFlags )
628 : {
629 0 : const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() );
630 :
631 : // Notify PDF writer about linked graphic (if any)
632 0 : bool bWritingPdfLinkedGraphic( false );
633 0 : Point aPt( rPt );
634 0 : Size aSz( rSz );
635 0 : Rectangle aCropRect;
636 : vcl::PDFExtOutDevData* pPDFExtOutDevData =
637 0 : dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData());
638 0 : if( pPDFExtOutDevData )
639 : {
640 : // only delegate image handling to PDF, if no special treatment is necessary
641 0 : if( GetGraphic().IsLink() &&
642 0 : rSz.Width() > 0L &&
643 0 : rSz.Height() > 0L &&
644 0 : !aGrfAttr.IsSpecialDrawMode() &&
645 0 : !aGrfAttr.IsMirrored() &&
646 0 : !aGrfAttr.IsRotated() &&
647 0 : !aGrfAttr.IsAdjusted() )
648 : {
649 0 : bWritingPdfLinkedGraphic = true;
650 :
651 0 : if( aGrfAttr.IsCropped() )
652 : {
653 0 : tools::PolyPolygon aClipPolyPoly;
654 : bool bRectClip;
655 : const bool bCrop = ImplGetCropParams( &rOutDev,
656 : aPt, aSz,
657 : &aGrfAttr,
658 : aClipPolyPoly,
659 0 : bRectClip );
660 0 : if ( bCrop && bRectClip )
661 : {
662 0 : aCropRect = aClipPolyPoly.GetBoundRect();
663 0 : }
664 : }
665 :
666 0 : pPDFExtOutDevData->BeginGroup();
667 : }
668 : }
669 :
670 0 : bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags );
671 :
672 : // Notify PDF writer about linked graphic (if any)
673 0 : if( bWritingPdfLinkedGraphic )
674 : {
675 0 : pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()),
676 0 : aGrfAttr.GetTransparency(),
677 : Rectangle( aPt, aSz ),
678 0 : aCropRect );
679 : }
680 :
681 0 : return bRet;
682 : }
683 :
684 0 : bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize,
685 : const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
686 : {
687 0 : if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 )
688 0 : return false;
689 :
690 0 : const MapMode aOutMapMode( pOut->GetMapMode() );
691 0 : const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
692 : // #106258# Clamp size to 1 for zero values. This is okay, since
693 : // logical size of zero is handled above already
694 0 : const Size aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ),
695 0 : ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) );
696 :
697 : //#i69780 clip final tile size to a sane max size
698 0 : while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16)
699 0 : nTileCacheSize1D /= 2;
700 0 : while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16)
701 0 : nTileCacheSize1D /= 2;
702 :
703 0 : return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D );
704 : }
705 :
706 0 : bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz,
707 : long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/,
708 : OutputDevice* pFirstFrameOutDev )
709 : {
710 0 : bool bRet = false;
711 :
712 0 : GetGraphic();
713 :
714 0 : if( !IsSwappedOut() )
715 : {
716 0 : const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
717 :
718 0 : if( mbAnimated )
719 : {
720 0 : Point aPt( rPt );
721 0 : Size aSz( rSz );
722 0 : bool bCropped = aAttr.IsCropped();
723 :
724 0 : if( bCropped )
725 : {
726 0 : tools::PolyPolygon aClipPolyPoly;
727 : bool bRectClip;
728 0 : const bool bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
729 :
730 0 : pOut->Push( PushFlags::CLIPREGION );
731 :
732 0 : if( bCrop )
733 : {
734 0 : if( bRectClip )
735 0 : pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() );
736 : else
737 0 : pOut->IntersectClipRegion(vcl::Region(aClipPolyPoly));
738 0 : }
739 : }
740 :
741 0 : if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev )
742 : {
743 0 : if( mpSimpleCache )
744 0 : delete mpSimpleCache;
745 :
746 0 : mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr );
747 0 : mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
748 : }
749 :
750 0 : mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev );
751 :
752 0 : if( bCropped )
753 0 : pOut->Pop();
754 :
755 0 : bRet = true;
756 : }
757 : else
758 0 : bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD );
759 : }
760 :
761 0 : return bRet;
762 : }
763 :
764 0 : void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
765 : {
766 0 : if( mpSimpleCache )
767 0 : mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
768 0 : }
769 :
770 79461 : const Graphic& GraphicObject::GetGraphic() const
771 : {
772 79461 : GraphicObject *pThis = const_cast<GraphicObject*>(this);
773 :
774 79461 : if (mbAutoSwapped)
775 58 : pThis->ImplAutoSwapIn();
776 :
777 : //fdo#50697 If we've been asked to provide the graphic, then reset
778 : //the cache timeout to start from now and not remain at the
779 : //time of creation
780 79461 : pThis->restartSwapOutTimer();
781 :
782 79461 : return maGraphic;
783 : }
784 :
785 2654 : void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj )
786 : {
787 2654 : mpMgr->ImplUnregisterObj( *this );
788 :
789 2654 : if( mpSwapOutTimer )
790 1634 : mpSwapOutTimer->Stop();
791 :
792 2654 : maGraphic = rGraphic;
793 2654 : mbAutoSwapped = false;
794 2654 : ImplAssignGraphicData();
795 2654 : maLink = "";
796 2654 : delete mpSimpleCache, mpSimpleCache = NULL;
797 :
798 2654 : mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
799 :
800 2654 : if( mpSwapOutTimer )
801 1634 : mpSwapOutTimer->Start();
802 :
803 : // Handle evtl. needed AfterDataChanges
804 2654 : ImplAfterDataChange();
805 2654 : }
806 :
807 48 : void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink )
808 : {
809 48 : SetGraphic( rGraphic );
810 48 : maLink = rLink;
811 48 : }
812 :
813 0 : Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const
814 : {
815 : // #104550# Extracted from svx/source/svdraw/svdograf.cxx
816 0 : Graphic aTransGraphic( maGraphic );
817 0 : const GraphicType eType = GetType();
818 0 : const Size aSrcSize( aTransGraphic.GetPrefSize() );
819 :
820 : // #104115# Convert the crop margins to graphic object mapmode
821 0 : const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() );
822 0 : const MapMode aMap100( MAP_100TH_MM );
823 :
824 0 : Size aCropLeftTop;
825 0 : Size aCropRightBottom;
826 :
827 0 : if( GRAPHIC_GDIMETAFILE == eType )
828 : {
829 0 : GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() );
830 :
831 0 : if( aMapGraph == MAP_PIXEL )
832 : {
833 : // crops are in 1/100th mm -> to aMapGraph -> to MAP_PIXEL
834 : aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
835 : Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
836 0 : aMap100);
837 : aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
838 : Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
839 0 : aMap100);
840 : }
841 : else
842 : {
843 : // crops are in GraphicObject units -> to aMapGraph
844 : aCropLeftTop = OutputDevice::LogicToLogic(
845 : Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
846 : aMap100,
847 0 : aMapGraph);
848 : aCropRightBottom = OutputDevice::LogicToLogic(
849 : Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
850 : aMap100,
851 0 : aMapGraph);
852 : }
853 :
854 : // #104115# If the metafile is cropped, give it a special
855 : // treatment: clip against the remaining area, scale up such
856 : // that this area later fills the desired size, and move the
857 : // origin to the upper left edge of that area.
858 0 : if( rAttr.IsCropped() )
859 : {
860 0 : const MapMode aMtfMapMode( aMtf.GetPrefMapMode() );
861 :
862 0 : Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(),
863 0 : aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(),
864 0 : aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(),
865 0 : aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() );
866 :
867 : // #104115# To correctly crop rotated metafiles, clip by view rectangle
868 0 : aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 );
869 :
870 : // #104115# To crop the metafile, scale larger than the output rectangle
871 0 : aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()),
872 0 : (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) );
873 :
874 : // #104115# Adapt the pref size by hand (scale changes it
875 : // proportionally, but we want it to be smaller than the
876 : // former size, to crop the excess out)
877 0 : aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() * (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width()) + .5),
878 0 : (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) );
879 :
880 : // #104115# Adapt the origin of the new mapmode, such that it
881 : // is shifted to the place where the cropped output starts
882 0 : Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5),
883 0 : (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) );
884 0 : MapMode aNewMap( rDestMap );
885 0 : aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) );
886 0 : aMtf.SetPrefMapMode( aNewMap );
887 : }
888 : else
889 : {
890 0 : aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) );
891 0 : aMtf.SetPrefMapMode( rDestMap );
892 : }
893 :
894 0 : aTransGraphic = aMtf;
895 : }
896 0 : else if( GRAPHIC_BITMAP == eType )
897 : {
898 0 : BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() );
899 0 : Rectangle aCropRect;
900 :
901 : // convert crops to pixel
902 0 : if(rAttr.IsCropped())
903 : {
904 0 : if( aMapGraph == MAP_PIXEL )
905 : {
906 : // crops are in 1/100th mm -> to MAP_PIXEL
907 : aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
908 : Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
909 0 : aMap100);
910 : aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
911 : Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
912 0 : aMap100);
913 : }
914 : else
915 : {
916 : // crops are in GraphicObject units -> to MAP_PIXEL
917 : aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
918 : Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
919 0 : aMapGraph);
920 : aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
921 : Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
922 0 : aMapGraph);
923 : }
924 :
925 : // convert from prefmapmode to pixel
926 : Size aSrcSizePixel(
927 : Application::GetDefaultDevice()->LogicToPixel(
928 : aSrcSize,
929 0 : aMapGraph));
930 :
931 0 : if(rAttr.IsCropped()
932 0 : && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height())
933 0 : && aSrcSizePixel.Width())
934 : {
935 : // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode())
936 : // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size.
937 : // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g.
938 : // existing cropping is calculated based on this logic values already.
939 : // aBitmapEx.Scale(aSrcSizePixel);
940 :
941 : // another possibility is to adapt the values created so far with a factor; this
942 : // will keep the original Bitmap untouched and thus quality will not change
943 : // caution: convert to double first, else pretty big errors may occur
944 0 : const double fFactorX((double)aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width());
945 0 : const double fFactorY((double)aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height());
946 :
947 0 : aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX);
948 0 : aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY);
949 0 : aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX);
950 0 : aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY);
951 :
952 0 : aSrcSizePixel = aBitmapEx.GetSizePixel();
953 : }
954 :
955 : // setup crop rectangle in pixel
956 0 : aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(),
957 0 : aSrcSizePixel.Width() - aCropRightBottom.Width(),
958 0 : aSrcSizePixel.Height() - aCropRightBottom.Height() );
959 : }
960 :
961 : // #105641# Also crop animations
962 0 : if( aTransGraphic.IsAnimated() )
963 : {
964 : sal_uInt16 nFrame;
965 0 : Animation aAnim( aTransGraphic.GetAnimation() );
966 :
967 0 : for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
968 : {
969 0 : AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
970 :
971 0 : if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) )
972 : {
973 : // setup actual cropping (relative to frame position)
974 0 : Rectangle aCropRectRel( aCropRect );
975 0 : aCropRectRel.Move( -aAnimBmp.aPosPix.X(),
976 0 : -aAnimBmp.aPosPix.Y() );
977 :
978 : // cropping affects this frame, apply it then
979 : // do _not_ apply enlargement, this is done below
980 : ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(),
981 0 : aCropRectRel, rDestSize, false );
982 :
983 0 : aAnim.Replace( aAnimBmp, nFrame );
984 : }
985 : // else: bitmap completely within crop area,
986 : // i.e. nothing is cropped away
987 0 : }
988 :
989 : // now, apply enlargement (if any) through global animation size
990 0 : if( aCropLeftTop.Width() < 0 ||
991 0 : aCropLeftTop.Height() < 0 ||
992 0 : aCropRightBottom.Width() < 0 ||
993 0 : aCropRightBottom.Height() < 0 )
994 : {
995 0 : Size aNewSize( aAnim.GetDisplaySizePixel() );
996 0 : aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0;
997 0 : aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0;
998 0 : aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0;
999 0 : aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0;
1000 0 : aAnim.SetDisplaySizePixel( aNewSize );
1001 : }
1002 :
1003 : // if topleft has changed, we must move all frames to the
1004 : // right and bottom, resp.
1005 0 : if( aCropLeftTop.Width() < 0 ||
1006 0 : aCropLeftTop.Height() < 0 )
1007 : {
1008 0 : Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0,
1009 0 : aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 );
1010 :
1011 0 : for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1012 : {
1013 0 : AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1014 :
1015 0 : aAnimBmp.aPosPix += aPosOffset;
1016 :
1017 0 : aAnim.Replace( aAnimBmp, nFrame );
1018 0 : }
1019 : }
1020 :
1021 0 : aTransGraphic = aAnim;
1022 : }
1023 : else
1024 : {
1025 : ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom,
1026 0 : aCropRect, rDestSize, true );
1027 :
1028 0 : aTransGraphic = aBitmapEx;
1029 : }
1030 :
1031 0 : aTransGraphic.SetPrefSize( rDestSize );
1032 0 : aTransGraphic.SetPrefMapMode( rDestMap );
1033 : }
1034 :
1035 0 : GraphicObject aGrfObj( aTransGraphic );
1036 0 : aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr );
1037 :
1038 0 : return aTransGraphic;
1039 : }
1040 :
1041 300 : Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl
1042 : {
1043 300 : GetGraphic();
1044 :
1045 300 : Graphic aGraphic;
1046 600 : GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
1047 :
1048 300 : if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() )
1049 : {
1050 300 : if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() )
1051 : {
1052 0 : if( GetType() == GRAPHIC_BITMAP )
1053 : {
1054 0 : if( IsAnimated() )
1055 : {
1056 0 : Animation aAnimation( maGraphic.GetAnimation() );
1057 0 : GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
1058 0 : aAnimation.SetLoopCount( mnAnimationLoopCount );
1059 0 : aGraphic = aAnimation;
1060 : }
1061 : else
1062 : {
1063 0 : BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
1064 0 : GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
1065 0 : aGraphic = aBmpEx;
1066 : }
1067 : }
1068 : else
1069 : {
1070 0 : GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
1071 0 : GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
1072 0 : aGraphic = aMtf;
1073 : }
1074 : }
1075 : else
1076 : {
1077 300 : if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
1078 : {
1079 0 : Animation aAnimation( maGraphic.GetAnimation() );
1080 0 : aAnimation.SetLoopCount( mnAnimationLoopCount );
1081 0 : aGraphic = aAnimation;
1082 : }
1083 : else
1084 300 : aGraphic = maGraphic;
1085 : }
1086 : }
1087 :
1088 600 : return aGraphic;
1089 : }
1090 :
1091 68 : bool GraphicObject::SwapOut()
1092 : {
1093 68 : const bool bRet = !mbAutoSwapped && maGraphic.SwapOut();
1094 :
1095 68 : if( bRet && mpMgr )
1096 68 : mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1097 :
1098 68 : return bRet;
1099 : }
1100 :
1101 4 : bool GraphicObject::SwapOut( SvStream* pOStm )
1102 : {
1103 4 : const bool bRet = !mbAutoSwapped && maGraphic.SwapOut( pOStm );
1104 :
1105 4 : if( bRet && mpMgr )
1106 4 : mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1107 :
1108 4 : return bRet;
1109 : }
1110 :
1111 8 : bool GraphicObject::SwapIn()
1112 : {
1113 8 : bool bRet = false;
1114 :
1115 8 : if( mbAutoSwapped )
1116 : {
1117 0 : ImplAutoSwapIn();
1118 0 : bRet = true;
1119 : }
1120 8 : else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1121 : {
1122 2 : bRet = true;
1123 : }
1124 : else
1125 : {
1126 6 : bRet = maGraphic.SwapIn();
1127 :
1128 6 : if( bRet && mpMgr )
1129 6 : mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1130 : }
1131 :
1132 8 : if( bRet )
1133 : {
1134 8 : ImplAssignGraphicData();
1135 :
1136 : // Handle evtl. needed AfterDataChanges
1137 8 : ImplAfterDataChange();
1138 : }
1139 :
1140 8 : return bRet;
1141 : }
1142 :
1143 112 : void GraphicObject::SetSwapState()
1144 : {
1145 112 : if( !IsSwappedOut() )
1146 : {
1147 112 : mbAutoSwapped = true;
1148 :
1149 112 : if( mpMgr )
1150 112 : mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1151 : }
1152 112 : }
1153 :
1154 204 : IMPL_LINK_NOARG(GraphicObject, ImplAutoSwapOutHdl)
1155 : {
1156 204 : if( !IsSwappedOut() )
1157 : {
1158 176 : mbIsInSwapOut = true;
1159 :
1160 176 : SvStream* pStream = GetSwapStream();
1161 :
1162 176 : if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
1163 : {
1164 60 : if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
1165 0 : mbAutoSwapped = SwapOut( NULL );
1166 : else
1167 : {
1168 60 : if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
1169 60 : mbAutoSwapped = SwapOut();
1170 : else
1171 : {
1172 0 : mbAutoSwapped = SwapOut( pStream );
1173 0 : delete pStream;
1174 : }
1175 : }
1176 : }
1177 :
1178 176 : mbIsInSwapOut = false;
1179 : }
1180 :
1181 204 : if( mpSwapOutTimer )
1182 204 : mpSwapOutTimer->Start();
1183 :
1184 204 : return 0L;
1185 : }
1186 :
1187 0 : SvStream& ReadGraphicObject( SvStream& rIStm, GraphicObject& rGraphicObj )
1188 : {
1189 0 : VersionCompat aCompat( rIStm, STREAM_READ );
1190 0 : Graphic aGraphic;
1191 0 : GraphicAttr aAttr;
1192 : bool bLink;
1193 :
1194 0 : ReadGraphic( rIStm, aGraphic );
1195 0 : ReadGraphicAttr( rIStm, aAttr );
1196 0 : rIStm.ReadCharAsBool( bLink );
1197 :
1198 0 : rGraphicObj.SetGraphic( aGraphic );
1199 0 : rGraphicObj.SetAttr( aAttr );
1200 :
1201 0 : if( bLink )
1202 : {
1203 0 : OUString aLink = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, RTL_TEXTENCODING_UTF8);
1204 0 : rGraphicObj.SetLink(aLink);
1205 : }
1206 : else
1207 0 : rGraphicObj.SetLink();
1208 :
1209 0 : rGraphicObj.SetSwapStreamHdl();
1210 :
1211 0 : return rIStm;
1212 : }
1213 :
1214 0 : SvStream& WriteGraphicObject( SvStream& rOStm, const GraphicObject& rGraphicObj )
1215 : {
1216 0 : VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
1217 0 : const bool bLink = rGraphicObj.HasLink();
1218 :
1219 0 : WriteGraphic( rOStm, rGraphicObj.GetGraphic() );
1220 0 : WriteGraphicAttr( rOStm, rGraphicObj.GetAttr() );
1221 0 : rOStm.WriteUChar( bLink );
1222 :
1223 0 : if( bLink )
1224 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8);
1225 :
1226 0 : return rOStm;
1227 : }
1228 :
1229 : #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
1230 :
1231 736 : GraphicObject GraphicObject::CreateGraphicObjectFromURL( const OUString &rURL )
1232 : {
1233 1472 : const OUString aURL( rURL ), aPrefix( UNO_NAME_GRAPHOBJ_URLPREFIX );
1234 736 : if( aURL.startsWith( aPrefix ) )
1235 : {
1236 : // graphic manager url
1237 724 : OString aUniqueID(OUStringToOString(rURL.copy(sizeof(UNO_NAME_GRAPHOBJ_URLPREFIX) - 1), RTL_TEXTENCODING_UTF8));
1238 724 : return GraphicObject( aUniqueID );
1239 : }
1240 : else
1241 : {
1242 12 : Graphic aGraphic;
1243 12 : if ( !aURL.isEmpty() )
1244 : {
1245 12 : boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ ));
1246 12 : if( pStream )
1247 0 : GraphicConverter::Import( *pStream, aGraphic );
1248 : }
1249 :
1250 12 : return GraphicObject( aGraphic );
1251 736 : }
1252 : }
1253 :
1254 : void
1255 4 : GraphicObject::InspectForGraphicObjectImageURL( const Reference< XInterface >& xIf, std::vector< OUString >& rvEmbedImgUrls )
1256 : {
1257 4 : static OUString sImageURL( "ImageURL" );
1258 4 : Reference< XPropertySet > xProps( xIf, UNO_QUERY );
1259 4 : if ( xProps.is() )
1260 : {
1261 :
1262 4 : if ( xProps->getPropertySetInfo()->hasPropertyByName( sImageURL ) )
1263 : {
1264 2 : OUString sURL;
1265 2 : xProps->getPropertyValue( sImageURL ) >>= sURL;
1266 2 : if ( !sURL.isEmpty() && sURL.startsWith( UNO_NAME_GRAPHOBJ_URLPREFIX ) )
1267 0 : rvEmbedImgUrls.push_back( sURL );
1268 : }
1269 : }
1270 8 : Reference< XNameContainer > xContainer( xIf, UNO_QUERY );
1271 4 : if ( xContainer.is() )
1272 : {
1273 2 : Sequence< OUString > sNames = xContainer->getElementNames();
1274 2 : sal_Int32 nContainees = sNames.getLength();
1275 4 : for ( sal_Int32 index = 0; index < nContainees; ++index )
1276 : {
1277 2 : Reference< XInterface > xCtrl;
1278 2 : xContainer->getByName( sNames[ index ] ) >>= xCtrl;
1279 2 : InspectForGraphicObjectImageURL( xCtrl, rvEmbedImgUrls );
1280 4 : }
1281 4 : }
1282 4 : }
1283 :
1284 : // calculate scalings between real image size and logic object size. This
1285 : // is necessary since the crop values are relative to original bitmap size
1286 4 : basegfx::B2DVector GraphicObject::calculateCropScaling(
1287 : double fWidth,
1288 : double fHeight,
1289 : double fLeftCrop,
1290 : double fTopCrop,
1291 : double fRightCrop,
1292 : double fBottomCrop) const
1293 : {
1294 4 : const MapMode aMapMode100thmm(MAP_100TH_MM);
1295 4 : Size aBitmapSize(GetPrefSize());
1296 4 : double fFactorX(1.0);
1297 4 : double fFactorY(1.0);
1298 :
1299 4 : if(MAP_PIXEL == GetPrefMapMode().GetMapUnit())
1300 : {
1301 2 : aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
1302 : }
1303 : else
1304 : {
1305 2 : aBitmapSize = OutputDevice::LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm);
1306 : }
1307 :
1308 4 : const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop);
1309 4 : const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop);
1310 :
1311 4 : if(!basegfx::fTools::equalZero(fDivX))
1312 : {
1313 4 : fFactorX = fabs(fWidth) / fDivX;
1314 : }
1315 :
1316 4 : if(!basegfx::fTools::equalZero(fDivY))
1317 : {
1318 4 : fFactorY = fabs(fHeight) / fDivY;
1319 : }
1320 :
1321 4 : return basegfx::B2DVector(fFactorX,fFactorY);
1322 : }
1323 :
1324 : // restart SwapOut timer
1325 79461 : void GraphicObject::restartSwapOutTimer() const
1326 : {
1327 79461 : if( mpSwapOutTimer && mpSwapOutTimer->IsActive() )
1328 : {
1329 6528 : mpSwapOutTimer->Stop();
1330 6528 : mpSwapOutTimer->Start();
1331 : }
1332 80688 : }
1333 :
1334 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|