xref: /AOO41X/main/filter/source/graphicfilter/icgm/bitmap.cxx (revision cbe4a5e32dd06077057875dd5ecd4d8f1991662a)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include "main.hxx"
28 
29 // ---------------------------------------------------------------
30 
CGMBitmap(CGM & rCGM)31 CGMBitmap::CGMBitmap( CGM& rCGM ) :
32     mpCGM                           ( &rCGM ),
33     pCGMBitmapDescriptor            ( new CGMBitmapDescriptor )
34 {
35     ImplGetBitmap( *pCGMBitmapDescriptor );
36 };
37 
38 // ---------------------------------------------------------------
39 
~CGMBitmap()40 CGMBitmap::~CGMBitmap()
41 {
42     delete pCGMBitmapDescriptor;
43 }
44 
45 // ---------------------------------------------------------------
46 
ImplGetBitmap(CGMBitmapDescriptor & rDesc)47 void CGMBitmap::ImplGetBitmap( CGMBitmapDescriptor& rDesc )
48 {
49     rDesc.mbStatus = sal_True;
50     long    nx, ny, nxC, nxCount, nyCount;
51 
52     if ( ImplGetDimensions( rDesc ) && rDesc.mpBuf )
53     {
54         if ( ( rDesc.mpBitmap = new Bitmap( Size( rDesc.mnX, rDesc.mnY ), (sal_uInt16)rDesc.mnDstBitsPerPixel ) ) != NULL )
55         {
56             if ( ( rDesc.mpAcc = rDesc.mpBitmap->AcquireWriteAccess() ) != NULL )
57             {
58 
59                 // the picture may either be read from left to right or right to left, from top to bottom ...
60 
61                 nxCount = rDesc.mnX + 1;    // +1 because we are using prefix decreasing
62                 nyCount = rDesc.mnY + 1;
63 
64                 switch ( rDesc.mnDstBitsPerPixel )
65                 {
66                     case 1 :
67                     {
68                         if ( rDesc.mnLocalColorPrecision == 1 )
69                             ImplSetCurrentPalette( rDesc );
70                         else
71                         {
72                             rDesc.mpAcc->SetPaletteEntryCount( 2 );
73                             rDesc.mpAcc->SetPaletteColor( 0, BMCOL( mpCGM->pElement->nBackGroundColor ) );
74                             rDesc.mpAcc->SetPaletteColor( 1,
75                                 ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
76                                     ? BMCOL( mpCGM->pElement->pFillBundle->GetColor() )
77                                         : BMCOL( mpCGM->pElement->aFillBundle.GetColor() ) ) ;
78                         }
79                         for ( ny = 0; --nyCount ; ny++, rDesc.mpBuf += rDesc.mnScanSize )
80                         {
81                             nxC = nxCount;
82                             for ( nx = 0; --nxC; nx++ )
83                             {   // this is not fast, but a one bit/pixel format is rarely used
84                                 rDesc.mpAcc->SetPixelIndex( ny, nx, static_cast<sal_uInt8>( (*( rDesc.mpBuf + (nx >> 3)) >> ((nx & 7)^7))) & 1 );
85                             }
86                         }
87                     }
88                     break;
89 
90                     case 2 :
91                     {
92                         ImplSetCurrentPalette( rDesc );
93                         for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
94                         {
95                             nxC = nxCount;
96                             for ( nx = 0; --nxC; nx++ )
97                             {   // this is not fast, but a two bits/pixel format is rarely used
98                                 rDesc.mpAcc->SetPixelIndex( ny, nx, static_cast<sal_uInt8>( (*(rDesc.mpBuf + (nx >> 2)) >> (((nx & 3)^3) << 1))) & 3 );
99                             }
100                         }
101                     }
102                     break;
103 
104                     case 4 :
105                     {
106                         ImplSetCurrentPalette( rDesc );
107                         for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
108                         {
109                             nxC = nxCount;
110                             sal_Int8  nDat;
111                             sal_uInt8* pTemp = rDesc.mpBuf;
112                             for ( nx = 0; --nxC; nx++ )
113                             {
114                                 nDat = *pTemp++;
115                                 rDesc.mpAcc->SetPixelIndex( ny, nx, static_cast<sal_uInt8>(nDat >> 4) );
116                                 if ( --nxC )
117                                 {
118                                     nx ++;
119                                     rDesc.mpAcc->SetPixelIndex( ny, nx, static_cast<sal_uInt8>(nDat & 15) );
120                                 }
121                                 else
122                                     break;
123                             }
124                         }
125                     }
126                     break;
127 
128                     case 8 :
129                     {
130                         ImplSetCurrentPalette( rDesc );
131                         for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
132                         {
133                             sal_uInt8* pTemp = rDesc.mpBuf;
134                             nxC = nxCount;
135                             for ( nx = 0; --nxC; nx++ )
136                             {
137                                 rDesc.mpAcc->SetPixelIndex( ny, nx, *(pTemp++) );
138                             }
139                         }
140                     }
141                     break;
142 
143                     case 24 :
144                     {
145                         {
146                             BitmapColor aBitmapColor;
147                             for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
148                             {
149                                 sal_uInt8* pTemp = rDesc.mpBuf;
150                                 nxC = nxCount;
151                                 for ( nx = 0; --nxC; nx++ )
152                                 {
153                                     aBitmapColor.SetRed( (sal_Int8)*pTemp++ );
154                                     aBitmapColor.SetGreen( (sal_Int8)*pTemp++ );
155                                     aBitmapColor.SetBlue( (sal_Int8)*pTemp++ );
156                                     rDesc.mpAcc->SetPixel( ny, nx, aBitmapColor );
157                                 }
158                             }
159                         }
160                     }
161                     break;
162                 };
163                 double nX = rDesc.mnR.X - rDesc.mnQ.X;
164                 double nY = rDesc.mnR.Y - rDesc.mnQ.Y;
165 
166                 rDesc.mndy = sqrt( nX * nX + nY * nY );
167 
168                 nX = rDesc.mnR.X - rDesc.mnP.X;
169                 nY = rDesc.mnR.Y - rDesc.mnP.Y;
170 
171                 rDesc.mndx = sqrt( nX * nX + nY * nY );
172 
173                 nX = rDesc.mnR.X - rDesc.mnP.X;
174                 nY = rDesc.mnR.Y - rDesc.mnP.Y;
175 
176                 rDesc.mnOrientation = acos( nX / sqrt( nX * nX + nY * nY ) ) * 57.29577951308;
177                 if ( nY > 0 )
178                     rDesc.mnOrientation = 360 - rDesc.mnOrientation;
179 
180                 nX = rDesc.mnQ.X - rDesc.mnR.X;
181                 nY = rDesc.mnQ.Y - rDesc.mnR.Y;
182 
183                 double fAngle = 0.01745329251994 * ( 360 - rDesc.mnOrientation );
184                 double fSin = sin(fAngle);
185                 double fCos = cos(fAngle);
186                 nX = fCos * nX + fSin * nY;
187                 nY = -( fSin * nX - fCos * nY );
188 
189                 fAngle = acos( nX / sqrt( nX * nX + nY * nY ) ) * 57.29577951308;
190                 if ( nY > 0 )
191                     fAngle = 360 - fAngle;
192 
193                 if ( fAngle > 180 )                 // wird das bild nach oben oder unten aufgebaut ?
194                 {
195                     rDesc.mnOrigin = rDesc.mnP;
196                 }
197                 else
198                 {
199                     rDesc.mbVMirror = sal_True;
200                     rDesc.mnOrigin = rDesc.mnP;
201                     rDesc.mnOrigin.X += rDesc.mnQ.X - rDesc.mnR.X;
202                     rDesc.mnOrigin.Y += rDesc.mnQ.Y - rDesc.mnR.Y;
203                 }
204             }
205             else
206                 rDesc.mbStatus = sal_False;
207         }
208         else
209             rDesc.mbStatus = sal_False;
210     }
211     else
212         rDesc.mbStatus = sal_False;
213 
214     if ( rDesc.mpAcc )
215     {
216         rDesc.mpBitmap->ReleaseAccess( rDesc.mpAcc );
217         rDesc.mpAcc = NULL;
218     }
219     if ( rDesc.mbStatus == sal_False )
220     {
221         if ( rDesc.mpBitmap )
222         {
223             delete rDesc.mpBitmap;
224             rDesc.mpBitmap = NULL;
225         }
226     }
227 }
228 
229 // ---------------------------------------------------------------
230 
ImplSetCurrentPalette(CGMBitmapDescriptor & rDesc)231 void CGMBitmap::ImplSetCurrentPalette( CGMBitmapDescriptor& rDesc )
232 {
233     sal_uInt16 nColors = sal::static_int_cast< sal_uInt16 >(
234         1 << rDesc.mnDstBitsPerPixel);
235     rDesc.mpAcc->SetPaletteEntryCount( nColors );
236     for ( sal_uInt16 i = 0; i < nColors; i++ )
237     {
238         rDesc.mpAcc->SetPaletteColor( i, BMCOL( mpCGM->pElement->aLatestColorTable[ i ] ) );
239     }
240 }
241 
242 // ---------------------------------------------------------------
243 
ImplGetDimensions(CGMBitmapDescriptor & rDesc)244 sal_Bool CGMBitmap::ImplGetDimensions( CGMBitmapDescriptor& rDesc )
245 {
246     mpCGM->ImplGetPoint( rDesc.mnP );           // parallelogram    p < - > r
247     mpCGM->ImplGetPoint( rDesc.mnQ );           //                          |
248     mpCGM->ImplGetPoint( rDesc.mnR );           //                          q
249     sal_uInt32 nPrecision = mpCGM->pElement->nIntegerPrecision;
250     rDesc.mnX = mpCGM->ImplGetUI( nPrecision );
251     rDesc.mnY = mpCGM->ImplGetUI( nPrecision );
252     rDesc.mnLocalColorPrecision = mpCGM->ImplGetI( nPrecision );
253     rDesc.mnScanSize = 0;
254     switch( rDesc.mnLocalColorPrecision )
255     {
256         case static_cast<long>(0x80000001) :    // monochrome ( bit = 0->backgroundcolor )
257         case 0 :                                //              bit = 1->fillcolor
258             rDesc.mnDstBitsPerPixel = 1;
259             break;
260         case 1 :                                // 2 color indexed ( monochrome )
261         case -1 :
262             rDesc.mnDstBitsPerPixel = 1;
263             break;
264         case 2 :                                // 4 color indexed
265         case -2 :
266             rDesc.mnDstBitsPerPixel = 2;
267             break;
268         case 4 :                                // 16 color indexed
269         case -4 :
270             rDesc.mnDstBitsPerPixel = 4;
271             break;
272         case 8 :                                // 256 color indexed
273         case -8 :
274             rDesc.mnDstBitsPerPixel = 8;
275             rDesc.mnScanSize = rDesc.mnX;
276             break;
277         case 16 :                               // NS
278         case -16 :
279             rDesc.mbStatus = sal_False;
280             break;
281         case 24 :                               // 24 bit directColor ( 8 bits each component )
282         case -24 :
283             rDesc.mnDstBitsPerPixel = 24;
284             break;
285         case 32 :                               // NS
286         case -32 :
287             rDesc.mbStatus = sal_False;
288             break;
289 
290     }
291     // mnCompressionMode == 0 : CCOMP_RUNLENGTH
292     //                   == 1 : CCOMP_PACKED ( no compression. each row starts on a 4 byte boundary )
293     if ( ( rDesc.mnCompressionMode = mpCGM->ImplGetUI16() ) != 1 )
294         rDesc.mbStatus = sal_False;
295 
296     if ( ( rDesc.mnX || rDesc.mnY ) == 0 )
297         rDesc.mbStatus = sal_False;
298 
299     sal_uInt32 nHeaderSize = 2 + 3 * nPrecision + 3 * mpCGM->ImplGetPointSize();
300     rDesc.mnScanSize = ( ( rDesc.mnX * rDesc.mnDstBitsPerPixel + 7 ) >> 3 );
301 
302     sal_uInt32  nScanSize;
303     nScanSize = rDesc.mnScanSize;
304     if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize )  // try a scansize without dw alignment
305     {
306         nScanSize = ( rDesc.mnScanSize + 1 ) & ~1;
307         if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize )  // then we'll try word alignment
308         {
309             nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
310             if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize )  // and last we'll try dword alignment
311             {
312                 nScanSize = ( rDesc.mnScanSize + 1 ) & ~1;          // and LAST BUT NOT LEAST we'll try word alignment without aligning the last line
313                 if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
314                 {
315                     nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
316                     if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
317                     {
318                         mpCGM->mnParaSize = 0;                              // this format is corrupt
319                         rDesc.mbStatus = sal_False;
320                     }
321                 }
322             }
323         }
324     }
325     rDesc.mnScanSize = nScanSize;
326     if ( rDesc.mbStatus )
327     {
328         rDesc.mpBuf = mpCGM->mpSource + mpCGM->mnParaSize;  // mpBuf now points to the first scanline
329         mpCGM->mnParaSize += rDesc.mnScanSize * rDesc.mnY;
330     }
331     return rDesc.mbStatus;
332 }
333 
334 // ---------------------------------------------------------------
335 
ImplInsert(CGMBitmapDescriptor & rSource,CGMBitmapDescriptor & rDest)336 void CGMBitmap::ImplInsert( CGMBitmapDescriptor& rSource, CGMBitmapDescriptor& rDest )
337 {
338     if ( ( rSource.mnR.Y == rDest.mnQ.Y ) && ( rSource.mnR.X == rDest.mnQ.X ) )
339     {   // Insert on Bottom
340         if ( mpCGM->mnVDCYmul == -1 )
341             rDest.mnOrigin = rSource.mnOrigin;          // neuer origin
342         rDest.mpBitmap->Expand( 0, rSource.mnY );
343         rDest.mpBitmap->CopyPixel( Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
344             Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), rSource.mpBitmap );
345         FloatPoint aFloatPoint;
346         aFloatPoint.X = rSource.mnQ.X - rSource.mnR.X;
347         aFloatPoint.Y = rSource.mnQ.Y - rSource.mnR.Y;
348         rDest.mnQ.X += aFloatPoint.X;
349         rDest.mnQ.Y += aFloatPoint.Y;
350         rDest.mnP = rSource.mnP;
351         rDest.mnR = rSource.mnR;
352     }
353     else
354     {   // Insert on Top
355         if ( mpCGM->mnVDCYmul == 1 )
356             rDest.mnOrigin = rSource.mnOrigin;          // neuer origin
357         rDest.mpBitmap->Expand( 0, rSource.mnY );
358         rDest.mpBitmap->CopyPixel( Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
359             Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), rSource.mpBitmap );
360         rDest.mnP = rSource.mnP;
361         rDest.mnR = rSource.mnR;
362     }
363     rDest.mnY += rSource.mnY;
364     rDest.mndy += rSource.mndy;
365 };
366 
367 // ---------------------------------------------------------------
368 
GetNext()369 CGMBitmap* CGMBitmap::GetNext()
370 {
371     if ( pCGMBitmapDescriptor->mpBitmap && pCGMBitmapDescriptor->mbStatus )
372     {
373         CGMBitmap* pCGMTempBitmap = new CGMBitmap( *mpCGM );
374         if ( pCGMTempBitmap )
375         {
376             if ( ( (long)pCGMTempBitmap->pCGMBitmapDescriptor->mnOrientation == (long)pCGMBitmapDescriptor->mnOrientation ) &&
377                 ( ( ( pCGMTempBitmap->pCGMBitmapDescriptor->mnR.X == pCGMBitmapDescriptor->mnQ.X ) &&
378                         ( pCGMTempBitmap->pCGMBitmapDescriptor->mnR.Y == pCGMBitmapDescriptor->mnQ.Y ) ) ||
379                 ( ( pCGMTempBitmap->pCGMBitmapDescriptor->mnQ.X == pCGMBitmapDescriptor->mnR.X ) &&
380                         ( pCGMTempBitmap->pCGMBitmapDescriptor->mnQ.Y == pCGMBitmapDescriptor->mnR.Y ) ) ) )
381             {
382                 ImplInsert( *(pCGMTempBitmap->pCGMBitmapDescriptor), *(pCGMBitmapDescriptor) );
383                 delete pCGMTempBitmap;
384                 return NULL;
385             }
386             else    // we'll replace the pointers and return the old one
387             {
388                 CGMBitmapDescriptor* pTempBD = pCGMBitmapDescriptor;
389                 pCGMBitmapDescriptor = pCGMTempBitmap->pCGMBitmapDescriptor;
390                 pCGMTempBitmap->pCGMBitmapDescriptor = pTempBD;
391                 return pCGMTempBitmap;
392             }
393         }
394         return NULL;
395     }
396     else
397         return NULL;
398 }
399 
400 // ---------------------------------------------------------------
401 
GetBitmap()402 CGMBitmapDescriptor* CGMBitmap::GetBitmap()
403 {
404     return pCGMBitmapDescriptor;
405 }
406 
407