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