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