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