1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/task/XStatusIndicator.hpp>
21 #include <unotools/ucbstreamhelper.hxx>
23 #include <osl/endian.h>
24 #include <vcl/virdev.hxx>
25 #include <vcl/graph.hxx>
26 #include <tools/stream.hxx>
29 #include <elements.hxx>
32 using namespace ::com::sun::star
;
34 // ---------------------------------------------------------------
36 void CGM::ImplCGMInit()
38 mbIsFinished
= mbPicture
= mbMetaFile
= mbPictureBody
= sal_False
;
48 pCopyOfE
= new CGMElements( *this );
49 pElement
= new CGMElements( *this );
52 // ---------------------------------------------------------------
54 #ifdef CGM_EXPORT_IMPRESS
56 CGM::CGM( sal_uInt32 nMode
, uno::Reference
< frame::XModel
> & rModel
) :
58 mbStatus ( sal_True
),
59 mpOutAct ( new CGMImpressOutAct( *this, rModel
) ),
62 mnMode
|= CGM_EXPORT_IMPRESS
;
67 // ---------------------------------------------------------------
72 #ifdef CGM_EXPORT_META
75 mpGDIMetaFile
->Stop();
76 mpGDIMetaFile
->SetPrefMapMode( MapMode() );
77 mpGDIMetaFile
->SetPrefSize( Size( static_cast< long >( mnOutdx
), static_cast< long >( mnOutdy
) ) );
79 *mpGraphic
= Graphic( *mpGDIMetaFile
);
82 for( size_t i
= 0, n
= maDefRepList
.size(); i
< n
; ++i
)
83 delete maDefRepList
[ i
];
85 maDefRepSizeList
.clear();
94 // ---------------------------------------------------------------
96 sal_uInt32
CGM::GetBackGroundColor()
98 return ( pElement
) ? pElement
->aColorTable
[ 0 ] : 0;
101 // ---------------------------------------------------------------
103 sal_uInt32
CGM::ImplGetUI16( sal_uInt32
/*nAlign*/ )
105 sal_uInt8
* pSource
= mpSource
+ mnParaSize
;
107 return ( pSource
[ 0 ] << 8 ) + pSource
[ 1 ];
110 // ---------------------------------------------------------------
112 sal_uInt8
CGM::ImplGetByte( sal_uInt32 nSource
, sal_uInt32 nPrecision
)
114 return (sal_uInt8
)( nSource
>> ( ( nPrecision
- 1 ) << 3 ) );
117 // ---------------------------------------------------------------
119 long CGM::ImplGetI( sal_uInt32 nPrecision
)
121 sal_uInt8
* pSource
= mpSource
+ mnParaSize
;
122 mnParaSize
+= nPrecision
;
127 return (char)*pSource
;
132 return (sal_Int16
)( ( pSource
[ 0 ] << 8 ) | pSource
[ 1 ] );
137 return ( ( pSource
[ 0 ] << 24 ) | ( pSource
[ 1 ] << 16 ) | pSource
[ 2 ] << 8 ) >> 8;
141 return (sal_Int32
)( ( pSource
[ 0 ] << 24 ) | ( pSource
[ 1 ] << 16 ) | ( pSource
[ 2 ] << 8 ) | ( pSource
[ 3 ] ) );
144 mbStatus
= sal_False
;
149 // ---------------------------------------------------------------
151 sal_uInt32
CGM::ImplGetUI( sal_uInt32 nPrecision
)
153 sal_uInt8
* pSource
= mpSource
+ mnParaSize
;
154 mnParaSize
+= nPrecision
;
158 return (sal_Int8
)*pSource
;
161 return (sal_uInt16
)( ( pSource
[ 0 ] << 8 ) | pSource
[ 1 ] );
165 return ( pSource
[ 0 ] << 16 ) | ( pSource
[ 1 ] << 8 ) | pSource
[ 2 ];
169 return (sal_uInt32
)( ( pSource
[ 0 ] << 24 ) | ( pSource
[ 1 ] << 16 ) | ( pSource
[ 2 ] << 8 ) | ( pSource
[ 3 ] ) );
172 mbStatus
= sal_False
;
177 // ---------------------------------------------------------------
179 void CGM::ImplGetSwitch4( sal_uInt8
* pSource
, sal_uInt8
* pDest
)
181 for ( int i
= 0; i
< 4; i
++ )
183 pDest
[ i
] = pSource
[ i
^ 3 ]; // Little Endian <-> Big Endian switch
187 // ---------------------------------------------------------------
189 void CGM::ImplGetSwitch8( sal_uInt8
* pSource
, sal_uInt8
* pDest
)
191 for ( int i
= 0; i
< 8; i
++ )
193 pDest
[ i
] = pSource
[ i
^ 7 ]; // Little Endian <-> Big Endian switch
197 // ---------------------------------------------------------------
199 double CGM::ImplGetFloat( RealPrecision eRealPrecision
, sal_uInt32 nRealSize
)
203 sal_Bool bCompatible
;
209 bCompatible
= sal_True
;
211 bCompatible
= sal_False
;
214 pPtr
= mpSource
+ mnParaSize
;
217 if ( nRealSize
== 4 )
218 ImplGetSwitch4( mpSource
+ mnParaSize
, &aBuf
[0] );
220 ImplGetSwitch8( mpSource
+ mnParaSize
, &aBuf
[0] );
223 if ( eRealPrecision
== RP_FLOAT
)
225 if ( nRealSize
== 4 )
227 memcpy( (void*)&fFloatBuf
, pPtr
, 4 );
228 nRetValue
= (double)fFloatBuf
;
232 memcpy( (void*)&fDoubleBuf
, pPtr
, 8 );
233 nRetValue
= fDoubleBuf
;
239 int nSwitch
= ( bCompatible
) ? 0 : 1 ;
240 if ( nRealSize
== 4 )
242 sal_uInt16
* pShort
= (sal_uInt16
*)pPtr
;
243 nVal
= pShort
[ nSwitch
];
245 nVal
|= pShort
[ nSwitch
^ 1 ];
246 nRetValue
= (double)nVal
;
251 sal_Int32
* pLong
= (sal_Int32
*)pPtr
;
252 nRetValue
= (double)abs( pLong
[ nSwitch
] );
254 nVal
= (sal_uInt32
)( pLong
[ nSwitch
^ 1 ] );
256 nRetValue
+= (double)nVal
;
257 if ( pLong
[ nSwitch
] < 0 )
259 nRetValue
= -nRetValue
;
264 mnParaSize
+= nRealSize
;
268 // ---------------------------------------------------------------
270 sal_uInt32
CGM::ImplGetPointSize()
272 if ( pElement
->eVDCType
== VDC_INTEGER
)
273 return pElement
->nVDCIntegerPrecision
<< 1;
275 return pElement
->nVDCRealSize
<< 1;
278 // ---------------------------------------------------------------
280 inline double CGM::ImplGetIX()
282 return ( ( ImplGetI( pElement
->nVDCIntegerPrecision
) + mnVDCXadd
) * mnVDCXmul
);
285 // ---------------------------------------------------------------
287 inline double CGM::ImplGetFX()
289 return ( ( ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
) + mnVDCXadd
) * mnVDCXmul
);
292 // ---------------------------------------------------------------
294 inline double CGM::ImplGetIY()
296 return ( ( ImplGetI( pElement
->nVDCIntegerPrecision
) + mnVDCYadd
) * mnVDCYmul
);
299 // ---------------------------------------------------------------
301 inline double CGM::ImplGetFY()
303 return ( ( ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
) + mnVDCYadd
) * mnVDCYmul
);
306 // ---------------------------------------------------------------
308 void CGM::ImplGetPoint( FloatPoint
& rFloatPoint
, sal_Bool bMap
)
310 if ( pElement
->eVDCType
== VDC_INTEGER
)
312 rFloatPoint
.X
= ImplGetIX();
313 rFloatPoint
.Y
= ImplGetIY();
315 else // ->floating points
317 rFloatPoint
.X
= ImplGetFX();
318 rFloatPoint
.Y
= ImplGetFY();
321 ImplMapPoint( rFloatPoint
);
324 // ---------------------------------------------------------------
326 void CGM::ImplGetRectangle( FloatRect
& rFloatRect
, sal_Bool bMap
)
328 if ( pElement
->eVDCType
== VDC_INTEGER
)
330 rFloatRect
.Left
= ImplGetIX();
331 rFloatRect
.Bottom
= ImplGetIY();
332 rFloatRect
.Right
= ImplGetIX();
333 rFloatRect
.Top
= ImplGetIY();
335 else // ->floating points
337 rFloatRect
.Left
= ImplGetFX();
338 rFloatRect
.Bottom
= ImplGetFY();
339 rFloatRect
.Right
= ImplGetFX();
340 rFloatRect
.Top
= ImplGetFY();
344 ImplMapX( rFloatRect
.Left
);
345 ImplMapX( rFloatRect
.Right
);
346 ImplMapY( rFloatRect
.Top
);
347 ImplMapY( rFloatRect
.Bottom
);
348 rFloatRect
.Justify();
352 // ---------------------------------------------------------------
354 void CGM::ImplGetRectangleNS( FloatRect
& rFloatRect
)
356 if ( pElement
->eVDCType
== VDC_INTEGER
)
358 rFloatRect
.Left
= ImplGetI( pElement
->nVDCIntegerPrecision
);
359 rFloatRect
.Bottom
= ImplGetI( pElement
->nVDCIntegerPrecision
);
360 rFloatRect
.Right
= ImplGetI( pElement
->nVDCIntegerPrecision
);
361 rFloatRect
.Top
= ImplGetI( pElement
->nVDCIntegerPrecision
);
363 else // ->floating points
365 rFloatRect
.Left
= ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
);
366 rFloatRect
.Bottom
= ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
);
367 rFloatRect
.Right
= ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
);
368 rFloatRect
.Top
= ImplGetFloat( pElement
->eVDCRealPrecision
, pElement
->nVDCRealSize
);
372 // ---------------------------------------------------------------
374 sal_uInt32
CGM::ImplGetBitmapColor( sal_Bool bDirect
)
376 // the background color is always a direct color
379 if ( ( pElement
->eColorSelectionMode
== CSM_DIRECT
) || bDirect
)
381 sal_uInt32 nColor
= ImplGetByte( ImplGetUI( pElement
->nColorPrecision
), 1 );
382 sal_uInt32 nDiff
= pElement
->nColorValueExtent
[ 3 ] - pElement
->nColorValueExtent
[ 0 ] + 1;
386 nColor
= ( ( nColor
- pElement
->nColorValueExtent
[ 0 ] ) << 8 ) / nDiff
;
387 nTmp
= nColor
<< 16 & 0xff0000;
389 nColor
= ImplGetByte( ImplGetUI( pElement
->nColorPrecision
), 1 );
390 nDiff
= pElement
->nColorValueExtent
[ 4 ] - pElement
->nColorValueExtent
[ 1 ] + 1;
393 nColor
= ( ( nColor
- pElement
->nColorValueExtent
[ 1 ] ) << 8 ) / nDiff
;
394 nTmp
|= nColor
<< 8 & 0xff00;
396 nColor
= ImplGetByte( ImplGetUI( pElement
->nColorPrecision
), 1 );
397 nDiff
= pElement
->nColorValueExtent
[ 5 ] - pElement
->nColorValueExtent
[ 2 ] + 1;
400 nColor
= ( ( nColor
- pElement
->nColorValueExtent
[ 2 ] ) << 8 ) / nDiff
;
401 nTmp
|= (sal_uInt8
)nColor
;
405 sal_uInt32 nIndex
= ImplGetUI( pElement
->nColorIndexPrecision
);
406 nTmp
= pElement
->aColorTable
[ (sal_uInt8
)( nIndex
) ] ;
411 // ---------------------------------------------------------------
413 // call this function each time after the mapmode settings has been changed
414 void CGM::ImplSetMapMode()
417 mnVDCdx
= pElement
->aVDCExtent
.Right
- pElement
->aVDCExtent
.Left
;
419 mnVDCXadd
= -pElement
->aVDCExtent
.Left
;
428 mnVDCdy
= pElement
->aVDCExtent
.Bottom
- pElement
->aVDCExtent
.Top
;
429 mnVDCYadd
= -pElement
->aVDCExtent
.Top
;
438 mbAngReverse
= sal_True
;
440 mbAngReverse
= sal_False
;
442 double fQuo1
= mnVDCdx
/ mnVDCdy
;
443 double fQuo2
= mnOutdx
/ mnOutdy
;
446 mnXFraction
= mnOutdx
/ mnVDCdx
;
447 mnYFraction
= mnOutdy
* ( fQuo2
/ fQuo1
) / mnVDCdy
;
451 mnXFraction
= mnOutdx
* ( fQuo1
/ fQuo2
) / mnVDCdx
;
452 mnYFraction
= mnOutdy
/ mnVDCdy
;
456 // ---------------------------------------------------------------
458 void CGM::ImplMapDouble( double& nNumb
)
460 if ( pElement
->eDeviceViewPortMap
== DVPM_FORCED
)
462 // point is 1mm * ScalingFactor
463 switch ( pElement
->eDeviceViewPortMode
)
467 nNumb
*= ( mnXFraction
+ mnYFraction
) / 2;
473 // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
474 nNumb
*= ( mnXFraction
+ mnYFraction
) / 2;
475 if ( pElement
->nDeviceViewPortScale
< 0 )
498 // ---------------------------------------------------------------
500 void CGM::ImplMapX( double& nNumb
)
502 if ( pElement
->eDeviceViewPortMap
== DVPM_FORCED
)
504 // point is 1mm * ScalingFactor
505 switch ( pElement
->eDeviceViewPortMode
)
509 nNumb
*= mnXFraction
;
515 // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
516 nNumb
*= mnXFraction
;
517 if ( pElement
->nDeviceViewPortScale
< 0 )
541 // ---------------------------------------------------------------
543 void CGM::ImplMapY( double& nNumb
)
545 if ( pElement
->eDeviceViewPortMap
== DVPM_FORCED
)
547 // point is 1mm * ScalingFactor
548 switch ( pElement
->eDeviceViewPortMode
)
552 nNumb
*= mnYFraction
;
558 // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
559 nNumb
*= mnYFraction
;
560 if ( pElement
->nDeviceViewPortScale
< 0 )
584 // ---------------------------------------------------------------
586 // convert a point to the current VC mapmode (1/100TH mm)
587 void CGM::ImplMapPoint( FloatPoint
& rFloatPoint
)
589 if ( pElement
->eDeviceViewPortMap
== DVPM_FORCED
)
591 // point is 1mm * ScalingFactor
592 switch ( pElement
->eDeviceViewPortMode
)
596 rFloatPoint
.X
*= mnXFraction
;
597 rFloatPoint
.Y
*= mnYFraction
;
603 rFloatPoint
.X
*= mnXFraction
;
604 rFloatPoint
.Y
*= mnYFraction
;
605 if ( pElement
->nDeviceViewPortScale
< 0 )
607 rFloatPoint
.X
= -rFloatPoint
.X
;
608 rFloatPoint
.Y
= -rFloatPoint
.Y
;
631 // ---------------------------------------------------------------
633 void CGM::ImplDoClass()
635 #ifdef CGM_USER_BREAKPOINT
637 #define CGM_BREAK_ACTION 0xffffffff
638 if ( mnActCount
== CGM_BREAK_ACTION
)
642 switch ( mnElementClass
)
644 case 0 : ImplDoClass0(); break;
645 case 1 : ImplDoClass1(); break;
646 case 2 : ImplDoClass2(); break;
647 case 3 : ImplDoClass3(); break;
654 case 5 : ImplDoClass5(); break;
655 case 6 : ImplDoClass6(); break;
656 case 7 : ImplDoClass7(); break;
657 case 8 : ImplDoClass8(); break;
658 case 9 : ImplDoClass9(); break;
659 case 15 :ImplDoClass15(); break;
665 // ---------------------------------------------------------------
667 void CGM::ImplDefaultReplacement()
669 if ( !maDefRepList
.empty() )
671 sal_uInt32 nOldEscape
= mnEscape
;
672 sal_uInt32 nOldElementClass
= mnElementClass
;
673 sal_uInt32 nOldElementID
= mnElementID
;
674 sal_uInt32 nOldElementSize
= mnElementSize
;
675 sal_uInt8
* pOldBuf
= mpSource
;
677 for ( size_t i
= 0, n
= maDefRepList
.size(); i
< n
; ++i
)
679 sal_uInt8
* pBuf
= maDefRepList
[ i
];
680 sal_uInt32 nElementSize
= maDefRepSizeList
[ i
];
681 sal_uInt32 nCount
= 0;
682 while ( mbStatus
&& ( nCount
< nElementSize
) )
684 mpSource
= pBuf
+ nCount
;
686 mnEscape
= ImplGetUI16();
687 mnElementClass
= mnEscape
>> 12;
688 mnElementID
= ( mnEscape
& 0x0fe0 ) >> 5;
689 mnElementSize
= mnEscape
& 0x1f;
690 if ( mnElementSize
== 31 )
692 mnElementSize
= ImplGetUI16();
694 nCount
+= mnParaSize
;
696 mpSource
= pBuf
+ nCount
;
697 if ( mnElementSize
& 1 )
699 nCount
+= mnElementSize
;
700 if ( ( mnElementClass
!= 1 ) || ( mnElementID
!= 0xc ) ) // recursion is not possible here!!
704 mnEscape
= nOldEscape
;
705 mnElementClass
= nOldElementClass
;
706 mnElementID
= nOldElementID
;
707 mnParaSize
= mnElementSize
= nOldElementSize
;
712 // ---------------------------------------------------------------
714 sal_Bool
CGM::Write( SvStream
& rIStm
)
717 mpBuf
= new sal_uInt8
[ 0xffff ];
721 rIStm
.Read( mpSource
, 2 );
722 mnEscape
= ImplGetUI16();
723 mnElementClass
= mnEscape
>> 12;
724 mnElementID
= ( mnEscape
& 0x0fe0 ) >> 5;
725 mnElementSize
= mnEscape
& 0x1f;
727 if ( mnElementSize
== 31 )
729 rIStm
.Read( mpSource
+ mnParaSize
, 2 );
730 mnElementSize
= ImplGetUI16();
734 rIStm
.Read( mpSource
+ mnParaSize
, mnElementSize
);
736 if ( mnElementSize
& 1 )
741 #ifdef CGM_USER_BREAKPOINT
743 if ( !mbStatus
|| mnParaSize
&& ( mnElementSize
!= mnParaSize
) )
751 // ---------------------------------------------------------------
753 SvStream
& operator>>( SvStream
& rOStm
, CGM
& /*rCGM*/ )
759 // ---------------------------------------------------------------
763 //================== GraphicImport - the exported function ================
765 extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32 SAL_CALL
766 ImportCGM( String
& rFileName
, uno::Reference
< frame::XModel
> & rXModel
, sal_uInt32 nMode
, void* pProgressBar
)
769 sal_uInt32 nStatus
= 0; // retvalue == 0 -> ERROR
770 // == 0xffrrggbb -> background color in the lower 24 bits
771 sal_Bool bProgressBar
= sal_False
;
779 pCGM
= new CGM( nMode
, rXModel
);
780 if ( pCGM
&& pCGM
->IsValid() )
782 if ( nMode
& CGM_IMPORT_CGM
)
784 SvStream
* pIn
= ::utl::UcbStreamHelper::CreateStream( rFileName
, STREAM_READ
);
787 pIn
->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN
);
788 pIn
->Seek( STREAM_SEEK_TO_END
);
789 sal_uInt32 nInSize
= pIn
->Tell();
792 #ifdef CGM_EXPORT_IMPRESS
793 uno::Reference
< task::XStatusIndicator
> aXStatInd
;
794 sal_uInt32 nNext
= 0;
795 sal_uInt32 nAdd
= nInSize
/ 20;
797 aXStatInd
= *(uno::Reference
< task::XStatusIndicator
> *)pProgressBar
;
798 bProgressBar
= aXStatInd
.is();
800 aXStatInd
->start( "CGM Import" , nInSize
);
803 while ( pCGM
->IsValid() && ( pIn
->Tell() < nInSize
) && !pCGM
->IsFinished() )
806 #ifdef CGM_EXPORT_IMPRESS
811 sal_uInt32 nCurrentPos
= pIn
->Tell();
812 if ( nCurrentPos
>= nNext
)
814 aXStatInd
->setValue( nCurrentPos
);
815 nNext
= nCurrentPos
+ nAdd
;
820 if ( pCGM
->Write( *pIn
) == sal_False
)
823 if ( pCGM
->IsValid() )
825 nStatus
= pCGM
->GetBackGroundColor() | 0xff000000;
827 #ifdef CGM_EXPORT_IMPRESS
836 catch( const ::com::sun::star::uno::Exception
& )
845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */