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