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: bitmap.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_goodies.hxx"
36 // ---------------------------------------------------------------
38 CGMBitmap::CGMBitmap( CGM
& rCGM
) :
40 pCGMBitmapDescriptor ( new CGMBitmapDescriptor
)
42 ImplGetBitmap( *pCGMBitmapDescriptor
);
45 // ---------------------------------------------------------------
47 CGMBitmap::~CGMBitmap()
49 delete pCGMBitmapDescriptor
;
52 // ---------------------------------------------------------------
54 void CGMBitmap::ImplGetBitmap( CGMBitmapDescriptor
& rDesc
)
56 rDesc
.mbStatus
= sal_True
;
57 long nx
, ny
, nxC
, nxCount
, nyCount
;
59 if ( ImplGetDimensions( rDesc
) && rDesc
.mpBuf
)
61 if ( ( rDesc
.mpBitmap
= new Bitmap( Size( rDesc
.mnX
, rDesc
.mnY
), (sal_uInt16
)rDesc
.mnDstBitsPerPixel
) ) != NULL
)
63 if ( ( rDesc
.mpAcc
= rDesc
.mpBitmap
->AcquireWriteAccess() ) != NULL
)
66 // the picture may either be read from left to right or right to left, from top to bottom ...
68 nxCount
= rDesc
.mnX
+ 1; // +1 because we are using prefix decreasing
69 nyCount
= rDesc
.mnY
+ 1;
71 switch ( rDesc
.mnDstBitsPerPixel
)
75 if ( rDesc
.mnLocalColorPrecision
== 1 )
76 ImplSetCurrentPalette( rDesc
);
79 rDesc
.mpAcc
->SetPaletteEntryCount( 2 );
80 rDesc
.mpAcc
->SetPaletteColor( 0, BMCOL( mpCGM
->pElement
->nBackGroundColor
) );
81 rDesc
.mpAcc
->SetPaletteColor( 1,
82 ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_FILLINTERIORSTYLE
)
83 ? BMCOL( mpCGM
->pElement
->pFillBundle
->GetColor() )
84 : BMCOL( mpCGM
->pElement
->aFillBundle
.GetColor() ) ) ;
86 for ( ny
= 0; --nyCount
; ny
++, rDesc
.mpBuf
+= rDesc
.mnScanSize
)
89 for ( nx
= 0; --nxC
; nx
++ )
90 { // this is not fast, but a one bit/pixel format is rarely used
91 rDesc
.mpAcc
->SetPixel( ny
, nx
, (sal_Int8
)( (*( rDesc
.mpBuf
+ ( nx
>> 3 ) ) >> ( ( nx
& 7 ) ^ 7 ) ) ) & 1 );
99 ImplSetCurrentPalette( rDesc
);
100 for ( ny
= 0; --nyCount
; ny
++, rDesc
.mpBuf
+= rDesc
.mnScanSize
)
103 for ( nx
= 0; --nxC
; nx
++ )
104 { // this is not fast, but a two bits/pixel format is rarely used
105 rDesc
.mpAcc
->SetPixel( ny
, nx
, (sal_Int8
)( (*( rDesc
.mpBuf
+ ( nx
>> 2 ) ) >> ( ( ( nx
& 3 ) ^ 3 ) << 1 ) ) ) & 3 );
113 ImplSetCurrentPalette( rDesc
);
114 for ( ny
= 0; --nyCount
; ny
++, rDesc
.mpBuf
+= rDesc
.mnScanSize
)
118 sal_uInt8
* pTemp
= rDesc
.mpBuf
;
119 for ( nx
= 0; --nxC
; nx
++ )
122 rDesc
.mpAcc
->SetPixel( ny
, nx
, (sal_Int8
)( nDat
>> 4 ) );
126 rDesc
.mpAcc
->SetPixel( ny
, nx
, (sal_Int8
)( nDat
& 15 ) );
137 ImplSetCurrentPalette( rDesc
);
138 for ( ny
= 0; --nyCount
; ny
++, rDesc
.mpBuf
+= rDesc
.mnScanSize
)
140 sal_uInt8
* pTemp
= rDesc
.mpBuf
;
142 for ( nx
= 0; --nxC
; nx
++ )
144 rDesc
.mpAcc
->SetPixel( ny
, nx
, (sal_Int8
)( *pTemp
++ ) );
153 BitmapColor aBitmapColor
;
154 for ( ny
= 0; --nyCount
; ny
++, rDesc
.mpBuf
+= rDesc
.mnScanSize
)
156 sal_uInt8
* pTemp
= rDesc
.mpBuf
;
158 for ( nx
= 0; --nxC
; nx
++ )
160 aBitmapColor
.SetRed( (sal_Int8
)*pTemp
++ );
161 aBitmapColor
.SetGreen( (sal_Int8
)*pTemp
++ );
162 aBitmapColor
.SetBlue( (sal_Int8
)*pTemp
++ );
163 rDesc
.mpAcc
->SetPixel( ny
, nx
, aBitmapColor
);
170 double nX
= rDesc
.mnR
.X
- rDesc
.mnQ
.X
;
171 double nY
= rDesc
.mnR
.Y
- rDesc
.mnQ
.Y
;
173 rDesc
.mndy
= sqrt( nX
* nX
+ nY
* nY
);
175 nX
= rDesc
.mnR
.X
- rDesc
.mnP
.X
;
176 nY
= rDesc
.mnR
.Y
- rDesc
.mnP
.Y
;
178 rDesc
.mndx
= sqrt( nX
* nX
+ nY
* nY
);
180 nX
= rDesc
.mnR
.X
- rDesc
.mnP
.X
;
181 nY
= rDesc
.mnR
.Y
- rDesc
.mnP
.Y
;
183 rDesc
.mnOrientation
= acos( nX
/ sqrt( nX
* nX
+ nY
* nY
) ) * 57.29577951308;
185 rDesc
.mnOrientation
= 360 - rDesc
.mnOrientation
;
187 nX
= rDesc
.mnQ
.X
- rDesc
.mnR
.X
;
188 nY
= rDesc
.mnQ
.Y
- rDesc
.mnR
.Y
;
190 double fAngle
= 0.01745329251994 * ( 360 - rDesc
.mnOrientation
);
191 double fSin
= sin(fAngle
);
192 double fCos
= cos(fAngle
);
193 nX
= fCos
* nX
+ fSin
* nY
;
194 nY
= -( fSin
* nX
- fCos
* nY
);
196 fAngle
= acos( nX
/ sqrt( nX
* nX
+ nY
* nY
) ) * 57.29577951308;
198 fAngle
= 360 - fAngle
;
200 if ( fAngle
> 180 ) // wird das bild nach oben oder unten aufgebaut ?
202 rDesc
.mnOrigin
= rDesc
.mnP
;
206 rDesc
.mbVMirror
= sal_True
;
207 rDesc
.mnOrigin
= rDesc
.mnP
;
208 rDesc
.mnOrigin
.X
+= rDesc
.mnQ
.X
- rDesc
.mnR
.X
;
209 rDesc
.mnOrigin
.Y
+= rDesc
.mnQ
.Y
- rDesc
.mnR
.Y
;
213 rDesc
.mbStatus
= sal_False
;
216 rDesc
.mbStatus
= sal_False
;
219 rDesc
.mbStatus
= sal_False
;
223 rDesc
.mpBitmap
->ReleaseAccess( rDesc
.mpAcc
);
226 if ( rDesc
.mbStatus
== sal_False
)
228 if ( rDesc
.mpBitmap
)
230 delete rDesc
.mpBitmap
;
231 rDesc
.mpBitmap
= NULL
;
236 // ---------------------------------------------------------------
238 void CGMBitmap::ImplSetCurrentPalette( CGMBitmapDescriptor
& rDesc
)
240 sal_uInt16 nColors
= sal::static_int_cast
< sal_uInt16
>(
241 1 << rDesc
.mnDstBitsPerPixel
);
242 rDesc
.mpAcc
->SetPaletteEntryCount( nColors
);
243 for ( sal_uInt16 i
= 0; i
< nColors
; i
++ )
245 rDesc
.mpAcc
->SetPaletteColor( i
, BMCOL( mpCGM
->pElement
->aLatestColorTable
[ i
] ) );
249 // ---------------------------------------------------------------
251 sal_Bool
CGMBitmap::ImplGetDimensions( CGMBitmapDescriptor
& rDesc
)
253 mpCGM
->ImplGetPoint( rDesc
.mnP
); // parallelogram p < - > r
254 mpCGM
->ImplGetPoint( rDesc
.mnQ
); // |
255 mpCGM
->ImplGetPoint( rDesc
.mnR
); // q
256 sal_uInt32 nPrecision
= mpCGM
->pElement
->nIntegerPrecision
;
257 rDesc
.mnX
= mpCGM
->ImplGetUI( nPrecision
);
258 rDesc
.mnY
= mpCGM
->ImplGetUI( nPrecision
);
259 rDesc
.mnLocalColorPrecision
= mpCGM
->ImplGetI( nPrecision
);
260 rDesc
.mnScanSize
= 0;
261 switch( rDesc
.mnLocalColorPrecision
)
263 case 0x80000001 : // monochrome ( bit = 0->backgroundcolor )
264 case 0 : // bit = 1->fillcolor
265 rDesc
.mnDstBitsPerPixel
= 1;
267 case 1 : // 2 color indexed ( monochrome )
269 rDesc
.mnDstBitsPerPixel
= 1;
271 case 2 : // 4 color indexed
273 rDesc
.mnDstBitsPerPixel
= 2;
275 case 4 : // 16 color indexed
277 rDesc
.mnDstBitsPerPixel
= 4;
279 case 8 : // 256 color indexed
281 rDesc
.mnDstBitsPerPixel
= 8;
282 rDesc
.mnScanSize
= rDesc
.mnX
;
286 rDesc
.mbStatus
= sal_False
;
288 case 24 : // 24 bit directColor ( 8 bits each component )
290 rDesc
.mnDstBitsPerPixel
= 24;
294 rDesc
.mbStatus
= sal_False
;
298 // mnCompressionMode == 0 : CCOMP_RUNLENGTH
299 // == 1 : CCOMP_PACKED ( no compression. each row starts on a 4 byte boundary )
300 if ( ( rDesc
.mnCompressionMode
= mpCGM
->ImplGetUI16() ) != 1 )
301 rDesc
.mbStatus
= sal_False
;
303 if ( ( rDesc
.mnX
|| rDesc
.mnY
) == 0 )
304 rDesc
.mbStatus
= sal_False
;
306 sal_uInt32 nHeaderSize
= 2 + 3 * nPrecision
+ 3 * mpCGM
->ImplGetPointSize();
307 rDesc
.mnScanSize
= ( ( rDesc
.mnX
* rDesc
.mnDstBitsPerPixel
+ 7 ) >> 3 );
309 sal_uInt32 nScanSize
;
310 nScanSize
= rDesc
.mnScanSize
;
311 if ( ( nScanSize
* rDesc
.mnY
+ nHeaderSize
) != mpCGM
->mnElementSize
) // try a scansize without dw alignment
313 nScanSize
= ( rDesc
.mnScanSize
+ 1 ) & ~1;
314 if ( ( nScanSize
* rDesc
.mnY
+ nHeaderSize
) != mpCGM
->mnElementSize
) // then we'll try word alignment
316 nScanSize
= ( rDesc
.mnScanSize
+ 3 ) & ~3;
317 if ( ( nScanSize
* rDesc
.mnY
+ nHeaderSize
) != mpCGM
->mnElementSize
) // and last we'll try dword alignment
319 nScanSize
= ( rDesc
.mnScanSize
+ 1 ) & ~1; // and LAST BUT NOT LEAST we'll try word alignment without aligning the last line
320 if ( ( nScanSize
* ( rDesc
.mnY
- 1 ) + rDesc
.mnScanSize
+ nHeaderSize
) != mpCGM
->mnElementSize
)
322 nScanSize
= ( rDesc
.mnScanSize
+ 3 ) & ~3;
323 if ( ( nScanSize
* ( rDesc
.mnY
- 1 ) + rDesc
.mnScanSize
+ nHeaderSize
) != mpCGM
->mnElementSize
)
325 mpCGM
->mnParaSize
= 0; // this format is corrupt
326 rDesc
.mbStatus
= sal_False
;
332 rDesc
.mnScanSize
= nScanSize
;
333 if ( rDesc
.mbStatus
)
335 rDesc
.mpBuf
= mpCGM
->mpSource
+ mpCGM
->mnParaSize
; // mpBuf now points to the first scanline
336 mpCGM
->mnParaSize
+= rDesc
.mnScanSize
* rDesc
.mnY
;
338 return rDesc
.mbStatus
;
341 // ---------------------------------------------------------------
343 void CGMBitmap::ImplInsert( CGMBitmapDescriptor
& rSource
, CGMBitmapDescriptor
& rDest
)
345 if ( ( rSource
.mnR
.Y
== rDest
.mnQ
.Y
) && ( rSource
.mnR
.X
== rDest
.mnQ
.X
) )
346 { // Insert on Bottom
347 if ( mpCGM
->mnVDCYmul
== -1 )
348 rDest
.mnOrigin
= rSource
.mnOrigin
; // neuer origin
349 rDest
.mpBitmap
->Expand( 0, rSource
.mnY
);
350 rDest
.mpBitmap
->CopyPixel( Rectangle( Point( 0, rDest
.mnY
), Size( rSource
.mnX
, rSource
.mnY
) ),
351 Rectangle( Point( 0, 0 ), Size( rSource
.mnX
, rSource
.mnY
) ), rSource
.mpBitmap
);
352 FloatPoint aFloatPoint
;
353 aFloatPoint
.X
= rSource
.mnQ
.X
- rSource
.mnR
.X
;
354 aFloatPoint
.Y
= rSource
.mnQ
.Y
- rSource
.mnR
.Y
;
355 rDest
.mnQ
.X
+= aFloatPoint
.X
;
356 rDest
.mnQ
.Y
+= aFloatPoint
.Y
;
357 rDest
.mnP
= rSource
.mnP
;
358 rDest
.mnR
= rSource
.mnR
;
362 if ( mpCGM
->mnVDCYmul
== 1 )
363 rDest
.mnOrigin
= rSource
.mnOrigin
; // neuer origin
364 rDest
.mpBitmap
->Expand( 0, rSource
.mnY
);
365 rDest
.mpBitmap
->CopyPixel( Rectangle( Point( 0, rDest
.mnY
), Size( rSource
.mnX
, rSource
.mnY
) ),
366 Rectangle( Point( 0, 0 ), Size( rSource
.mnX
, rSource
.mnY
) ), rSource
.mpBitmap
);
367 rDest
.mnP
= rSource
.mnP
;
368 rDest
.mnR
= rSource
.mnR
;
370 rDest
.mnY
+= rSource
.mnY
;
371 rDest
.mndy
+= rSource
.mndy
;
374 // ---------------------------------------------------------------
376 CGMBitmap
* CGMBitmap::GetNext()
378 if ( pCGMBitmapDescriptor
->mpBitmap
&& pCGMBitmapDescriptor
->mbStatus
)
380 CGMBitmap
* pCGMTempBitmap
= new CGMBitmap( *mpCGM
);
381 if ( pCGMTempBitmap
)
383 if ( ( (long)pCGMTempBitmap
->pCGMBitmapDescriptor
->mnOrientation
== (long)pCGMBitmapDescriptor
->mnOrientation
) &&
384 ( ( ( pCGMTempBitmap
->pCGMBitmapDescriptor
->mnR
.X
== pCGMBitmapDescriptor
->mnQ
.X
) &&
385 ( pCGMTempBitmap
->pCGMBitmapDescriptor
->mnR
.Y
== pCGMBitmapDescriptor
->mnQ
.Y
) ) ||
386 ( ( pCGMTempBitmap
->pCGMBitmapDescriptor
->mnQ
.X
== pCGMBitmapDescriptor
->mnR
.X
) &&
387 ( pCGMTempBitmap
->pCGMBitmapDescriptor
->mnQ
.Y
== pCGMBitmapDescriptor
->mnR
.Y
) ) ) )
389 ImplInsert( *(pCGMTempBitmap
->pCGMBitmapDescriptor
), *(pCGMBitmapDescriptor
) );
390 delete pCGMTempBitmap
;
393 else // we'll replace the pointers and return the old one
395 CGMBitmapDescriptor
* pTempBD
= pCGMBitmapDescriptor
;
396 pCGMBitmapDescriptor
= pCGMTempBitmap
->pCGMBitmapDescriptor
;
397 pCGMTempBitmap
->pCGMBitmapDescriptor
= pTempBD
;
398 return pCGMTempBitmap
;
407 // ---------------------------------------------------------------
409 CGMBitmapDescriptor
* CGMBitmap::GetBitmap()
411 return pCGMBitmapDescriptor
;