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