1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impgraph.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/vcompat.hxx>
34 #include <tools/urlobj.hxx>
35 #include <tools/debug.hxx>
36 #include <ucbhelper/content.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #ifndef _UNTOOLS_TEMPFILE_HXX
39 #include <unotools/tempfile.hxx>
41 #include <vcl/outdev.hxx>
42 #include <vcl/virdev.hxx>
43 #include <tools/debug.hxx>
44 #include <tools/stream.hxx>
45 #include <vcl/impgraph.hxx>
46 #include <vcl/gfxlink.hxx>
47 #include <vcl/cvtgrf.hxx>
48 #include <vcl/salbtype.hxx>
49 #include <vcl/graph.hxx>
50 #include <vcl/metaact.hxx>
51 #include <com/sun/star/ucb/CommandAbortedException.hpp>
57 #define GRAPHIC_MAXPARTLEN 256000L
58 #define GRAPHIC_MTFTOBMP_MAXEXT 2048
59 #define GRAPHIC_STREAMBUFSIZE 8192UL
61 #define SYS_WINMETAFILE 0x00000003L
62 #define SYS_WNTMETAFILE 0x00000004L
63 #define SYS_OS2METAFILE 0x00000005L
64 #define SYS_MACMETAFILE 0x00000006L
66 #define GRAPHIC_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'G', 'R', 'F', '5' ))
67 #define NATIVE_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'N', 'A', 'T', '5' ))
75 INetURLObject aSwapURL
;
89 GraphicReader::~GraphicReader()
94 // ------------------------------------------------------------------------
96 BOOL
GraphicReader::IsPreviewModeEnabled() const
100 if( mpReaderData
->maPreviewSize
.Width() )
102 if( mpReaderData
->maPreviewSize
.Height() )
107 // ------------------------------------------------------------------------
109 void GraphicReader::DisablePreviewMode()
112 mpReaderData
->maPreviewSize
= Size( 0, 0 );
115 // ------------------------------------------------------------------------
117 void GraphicReader::SetPreviewSize( const Size
& rSize
)
120 mpReaderData
= new ReaderData
;
121 mpReaderData
->maPreviewSize
= rSize
;
124 // ------------------------------------------------------------------------
126 Size
GraphicReader::GetPreviewSize() const
130 aSize
= mpReaderData
->maPreviewSize
;
138 ImpGraphic::ImpGraphic() :
139 mpAnimation ( NULL
),
143 meType ( GRAPHIC_NONE
),
144 mnDocFilePos ( 0UL ),
148 mbSwapUnderway ( FALSE
)
152 // ------------------------------------------------------------------------
154 ImpGraphic::ImpGraphic( const ImpGraphic
& rImpGraphic
) :
155 maMetaFile ( rImpGraphic
.maMetaFile
),
156 maEx ( rImpGraphic
.maEx
),
158 mpSwapFile ( rImpGraphic
.mpSwapFile
),
159 meType ( rImpGraphic
.meType
),
160 maDocFileURLStr ( rImpGraphic
.maDocFileURLStr
),
161 mnDocFilePos ( rImpGraphic
.mnDocFilePos
),
162 mnSizeBytes ( rImpGraphic
.mnSizeBytes
),
164 mbSwapOut ( rImpGraphic
.mbSwapOut
),
165 mbSwapUnderway ( FALSE
)
168 mpSwapFile
->nRefCount
++;
170 if( rImpGraphic
.mpGfxLink
)
171 mpGfxLink
= new GfxLink( *rImpGraphic
.mpGfxLink
);
175 if( rImpGraphic
.mpAnimation
)
177 mpAnimation
= new Animation( *rImpGraphic
.mpAnimation
);
178 maEx
= mpAnimation
->GetBitmapEx();
184 // ------------------------------------------------------------------------
186 ImpGraphic::ImpGraphic( const Bitmap
& rBitmap
) :
188 mpAnimation ( NULL
),
192 meType ( !rBitmap
? GRAPHIC_NONE
: GRAPHIC_BITMAP
),
193 mnDocFilePos ( 0UL ),
197 mbSwapUnderway ( FALSE
)
201 // ------------------------------------------------------------------------
203 ImpGraphic::ImpGraphic( const BitmapEx
& rBitmapEx
) :
205 mpAnimation ( NULL
),
209 meType ( !rBitmapEx
? GRAPHIC_NONE
: GRAPHIC_BITMAP
),
210 mnDocFilePos ( 0UL ),
214 mbSwapUnderway ( FALSE
)
218 // ------------------------------------------------------------------------
220 ImpGraphic::ImpGraphic( const Animation
& rAnimation
) :
221 maEx ( rAnimation
.GetBitmapEx() ),
222 mpAnimation ( new Animation( rAnimation
) ),
226 meType ( GRAPHIC_BITMAP
),
227 mnDocFilePos ( 0UL ),
231 mbSwapUnderway ( FALSE
)
235 // ------------------------------------------------------------------------
237 ImpGraphic::ImpGraphic( const GDIMetaFile
& rMtf
) :
239 mpAnimation ( NULL
),
243 meType ( GRAPHIC_GDIMETAFILE
),
244 mnDocFilePos ( 0UL ),
248 mbSwapUnderway ( FALSE
)
252 // ------------------------------------------------------------------------
254 ImpGraphic::~ImpGraphic()
258 if( (ULONG
) mpContext
> 1UL )
262 // ------------------------------------------------------------------------
264 ImpGraphic
& ImpGraphic::operator=( const ImpGraphic
& rImpGraphic
)
266 if( &rImpGraphic
!= this )
268 if( !mbSwapUnderway
)
271 maMetaFile
= rImpGraphic
.maMetaFile
;
272 meType
= rImpGraphic
.meType
;
273 mnSizeBytes
= rImpGraphic
.mnSizeBytes
;
277 if ( rImpGraphic
.mpAnimation
)
279 mpAnimation
= new Animation( *rImpGraphic
.mpAnimation
);
280 maEx
= mpAnimation
->GetBitmapEx();
285 maEx
= rImpGraphic
.maEx
;
288 if( !mbSwapUnderway
)
290 maDocFileURLStr
= rImpGraphic
.maDocFileURLStr
;
291 mnDocFilePos
= rImpGraphic
.mnDocFilePos
;
292 mbSwapOut
= rImpGraphic
.mbSwapOut
;
293 mpSwapFile
= rImpGraphic
.mpSwapFile
;
296 mpSwapFile
->nRefCount
++;
301 if( rImpGraphic
.mpGfxLink
)
302 mpGfxLink
= new GfxLink( *rImpGraphic
.mpGfxLink
);
310 // ------------------------------------------------------------------------
312 BOOL
ImpGraphic::operator==( const ImpGraphic
& rImpGraphic
) const
316 if( this == &rImpGraphic
)
318 else if( !ImplIsSwapOut() && ( rImpGraphic
.meType
== meType
) )
322 case( GRAPHIC_NONE
):
326 case( GRAPHIC_GDIMETAFILE
):
328 if( rImpGraphic
.maMetaFile
== maMetaFile
)
333 case( GRAPHIC_BITMAP
):
337 if( rImpGraphic
.mpAnimation
&& ( *rImpGraphic
.mpAnimation
== *mpAnimation
) )
340 else if( !rImpGraphic
.mpAnimation
&& ( rImpGraphic
.maEx
== maEx
) )
353 // ------------------------------------------------------------------------
355 void ImpGraphic::ImplClearGraphics( BOOL bCreateSwapInfo
)
357 if( bCreateSwapInfo
&& !ImplIsSwapOut() )
359 maSwapInfo
.maPrefMapMode
= ImplGetPrefMapMode();
360 maSwapInfo
.maPrefSize
= ImplGetPrefSize();
368 mpAnimation
->Clear();
380 // ------------------------------------------------------------------------
382 void ImpGraphic::ImplClear()
386 if( mpSwapFile
->nRefCount
> 1 )
387 mpSwapFile
->nRefCount
--;
392 ::ucbhelper::Content
aCnt( mpSwapFile
->aSwapURL
.GetMainURL( INetURLObject::NO_DECODE
),
393 ::com::sun::star::uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
>() );
395 aCnt
.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
396 ::com::sun::star::uno::makeAny( sal_Bool( sal_True
) ) );
398 catch( const ::com::sun::star::ucb::ContentCreationException
& )
401 catch( const ::com::sun::star::uno::RuntimeException
& )
404 catch( const ::com::sun::star::ucb::CommandAbortedException
& )
407 catch( const ::com::sun::star::uno::Exception
& )
419 maDocFileURLStr
.Erase();
422 ImplClearGraphics( FALSE
);
423 meType
= GRAPHIC_NONE
;
427 // ------------------------------------------------------------------------
429 GraphicType
ImpGraphic::ImplGetType() const
434 // ------------------------------------------------------------------------
436 void ImpGraphic::ImplSetDefaultType()
439 meType
= GRAPHIC_DEFAULT
;
442 // ------------------------------------------------------------------------
444 BOOL
ImpGraphic::ImplIsSupportedGraphic() const
446 return( meType
!= GRAPHIC_NONE
);
449 // ------------------------------------------------------------------------
451 BOOL
ImpGraphic::ImplIsTransparent() const
455 if( meType
== GRAPHIC_BITMAP
)
456 bRet
= ( mpAnimation
? mpAnimation
->IsTransparent() : maEx
.IsTransparent() );
463 // ------------------------------------------------------------------------
465 BOOL
ImpGraphic::ImplIsAlpha() const
469 if( meType
== GRAPHIC_BITMAP
)
470 bRet
= ( NULL
== mpAnimation
) && maEx
.IsAlpha();
477 // ------------------------------------------------------------------------
479 BOOL
ImpGraphic::ImplIsAnimated() const
481 return( mpAnimation
!= NULL
);
484 // ------------------------------------------------------------------------
486 Bitmap
ImpGraphic::ImplGetBitmap(const GraphicConversionParameters
& rParameters
) const
490 if( meType
== GRAPHIC_BITMAP
)
492 const BitmapEx
& rRetBmpEx
= ( mpAnimation
? mpAnimation
->GetBitmapEx() : maEx
);
493 const Color
aReplaceColor( COL_WHITE
);
495 aRetBmp
= rRetBmpEx
.GetBitmap( &aReplaceColor
);
497 if(rParameters
.getSizePixel().Width() || rParameters
.getSizePixel().Height())
498 aRetBmp
.Scale(rParameters
.getSizePixel());
500 else if( ( meType
!= GRAPHIC_DEFAULT
) && ImplIsSupportedGraphic() )
502 // use corner points of graphic to determine the pixel
503 // extent of the graphic (rounding errors are possible else)
506 const Point
aTLPix( aVDev
.LogicToPixel( aNullPt
, maMetaFile
.GetPrefMapMode() ) );
507 const Point
aBRPix( aVDev
.LogicToPixel( Point( maMetaFile
.GetPrefSize().Width() - 1, maMetaFile
.GetPrefSize().Height() - 1 ), maMetaFile
.GetPrefMapMode() ) );
508 Size
aDrawSize( aVDev
.LogicToPixel( maMetaFile
.GetPrefSize(), maMetaFile
.GetPrefMapMode() ) );
509 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
511 if(rParameters
.getSizePixel().Width() && rParameters
.getSizePixel().Height())
513 aDrawSize
.Width() = FRound((double)rParameters
.getSizePixel().Width() *
514 (double)aDrawSize
.Width() / (double)aSizePix
.Width());
515 aDrawSize
.Height() = FRound((double)rParameters
.getSizePixel().Height() *
516 (double)aDrawSize
.Height() / (double)aSizePix
.Height());
518 aSizePix
= rParameters
.getSizePixel();
521 if( aSizePix
.Width() && aSizePix
.Height() && !rParameters
.getUnlimitedSize()
522 && (aSizePix
.Width() > GRAPHIC_MTFTOBMP_MAXEXT
|| aSizePix
.Height() > GRAPHIC_MTFTOBMP_MAXEXT
))
524 const Size
aOldSizePix( aSizePix
);
525 double fWH
= (double) aSizePix
.Width() / aSizePix
.Height();
528 aSizePix
.Width() = FRound( GRAPHIC_MTFTOBMP_MAXEXT
* fWH
), aSizePix
.Height() = GRAPHIC_MTFTOBMP_MAXEXT
;
530 aSizePix
.Width() = GRAPHIC_MTFTOBMP_MAXEXT
, aSizePix
.Height() = FRound( GRAPHIC_MTFTOBMP_MAXEXT
/ fWH
);
532 aDrawSize
.Width() = FRound( ( (double) aDrawSize
.Width() * aSizePix
.Width() ) / aOldSizePix
.Width() );
533 aDrawSize
.Height() = FRound( ( (double) aDrawSize
.Height() * aSizePix
.Height() ) / aOldSizePix
.Height() );
536 if( aVDev
.SetOutputSizePixel( aSizePix
) )
538 if(rParameters
.getAntiAliase())
540 aVDev
.SetAntialiasing(aVDev
.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW
);
543 if(rParameters
.getSnapHorVerLines())
545 aVDev
.SetAntialiasing(aVDev
.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE
);
548 ImplDraw( &aVDev
, aNullPt
, aDrawSize
);
549 aRetBmp
= aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() );
555 aRetBmp
.SetPrefMapMode( ImplGetPrefMapMode() );
556 aRetBmp
.SetPrefSize( ImplGetPrefSize() );
562 // ------------------------------------------------------------------------
564 BitmapEx
ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters
& rParameters
) const
568 if( meType
== GRAPHIC_BITMAP
)
570 aRetBmpEx
= ( mpAnimation
? mpAnimation
->GetBitmapEx() : maEx
);
572 if(rParameters
.getSizePixel().Width() || rParameters
.getSizePixel().Height())
573 aRetBmpEx
.Scale(rParameters
.getSizePixel());
575 else if( ( meType
!= GRAPHIC_DEFAULT
) && ImplIsSupportedGraphic() )
577 const ImpGraphic
aMonoMask( maMetaFile
.GetMonochromeMtf( COL_BLACK
) );
578 aRetBmpEx
= BitmapEx(ImplGetBitmap(rParameters
), aMonoMask
.ImplGetBitmap(rParameters
));
584 // ------------------------------------------------------------------------
586 Animation
ImpGraphic::ImplGetAnimation() const
588 Animation aAnimation
;
591 aAnimation
= *mpAnimation
;
596 // ------------------------------------------------------------------------
598 const GDIMetaFile
& ImpGraphic::ImplGetGDIMetaFile() const
603 // ------------------------------------------------------------------------
605 Size
ImpGraphic::ImplGetPrefSize() const
609 if( ImplIsSwapOut() )
610 aSize
= maSwapInfo
.maPrefSize
;
615 case( GRAPHIC_NONE
):
616 case( GRAPHIC_DEFAULT
):
619 case( GRAPHIC_BITMAP
):
621 aSize
= maEx
.GetPrefSize();
623 if( !aSize
.Width() || !aSize
.Height() )
624 aSize
= maEx
.GetSizePixel();
630 if( ImplIsSupportedGraphic() )
631 aSize
= maMetaFile
.GetPrefSize();
640 // ------------------------------------------------------------------------
642 void ImpGraphic::ImplSetPrefSize( const Size
& rPrefSize
)
646 case( GRAPHIC_NONE
):
647 case( GRAPHIC_DEFAULT
):
650 case( GRAPHIC_BITMAP
):
651 // #108077# Push through pref size to animation object,
652 // will be lost on copy otherwise
653 if( ImplIsAnimated() )
654 const_cast< BitmapEx
& >(mpAnimation
->GetBitmapEx()).SetPrefSize( rPrefSize
);
656 maEx
.SetPrefSize( rPrefSize
);
661 if( ImplIsSupportedGraphic() )
662 maMetaFile
.SetPrefSize( rPrefSize
);
668 // ------------------------------------------------------------------------
670 MapMode
ImpGraphic::ImplGetPrefMapMode() const
674 if( ImplIsSwapOut() )
675 aMapMode
= maSwapInfo
.maPrefMapMode
;
680 case( GRAPHIC_NONE
):
681 case( GRAPHIC_DEFAULT
):
684 case( GRAPHIC_BITMAP
):
686 const Size
aSize( maEx
.GetPrefSize() );
688 if ( aSize
.Width() && aSize
.Height() )
689 aMapMode
= maEx
.GetPrefMapMode();
695 if( ImplIsSupportedGraphic() )
696 return maMetaFile
.GetPrefMapMode();
705 // ------------------------------------------------------------------------
707 void ImpGraphic::ImplSetPrefMapMode( const MapMode
& rPrefMapMode
)
711 case( GRAPHIC_NONE
):
712 case( GRAPHIC_DEFAULT
):
715 case( GRAPHIC_BITMAP
):
716 // #108077# Push through pref mapmode to animation object,
717 // will be lost on copy otherwise
718 if( ImplIsAnimated() )
719 const_cast< BitmapEx
& >(mpAnimation
->GetBitmapEx()).SetPrefMapMode( rPrefMapMode
);
721 maEx
.SetPrefMapMode( rPrefMapMode
);
726 if( ImplIsSupportedGraphic() )
727 maMetaFile
.SetPrefMapMode( rPrefMapMode
);
733 // ------------------------------------------------------------------------
735 ULONG
ImpGraphic::ImplGetSizeBytes() const
737 if( 0 == mnSizeBytes
)
739 if( meType
== GRAPHIC_BITMAP
)
741 mnSizeBytes
= mpAnimation
? mpAnimation
->GetSizeBytes() : maEx
.GetSizeBytes();
743 else if( meType
== GRAPHIC_GDIMETAFILE
)
745 mnSizeBytes
= maMetaFile
.GetSizeBytes();
749 return( mnSizeBytes
);
752 // ------------------------------------------------------------------------
754 void ImpGraphic::ImplDraw( OutputDevice
* pOutDev
, const Point
& rDestPt
) const
756 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
760 case( GRAPHIC_DEFAULT
):
763 case( GRAPHIC_BITMAP
):
766 mpAnimation
->Draw( pOutDev
, rDestPt
);
768 maEx
.Draw( pOutDev
, rDestPt
);
773 ImplDraw( pOutDev
, rDestPt
, maMetaFile
.GetPrefSize() );
779 // ------------------------------------------------------------------------
781 void ImpGraphic::ImplDraw( OutputDevice
* pOutDev
,
782 const Point
& rDestPt
, const Size
& rDestSize
) const
784 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
788 case( GRAPHIC_DEFAULT
):
791 case( GRAPHIC_BITMAP
):
794 mpAnimation
->Draw( pOutDev
, rDestPt
, rDestSize
);
796 maEx
.Draw( pOutDev
, rDestPt
, rDestSize
);
802 ( (ImpGraphic
*) this )->maMetaFile
.WindStart();
803 ( (ImpGraphic
*) this )->maMetaFile
.Play( pOutDev
, rDestPt
, rDestSize
);
804 ( (ImpGraphic
*) this )->maMetaFile
.WindStart();
811 // ------------------------------------------------------------------------
813 void ImpGraphic::ImplStartAnimation( OutputDevice
* pOutDev
,
814 const Point
& rDestPt
,
816 OutputDevice
* pFirstFrameOutDev
)
818 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation
)
819 mpAnimation
->Start( pOutDev
, rDestPt
, nExtraData
, pFirstFrameOutDev
);
822 // ------------------------------------------------------------------------
824 void ImpGraphic::ImplStartAnimation( OutputDevice
* pOutDev
, const Point
& rDestPt
,
825 const Size
& rDestSize
, long nExtraData
,
826 OutputDevice
* pFirstFrameOutDev
)
828 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation
)
829 mpAnimation
->Start( pOutDev
, rDestPt
, rDestSize
, nExtraData
, pFirstFrameOutDev
);
832 // ------------------------------------------------------------------------
834 void ImpGraphic::ImplStopAnimation( OutputDevice
* pOutDev
, long nExtraData
)
836 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation
)
837 mpAnimation
->Stop( pOutDev
, nExtraData
);
840 // ------------------------------------------------------------------------
842 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link
& rLink
)
845 mpAnimation
->SetNotifyHdl( rLink
);
848 // ------------------------------------------------------------------------
850 Link
ImpGraphic::ImplGetAnimationNotifyHdl() const
855 aLink
= mpAnimation
->GetNotifyHdl();
860 // ------------------------------------------------------------------------
862 ULONG
ImpGraphic::ImplGetAnimationLoopCount() const
864 return( mpAnimation
? mpAnimation
->GetLoopCount() : 0UL );
867 // ------------------------------------------------------------------------
869 void ImpGraphic::ImplResetAnimationLoopCount()
872 mpAnimation
->ResetLoopCount();
875 // ------------------------------------------------------------------------
877 List
* ImpGraphic::ImplGetAnimationInfoList() const
879 return( mpAnimation
? mpAnimation
->GetAInfoList() : NULL
);
882 // ------------------------------------------------------------------------
884 GraphicReader
* ImpGraphic::ImplGetContext()
889 // ------------------------------------------------------------------------
891 void ImpGraphic::ImplSetContext( GraphicReader
* pReader
)
896 // ------------------------------------------------------------------------
898 void ImpGraphic::ImplSetDocFileName( const String
& rName
, ULONG nFilePos
)
900 const INetURLObject
aURL( rName
);
902 DBG_ASSERT( !rName
.Len() || ( aURL
.GetProtocol() != INET_PROT_NOT_VALID
), "Graphic::SetDocFileName(...): invalid URL" );
904 maDocFileURLStr
= aURL
.GetMainURL( INetURLObject::NO_DECODE
);
905 mnDocFilePos
= nFilePos
;
908 // ------------------------------------------------------------------------
910 const String
& ImpGraphic::ImplGetDocFileName() const
912 return maDocFileURLStr
;
915 // ------------------------------------------------------------------------
917 ULONG
ImpGraphic::ImplGetDocFilePos() const
922 // ------------------------------------------------------------------------
924 BOOL
ImpGraphic::ImplReadEmbedded( SvStream
& rIStm
, BOOL bSwap
)
928 const ULONG nStartPos
= rIStm
.Tell();
933 const USHORT nOldFormat
= rIStm
.GetNumberFormatInt();
936 if( !mbSwapUnderway
)
938 const String
aTempURLStr( maDocFileURLStr
);
939 const ULONG nTempPos
= mnDocFilePos
;
943 maDocFileURLStr
= aTempURLStr
;
944 mnDocFilePos
= nTempPos
;
947 rIStm
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
951 if( GRAPHIC_FORMAT_50
== nId
)
953 // read new style header
954 VersionCompat
* pCompat
= new VersionCompat( rIStm
, STREAM_READ
);
965 // read old style header
966 long nWidth
, nHeight
;
967 long nMapMode
, nScaleNumX
, nScaleDenomX
;
968 long nScaleNumY
, nScaleDenomY
, nOffsX
, nOffsY
;
970 rIStm
.SeekRel( -4L );
972 rIStm
>> nType
>> nLen
>> nWidth
>> nHeight
;
973 rIStm
>> nMapMode
>> nScaleNumX
>> nScaleDenomX
>> nScaleNumY
;
974 rIStm
>> nScaleDenomY
>> nOffsX
>> nOffsY
;
979 nType
= SWAPLONG( nType
);
980 nLen
= SWAPLONG( nLen
);
981 nWidth
= SWAPLONG( nWidth
);
982 nHeight
= SWAPLONG( nHeight
);
983 nMapMode
= SWAPLONG( nMapMode
);
984 nScaleNumX
= SWAPLONG( nScaleNumX
);
985 nScaleDenomX
= SWAPLONG( nScaleDenomX
);
986 nScaleNumY
= SWAPLONG( nScaleNumY
);
987 nScaleDenomY
= SWAPLONG( nScaleDenomY
);
988 nOffsX
= SWAPLONG( nOffsX
);
989 nOffsY
= SWAPLONG( nOffsY
);
992 aSize
= Size( nWidth
, nHeight
);
993 aMapMode
= MapMode( (MapUnit
) nMapMode
, Point( nOffsX
, nOffsY
),
994 Fraction( nScaleNumX
, nScaleDenomX
),
995 Fraction( nScaleNumY
, nScaleDenomY
) );
998 nHeaderLen
= rIStm
.Tell() - nStartPos
;
999 meType
= (GraphicType
) nType
;
1003 if( meType
== GRAPHIC_BITMAP
)
1005 maEx
.aBitmapSize
= aSize
;
1007 if( aMapMode
!= MapMode() )
1009 maEx
.SetPrefMapMode( aMapMode
);
1010 maEx
.SetPrefSize( aSize
);
1015 maMetaFile
.SetPrefMapMode( aMapMode
);
1016 maMetaFile
.SetPrefSize( aSize
);
1021 if( maDocFileURLStr
.Len() )
1023 rIStm
.Seek( nStartPos
+ nHeaderLen
+ nLen
);
1024 bRet
= mbSwapOut
= TRUE
;
1028 ::utl::TempFile aTempFile
;
1029 const INetURLObject
aTmpURL( aTempFile
.GetURL() );
1031 if( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
).getLength() )
1033 SvStream
* pOStm
= ::utl::UcbStreamHelper::CreateStream( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
), STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
1037 ULONG nFullLen
= nHeaderLen
+ nLen
;
1038 ULONG nPartLen
= Min( nFullLen
, (ULONG
) GRAPHIC_MAXPARTLEN
);
1039 BYTE
* pBuffer
= (BYTE
*) rtl_allocateMemory( nPartLen
);
1041 pOStm
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1045 rIStm
.Seek( nStartPos
);
1049 rIStm
.Read( (char*) pBuffer
, nPartLen
);
1050 pOStm
->Write( (char*) pBuffer
, nPartLen
);
1052 nFullLen
-= nPartLen
;
1054 if( nFullLen
< GRAPHIC_MAXPARTLEN
)
1055 nPartLen
= nFullLen
;
1058 rtl_freeMemory( pBuffer
);
1059 ULONG nReadErr
= rIStm
.GetError(), nWriteErr
= pOStm
->GetError();
1060 delete pOStm
, pOStm
= NULL
;
1062 if( !nReadErr
&& !nWriteErr
)
1064 bRet
= mbSwapOut
= TRUE
;
1065 mpSwapFile
= new ImpSwapFile
;
1066 mpSwapFile
->nRefCount
= 1;
1067 mpSwapFile
->aSwapURL
= aTmpURL
;
1073 ::ucbhelper::Content
aCnt( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
),
1074 ::com::sun::star::uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
>() );
1076 aCnt
.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1077 ::com::sun::star::uno::makeAny( sal_Bool( sal_True
) ) );
1079 catch( const ::com::sun::star::ucb::ContentCreationException
& )
1082 catch( const ::com::sun::star::uno::RuntimeException
& )
1085 catch( const ::com::sun::star::ucb::CommandAbortedException
& )
1088 catch( const ::com::sun::star::uno::Exception
& )
1099 else if( meType
== GRAPHIC_BITMAP
|| meType
== GRAPHIC_GDIMETAFILE
)
1102 bRet
= ( rIStm
.GetError() == 0UL );
1104 else if( meType
>= SYS_WINMETAFILE
&& meType
<= SYS_MACMETAFILE
)
1106 Graphic aSysGraphic
;
1109 switch( sal::static_int_cast
<ULONG
>(meType
) )
1111 case( SYS_WINMETAFILE
):
1112 case( SYS_WNTMETAFILE
): nCvtType
= CVT_WMF
; break;
1113 case( SYS_OS2METAFILE
): nCvtType
= CVT_MET
; break;
1114 case( SYS_MACMETAFILE
): nCvtType
= CVT_PCT
; break;
1117 nCvtType
= CVT_UNKNOWN
;
1121 if( nType
&& GraphicConverter::Import( rIStm
, aSysGraphic
, nCvtType
) == ERRCODE_NONE
)
1123 *this = ImpGraphic( aSysGraphic
.GetGDIMetaFile() );
1124 bRet
= ( rIStm
.GetError() == 0UL );
1127 meType
= GRAPHIC_DEFAULT
;
1132 ImplSetPrefMapMode( aMapMode
);
1133 ImplSetPrefSize( aSize
);
1139 rIStm
.SetNumberFormatInt( nOldFormat
);
1144 // ------------------------------------------------------------------------
1146 BOOL
ImpGraphic::ImplWriteEmbedded( SvStream
& rOStm
)
1150 if( ( meType
!= GRAPHIC_NONE
) && ( meType
!= GRAPHIC_DEFAULT
) && !ImplIsSwapOut() )
1152 const MapMode
aMapMode( ImplGetPrefMapMode() );
1153 const Size
aSize( ImplGetPrefSize() );
1154 const USHORT nOldFormat
= rOStm
.GetNumberFormatInt();
1155 ULONG nDataFieldPos
;
1157 rOStm
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1159 // write correct version ( old style/new style header )
1160 if( rOStm
.GetVersion() >= SOFFICE_FILEFORMAT_50
)
1162 // write ID for new format (5.0)
1163 rOStm
<< GRAPHIC_FORMAT_50
;
1165 // write new style header
1166 VersionCompat
* pCompat
= new VersionCompat( rOStm
, STREAM_WRITE
, 1 );
1168 rOStm
<< (long) meType
;
1170 // data size is updated later
1171 nDataFieldPos
= rOStm
.Tell();
1181 // write old style (<=4.0) header
1182 rOStm
<< (long) meType
;
1184 // data size is updated later
1185 nDataFieldPos
= rOStm
.Tell();
1188 rOStm
<< (long) aSize
.Width();
1189 rOStm
<< (long) aSize
.Height();
1190 rOStm
<< (long) aMapMode
.GetMapUnit();
1191 rOStm
<< (long) aMapMode
.GetScaleX().GetNumerator();
1192 rOStm
<< (long) aMapMode
.GetScaleX().GetDenominator();
1193 rOStm
<< (long) aMapMode
.GetScaleY().GetNumerator();
1194 rOStm
<< (long) aMapMode
.GetScaleY().GetDenominator();
1195 rOStm
<< (long) aMapMode
.GetOrigin().X();
1196 rOStm
<< (long) aMapMode
.GetOrigin().Y();
1200 if( !rOStm
.GetError() )
1202 const ULONG nDataStart
= rOStm
.Tell();
1204 if( ImplIsSupportedGraphic() )
1207 if( !rOStm
.GetError() )
1209 const ULONG nStmPos2
= rOStm
.Tell();
1210 rOStm
.Seek( nDataFieldPos
);
1211 rOStm
<< (long) ( nStmPos2
- nDataStart
);
1212 rOStm
.Seek( nStmPos2
);
1217 rOStm
.SetNumberFormatInt( nOldFormat
);
1223 // ------------------------------------------------------------------------
1225 BOOL
ImpGraphic::ImplSwapOut()
1229 if( !ImplIsSwapOut() )
1231 if( !maDocFileURLStr
.Len() )
1233 ::utl::TempFile aTempFile
;
1234 const INetURLObject
aTmpURL( aTempFile
.GetURL() );
1236 if( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
).getLength() )
1238 SvStream
* pOStm
= ::utl::UcbStreamHelper::CreateStream( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
), STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
1242 pOStm
->SetVersion( SOFFICE_FILEFORMAT_50
);
1243 pOStm
->SetCompressMode( COMPRESSMODE_NATIVE
);
1245 if( ( bRet
= ImplSwapOut( pOStm
) ) == TRUE
)
1247 mpSwapFile
= new ImpSwapFile
;
1248 mpSwapFile
->nRefCount
= 1;
1249 mpSwapFile
->aSwapURL
= aTmpURL
;
1253 delete pOStm
, pOStm
= NULL
;
1257 ::ucbhelper::Content
aCnt( aTmpURL
.GetMainURL( INetURLObject::NO_DECODE
),
1258 ::com::sun::star::uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
>() );
1260 aCnt
.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1261 ::com::sun::star::uno::makeAny( sal_Bool( sal_True
) ) );
1263 catch( const ::com::sun::star::ucb::ContentCreationException
& )
1266 catch( const ::com::sun::star::uno::RuntimeException
& )
1269 catch( const ::com::sun::star::ucb::CommandAbortedException
& )
1272 catch( const ::com::sun::star::uno::Exception
& )
1283 ImplClearGraphics( TRUE
);
1284 bRet
= mbSwapOut
= TRUE
;
1291 // ------------------------------------------------------------------------
1293 BOOL
ImpGraphic::ImplSwapOut( SvStream
* pOStm
)
1299 pOStm
->SetBufferSize( GRAPHIC_STREAMBUFSIZE
);
1301 if( !pOStm
->GetError() && ImplWriteEmbedded( *pOStm
) )
1305 if( !pOStm
->GetError() )
1307 ImplClearGraphics( TRUE
);
1308 bRet
= mbSwapOut
= TRUE
;
1314 ImplClearGraphics( TRUE
);
1315 bRet
= mbSwapOut
= TRUE
;
1321 // ------------------------------------------------------------------------
1323 BOOL
ImpGraphic::ImplSwapIn()
1327 if( ImplIsSwapOut() )
1332 aSwapURL
= mpSwapFile
->aSwapURL
.GetMainURL( INetURLObject::NO_DECODE
);
1334 aSwapURL
= maDocFileURLStr
;
1336 if( aSwapURL
.Len() )
1338 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( aSwapURL
, STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
1342 pIStm
->SetVersion( SOFFICE_FILEFORMAT_50
);
1343 pIStm
->SetCompressMode( COMPRESSMODE_NATIVE
);
1346 pIStm
->Seek( mnDocFilePos
);
1348 bRet
= ImplSwapIn( pIStm
);
1353 if( mpSwapFile
->nRefCount
> 1 )
1354 mpSwapFile
->nRefCount
--;
1359 ::ucbhelper::Content
aCnt( aSwapURL
,
1360 ::com::sun::star::uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
>() );
1362 aCnt
.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1363 ::com::sun::star::uno::makeAny( sal_Bool( sal_True
) ) );
1365 catch( const ::com::sun::star::ucb::ContentCreationException
& )
1368 catch( const ::com::sun::star::uno::RuntimeException
& )
1371 catch( const ::com::sun::star::ucb::CommandAbortedException
& )
1374 catch( const ::com::sun::star::uno::Exception
& )
1390 // ------------------------------------------------------------------------
1392 BOOL
ImpGraphic::ImplSwapIn( SvStream
* pIStm
)
1398 pIStm
->SetBufferSize( GRAPHIC_STREAMBUFSIZE
);
1400 if( !pIStm
->GetError() )
1402 mbSwapUnderway
= TRUE
;
1403 bRet
= ImplReadEmbedded( *pIStm
);
1404 mbSwapUnderway
= FALSE
;
1416 // ------------------------------------------------------------------------
1418 BOOL
ImpGraphic::ImplIsSwapOut() const
1423 // ------------------------------------------------------------------------
1425 void ImpGraphic::ImplSetLink( const GfxLink
& rGfxLink
)
1428 mpGfxLink
= new GfxLink( rGfxLink
);
1430 if( mpGfxLink
->IsNative() )
1431 mpGfxLink
->SwapOut();
1434 // ------------------------------------------------------------------------
1436 GfxLink
ImpGraphic::ImplGetLink()
1438 return( mpGfxLink
? *mpGfxLink
: GfxLink() );
1441 // ------------------------------------------------------------------------
1443 BOOL
ImpGraphic::ImplIsLink() const
1445 return ( mpGfxLink
!= NULL
) ? TRUE
: FALSE
;
1448 // ------------------------------------------------------------------------
1450 ULONG
ImpGraphic::ImplGetChecksum() const
1454 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
1458 case( GRAPHIC_DEFAULT
):
1461 case( GRAPHIC_BITMAP
):
1464 nRet
= mpAnimation
->GetChecksum();
1466 nRet
= maEx
.GetChecksum();
1471 nRet
= maMetaFile
.GetChecksum();
1479 // ------------------------------------------------------------------------
1481 BOOL
ImpGraphic::ImplExportNative( SvStream
& rOStm
) const
1483 BOOL bResult
= FALSE
;
1485 if( !rOStm
.GetError() )
1487 if( !ImplIsSwapOut() )
1489 if( mpGfxLink
&& mpGfxLink
->IsNative() )
1490 bResult
= mpGfxLink
->ExportNative( rOStm
);
1494 bResult
= ( rOStm
.GetError() == ERRCODE_NONE
);
1498 rOStm
.SetError( SVSTREAM_GENERALERROR
);
1504 // ------------------------------------------------------------------------
1506 SvStream
& operator>>( SvStream
& rIStm
, ImpGraphic
& rImpGraphic
)
1508 if( !rIStm
.GetError() )
1510 const ULONG nStmPos1
= rIStm
.Tell();
1513 if ( !rImpGraphic
.mbSwapUnderway
)
1514 rImpGraphic
.ImplClear();
1519 // if there is no more data, avoid further expensive
1520 // reading which will create VDevs and other stuff, just to
1521 // read nothing. CAUTION: Eof is only true AFTER reading another
1522 // byte, a speciality of SvMemoryStream (!)
1523 if(!rIStm
.GetError() && !rIStm
.IsEof())
1525 if( NATIVE_FORMAT_50
== nTmp
)
1529 VersionCompat
* pCompat
;
1532 pCompat
= new VersionCompat( rIStm
, STREAM_READ
);
1537 // set dummy link to avoid creation of additional link after filtering;
1538 // we set a default link to avoid unnecessary swapping of native data
1539 aGraphic
.SetLink( GfxLink() );
1541 if( !rIStm
.GetError() && aLink
.LoadNative( aGraphic
) )
1543 // set link only, if no other link was set
1544 const BOOL bSetLink
= ( rImpGraphic
.mpGfxLink
== NULL
);
1547 rImpGraphic
= *aGraphic
.ImplGetImpGraphic();
1549 if( aLink
.IsPrefMapModeValid() )
1550 rImpGraphic
.ImplSetPrefMapMode( aLink
.GetPrefMapMode() );
1552 if( aLink
.IsPrefSizeValid() )
1553 rImpGraphic
.ImplSetPrefSize( aLink
.GetPrefSize() );
1556 rImpGraphic
.ImplSetLink( aLink
);
1560 rIStm
.Seek( nStmPos1
);
1561 rIStm
.SetError( ERRCODE_IO_WRONGFORMAT
);
1567 const USHORT nOldFormat
= rIStm
.GetNumberFormatInt();
1569 rIStm
.SeekRel( -4 );
1570 rIStm
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1573 if( !rIStm
.GetError() )
1575 UINT32
nMagic1(0), nMagic2(0);
1576 ULONG nActPos
= rIStm
.Tell();
1578 rIStm
>> nMagic1
>> nMagic2
;
1579 rIStm
.Seek( nActPos
);
1581 rImpGraphic
= ImpGraphic( aBmpEx
);
1583 if( !rIStm
.GetError() && ( 0x5344414e == nMagic1
) && ( 0x494d4931 == nMagic2
) )
1585 delete rImpGraphic
.mpAnimation
;
1586 rImpGraphic
.mpAnimation
= new Animation
;
1587 rIStm
>> *rImpGraphic
.mpAnimation
;
1589 // #108077# manually set loaded BmpEx to Animation
1590 // (which skips loading its BmpEx if already done)
1591 rImpGraphic
.mpAnimation
->SetBitmapEx(aBmpEx
);
1600 rIStm
.Seek( nStmPos1
);
1604 if( !rIStm
.GetError() )
1607 rIStm
.Seek( nStmPos1
);
1610 rIStm
.SetNumberFormatInt( nOldFormat
);
1618 // ------------------------------------------------------------------------
1620 SvStream
& operator<<( SvStream
& rOStm
, const ImpGraphic
& rImpGraphic
)
1622 if( !rOStm
.GetError() )
1624 if( !rImpGraphic
.ImplIsSwapOut() )
1626 if( ( rOStm
.GetVersion() >= SOFFICE_FILEFORMAT_50
) &&
1627 ( rOStm
.GetCompressMode() & COMPRESSMODE_NATIVE
) &&
1628 rImpGraphic
.mpGfxLink
&& rImpGraphic
.mpGfxLink
->IsNative() )
1630 VersionCompat
* pCompat
;
1633 rOStm
<< NATIVE_FORMAT_50
;
1635 // write compat info
1636 pCompat
= new VersionCompat( rOStm
, STREAM_WRITE
, 1 );
1639 rImpGraphic
.mpGfxLink
->SetPrefMapMode( rImpGraphic
.ImplGetPrefMapMode() );
1640 rImpGraphic
.mpGfxLink
->SetPrefSize( rImpGraphic
.ImplGetPrefSize() );
1641 rOStm
<< *rImpGraphic
.mpGfxLink
;
1646 const USHORT nOldFormat
= rOStm
.GetNumberFormatInt();
1647 rOStm
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1649 switch( rImpGraphic
.ImplGetType() )
1651 case( GRAPHIC_NONE
):
1652 case( GRAPHIC_DEFAULT
):
1655 case GRAPHIC_BITMAP
:
1657 if ( rImpGraphic
.ImplIsAnimated() )
1658 rOStm
<< *rImpGraphic
.mpAnimation
;
1660 rOStm
<< rImpGraphic
.maEx
;
1666 if( rImpGraphic
.ImplIsSupportedGraphic() )
1667 rOStm
<< rImpGraphic
.maMetaFile
;
1672 rOStm
.SetNumberFormatInt( nOldFormat
);
1676 rOStm
.SetError( SVSTREAM_GENERALERROR
);