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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_filter.hxx"
24 
25 #include <svtools/fltcall.hxx>
26 #include <math.h>
27 #include <tools/stream.hxx>
28 #include <tools/bigint.hxx>
29 #include <vcl/metaact.hxx>
30 #include <vcl/salbtype.hxx>
31 #include <tools/poly.hxx>
32 #include <vcl/graph.hxx>
33 #include <vcl/gradient.hxx>
34 #include <vcl/hatch.hxx>
35 #include <vcl/metric.hxx>
36 #include <vcl/font.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/msgbox.hxx>
40 #include <svl/solar.hrc>
41 #include <vcl/gdimetafiletools.hxx>
42 #include <vcl/dibtools.hxx>
43 
44 // -----------------------------Feld-Typen-------------------------------
45 
46 #define BegDocumnMagic 0xA8A8 /* Begin Document */
47 #define EndDocumnMagic 0xA8A9 /* End Document   */
48 
49 #define BegResGrpMagic 0xC6A8 /* Begin Resource Group */
50 #define EndResGrpMagic 0xC6A9 /* End Resource Group   */
51 
52 #define BegColAtrMagic 0x77A8 /* Begin Color Attribute Table */
53 #define EndColAtrMagic 0x77A9 /* End Color Attribute Table   */
54 #define BlkColAtrMagic 0x77B0 /* Color Attribute Table       */
55 #define MapColAtrMagic 0x77AB /* Map Color Attribute Table   */
56 
57 #define BegImgObjMagic 0xFBA8 /* Begin Image Object    */
58 #define EndImgObjMagic 0xFBA9 /* End Image Object      */
59 #define DscImgObjMagic 0xFBA6 /* Image Data Descriptor */
60 #define DatImgObjMagic 0xFBEE /* Image Picture Data    */
61 
62 #define BegObjEnvMagic 0xC7A8 /* Begin Object Environment Group */
63 #define EndObjEnvMagic 0xC7A9 /* End Object Environment Group   */
64 
65 #define BegGrfObjMagic 0xBBA8 /* Begin Graphics Object   */
66 #define EndGrfObjMagic 0xBBA9 /* End Graphics Object     */
67 #define DscGrfObjMagic 0xBBA6 /* Graphics Data Descritor */
68 #define DatGrfObjMagic 0xBBEE /* Graphics Data           */
69 
70 #define MapCodFntMagic 0x8AAB /* Map Coded Font    */
71 #define MapDatResMagic 0xC3AB /* Map Data Resource */
72 
73 // Struktur des Metafiles
74 // BegDocumn
75 //   BegResGrp
76 //     BegColAtr
77 //       BlkColAtr
78 //     EndColAtr
79 //     BegImgObj[0..n]
80 //       BegResGrp[]
81 //         BegColAtr[]
82 //           BlkColAtr
83 //         EndColAtr
84 //       EndResGrp
85 //       BegObjEnv[]
86 //         MapColAtr
87 //       EndObjEnv
88 //       DscImgObj
89 //       DatImgOb1
90 //       DatImgOb2[1..n]
91 //     EndImgObj
92 //     BegGrfObj
93 //       BegObjEnv[]
94 //         MapColAtr
95 //         MapCodFnt1
96 //         MapCodFnt2[0..n]
97 //         MapDatRes[0..n]
98 //       EndObjEnv
99 //       DscGrfObj
100 //       DatGrfObj[0..n]
101 //     EndGrfObj
102 //   EndResGrp
103 // EndDocumn
104 
105 //============================== METWriter ===================================
106 
107 struct METChrSet
108 {
109 	struct METChrSet * pSucc;
110 	sal_uInt8 nSet;
111 	String aName;
112 	FontWeight eWeight;
113 };
114 
115 struct METGDIStackMember
116 {
117 	struct METGDIStackMember *	pSucc;
118 	Color						aLineColor;
119 	Color						aFillColor;
120 	RasterOp					eRasterOp;
121 	Font						aFont;
122 	MapMode						aMapMode;
123 	Rectangle					aClipRect;
124 };
125 
126 class METWriter
127 {
128 private:
129 
130 	sal_Bool				bStatus;
131 	sal_uLong				nLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde.
132 	SvStream*			pMET;
133 	Rectangle			aPictureRect;
134 	MapMode				aPictureMapMode;
135 	MapMode				aTargetMapMode;
136 	sal_uLong				nActualFieldStartPos;     // Anfangs-Position des aktuellen 'Field'
137 	sal_uLong				nNumberOfDataFields;  // Anzahl der angefangenen 'Graphcis Data Fields'
138 	Color				aGDILineColor;
139 	Color				aGDIFillColor;
140 	RasterOp			eGDIRasterOp;
141 	Font				aGDIFont;
142 	MapMode				aGDIMapMode;   // derzeit unbenutzt!
143 	Rectangle			aGDIClipRect; // derzeit unbenutzt!
144 	METGDIStackMember*	pGDIStack;
145 	Color				aMETColor;
146 	Color				aMETBackgroundColor;
147 	Color				aMETPatternSymbol;
148 	RasterOp			eMETMix	;
149 	long				nMETStrokeLineWidth;
150 	Size				aMETChrCellSize;
151 	short				nMETChrAngle;
152 	sal_uInt8				nMETChrSet;
153 	METChrSet*			pChrSetList; // Liste der Character-Sets
154 	sal_uInt8				nNextChrSetId; // die erste unbenutzte ChrSet-Id
155 	sal_uLong				nActBitmapId; // Field-Id der naechsten Bitmap
156 	sal_uLong				nNumberOfActions; // Anzahl der Actions im GDIMetafile
157 	sal_uLong				nNumberOfBitmaps; // Anzahl der Bitmaps
158 	sal_uLong				nWrittenActions;  // Anzahl der bereits verarbeiteten Actions beim Schreiben der Orders
159 	sal_uLong				nWrittenBitmaps;  // Anzahl der bereits geschriebenen Bitmaps
160 	sal_uLong				nActBitmapPercent; // Wieviel Prozent die naechste Bitmap schon geschrieben ist.
161 
162 	::std::auto_ptr< VirtualDevice >    apDummyVDev;
163 	OutputDevice*                       pCompDev;
164 
165 	com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
166 
167 	void MayCallback();
168 		// Berechnet anhand der obigen 5 Parameter eine Prozentzahl
169 		// und macht dann ggf. einen Callback. Setzt bStatus auf sal_False wenn User abbrechen
170 		// moechte.
171 
172 	void CountActionsAndBitmaps(const GDIMetaFile * pMTF);
173 		// Zaehlt die Bitmaps und Actions (nNumberOfActions und nNumberOfBitmaps muessen
174 		// zu Anfang auf 0 gesetzt werden, weil diese Methode rekursiv ist)
175 
176 	void WriteBigEndianShort(sal_uInt16 nWord);
177 	void WriteBigEndianLong(sal_uLong nLong);
178 
179 	void WritePoint(Point aPt);
180 	void WriteClipRect( const Rectangle& rRect );
181 	void WriteFieldIntroducer(sal_uInt16 nFieldSize, sal_uInt16 nFieldType,
182 							  sal_uInt8 nFlags, sal_uInt16 nSegSeqNum);
183 	void UpdateFieldSize();
184 
185 	void WriteFieldId(sal_uLong nId);
186 
187 	void CreateChrSets(const GDIMetaFile * pMTF);
188 	void CreateChrSet(const Font & rFont);
189 	void WriteChrSets();
190 	sal_uInt8 FindChrSet(const Font & rFont);
191 
192 	void WriteColorAttributeTable(sal_uLong nFieldId=4, BitmapPalette* pPalette=NULL,
193 								  sal_uInt8 nBasePartFlags=0x40, sal_uInt8 nBasePartLCTID=0);
194 
195 	void WriteImageObject(const Bitmap & rBitmap);
196 	void WriteImageObjects(const GDIMetaFile * pMTF);
197 
198 	void WriteDataDescriptor(const GDIMetaFile * pMTF);
199 
200 	void WillWriteOrder(sal_uLong nNextOrderMaximumLength);
201 
202 	void METSetAndPushLineInfo( const LineInfo& rLineInfo );
203 	void METPopLineInfo( const LineInfo& rLineInfo );
204 	void METBitBlt(Point aPt, Size aSize, const Size& rSizePixel);
205 	void METBeginArea(sal_Bool bBoundaryLine);
206 	void METEndArea();
207 	void METBeginPath(sal_uInt32 nPathId);
208 	void METEndPath();
209 	void METFillPath(sal_uInt32 nPathId);
210 	void METOutlinePath(sal_uInt32 nPathId);
211 	void METCloseFigure();
212 	void METMove(Point aPt);
213 	void METLine(Point aPt1, Point aPt2);
214 	void METLine(const Polygon & rPolygon);
215 	void METLine(const PolyPolygon & rPolyPolygon);
216 	void METLineAtCurPos(Point aPt);
217 	void METBox(sal_Bool bFill, sal_Bool bBoundary,
218 				Rectangle aRect, sal_uInt32 nHAxis, sal_uInt32 nVAxis);
219 	void METFullArc(Point aCenter, double fMultiplier);
220 	void METPartialArcAtCurPos(Point aCenter, double fMultiplier,
221 							   double fStartAngle, double fSweepAngle);
222 	void METChrStr(Point aPt, String aStr);
223 	void METSetArcParams(long nP, long nQ, long nR, long nS);
224 	void METSetColor(Color aColor);
225 	void METSetBackgroundColor(Color aColor);
226 	void METSetMix(RasterOp eROP);
227 	void METSetChrCellSize(Size aSize);
228 	void METSetChrAngle(short nAngle);
229 	void METSetChrSet(sal_uInt8 nSet);
230 
231 	void WriteOrders(const GDIMetaFile * pMTF);
232 
233 	void WriteObjectEnvironmentGroup(const GDIMetaFile * pMTF);
234 
235 	void WriteGraphicsObject(const GDIMetaFile * pMTF);
236 
237 	void WriteResourceGroup(const GDIMetaFile * pMTF);
238 
239 	void WriteDocument(const GDIMetaFile * pMTF);
240 
241 public:
242 
METWriter()243 	METWriter() :
244         pCompDev( NULL )
245 	{
246 #ifndef NO_GETAPPWINDOW
247 	    pCompDev = reinterpret_cast< OutputDevice* >( Application::GetAppWindow() );
248 #endif
249         if( !pCompDev )
250         {
251             apDummyVDev.reset( new VirtualDevice );
252             pCompDev = apDummyVDev.get();
253         }
254 	}
255 
256 	sal_Bool WriteMET( const GDIMetaFile & rMTF, SvStream & rTargetStream,
257 						FilterConfigItem* pConfigItem );
258 };
259 
260 
261 //========================== Methoden von METWriter ==========================
262 
MayCallback()263 void METWriter::MayCallback()
264 {
265 	if ( xStatusIndicator.is() )
266 	{
267 		sal_uLong nPercent;
268 		nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
269 				*100/((nNumberOfBitmaps<<14)+nNumberOfActions);
270 
271 		if (nPercent>=nLastPercent+3)
272 		{
273 			nLastPercent = nPercent;
274 			if ( nPercent <= 100 )
275 				xStatusIndicator->setValue( nPercent );
276 		}
277 	}
278 }
279 
WriteClipRect(const Rectangle & rRect)280 void METWriter::WriteClipRect( const Rectangle& rRect )
281 {
282 	aGDIClipRect = rRect;
283 	sal_uInt32 nPathId = ( rRect.IsEmpty() ) ? 0 : 1;
284 	if ( nPathId )
285 	{
286 		Polygon aPoly( rRect );
287 		METBeginPath( nPathId );
288 		METLine( aPoly );
289 		METEndPath();
290 	}
291 	WillWriteOrder(8);
292 	*pMET << (sal_uInt8)0xb4 << (sal_uInt8)6
293 		  << (sal_uInt8)0x00 << (sal_uInt8)0 << nPathId;
294 }
295 
CountActionsAndBitmaps(const GDIMetaFile * pMTF)296 void METWriter::CountActionsAndBitmaps(const GDIMetaFile * pMTF)
297 {
298 	const MetaAction* pMA;
299 
300 	for( sal_uLong nAction = 0, nActionCount=pMTF->GetActionCount(); nAction < nActionCount; nAction++ )
301 	{
302 		pMA =  pMTF->GetAction(nAction);
303 
304 		switch (pMA->GetType())
305 		{
306 			case META_EPS_ACTION :
307 			{
308 				const GDIMetaFile aGDIMetaFile( ((const MetaEPSAction*)pMA)->GetSubstitute() );
309 				sal_Int32 nCount = aGDIMetaFile.GetActionCount();
310 				sal_Int32 i;
311 				for ( i = 0; i < nCount; i++ )
312 					if ( ((const MetaAction*)aGDIMetaFile.GetAction( i ))->GetType() == META_BMPSCALE_ACTION )
313 						break;
314 				if ( i == nCount)
315 					break;
316 			}
317 			case META_BMP_ACTION:
318 			case META_BMPSCALE_ACTION:
319 			case META_BMPSCALEPART_ACTION:
320 			case META_BMPEX_ACTION:
321 			case META_BMPEXSCALE_ACTION:
322 			case META_BMPEXSCALEPART_ACTION:
323 				nNumberOfBitmaps++;
324 			break;
325 		}
326 		nNumberOfActions++;
327 	}
328 }
329 
330 
WriteBigEndianShort(sal_uInt16 nWord)331 void METWriter::WriteBigEndianShort(sal_uInt16 nWord)
332 {
333 	*pMET << ((sal_uInt8)(nWord>>8)) << ((sal_uInt8)(nWord&0x00ff));
334 }
335 
336 
WriteBigEndianLong(sal_uLong nLong)337 void METWriter::WriteBigEndianLong(sal_uLong nLong)
338 {
339 	WriteBigEndianShort((sal_uInt16)(nLong>>16));
340 	WriteBigEndianShort((sal_uInt16)(nLong&0x0000ffff));
341 }
342 
343 
WritePoint(Point aPt)344 void METWriter::WritePoint(Point aPt)
345 {
346 	Point aNewPt = pCompDev->LogicToLogic( aPt, aPictureMapMode, aTargetMapMode );
347 
348 	*pMET << (long) ( aNewPt.X() - aPictureRect.Left() )
349 		  << (long) ( aPictureRect.Bottom() - aNewPt.Y() );
350 }
351 
352 
WriteFieldIntroducer(sal_uInt16 nFieldSize,sal_uInt16 nFieldType,sal_uInt8 nFlags,sal_uInt16 nSegSeqNum)353 void METWriter::WriteFieldIntroducer(sal_uInt16 nFieldSize, sal_uInt16 nFieldType,
354 									 sal_uInt8 nFlags, sal_uInt16 nSegSeqNum)
355 {
356 	nActualFieldStartPos=pMET->Tell();
357 	WriteBigEndianShort(nFieldSize);
358 	*pMET << (sal_uInt8)0xd3 << nFieldType << nFlags << nSegSeqNum;
359 }
360 
361 
UpdateFieldSize()362 void METWriter::UpdateFieldSize()
363 {
364 	sal_uLong nPos;
365 
366 	nPos=pMET->Tell();
367 	pMET->Seek(nActualFieldStartPos);
368 	WriteBigEndianShort((sal_uInt16)(nPos-nActualFieldStartPos));
369 	pMET->Seek(nPos);
370 }
371 
372 
WriteFieldId(sal_uLong nId)373 void METWriter::WriteFieldId(sal_uLong nId)
374 {
375 	sal_uInt8 nbyte;
376 	short i;
377 
378 	for (i=1; i<=8; i++) {
379 		nbyte= '0' + (sal_uInt8)((nId >> (32-i*4)) & 0x0f);
380 		*pMET << nbyte;
381 	}
382 }
383 
384 
CreateChrSets(const GDIMetaFile * pMTF)385 void METWriter::CreateChrSets(const GDIMetaFile * pMTF)
386 {
387 	sal_uLong nAction, nActionCount;
388 	const MetaAction * pMA;
389 
390 	if (bStatus==sal_False)
391 		return;
392 
393 	nActionCount=pMTF->GetActionCount();
394 
395 	for (nAction=0; nAction<nActionCount; nAction++)
396 	{
397 		pMA = pMTF->GetAction(nAction);
398 
399 		switch (pMA->GetType())
400 		{
401 			case META_FONT_ACTION:
402 			{
403 				const MetaFontAction* pA = (const MetaFontAction*) pMA;
404 				CreateChrSet( pA->GetFont() );
405 			}
406 			break;
407 		}
408 	}
409 }
410 
411 
CreateChrSet(const Font & rFont)412 void METWriter::CreateChrSet(const Font & rFont)
413 {
414 	METChrSet * pCS;
415 
416 	if ( FindChrSet( rFont ) == 0 )
417 	{
418 		pCS = new METChrSet;
419 		pCS->pSucc = pChrSetList; pChrSetList=pCS;
420 		pCS->nSet = nNextChrSetId++;
421 		pCS->aName = rFont.GetName();
422 		pCS->eWeight = rFont.GetWeight();
423 	}
424 }
425 
426 
FindChrSet(const Font & rFont)427 sal_uInt8 METWriter::FindChrSet(const Font & rFont)
428 {
429 	METChrSet* pCS;
430 
431 	for (pCS=pChrSetList; pCS!=NULL; pCS=pCS->pSucc)
432 	{
433 		if (pCS->aName==rFont.GetName() && pCS->eWeight==rFont.GetWeight() )
434 			return pCS->nSet;
435 	}
436 
437 	return 0;
438 }
439 
440 
WriteChrSets()441 void METWriter::WriteChrSets()
442 {
443 	sal_uInt16 i;
444 	char c = 0;
445 	METChrSet * pCS;
446 	sal_uInt8 nbyte;
447 
448 	for (pCS=pChrSetList; pCS!=NULL; pCS=pCS->pSucc)
449 	{
450 
451 		WriteFieldIntroducer(0x58,MapCodFntMagic,0,0);
452 
453 		WriteBigEndianShort(0x0050);
454 
455 		*pMET << (sal_uInt8)0x0c << (sal_uInt8)0x02 << (sal_uInt8)0x84 << (sal_uInt8)0x00;
456 		*pMET << (sal_uInt8)0xa4 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x01;
457 		*pMET << (sal_uInt8)0x01 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
458 
459 		*pMET << (sal_uInt8)0x04 << (sal_uInt8)0x24 << (sal_uInt8)0x05 << (sal_uInt8)pCS->nSet;
460 
461 		*pMET << (sal_uInt8)0x14 << (sal_uInt8)0x1f;
462 		switch (pCS->eWeight)
463 		{
464 			case WEIGHT_THIN:       nbyte=1; break;
465 			case WEIGHT_ULTRALIGHT: nbyte=2; break;
466 			case WEIGHT_LIGHT:      nbyte=3; break;
467 			case WEIGHT_SEMILIGHT:  nbyte=4; break;
468 			case WEIGHT_NORMAL:     nbyte=5; break;
469 			case WEIGHT_SEMIBOLD:   nbyte=6; break;
470 			case WEIGHT_BOLD:       nbyte=7; break;
471 			case WEIGHT_ULTRABOLD:  nbyte=8; break;
472 			case WEIGHT_BLACK:      nbyte=9; break;
473 			default:                nbyte=5;
474 		}
475 		*pMET << nbyte;
476 		*pMET << (sal_uInt8)0x05;
477 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
478 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
479 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
480 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x0c;
481 
482 		*pMET << (sal_uInt8)0x06 << (sal_uInt8)0x20 << (sal_uInt8)0x03 << (sal_uInt8)0xd4;
483 		*pMET << (sal_uInt8)0x03 << (sal_uInt8)0x52;
484 
485 		*pMET << (sal_uInt8)0x24 << (sal_uInt8)0x02 << (sal_uInt8)0x08 << (sal_uInt8)0x00;
486         ByteString n(pCS->aName, gsl_getSystemTextEncoding());
487 		for (i=0; i<32; i++)
488 		{
489 			if ( i == 0 || c != 0 )
490 				c = n.GetChar( i );
491 			*pMET << c;
492 		}
493 	}
494 }
495 
496 
WriteColorAttributeTable(sal_uLong nFieldId,BitmapPalette * pPalette,sal_uInt8 nBasePartFlags,sal_uInt8 nBasePartLCTID)497 void METWriter::WriteColorAttributeTable(sal_uLong nFieldId, BitmapPalette* pPalette, sal_uInt8 nBasePartFlags, sal_uInt8 nBasePartLCTID)
498 {
499 	sal_uInt16 nIndex,nNumI,i;
500 
501 	if (bStatus==sal_False) return;
502 
503 	//--- Das Feld 'Begin Color Attribute Table':
504 	WriteFieldIntroducer(16,BegColAtrMagic,0,0);
505 	WriteFieldId(nFieldId);
506 
507 	//--- Das Feld 'Color Attribute Table':
508 	WriteFieldIntroducer(0,BlkColAtrMagic,0,0);
509 	*pMET << nBasePartFlags << (sal_uInt8)0x00 << nBasePartLCTID; // 'Base Part'
510 	if (pPalette!=NULL)
511 	{
512 		nIndex=0;
513 		while (nIndex<pPalette->GetEntryCount())
514 		{
515 			nNumI=pPalette->GetEntryCount()-nIndex;
516 			if (nNumI>81) nNumI=81;
517 			*pMET << (sal_uInt8)(11+nNumI*3);                   // Laenge des Parameters
518 			*pMET << (sal_uInt8)1 << (sal_uInt8)0 << (sal_uInt8)1;        // typ: element list, Reserved, Format: RGB
519 			*pMET << (sal_uInt8)0; WriteBigEndianShort(nIndex); // Start-Index (3 Bytes)
520 			*pMET << (sal_uInt8)8 << (sal_uInt8)8 << (sal_uInt8)8;        // Bits je Komponente R,G,B
521 			*pMET << (sal_uInt8)3;                              // Anzahl Bytes je Eintrag
522 			for (i=0; i<nNumI; i++)
523 			{
524 				const BitmapColor& rCol = (*pPalette)[ nIndex ];
525 
526 				*pMET << (sal_uInt8) rCol.GetRed();
527 				*pMET << (sal_uInt8) rCol.GetGreen();
528 				*pMET << (sal_uInt8) rCol.GetBlue();
529 				nIndex++;
530 			}
531 		}
532 	}
533 	else
534 	{
535 		// 'Trible Generating'
536 		*pMET << (sal_uInt8)0x0a << (sal_uInt8)0x02 << (sal_uInt8)0x00 << (sal_uInt8)0x01 << (sal_uInt8)0x00;
537 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x08 << (sal_uInt8)0x08 << (sal_uInt8)0x08;
538 	}
539 	UpdateFieldSize();
540 
541 	//--- Das Feld 'End Color Attribute Table':
542 	WriteFieldIntroducer(16,EndColAtrMagic,0,0);
543 	WriteFieldId(nFieldId);
544 
545 	if (pMET->GetError())
546 		bStatus=sal_False;
547 }
548 
549 
WriteImageObject(const Bitmap & rBitmap)550 void METWriter::WriteImageObject(const Bitmap & rBitmap)
551 {
552 	SvMemoryStream aTemp(0x00010000,0x00010000);
553 	sal_uInt32 nWidth,nHeight,nResX,nResY;
554 	sal_uLong nBytesPerLine,i,j,nNumColors,ny,nLines;
555 	sal_uLong nActColMapId;
556 	sal_uInt16 nBitsPerPixel;
557 	sal_uInt8 nbyte, * pBuf;
558 
559 	if (bStatus==sal_False)
560 		return;
561 
562 	nActColMapId=((nActBitmapId>>24)&0x000000ff) | ((nActBitmapId>> 8)&0x0000ff00) |
563 				 ((nActBitmapId<< 8)&0x00ff0000) | ((nActBitmapId<<24)&0xff000000);
564 
565 	//--- Das Feld 'Begin Image Object':
566 	WriteFieldIntroducer(16,BegImgObjMagic,0,0);
567 	WriteFieldId(nActBitmapId);
568 
569 	// Windows-BMP-Datei erzeugen:
570     WriteDIB(rBitmap, aTemp, false, true);
571 
572 	// Header der Windows-BMP-Datei einlesen:
573 	aTemp.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
574 	aTemp.Seek(18);
575 	aTemp >> nWidth >> nHeight;
576 	aTemp.SeekRel(2);
577 	aTemp >> nBitsPerPixel;
578 	aTemp.SeekRel(8);
579 	aTemp >> nResX >> nResY;
580 	aTemp.SeekRel(8);
581 
582 	nNumColors=1<<nBitsPerPixel;
583 	nBytesPerLine=((nWidth*nBitsPerPixel+0x0000001f) & 0xffffffe0 ) >> 3;
584 
585 	// ggf. Farbpalette einlesen und in die MET-Datei schreiben:
586 	if (nBitsPerPixel<=8)
587 	{
588 		BitmapPalette	aPal( (sal_uInt16) nNumColors );
589 		sal_uInt8			nr,ng,nb;
590 
591 		for (i=0; i<nNumColors; i++)
592 		{
593 			aTemp >> nb >> ng >> nr; aTemp.SeekRel(1);
594 			aPal[ (sal_uInt16) i ] = BitmapColor( nr, ng, nb );
595 		}
596 
597 		//--- Das Feld 'Begin Resource Group':
598 		WriteFieldIntroducer(16,BegResGrpMagic,0,0);
599 		WriteFieldId(nActColMapId);
600 
601 		//--- Farbtabelle schreiben:
602 		WriteColorAttributeTable(nActColMapId,&aPal,0,1);
603 
604 		//--- Das Feld 'End Resource Group':
605 		WriteFieldIntroducer(16,EndResGrpMagic,0,0);
606 		WriteFieldId(nActColMapId);
607 
608 		//--- Das Feld 'Begin Object Environment Group':
609 		WriteFieldIntroducer(16,BegObjEnvMagic,0,0);
610 		WriteFieldId(nActBitmapId);
611 
612 		//--- Das Feld 'Map Color Attribute Table':
613 		WriteFieldIntroducer(26,MapColAtrMagic,0,0);
614 		WriteBigEndianShort(0x0012);
615 		*pMET << (sal_uInt8)0x0c << (sal_uInt8)0x02 << (sal_uInt8)0x84 << (sal_uInt8)0x00;
616 		WriteFieldId(nActColMapId);
617 		*pMET << (sal_uInt8)0x04 << (sal_uInt8)0x24 << (sal_uInt8)0x07 << (sal_uInt8)0x01;
618 
619 		//--- Das Feld 'End Object Environment Group':
620 		WriteFieldIntroducer(16,EndObjEnvMagic,0,0);
621 		WriteFieldId(nActBitmapId);
622 	}
623 
624 	//--- Das Feld 'Image Data Descriptor':
625 	WriteFieldIntroducer(17,DscImgObjMagic,0,0);
626 	*pMET << (sal_uInt8)0x01; // Unit of measure: tens of centimeters
627 	WriteBigEndianShort((sal_uInt16)nResX);
628 	WriteBigEndianShort((sal_uInt16)nResY);
629 	WriteBigEndianShort((sal_uInt16)nWidth);
630 	WriteBigEndianShort((sal_uInt16)nHeight);
631 
632 	//--- Das erste Feld 'Image Picture Data':
633 	WriteFieldIntroducer(0,DatImgObjMagic,0,0);
634 
635 	// Begin Segment:
636 	*pMET << (sal_uInt8)0x70 << (sal_uInt8)0x00;
637 
638 	// Begin Image Content:
639 	*pMET << (sal_uInt8)0x91 << (sal_uInt8)0x01 << (sal_uInt8)0xff;
640 
641 	// Image Size:
642 	*pMET << (sal_uInt8)0x94 << (sal_uInt8)0x09 << (sal_uInt8)0x02;
643 	*pMET << (sal_uInt16) 0 << (sal_uInt16) 0;
644 	WriteBigEndianShort((sal_uInt16)nHeight);
645 	WriteBigEndianShort((sal_uInt16)nWidth);
646 
647 	// Image Encoding:
648 	*pMET << (sal_uInt8)0x95 << (sal_uInt8)0x02 << (sal_uInt8)0x03 << (sal_uInt8)0x03;
649 
650 	// Image IDE-Size:
651 	*pMET << (sal_uInt8)0x96 << (sal_uInt8)0x01 << (sal_uInt8)nBitsPerPixel;
652 
653 	if (nBitsPerPixel<=8) {
654 		// Image LUT-ID
655 		*pMET << (sal_uInt8)0x97 << (sal_uInt8)0x01 << (sal_uInt8)0x01;
656 	}
657 	else {
658 		// IDE Structure
659 		*pMET << (sal_uInt8)0x9b << (sal_uInt8)0x08 << (sal_uInt8)0x00 << (sal_uInt8)0x01;
660 		*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x08;
661 		*pMET << (sal_uInt8)0x08 << (sal_uInt8)0x08;
662 	}
663 
664 	pBuf=new sal_uInt8[nBytesPerLine];
665 	ny=0;
666 	while (ny<nHeight) {
667 
668 		// Abschliessen des vorherigen Feldes 'Image Picture Data':
669 		UpdateFieldSize();
670 
671 		// Und ein neues Feld 'Image Picture Data' anfangen:
672 		WriteFieldIntroducer(0,DatImgObjMagic,0,0);
673 
674 		// Einige Scanlines lesen und schreiben:
675 		nLines=nHeight-ny;
676 		if (nLines*nBytesPerLine>30000) nLines=30000/nBytesPerLine;
677 		if (nLines<1) nLines=1;
678 		WriteBigEndianShort(0xfe92);
679 		WriteBigEndianShort((sal_uInt16)(nLines*nBytesPerLine));
680 		for (i=0; i<nLines; i++) {
681 			aTemp.Read(pBuf,nBytesPerLine);
682 			if (nBitsPerPixel==24) {
683 				for (j=2; j<nBytesPerLine; j+=3) {
684 					nbyte=pBuf[j]; pBuf[j]=pBuf[j-2]; pBuf[j-2]=nbyte;
685 				}
686 			}
687 			pMET->Write(pBuf,nBytesPerLine);
688 			ny++;
689 		}
690 		if (aTemp.GetError() || pMET->GetError()) bStatus=sal_False;
691 		nActBitmapPercent=(ny+1)*100/nHeight;
692 		MayCallback();
693 		if (bStatus==sal_False) { delete[] pBuf; return; }
694 	}
695 	delete[] pBuf;
696 
697 	// End Image Content:
698 	*pMET << (sal_uInt8)0x93 << (sal_uInt8)0x00;
699 
700 	// End Segment:
701 	*pMET << (sal_uInt8)0x71 << (sal_uInt8)0x00;
702 
703 	// Abschliessen des letzten Feldes 'Image Picture Data':
704 	UpdateFieldSize();
705 
706 	//--- Das Feld 'End Image Object':
707 	WriteFieldIntroducer(16,EndImgObjMagic,0,0);
708 	WriteFieldId(nActBitmapId);
709 
710 	// Ids erhoehen:
711 	nActBitmapId++;
712 
713 	// Bitmaps zaehlen:
714 	nWrittenBitmaps++;
715 	nActBitmapPercent=0;
716 
717 	if (pMET->GetError()) bStatus=sal_False;
718 }
719 
720 
WriteImageObjects(const GDIMetaFile * pMTF)721 void METWriter::WriteImageObjects(const GDIMetaFile * pMTF)
722 {
723 	const MetaAction*	pMA;
724 
725 	if (bStatus==sal_False)
726 		return;
727 
728 	for ( sal_uLong nAction = 0, nActionCount = pMTF->GetActionCount(); nAction < nActionCount; nAction++)
729 	{
730 		pMA = pMTF->GetAction(nAction);
731 
732 		switch (pMA->GetType())
733 		{
734 			case META_BMP_ACTION:
735 			{
736 				METSetMix( eGDIRasterOp );
737 				WriteImageObject( ( (MetaBmpAction*) pMA )->GetBitmap() );
738 			}
739 			break;
740 
741 			case META_BMPSCALE_ACTION:
742 			{
743 				METSetMix( eGDIRasterOp );
744 				WriteImageObject( ( (MetaBmpScaleAction*) pMA )->GetBitmap() );
745 			}
746 			break;
747 
748 			case META_BMPSCALEPART_ACTION:
749 			{
750 				METSetMix( eGDIRasterOp );
751 				WriteImageObject( ( (MetaBmpScalePartAction*) pMA )->GetBitmap() );
752 			}
753 			break;
754 
755 			case META_BMPEX_ACTION:
756 			{
757 				METSetMix( eGDIRasterOp );
758 				WriteImageObject( Graphic( ( (MetaBmpExAction*) pMA )->GetBitmapEx() ).GetBitmap() );
759 			}
760 			break;
761 
762 			case META_BMPEXSCALE_ACTION:
763 			{
764 				METSetMix( eGDIRasterOp );
765 				WriteImageObject( Graphic( ( (MetaBmpExScaleAction*) pMA )->GetBitmapEx() ).GetBitmap() );
766 			}
767 			break;
768 
769 			case META_BMPEXSCALEPART_ACTION:
770 			{
771 				METSetMix( eGDIRasterOp );
772 				WriteImageObject( Graphic( ( (MetaBmpExScalePartAction*) pMA )->GetBitmapEx() ).GetBitmap() );
773 			}
774 			break;
775 
776 			case META_EPS_ACTION :
777 			{
778 				const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
779 				const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
780 
781 				sal_Int32 nCount = aGDIMetaFile.GetActionCount();
782 				for ( sal_Int32 i = 0; i < nCount; i++ )
783 				{
784 					const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
785 					if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
786 					{
787 						const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
788 						METSetMix( eGDIRasterOp );
789 						WriteImageObject( pBmpScaleAction->GetBitmap() );
790 						break;
791 					}
792 				}
793 			}
794 			break;
795 
796 		}
797 
798 		if (bStatus==sal_False)
799 			break;
800 	}
801 
802 	if (pMET->GetError())
803 		bStatus=sal_False;
804 }
805 
WriteDataDescriptor(const GDIMetaFile *)806 void METWriter::WriteDataDescriptor(const GDIMetaFile *)
807 {
808 	if (bStatus==sal_False)
809 		return;
810 
811 	WriteFieldIntroducer(0,DscGrfObjMagic,0,0);
812 
813 	//------------------------------------------------------------------------------
814 	// Im Folgenden die OS2-Orginal-Dokumentation und die Implementation dazu (uff)
815 	//------------------------------------------------------------------------------
816 
817 	//  Parameters (all required and in this order)
818 
819 	//  0         0xF7 Specify GVM Subset
820 	//  1         Length of following data 0x07
821 	//  2         0xB0 drawing order subset
822 	//  3-4       0x0000
823 	//  5         0x23 Level 3.2
824 	//  6         0x01 Version 1
825 	//  7         Length of following field 0x01
826 	//  8         Coordinate types in data
827 	//       0x04Intel16
828 	//       0x05Intel32
829 	*pMET << (sal_uInt8)0xf7 << (sal_uInt8)0x07 << (sal_uInt8)0xb0 << (sal_uInt8)0x00
830 		  << (sal_uInt8)0x00 << (sal_uInt8)0x23 << (sal_uInt8)0x01 << (sal_uInt8)0x01
831 		  << (sal_uInt8)0x05;
832 
833 	//  0         0xF6 Set Picture Descriptor
834 	//  1         Length of following data
835 	//  2         Flags
836 	//       0    B'0' Picture in 2D
837 	//       1    Picture Dimensions
838 	//            B'0'  Not absolute (PU_ARBITRARY PS)
839 	//            B'1'  Absolute (example: PU_TWIPS PS)
840 	//       2    Picture Elements
841 	//            B'0'  Not pels
842 	//            B'1'  Pels (PU_PELS PS)
843 	//                  (Bit 1 must also be set)
844 	//       3-7  B'00000'
845 	//  3         0x00 Reserved
846 	//  4         Picture frame size coordinate type
847 	//       0x04  Intel16
848 	//       0x05  Intel32
849 	//  5         UnitsOfMeasure
850 	//       0x00  Ten inches
851 	//       0x01  Decimeter
852 	//  6-11 or 6-17(2 or 4 bytes) Resolution.
853 	//       GPS Units / UOM on x axis
854 	//       GPS Units / UOM on y axis
855 	//       GPS Units / UOM on z axis
856 	//  12-23 or 18-41(2 or 4 bytes) Window Size.
857 	//       GPS X left, X right
858 	//       GPS Y bottom, Y top
859 	//       GPS Z near, Z far
860 	Size aUnitsPerDecimeter=OutputDevice::LogicToLogic(Size(10,10),MapMode(MAP_CM),aPictureMapMode);
861 	*pMET << (sal_uInt8)0xf6 << (sal_uInt8)0x28 << (sal_uInt8)0x40 << (sal_uInt8)0x00
862 		  << (sal_uInt8)0x05 << (sal_uInt8)0x01
863 		  << (sal_uInt32)(aUnitsPerDecimeter.Width())
864 		  << (sal_uInt32)(aUnitsPerDecimeter.Height())
865 		  << (sal_uInt32)0
866 		  << (sal_uInt32)0 << (sal_uInt32)aPictureRect.GetWidth()
867 		  << (sal_uInt32)0 << (sal_uInt32)aPictureRect.GetHeight()
868 		  << (sal_uInt32)0 << (sal_uInt32)0;
869 
870 	//  0         0x21 Set Current Defaults
871 	//  1         Length of following data
872 	//  2         Set Default Parameter Format 0x08
873 	//  3-4       Mask 0xE000
874 	//  5         Names 0x8F
875 	//  6         Coordinates
876 	//       0x00  Picture in 2D
877 	//  7         Transforms
878 	//       0x04  Intel16
879 	//       0x05  Intel32
880 	//  8         Geometrics
881 	//       0x04  Intel16
882 	//       0x05  Intel32
883 	*pMET << (sal_uInt8)0x21 << (sal_uInt8)0x07 << (sal_uInt8)0x08 << (sal_uInt8)0xe0
884 		  << (sal_uInt8)0x00 << (sal_uInt8)0x8f << (sal_uInt8)0x00 << (sal_uInt8)0x05
885 		  << (sal_uInt8)0x05;
886 
887 	//  0         0x21 Set Current Defaults
888 	//  1         Length of following data
889 	//  2         Set default viewing transform 0x07
890 	//  3-4       Mask 0xCC0C
891 	//  5         Names 0x8F
892 	//  6-n       M11, M12, M21, M22, M41, M42   Matrix elements
893 	*pMET << (sal_uInt8)0x21 << (sal_uInt8)0x1c << (sal_uInt8)0x07 << (sal_uInt8)0xcc
894 		  << (sal_uInt8)0x0c << (sal_uInt8)0x8f
895 		  << (sal_uInt32)0x00010000 << (sal_uInt32)0x00000000 << (sal_uInt32)0x00000000
896 		  << (sal_uInt32)0x00010000 << (sal_uInt32)0x00000000 << (sal_uInt32)0x00000000;
897 
898 	//  0         0x21 Set Current Defaults
899 	//  1         Length of following data
900 	//  2         Set default line attributes 0x01
901 	//  3-4       Mask - OR of as many of the following bits as are required:
902 	//       0x8000  Line type
903 	//       0x4000  Line width
904 	//       0x2000  Line end
905 	//       0x1000  Line join
906 	//       0x0800  Stroke width
907 	//       0x0008  Line color
908 	//       0x0002  Line mix
909 	//  5         Flags
910 	//
911 	//       0x0F Set indicated default attributes to initial values. (Data field is not present in this
912 	//             instance).
913 	//       0x8F Set indicated default attributes to specified values.
914 	//  6-n       Data - data values as required, in the following order if present.
915 	//            No space is reserved for attributes for which the corresponding mask flag was not
916 	//            set.
917 	//
918 	//       (1 byte)  - Line type
919 	//       (1 byte)  - Line width
920 	//       (1 byte)  - Line end
921 	//       (1 byte)  - Line join
922 	//       (G bytes) - Stroke width
923 	//       (4 bytes) - Line color
924 	//       (1 byte)  - Line mix (G=2 or 4 depending on the Geometrics parameter of Set Default
925 	//            Parameter Format)
926 	// Nanu! witziger-weise fehlt obiger Abschnitt in den Metadateien. Also lassen wir ihn auch weg
927 
928 	//  0         0x21 Set Current Defaults
929 	//  1         Length of following data
930 	//  2         Set Default Character Attributes 0x02
931 	//  3-4       Mask - OR of as many of the following bits as are required:
932 	//
933 	//       0x8000  Character angle
934 	//       0x4000  Character box
935 	//       0x2000  Character direction
936 	//       0x1000  Character precision
937 	//       0x0800  Character set
938 	//       0x0400  Character shear
939 	//       0x0040  Character break extra
940 	//       0x0020  Character extra
941 	//       0x0008  Character color
942 	//       0x0004  Character background color
943 	//       0x0002  Character mix
944 	//       0x0001  Character background mix
945 	//  5         Flags
946 	//       0x0FSet indicated default attributes to initial values.  (Data field is not present in this
947 	//            case).
948 	//       0x8FSet indicated default attributes to specified values.
949 	//  6-n       Data - data values as required, in the following order if present.
950 	//            No space is reserved for attributes for which the corresponding Mask flag was not
951 	//            set.
952 	//       (2*G bytes)     - Character angle
953 	//       (2*G + 4 bytes)- Character box
954 	//       (1 byte)        - Character direction
955 	//       (1 byte)        - Character precision
956 	//       (1 byte)        - Character set
957 	//       (2*G bytes)     - Character shear
958 	//       (4 bytes)       - Character break extra
959 	//       (4 bytes)       - Character extra
960 	//       (4 bytes)       - Character color
961 	//       (4 bytes)       - Character background color
962 	//       (1 byte)        - Character mix
963 	//       (1 byte)        - Character background mix (G=2 or 4 depending on the Geometrics
964 	//            parameter of Set Default Parameter Format)
965 	*pMET << (sal_uInt8)0x21 << (sal_uInt8)0x10 << (sal_uInt8)0x02 << (sal_uInt8)0x40
966 		  << (sal_uInt8)0x00 << (sal_uInt8)0x8f
967 		  << (sal_uInt8)0xaa << (sal_uInt8)0x02 << (sal_uInt8)0x00 << (sal_uInt8)0x00
968 		  << (sal_uInt8)0x44 << (sal_uInt8)0x04 << (sal_uInt8)0x00 << (sal_uInt8)0x00
969 		  << (sal_uInt8)0xa8 << (sal_uInt8)0xaa << (sal_uInt8)0x40 << (sal_uInt8)0x44;
970 
971 	//  0         0x21 Set Current Defaults
972 	//  1         Length of following data
973 	//  2         Set Default Marker Attributes 0x03
974 	//  3-4       Mask - OR of as many of the following bits as are required:
975 	//       0x4000  Marker box
976 	//       0x1000  Marker precision
977 	//       0x0800  Marker set
978 	//       0x0100  Marker symbol
979 	//       0x0008  Marker color
980 	//       0x0004  Marker background color
981 	//       0x0002  Marker mix
982 	//       0x0001  Marker background mix
983 	//  5         Flags
984 	//       0x0F  Set indicated default attributes to initial values.
985 	//             (Data field is not present in this instance)
986 	//       0x8F  Set indicated default attributes to specified values.
987 	//  6-n       Data - data values as required, in this order if present.
988 	//            No space is reserved for attributes for which the corresponding Mask flag was not
989 	//            set.
990 	//       (2*G bytes)    - Marker box
991 	//       (1 byte)       - Marker precision
992 	//       (1 byte)       - Marker set
993 	//       (1 byte)       - Marker symbol
994 	//       (4 bytes)      - Marker color
995 	//       (4 bytes)      - Marker background color
996 	//       (1 byte)       - Marker mix
997 	//       (1 byte)       - Marker background mix (G=2 or 4 depending on the Geometrics
998 	//            parameter of Set Default Parameter Format)
999 	*pMET << (sal_uInt8)0x21 << (sal_uInt8)0x0c << (sal_uInt8)0x03 << (sal_uInt8)0x40
1000 		  << (sal_uInt8)0x00 << (sal_uInt8)0x8f
1001 		  << (sal_uInt8)0x66 << (sal_uInt8)0x02 << (sal_uInt8)0x00 << (sal_uInt8)0x00
1002 		  << (sal_uInt8)0x66 << (sal_uInt8)0x02 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
1003 
1004 	//  0         0x21 Set Current Defaults
1005 	//  1         Length of following data
1006 	//  2         Set Default Pattern Attributes 0x04
1007 	//  3-4       Mask - OR of as many of the following bits as are required:
1008 	//       0x0800  Pattern set
1009 	//       0x0100  Pattern symbol
1010 	//       0x0080  Pattern reference point
1011 	//       0x0008  Pattern color
1012 	//       0x0004  Pattern background color
1013 	//       0x0002  Pattern mix
1014 	//       0x0001  Pattern background mix
1015 	//       5       Flags
1016 	//
1017 	//            0x0F Set indicated default attributes to initial values.
1018 	//                  (Data field is not present in this instance)
1019 	//            0x8F Set indicated default attributes to specified values.
1020 	//       6-n     Data - data values as required, in this order if present.
1021 	//               No space is reserved for attributes for which the corresponding Mask flag was
1022 	//               not set.
1023 	//
1024 	//            (1 byte)     - Pattern set
1025 	//            (1 byte)     - Pattern symbol
1026 	//            (2*G bytes)  - Pattern reference point
1027 	//            (4 bytes)    - Pattern color
1028 	//            (4 bytes)    - Pattern background color
1029 	//            (1 byte)     - Pattern mix
1030 	//            (1 byte)     - Pattern background mix (G=2 or 4 depending on the Geometrics
1031 	//               parameter of Set Default Parameter Format)
1032 	//       0       0x21 Set Current Defaults
1033 	//       1       Length of following data
1034 	//       2       Set Default Image Attributes 0x06
1035 	//       3-4     Mask - OR of as many of these bits as are required:
1036 	//            0x0008  Image color
1037 	//            0x0004  Image background color
1038 	//            0x0002  Image mix
1039 	//            0x0001  Image background mix
1040 	//       5       Flags
1041 	//            0x0F Set indicated default attributes to initial values. (Data field is not present in
1042 	//                  this instance)
1043 	//            0x8F Set indicated default attributes to specified values.
1044 	//       6-n     Data - data values as required, in this order if present.
1045 	//               No space is reserved for attributes for which the corresponding Mask flag was
1046 	//               not set.
1047 	//            (4 bytes)  - Image color
1048 	//            (4 bytes)  - Image background color
1049 	//            (1 byte)   - Image mix
1050 	//            (1 byte)   - Image background mix
1051 	//       0       0x21 Set Current Defaults
1052 	//       1       Length of following data
1053 	//       2       Set Default Viewing Window 0x05
1054 	//       3-4     Mask - OR of as many of the following bits as are required:
1055 	//            0x8000  x left limit
1056 	//            0x4000  x right limit
1057 	//            0x2000  y bottom limit
1058 	//            0x1000  y top limit
1059 	//       5       Flags
1060 	//            0x0F Set indicated default attributes to initial values.
1061 	//                  (Data field is not present in this case).
1062 	//            0x8F Set indicated default attributes to specified values.
1063 	//       6-n     Data - data values as required, in the following order if present.
1064 	//               No space is reserved for attributes for which the corresponding Mask flag was
1065 	//               not set.
1066 	//            (2*G bytes)  - x left limit
1067 	//            (2*G bytes)  - x right limit
1068 	//            (2*G bytes)  - y bottom limit
1069 	//            (2*G bytes)  - y top limit (G=2 or 4 depending on the Geometrics parameter of Set
1070 	//               Default Parameter Format)
1071 	//       0       0x21 Set Current Defaults
1072 	//       1       Length of following data
1073 	//       2       Set Default Arc Parameters 0x0B
1074 	//       3-4     Mask - OR of as many of the following bits as are required:
1075 	//            0x8000  P value
1076 	//            0x4000  Q value
1077 	//            0x2000  R value
1078 	//            0x1000  S value
1079 	//       5       Flags
1080 	//            0x0F Set indicated default attributes to initial values.
1081 	//                  (Data field is not present in this case).
1082 	//            0x8F Set indicated default attributes to specified values.
1083 	//       6-n     Data - data values as required, in the following order if present.
1084 	//               No space is reserved for attributes for which the corresponding Mask flag was
1085 	//               not set.
1086 	//            (G bytes)  - P value
1087 	//            (G bytes)  - Q value
1088 	//            (G bytes)  - R value
1089 	//            (G bytes)  - S value (G=2 or 4 depending on the Geometrics parameter of Set
1090 	//               Default Parameter Format)
1091 	//       0       0x21 Set Current Defaults
1092 	//       1       Length of following data
1093 	//       2       Set Default Pick Identifier 0x0C
1094 	//       3-4     Mask - OR of as many of the following bits as are required:
1095 	//            0x8000  Pick identifier
1096 	//       5       Flags
1097 	//            0x0F Set indicated default attributes to initial values.
1098 	//                  (Data field is not present in this case).
1099 	//            0x8F Set indicated default attributes to specified values.
1100 	//       6-n     Data - data values as required, in the following order if present.
1101 	//               No space is reserved for attributes for which the corresponding Mask flag was
1102 	//               not set.
1103 	//            (4 bytes)  - Pick identifier
1104 
1105 	//       0       0xE7 Set Bit-map Identifier
1106 	//       1       Length of following data 0x07
1107 	//       2-3     Usage Flags 0x8000
1108 	//       4-7     Bit-map handle
1109 	//       8       Lcid
1110 	if (nNumberOfBitmaps>0) {
1111 		*pMET << (sal_uInt8)0xe7 << (sal_uInt8)0x07 << (sal_uInt8)0x80 << (sal_uInt8)0x00;
1112 		WriteBigEndianLong(nActBitmapId);
1113 		*pMET << (sal_uInt8)0xfe;
1114 	}
1115 
1116 	UpdateFieldSize();
1117 
1118 	if (pMET->GetError()) bStatus=sal_False;
1119 }
1120 
1121 
WillWriteOrder(sal_uLong nNextOrderMaximumLength)1122 void METWriter::WillWriteOrder(sal_uLong nNextOrderMaximumLength)
1123 {
1124 	// Die Parameter eines 'Graphics Data Fields' duerfen (laut OS2-Doku)
1125 	// hoechstens 32759 Bytes umfassen. Gemeint ist die Laenge des Feldes minus
1126 	// dem 'Structured Field Introducer' (groesse: 8). Also darf die Groesse
1127 	// des ganzen Fields hoechstens 8+32759=32767=0x7fff sein.
1128 	// Zur Sicherheit nehmen wir lieber 30000 als Grenze.
1129 
1130 	if (pMET->Tell()-nActualFieldStartPos+nNextOrderMaximumLength>30000)
1131 	{
1132 		UpdateFieldSize();
1133 		WriteFieldIntroducer(0,DatGrfObjMagic,0,0);
1134 		nNumberOfDataFields++;
1135 	}
1136 }
1137 
1138 
1139 
METBitBlt(Point aPt,Size aSize,const Size & rBmpSizePixel)1140 void METWriter::METBitBlt(Point aPt, Size aSize, const Size& rBmpSizePixel)
1141 {
1142 	WillWriteOrder(46);
1143 	*pMET << (sal_uInt8)0xd6 << (sal_uInt8)44 << (sal_uInt16)0 << (sal_uInt16) 0x00cc;
1144 	WriteBigEndianLong(nActBitmapId++);
1145 	*pMET << (sal_uInt8)0x02 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
1146 	WritePoint(Point(aPt.X(),aPt.Y()+aSize.Height()));
1147 	WritePoint(Point(aPt.X()+aSize.Width(),aPt.Y()));
1148 	*pMET << (sal_uInt32)0 << (sal_uInt32)0
1149 		  << (sal_uInt32)(rBmpSizePixel.Width())
1150 		  << (sal_uInt32)(rBmpSizePixel.Height());
1151 }
1152 
METSetAndPushLineInfo(const LineInfo & rLineInfo)1153 void METWriter::METSetAndPushLineInfo( const LineInfo& rLineInfo )
1154 {
1155 	sal_Int32 nWidth = pCompDev->LogicToLogic( Size( rLineInfo.GetWidth(),0 ), aPictureMapMode, aTargetMapMode ).Width();
1156 
1157 	WillWriteOrder( 8 );			// set stroke linewidth
1158 	*pMET	<< (sal_uInt8)0x15
1159 			<< (sal_uInt8)6
1160 			<< (sal_uInt8)0				// Flags
1161 			<< (sal_uInt8)0
1162 			<< nWidth;
1163 
1164 	if ( rLineInfo.GetStyle() != LINE_SOLID )
1165 	{
1166 		sal_uInt8 nStyle = 0;			// LineDefault;
1167 
1168 		switch ( rLineInfo.GetStyle() )
1169 		{
1170 			case LINE_NONE :
1171 				nStyle = 8;
1172 			break;
1173 
1174 			case LINE_DASH :
1175 			{
1176 				if ( rLineInfo.GetDotCount() )
1177 				{
1178 					if ( !rLineInfo.GetDashCount() )
1179 						nStyle = 1;	// LINE_DOT
1180 					else
1181 						nStyle = 3;	// LINE_DASH_DOT
1182 				}
1183 				else
1184 					nStyle = 2;		// LINE_DASH
1185 			}
1186 			break;
1187 			case LineStyle_SOLID:
1188 			case LineStyle_FORCE_EQUAL_SIZE:
1189 				break;  // not handled -Wall
1190 		}
1191 		WillWriteOrder( 2 );
1192 		*pMET << (sal_uInt8)0x18 << nStyle;		// set LineType
1193 	}
1194 }
1195 
METPopLineInfo(const LineInfo & rLineInfo)1196 void METWriter::METPopLineInfo( const LineInfo& rLineInfo )
1197 {
1198 	WillWriteOrder( 8 );			// set stroke linewidth
1199 	*pMET	<< (sal_uInt8)0x15
1200 			<< (sal_uInt8)6
1201 			<< (sal_uInt8)0				// Flags
1202 			<< (sal_uInt8)0
1203 			<< (sal_uInt32)1;
1204 
1205 	if ( rLineInfo.GetStyle() != LINE_SOLID )
1206 	{
1207 		WillWriteOrder( 2 );
1208 		*pMET << (sal_uInt8)0x18 << (sal_uInt8)0;		// set LineType
1209 	}
1210 }
1211 
METBeginArea(sal_Bool bBoundaryLine)1212 void METWriter::METBeginArea(sal_Bool bBoundaryLine)
1213 {
1214 	WillWriteOrder(2);
1215 	*pMET << (sal_uInt8)0x68;
1216 	if (bBoundaryLine) *pMET << (sal_uInt8)0xc0;
1217 	else               *pMET << (sal_uInt8)0x80;
1218 }
1219 
1220 
METEndArea()1221 void METWriter::METEndArea()
1222 {
1223 	WillWriteOrder(2);
1224 	*pMET << (sal_uInt8)0x60 << (sal_uInt8)0;
1225 }
1226 
1227 
METBeginPath(sal_uInt32 nPathId)1228 void METWriter::METBeginPath(sal_uInt32 nPathId)
1229 {
1230 	WillWriteOrder(8);
1231 	*pMET << (sal_uInt8)0xd0 << (sal_uInt8)6 << (sal_uInt16) 0 << nPathId;
1232 }
1233 
1234 
METEndPath()1235 void METWriter::METEndPath()
1236 {
1237 	WillWriteOrder(2);
1238 	*pMET << (sal_uInt8)0x7f << (sal_uInt8)0;
1239 }
1240 
1241 
METFillPath(sal_uInt32 nPathId)1242 void METWriter::METFillPath(sal_uInt32 nPathId)
1243 {
1244 	WillWriteOrder(8);
1245 	*pMET << (sal_uInt8)0xd7 << (sal_uInt8)6
1246 		  << (sal_uInt8)0x00 << (sal_uInt8)0 << nPathId;
1247 }
1248 
1249 
METOutlinePath(sal_uInt32 nPathId)1250 void METWriter::METOutlinePath(sal_uInt32 nPathId)
1251 {
1252 	WillWriteOrder(8);
1253 	*pMET << (sal_uInt8)0xd4 << (sal_uInt8)6
1254 		  << (sal_uInt8)0 << (sal_uInt8)0 << nPathId;
1255 }
1256 
1257 
METCloseFigure()1258 void METWriter::METCloseFigure()
1259 {
1260 	WillWriteOrder(2);
1261 	*pMET << (sal_uInt8)0x7d << (sal_uInt8)0;
1262 }
1263 
1264 
METMove(Point aPt)1265 void METWriter::METMove(Point aPt)
1266 {
1267 	WillWriteOrder(10);
1268 	*pMET << (sal_uInt8)0x21 << (sal_uInt8)8;
1269 	WritePoint(aPt);
1270 }
1271 
1272 
METLine(Point aPt1,Point aPt2)1273 void METWriter::METLine(Point aPt1, Point aPt2)
1274 {
1275 	WillWriteOrder(18);
1276 	*pMET << (sal_uInt8)0xc1 << (sal_uInt8)16;
1277 	WritePoint(aPt1); WritePoint(aPt2);
1278 }
1279 
1280 
METLine(const Polygon & rPolygon)1281 void METWriter::METLine(const Polygon & rPolygon)
1282 {
1283 	sal_uInt16 nNumPoints,i,j,nOrderPoints;
1284 	sal_Bool bFirstOrder;
1285 
1286 	bFirstOrder=sal_True;
1287 	i=0; nNumPoints=rPolygon.GetSize();
1288 	while (i<nNumPoints) {
1289 		nOrderPoints=nNumPoints-i;
1290 		if (nOrderPoints>30) nOrderPoints=30;
1291 		WillWriteOrder(nOrderPoints*8+2);
1292 		if (bFirstOrder==sal_True) {
1293 			*pMET << (sal_uInt8)0xc1; // Line at given pos
1294 			bFirstOrder=sal_False;
1295 		}
1296 		else {
1297 			*pMET << (sal_uInt8)0x81; // Line at current pos
1298 		}
1299 		*pMET << (sal_uInt8)(nOrderPoints*8);
1300 		for (j=0; j<nOrderPoints; j++) WritePoint(rPolygon.GetPoint(i++));
1301 	}
1302 }
1303 
1304 
METLine(const PolyPolygon & rPolyPolygon)1305 void METWriter::METLine(const PolyPolygon & rPolyPolygon)
1306 {
1307 	sal_uInt16 i,nCount;
1308 	nCount=rPolyPolygon.Count();
1309 	for (i=0; i<nCount; i++) {
1310 		METLine(rPolyPolygon.GetObject(i));
1311 		METCloseFigure();
1312 	}
1313 }
1314 
1315 
METLineAtCurPos(Point aPt)1316 void METWriter::METLineAtCurPos(Point aPt)
1317 {
1318 	WillWriteOrder(10);
1319 	*pMET << (sal_uInt8)0x81 << (sal_uInt8)8;
1320 	WritePoint(aPt);
1321 }
1322 
1323 
METBox(sal_Bool bFill,sal_Bool bBoundary,Rectangle aRect,sal_uInt32 nHAxis,sal_uInt32 nVAxis)1324 void METWriter::METBox(sal_Bool bFill, sal_Bool bBoundary,
1325 					   Rectangle aRect, sal_uInt32 nHAxis, sal_uInt32 nVAxis)
1326 {
1327 	sal_uInt8 nFlags=0;
1328 	if (bFill)     nFlags|=0x40;
1329 	if (bBoundary) nFlags|=0x20;
1330 
1331 	WillWriteOrder(28);
1332 	*pMET << (sal_uInt8)0xc0 << (sal_uInt8)26 << nFlags << (sal_uInt8)0;
1333 	WritePoint(aRect.BottomLeft());
1334 	WritePoint(aRect.TopRight());
1335 	*pMET << nHAxis << nVAxis;
1336 }
1337 
1338 
METFullArc(Point aCenter,double fMultiplier)1339 void METWriter::METFullArc(Point aCenter, double fMultiplier)
1340 {
1341 	WillWriteOrder(14);
1342 	*pMET << (sal_uInt8)0xc7 << (sal_uInt8)12;
1343 	WritePoint(aCenter);
1344 	*pMET << (long)(fMultiplier*65536.0+0.5);
1345 }
1346 
1347 
METPartialArcAtCurPos(Point aCenter,double fMultiplier,double fStartAngle,double fSweepAngle)1348 void METWriter::METPartialArcAtCurPos(Point aCenter, double fMultiplier,
1349 									  double fStartAngle, double fSweepAngle)
1350 {
1351 	fStartAngle*=180.0/3.14159265359;
1352 	while (fStartAngle>360.0) fStartAngle-=360.0;
1353 	while (fStartAngle<0.0) fStartAngle+=360.0;
1354 	fSweepAngle*=180.0/3.14159265359;
1355 	while (fSweepAngle>360.0) fSweepAngle-=360.0;
1356 	while (fSweepAngle<.00) fSweepAngle+=360.0;
1357 	WillWriteOrder(22);
1358 	*pMET << (sal_uInt8)0xa3 << (sal_uInt8)20;
1359 	WritePoint(aCenter);
1360 	*pMET << (long)(fMultiplier*65536.0+0.5);
1361 	*pMET << (long)(fStartAngle*65536.0+0.5);
1362 	*pMET << (long)(fSweepAngle*65536.0+0.5);
1363 }
1364 
1365 
METChrStr(Point aPt,String aUniStr)1366 void METWriter::METChrStr( Point aPt, String aUniStr )
1367 {
1368 	sal_uInt16 nLen,i;
1369 	ByteString aStr( aUniStr, gsl_getSystemTextEncoding() );
1370 	nLen = aStr.Len();
1371 	WillWriteOrder( 11 + nLen );
1372 	*pMET << (sal_uInt8)0xc3 << (sal_uInt8)( 9 + nLen );
1373 	WritePoint(aPt);
1374 	for ( i = 0; i < nLen; i++ )
1375 		*pMET << aStr.GetChar( i );
1376 	*pMET << (sal_uInt8)0;
1377 }
1378 
1379 
METSetArcParams(long nP,long nQ,long nR,long nS)1380 void METWriter::METSetArcParams(long nP, long nQ, long nR, long nS)
1381 {
1382 	WillWriteOrder(18);
1383 	*pMET << (sal_uInt8)0x22 << (sal_uInt8)16 << nP << nQ << nR << nS;
1384 }
1385 
1386 
METSetColor(Color aColor)1387 void METWriter::METSetColor(Color aColor)
1388 {
1389 	if (aColor==aMETColor) return;
1390 	aMETColor=aColor;
1391 
1392 	WillWriteOrder(6);
1393 	*pMET << (sal_uInt8)0xa6 << (sal_uInt8)4 << (sal_uInt8)0
1394 		  << (sal_uInt8)(aColor.GetBlue())
1395 		  << (sal_uInt8)(aColor.GetGreen())
1396 		  << (sal_uInt8)(aColor.GetRed());
1397 }
1398 
1399 
METSetBackgroundColor(Color aColor)1400 void METWriter::METSetBackgroundColor(Color aColor)
1401 {
1402 	if (aColor==aMETBackgroundColor) return;
1403 	aMETBackgroundColor=aColor;
1404 
1405 	WillWriteOrder(6);
1406 	*pMET << (sal_uInt8)0xa7 << (sal_uInt8)4 << (sal_uInt8)0
1407 		  << (sal_uInt8)(aColor.GetBlue())
1408 		  << (sal_uInt8)(aColor.GetGreen())
1409 		  << (sal_uInt8)(aColor.GetRed());
1410 }
1411 
METSetMix(RasterOp eROP)1412 void METWriter::METSetMix(RasterOp eROP)
1413 {
1414 	sal_uInt8 nMix;
1415 
1416 	if (eMETMix==eROP)
1417 		return;
1418 
1419 	eMETMix=eROP;
1420 
1421 	switch (eROP)
1422 	{
1423 		case ROP_INVERT: nMix=0x0c; break;
1424 		case ROP_XOR:    nMix=0x04; break;
1425 		default:         nMix=0x02;
1426 	}
1427 
1428 	WillWriteOrder(2);
1429 	*pMET << (sal_uInt8)0x0c << nMix;
1430 }
1431 
1432 
METSetChrCellSize(Size aSize)1433 void METWriter::METSetChrCellSize(Size aSize)
1434 {
1435 	if (aMETChrCellSize==aSize)
1436 		return;
1437 
1438 	aMETChrCellSize=aSize;
1439 	WillWriteOrder(10);
1440 	if (aSize.Width()==0) aSize.Width()=aSize.Height();
1441 	*pMET << (sal_uInt8)0x33 << (sal_uInt8)8 << (long)aSize.Width() << (long)aSize.Height();
1442 }
1443 
1444 
METSetChrAngle(short nAngle)1445 void METWriter::METSetChrAngle(short nAngle)
1446 {
1447 	double fa;
1448 	long nax,nay;
1449 
1450 	if (nMETChrAngle==nAngle) return;
1451 	nMETChrAngle=nAngle;
1452 
1453 	if (nAngle==0)
1454 	{
1455 		nax=256;
1456 		nay=0;
1457 	}
1458 	else
1459 	{
1460 		fa=((double)nAngle)/1800.0*3.14159265359;
1461 		nax=(long)(256.0*cos(fa)+0.5);
1462 		nay=(long)(256.0*sin(fa)+0.5);
1463 	}
1464 
1465 	WillWriteOrder(10);
1466 	*pMET << (sal_uInt8)0x34 << (sal_uInt8)8 << nax << nay;
1467 }
1468 
1469 
METSetChrSet(sal_uInt8 nSet)1470 void METWriter::METSetChrSet(sal_uInt8 nSet)
1471 {
1472 	if (nMETChrSet==nSet)
1473 		return;
1474 
1475 	nMETChrSet=nSet;
1476 	WillWriteOrder(2);
1477 	*pMET << (sal_uInt8)0x38 << nSet;
1478 }
1479 
1480 
WriteOrders(const GDIMetaFile * pMTF)1481 void METWriter::WriteOrders( const GDIMetaFile* pMTF )
1482 {
1483 	if(bStatus==sal_False)
1484 		return;
1485 
1486 	for( sal_uLong nA = 0, nACount = pMTF->GetActionCount(); nA < nACount; nA++ )
1487 	{
1488 		const MetaAction* pMA = pMTF->GetAction( nA );
1489 
1490 		switch (pMA->GetType())
1491 		{
1492 			case META_PIXEL_ACTION:
1493 			{
1494 				const MetaPixelAction* pA = (const MetaPixelAction*) pMA;
1495 				METSetMix( eGDIRasterOp );
1496 				METSetColor( pA->GetColor() );
1497 				METLine( pA->GetPoint(),pA->GetPoint() );
1498 			}
1499 			break;
1500 
1501 			case META_POINT_ACTION:
1502 			{
1503 				const MetaPointAction* pA = (const MetaPointAction*) pMA;
1504 
1505 				METSetArcParams(1,1,0,0);
1506 				METSetMix(eGDIRasterOp);
1507 				METSetColor(aGDILineColor);
1508 				METBeginArea(sal_False);
1509 				METFullArc(pA->GetPoint(),0.5);
1510 				METEndArea();
1511 			}
1512 			break;
1513 
1514 			case META_LINE_ACTION:
1515 			{
1516 				const MetaLineAction* pA = (const MetaLineAction*) pMA;
1517 
1518 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1519 				{
1520 					LineInfo aLineInfo( pA->GetLineInfo() );
1521 					if ( ! ( aLineInfo.IsDefault() ) )
1522 						METSetAndPushLineInfo( aLineInfo );
1523 
1524 					METSetMix( eGDIRasterOp );
1525 					METSetColor(aGDILineColor);
1526 					METBeginPath( 1 );
1527 					METLine( pA->GetStartPoint(), pA->GetEndPoint() );
1528 					METEndPath();
1529 					METOutlinePath( 1 );
1530 
1531 					if ( ! ( aLineInfo.IsDefault() ) )
1532 						METPopLineInfo( aLineInfo );
1533 				}
1534 			}
1535 			break;
1536 
1537 			case META_RECT_ACTION:
1538 			{
1539 				const MetaRectAction* pA = (const MetaRectAction*) pMA;
1540 
1541 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1542 				{
1543 					METSetMix( eGDIRasterOp );
1544 					METSetColor( aGDIFillColor );
1545 					METSetBackgroundColor( aGDIFillColor );
1546 					METBox( sal_True, sal_False, pA->GetRect(), 0, 0 );
1547 				}
1548 
1549 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1550 				{
1551 					METSetMix( eGDIRasterOp );
1552 					METSetColor( aGDILineColor );
1553 					METBox( sal_False, sal_True, pA->GetRect(), 0, 0 );
1554 				}
1555 			}
1556 			break;
1557 
1558 			case META_ROUNDRECT_ACTION:
1559 			{
1560 				const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1561 
1562 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1563 				{
1564 					METSetMix( eGDIRasterOp );
1565 					METSetColor( aGDIFillColor );
1566 					METSetBackgroundColor( aGDIFillColor );
1567 					METBox( sal_True, sal_False, pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1568 				}
1569 
1570 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1571 				{
1572 					METSetMix( eGDIRasterOp );
1573 					METSetColor( aGDILineColor );
1574 					METBox( sal_False, sal_True, pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1575 				}
1576 			}
1577 			break;
1578 
1579 			case META_ELLIPSE_ACTION:
1580 			{
1581 				const MetaEllipseAction*	pA = (const MetaEllipseAction*) pMA;
1582 				Point						aCenter;
1583 
1584 				aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1585 				aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1586 
1587 				METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1588 
1589 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1590 				{
1591 					METSetMix( eGDIRasterOp );
1592 					METSetColor( aGDIFillColor );
1593 					METSetBackgroundColor( aGDIFillColor );
1594 					METBeginArea(sal_False);
1595 					METFullArc(aCenter,0.5);
1596 					METEndArea();
1597 				}
1598 
1599 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1600 				{
1601 					METSetMix( eGDIRasterOp );
1602 					METSetColor( aGDILineColor );
1603 					METFullArc( aCenter,0.5 );
1604 				}
1605 			}
1606 			break;
1607 
1608 			case META_ARC_ACTION:
1609 			{
1610 				const MetaArcAction*	pA = (const MetaArcAction*) pMA;
1611 				Point					aStartPos,aCenter;
1612 				double					fdx,fdy,fa1,fa2;
1613 
1614 				aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1615 				aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1616 				fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1617 				fdy=(double)(pA->GetStartPoint().Y()-aCenter.Y());
1618 				fdx*=(double)pA->GetRect().GetHeight();
1619 				fdy*=(double)pA->GetRect().GetWidth();
1620 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1621 				fa1=atan2(-fdy,fdx);
1622 				fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1623 				fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1624 				fdx*=(double)pA->GetRect().GetHeight();
1625 				fdy*=(double)pA->GetRect().GetWidth();
1626 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1627 				fa2=atan2(-fdy,fdx);
1628 				aStartPos.X()=aCenter.X()+(long)(((double)pA->GetRect().GetWidth())*cos(fa1)/2.0+0.5);
1629 				aStartPos.Y()=aCenter.Y()-(long)(((double)pA->GetRect().GetHeight())*sin(fa1)/2.0+0.5);
1630 
1631 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1632 				{
1633 					METSetMix( eGDIRasterOp );
1634 					METSetColor( aGDILineColor );
1635 					METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1636 					METBeginPath(1);
1637 					METMove(aStartPos);
1638 					METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1639 					METEndPath();
1640 					METOutlinePath(1);
1641 				}
1642 			}
1643 			break;
1644 
1645 			case META_PIE_ACTION:
1646 			{
1647 				const MetaPieAction*	pA = (const MetaPieAction*) pMA;
1648 				Point					aCenter;
1649 				double					fdx,fdy,fa1,fa2;
1650 
1651 				aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1652 				aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1653 				fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1654 				fdy=(double)(pA->GetStartPoint().Y()-aCenter.Y());
1655 				fdx*=(double)pA->GetRect().GetHeight();
1656 				fdy*=(double)pA->GetRect().GetWidth();
1657 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1658 				fa1=atan2(-fdy,fdx);
1659 				fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1660 				fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1661 				fdx*=(double)pA->GetRect().GetHeight();
1662 				fdy*=(double)pA->GetRect().GetWidth();
1663 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1664 				fa2=atan2(-fdy,fdx);
1665 
1666 				METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1667 
1668 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1669 				{
1670 					METSetMix( eGDIRasterOp );
1671 					METSetColor( aGDIFillColor );
1672 					METSetBackgroundColor( aGDIFillColor );
1673 					METBeginPath(1);
1674 					METMove(aCenter);
1675 					METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1676 					METLineAtCurPos(aCenter);
1677 					METEndPath();
1678 					METFillPath(1);
1679 				}
1680 
1681 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1682 				{
1683 					METSetMix( eGDIRasterOp );
1684 					METSetColor( aGDILineColor );
1685 					METBeginPath(1);
1686 					METMove(aCenter);
1687 					METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1688 					METLineAtCurPos(aCenter);
1689 					METEndPath();
1690 					METOutlinePath(1);
1691 				}
1692 			}
1693 			break;
1694 
1695 			case META_CHORD_ACTION:
1696 			{
1697 				const MetaChordAction*	pA = (const MetaChordAction*) pMA;
1698 				Point					aStartPos,aCenter;
1699 				double					fdx,fdy,fa1,fa2;
1700 
1701 				aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1702 				aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1703 				fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1704 				fdy=(double)(pA->GetStartPoint().Y()-aCenter.Y());
1705 				fdx*=(double)pA->GetRect().GetHeight();
1706 				fdy*=(double)pA->GetRect().GetWidth();
1707 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1708 				fa1=atan2(-fdy,fdx);
1709 				fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1710 				fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1711 				fdx*=(double)pA->GetRect().GetHeight();
1712 				fdy*=(double)pA->GetRect().GetWidth();
1713 				if (fdx==0.0 && fdy==0.0) fdx=1.0;
1714 				fa2=atan2(-fdy,fdx);
1715 				aStartPos.X()=aCenter.X()+(long)(((double)pA->GetRect().GetWidth())*cos(fa1)/2.0+0.5);
1716 				aStartPos.Y()=aCenter.Y()-(long)(((double)pA->GetRect().GetHeight())*sin(fa1)/2.0+0.5);
1717 
1718 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1719 				{
1720 					METSetMix( eGDIRasterOp );
1721 					METSetColor( aGDIFillColor );
1722 					METSetBackgroundColor( aGDIFillColor );
1723 					METBeginPath(1);
1724 					METMove(aStartPos);
1725 					METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1726 					METLineAtCurPos(aStartPos);
1727 					METEndPath();
1728 					METFillPath(1);
1729 				}
1730 
1731 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1732 				{
1733 					METSetMix( eGDIRasterOp );
1734 					METSetColor( aGDILineColor );
1735 					METBeginPath(1);
1736 					METMove(aStartPos);
1737 					METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1738 					METLineAtCurPos(aStartPos);
1739 					METEndPath();
1740 					METOutlinePath(1);
1741 				}
1742 			}
1743 			break;
1744 
1745 			case META_POLYLINE_ACTION:
1746 			{
1747 				const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1748 
1749 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1750 				{
1751 					LineInfo aLineInfo( pA->GetLineInfo() );
1752 					if ( ! ( aLineInfo.IsDefault() ) )
1753 						METSetAndPushLineInfo( aLineInfo );
1754 
1755 					METSetMix(eGDIRasterOp);
1756 					METSetColor(aGDILineColor);
1757 					METBeginPath(1);
1758 					Polygon aSimplePoly;
1759 					const Polygon& rPoly = pA->GetPolygon();
1760 					if ( rPoly.HasFlags() )
1761 						rPoly.AdaptiveSubdivide( aSimplePoly );
1762 					else
1763 						aSimplePoly = rPoly;
1764 					METLine( aSimplePoly );
1765 					METEndPath();
1766 					METOutlinePath(1);
1767 
1768 					if ( ! ( aLineInfo.IsDefault() ) )
1769 						METPopLineInfo( aLineInfo );
1770 				}
1771 			}
1772 			break;
1773 
1774 			case META_POLYGON_ACTION:
1775 			{
1776 				const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1777 				Polygon aSimplePoly;
1778 				const Polygon& rPoly = pA->GetPolygon();
1779 				if ( rPoly.HasFlags() )
1780 					rPoly.AdaptiveSubdivide( aSimplePoly );
1781 				else
1782 					aSimplePoly = rPoly;
1783 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1784 				{
1785 					METSetMix(eGDIRasterOp);
1786 					METSetColor(aGDIFillColor );
1787 					METSetBackgroundColor(aGDIFillColor );
1788 					METBeginPath(1);
1789 					METLine( aSimplePoly );
1790 					METEndPath();
1791 					METFillPath(1);
1792 				}
1793 
1794 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1795 				{
1796 					METSetMix(eGDIRasterOp);
1797 					METSetColor(aGDILineColor );
1798 					METBeginPath(1);
1799 					METLine( aSimplePoly );
1800 					METEndPath();
1801 					METOutlinePath(1);
1802 				}
1803 			}
1804 			break;
1805 
1806 			case META_POLYPOLYGON_ACTION:
1807 			{
1808 				const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1809 
1810 				PolyPolygon aSimplePolyPoly( pA->GetPolyPolygon() );
1811 				sal_uInt16 i, nCount = aSimplePolyPoly.Count();
1812 				for ( i = 0; i < nCount; i++ )
1813 				{
1814 					if ( aSimplePolyPoly[ i ].HasFlags() )
1815 					{
1816 						Polygon aSimplePoly;
1817 						aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
1818 						aSimplePolyPoly[ i ] = aSimplePoly;
1819 					}
1820 				}
1821 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1822 				{
1823 					METSetMix(eGDIRasterOp);
1824 					METSetColor(aGDIFillColor);
1825 					METSetBackgroundColor(aGDIFillColor);
1826 					METBeginPath(1);
1827 					METLine( aSimplePolyPoly );
1828 					METEndPath();
1829 					METFillPath(1);
1830 				}
1831 
1832 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
1833 				{
1834 					METSetMix(eGDIRasterOp);
1835 					METSetColor(aGDILineColor);
1836 					METBeginPath(1);
1837 					METLine( aSimplePolyPoly );
1838 					METEndPath();
1839 					METOutlinePath(1);
1840 				}
1841 			}
1842 			break;
1843 
1844 			case META_TEXT_ACTION:
1845 			{
1846 				const MetaTextAction*	pA = (const MetaTextAction*) pMA;
1847 				Point					aPt( pA->GetPoint() );
1848 
1849 				if( aGDIFont.GetAlign() != ALIGN_BASELINE)
1850 				{
1851 					VirtualDevice aVDev;
1852 
1853 					if( aGDIFont.GetAlign()==ALIGN_TOP )
1854 						aPt.Y()+=(long)aVDev.GetFontMetric( aGDIFont ).GetAscent();
1855 					else
1856 						aPt.Y()-=(long)aVDev.GetFontMetric( aGDIFont ).GetDescent();
1857 				}
1858 
1859 				METSetMix(eGDIRasterOp);
1860 				METSetColor(aGDIFont.GetColor());
1861 				METSetBackgroundColor(aGDIFont.GetFillColor());
1862 				METSetChrCellSize(aGDIFont.GetSize());
1863 				METSetChrAngle(aGDIFont.GetOrientation());
1864 				METSetChrSet(FindChrSet(aGDIFont));
1865 				METChrStr(aPt, String(pA->GetText(),pA->GetIndex(),pA->GetLen()));
1866 			}
1867 			break;
1868 
1869 			case META_TEXTARRAY_ACTION:
1870 			{
1871 				const MetaTextArrayAction*	pA = (const MetaTextArrayAction*) pMA;
1872 				sal_uInt16						i;
1873 				String						aStr;
1874 				Polygon						aPolyDummy(1);
1875 				short						nOrientation;
1876 				Point						aPt( pA->GetPoint() );
1877 
1878 				if( aGDIFont.GetAlign() != ALIGN_BASELINE )
1879 				{
1880 					VirtualDevice aVDev;
1881 					if( aGDIFont.GetAlign() == ALIGN_TOP )
1882 						aPt.Y()+=(long)aVDev.GetFontMetric(aGDIFont).GetAscent();
1883 					else
1884 						aPt.Y()-=(long)aVDev.GetFontMetric(aGDIFont).GetDescent();
1885 				}
1886 
1887 				METSetMix(eGDIRasterOp);
1888 				METSetColor(aGDIFont.GetColor());
1889 				METSetBackgroundColor(aGDIFont.GetFillColor());
1890 				METSetChrCellSize(aGDIFont.GetSize());
1891 				METSetChrAngle( nOrientation = aGDIFont.GetOrientation() );
1892 				METSetChrSet(FindChrSet(aGDIFont));
1893 				aStr=String(pA->GetText(),pA->GetIndex(),pA->GetLen());
1894 
1895 				if( pA->GetDXArray()!=NULL )
1896 				{
1897 					Point aPt2;
1898 
1899 					for( i=0; i < aStr.Len(); i++ )
1900 					{
1901 						aPt2 = aPt;
1902 						if ( i > 0 )
1903 						{
1904 							aPt2.X() += pA->GetDXArray()[i-1];
1905 							if ( nOrientation )
1906 							{
1907 								aPolyDummy.SetPoint( aPt2, 0 );
1908 								aPolyDummy.Rotate( aPt, nOrientation );
1909 								aPt2 = aPolyDummy.GetPoint( 0 );
1910 							}
1911 						}
1912 						METChrStr( aPt2, String( aStr.GetChar( i ) ) );
1913 					}
1914 				}
1915 				else
1916 					METChrStr( aPt, aStr );
1917 			}
1918 			break;
1919 
1920 			case META_STRETCHTEXT_ACTION:
1921 			{
1922 				const MetaStretchTextAction*	pA = (const MetaStretchTextAction*) pMA;
1923 				VirtualDevice					aVDev;
1924 				sal_uInt16							i;
1925 				sal_Int32*					pDXAry;
1926 				sal_Int32						nNormSize;
1927 				String							aStr;
1928 				Polygon							aPolyDummy(1);
1929 				short							nOrientation;
1930 				Point							aPt( pA->GetPoint() );
1931 				Point							aPt2;
1932 
1933 				aVDev.SetFont( aGDIFont );
1934 
1935 				if( aGDIFont.GetAlign() != ALIGN_BASELINE)
1936 				{
1937 					if( aGDIFont.GetAlign() == ALIGN_TOP )
1938 						aPt.Y()+=(long)aVDev.GetFontMetric().GetAscent();
1939 					else
1940 						aPt.Y()-=(long)aVDev.GetFontMetric().GetDescent();
1941 				}
1942 
1943 				METSetMix(eGDIRasterOp);
1944 				METSetColor(aGDIFont.GetColor());
1945 				METSetBackgroundColor(aGDIFont.GetFillColor());
1946 				METSetChrCellSize(aGDIFont.GetSize());
1947 				METSetChrAngle( nOrientation = aGDIFont.GetOrientation() );
1948 				METSetChrSet(FindChrSet(aGDIFont));
1949 				aStr=String(pA->GetText(),pA->GetIndex(),pA->GetLen());
1950 				pDXAry=new sal_Int32[aStr.Len()];
1951 				nNormSize = aVDev.GetTextArray( aStr, pDXAry );
1952 
1953 				for ( i = 0; i < aStr.Len(); i++ )
1954 				{
1955 					aPt2 = aPt;
1956 					if ( i > 0 )
1957 					{
1958 						aPt2.X() += pDXAry[i-1]*((long)pA->GetWidth())/ nNormSize;
1959 						if ( nOrientation )
1960 						{
1961 							aPolyDummy.SetPoint( aPt2, 0 );
1962 							aPolyDummy.Rotate( aPt, nOrientation );
1963 							aPt2 = aPolyDummy.GetPoint( 0 );
1964 						}
1965 					}
1966 					METChrStr( aPt2, String( aStr.GetChar( i ) ) );
1967 				}
1968 
1969 				delete[] pDXAry;
1970 			}
1971 			break;
1972 
1973 			case META_TEXTRECT_ACTION:
1974 			{
1975 //				DBG_ERROR( "Unsupported MET-Action: META_TEXTRECT_ACTION!" );
1976 			}
1977 			break;
1978 
1979 			case META_BMP_ACTION:
1980 			{
1981 				const MetaBmpAction*    pA = (const MetaBmpAction*) pMA;
1982 				const Size              aSizePixel( pA->GetBitmap().GetSizePixel() );
1983 
1984 				METSetMix(eGDIRasterOp);
1985 				METBitBlt( pA->GetPoint(), pCompDev->PixelToLogic( aSizePixel, aPictureMapMode ), aSizePixel );
1986 			}
1987 			break;
1988 
1989 			case META_BMPSCALE_ACTION:
1990 			{
1991 				const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1992 
1993 				METSetMix(eGDIRasterOp);
1994 				METBitBlt( pA->GetPoint(), pA->GetSize(), pA->GetBitmap().GetSizePixel() );
1995 			}
1996 			break;
1997 
1998 			case META_BMPSCALEPART_ACTION:
1999 			{
2000 				const MetaBmpScalePartAction*	pA = (const MetaBmpScalePartAction*) pMA;
2001 				Bitmap							aTmp( pA->GetBitmap() );
2002 
2003 				aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
2004 				METSetMix( eGDIRasterOp );
2005 				METBitBlt( pA->GetDestPoint(), pA->GetDestSize(), pA->GetBitmap().GetSizePixel() );
2006 			}
2007 			break;
2008 
2009 			case META_BMPEX_ACTION:
2010 			{
2011 				const MetaBmpExAction*	pA = (const MetaBmpExAction*) pMA;
2012 				const Size              aSizePixel( pA->GetBitmapEx().GetSizePixel() );
2013 
2014 				METSetMix( eGDIRasterOp );
2015 				METBitBlt( pA->GetPoint(), pCompDev->PixelToLogic( aSizePixel, aPictureMapMode ), aSizePixel );
2016 			}
2017 			break;
2018 
2019 			case META_BMPEXSCALE_ACTION:
2020 			{
2021 				const MetaBmpExScaleAction*	pA = (const MetaBmpExScaleAction*) pMA;
2022 				const Size                  aSizePixel( pA->GetBitmapEx().GetSizePixel() );
2023 
2024 				METSetMix( eGDIRasterOp );
2025 				METBitBlt( pA->GetPoint(), pA->GetSize(), aSizePixel );
2026 			}
2027 			break;
2028 
2029 			case META_BMPEXSCALEPART_ACTION:
2030 			{
2031 				const MetaBmpExScalePartAction*	pA = (const MetaBmpExScalePartAction*) pMA;
2032 				Bitmap							aTmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
2033 
2034 				aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
2035 				METSetMix( eGDIRasterOp );
2036 				METBitBlt( pA->GetDestPoint(), pA->GetDestSize(), aTmp.GetSizePixel() );
2037 			}
2038 			break;
2039 
2040 			case META_EPS_ACTION :
2041 			{
2042 				const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
2043 				const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
2044 
2045 				sal_Int32 nCount = aGDIMetaFile.GetActionCount();
2046 				for ( sal_Int32 i = 0; i < nCount; i++ )
2047 				{
2048 					const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
2049 					if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
2050 					{
2051 						const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
2052 						METSetMix(eGDIRasterOp);
2053 						METBitBlt( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap().GetSizePixel() );
2054 						break;
2055 					}
2056 				}
2057 			}
2058 			break;
2059 
2060 			case META_MASK_ACTION:
2061 			{
2062 //				DBG_ERROR( "Unsupported MET-Action: META_MASK_ACTION!" );
2063 			}
2064 			break;
2065 
2066 			case META_MASKSCALE_ACTION:
2067 			{
2068 //				DBG_ERROR( "Unsupported MET-Action: META_MASKSCALE_ACTION!" );
2069 			}
2070 			break;
2071 
2072 			case META_MASKSCALEPART_ACTION:
2073 			{
2074 //				DBG_ERROR( "Unsupported MET-Action: META_MASKSCALEPART_ACTION!" );
2075 			}
2076 			break;
2077 
2078 			case META_GRADIENT_ACTION:
2079 			{
2080 				VirtualDevice				aVDev;
2081 				GDIMetaFile					aTmpMtf;
2082 				const MetaGradientAction*	pA = (const MetaGradientAction*) pMA;
2083 
2084 				aVDev.SetMapMode( aTargetMapMode );
2085 				aVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
2086 				WriteOrders( &aTmpMtf );
2087 			}
2088 			break;
2089 
2090 			case META_HATCH_ACTION:
2091 			{
2092 				VirtualDevice			aVDev;
2093 				GDIMetaFile				aTmpMtf;
2094 				const MetaHatchAction*	pA = (const MetaHatchAction*) pMA;
2095 
2096 				aVDev.SetMapMode( aTargetMapMode );
2097 				aVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
2098 				WriteOrders( &aTmpMtf );
2099 			}
2100 			break;
2101 
2102 			case META_WALLPAPER_ACTION:
2103 			{
2104 //				DBG_ERROR( "Unsupported MET-Action: META_WALLPAPER_ACTION!" );
2105 			}
2106 			break;
2107 
2108 			case META_CLIPREGION_ACTION:
2109 			{
2110 //				DBG_ERROR( "Unsupported MET-Action: META_CLIPREGION_ACTION!" );
2111 			}
2112 			break;
2113 
2114 			case META_ISECTRECTCLIPREGION_ACTION:
2115 			{
2116 				const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
2117 				WriteClipRect( pA->GetRect() );
2118 			}
2119 			break;
2120 
2121 			case META_ISECTREGIONCLIPREGION_ACTION:
2122 			{
2123 //				DBG_ERROR( "Unsupported MET-Action: META_ISECTREGIONCLIPREGION_ACTION!" );
2124 			}
2125 			break;
2126 
2127 			case META_MOVECLIPREGION_ACTION:
2128 			{
2129 //				DBG_ERROR( "Unsupported MET-Action: META_MOVECLIPREGION_ACTION!" );
2130 			}
2131 			break;
2132 
2133 			case META_LINECOLOR_ACTION:
2134 			{
2135 				const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
2136 
2137 				if( pA->IsSetting() )
2138 					aGDILineColor = pA->GetColor();
2139 				else
2140 					aGDILineColor = Color( COL_TRANSPARENT );
2141 			}
2142 			break;
2143 
2144 			case META_FILLCOLOR_ACTION:
2145 			{
2146 				const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
2147 
2148 				if( pA->IsSetting() )
2149 					aGDIFillColor = pA->GetColor();
2150 				else
2151 					aGDIFillColor = Color( COL_TRANSPARENT );
2152 			}
2153 			break;
2154 
2155 			case META_TEXTCOLOR_ACTION:
2156 			{
2157 				const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
2158 				aGDIFont.SetColor( pA->GetColor() );
2159 			}
2160 			break;
2161 
2162 			case META_TEXTFILLCOLOR_ACTION:
2163 			{
2164 				const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
2165 
2166 				if( pA->IsSetting() )
2167 					aGDIFont.SetFillColor( pA->GetColor() );
2168 				else
2169 					aGDIFont.SetFillColor( Color( COL_TRANSPARENT ) );
2170 			}
2171 			break;
2172 
2173 			case META_TEXTALIGN_ACTION:
2174 			{
2175 //				DBG_ERROR( "Unsupported MET-Action: META_TEXTALIGN_ACTION!" );
2176 			}
2177 			break;
2178 
2179 			case META_MAPMODE_ACTION:
2180 			{
2181 				const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
2182 
2183 				if( aPictureMapMode != pA->GetMapMode() )
2184 				{
2185 					if ( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
2186 					{
2187 						MapMode aMM = pA->GetMapMode();
2188 						Fraction aScaleX = aMM.GetScaleX();
2189 						Fraction aScaleY = aMM.GetScaleY();
2190 
2191 						Point aOrigin = aPictureMapMode.GetOrigin();
2192 						BigInt aX( aOrigin.X() );
2193 						aX *= BigInt( aScaleX.GetDenominator() );
2194 
2195 						if( aOrigin.X() >= 0 )
2196 						{
2197 							if( aScaleX.GetNumerator() >= 0 )
2198 								aX += BigInt( aScaleX.GetNumerator()/2 );
2199 							else
2200 								aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
2201 						}
2202 						else
2203 						{
2204 							if( aScaleX.GetNumerator() >= 0 )
2205 								aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
2206 							else
2207 								aX += BigInt( aScaleX.GetNumerator()/2 );
2208 						}
2209 
2210 						aX /= BigInt( aScaleX.GetNumerator() );
2211 						aOrigin.X() = (long) aX + aMM.GetOrigin().X();
2212 
2213 						BigInt aY( aOrigin.Y() );
2214 						aY *= BigInt( aScaleY.GetDenominator() );
2215 
2216 						if( aOrigin.Y() >= 0 )
2217 						{
2218 							if( aScaleY.GetNumerator() >= 0 )
2219 								aY += BigInt( aScaleY.GetNumerator()/2 );
2220 							else
2221 								aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
2222 						}
2223 						else
2224 						{
2225 							if( aScaleY.GetNumerator() >= 0 )
2226 								aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
2227 							else
2228 								aY += BigInt( aScaleY.GetNumerator()/2 );
2229 						}
2230 
2231 						aY /= BigInt( aScaleY.GetNumerator() );
2232 						aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
2233 						aPictureMapMode.SetOrigin( aOrigin );
2234 
2235 						aScaleX *= aPictureMapMode.GetScaleX();
2236 						aScaleY *= aPictureMapMode.GetScaleY();
2237 						aPictureMapMode.SetScaleX( aScaleX );
2238 						aPictureMapMode.SetScaleY( aScaleY );
2239 					}
2240 					else
2241 						aPictureMapMode=pA->GetMapMode();
2242 				}
2243 			}
2244 			break;
2245 
2246 			case META_FONT_ACTION:
2247 			{
2248 				aGDIFont = ( (const MetaFontAction*) pMA )->GetFont();
2249 			}
2250 			break;
2251 
2252 			case META_PUSH_ACTION:
2253 			{
2254 				METGDIStackMember* pGS = new METGDIStackMember;
2255 
2256 				pGS->pSucc=pGDIStack; pGDIStack=pGS;
2257 				pGS->aLineColor=aGDILineColor;
2258 				pGS->aFillColor=aGDIFillColor;
2259 				pGS->eRasterOp=eGDIRasterOp;
2260 				pGS->aFont=aGDIFont;
2261 				pGS->aMapMode=aPictureMapMode;
2262 				pGS->aClipRect=aGDIClipRect;
2263 			}
2264 			break;
2265 
2266 			case META_POP_ACTION:
2267 			{
2268 				METGDIStackMember* pGS;
2269 
2270 				if( pGDIStack )
2271 				{
2272 					pGS=pGDIStack; pGDIStack=pGS->pSucc;
2273 					aGDILineColor=pGS->aLineColor;
2274 					aGDIFillColor=pGS->aFillColor;
2275 					eGDIRasterOp=pGS->eRasterOp;
2276 					aGDIFont=pGS->aFont;
2277 					if ( pGS->aClipRect != aGDIClipRect )
2278 						WriteClipRect( pGS->aClipRect );
2279 					aPictureMapMode=pGS->aMapMode;
2280 					delete pGS;
2281 				}
2282 			}
2283 			break;
2284 
2285 			case META_RASTEROP_ACTION:
2286 			{
2287 				eGDIRasterOp = ( (const MetaRasterOpAction*) pMA )->GetRasterOp();
2288 			}
2289 			break;
2290 
2291 			case META_TRANSPARENT_ACTION:
2292 			{
2293 				if( aGDIFillColor != Color( COL_TRANSPARENT ) )
2294 				{
2295 					METSetMix(eGDIRasterOp);
2296 					METSetColor(aGDIFillColor);
2297 					METSetBackgroundColor(aGDIFillColor);
2298 					METBeginPath(1);
2299 					METLine(( (const MetaTransparentAction*) pMA )->GetPolyPolygon());
2300 					METEndPath();
2301 					METFillPath(1);
2302 				}
2303 
2304 				if( aGDILineColor != Color( COL_TRANSPARENT ) )
2305 				{
2306 					METSetMix(eGDIRasterOp);
2307 					METSetColor(aGDILineColor);
2308 					METBeginPath(1);
2309 					METLine(( (const MetaTransparentAction*) pMA )->GetPolyPolygon());
2310 					METEndPath();
2311 					METOutlinePath(1);
2312 				}
2313 			}
2314 			break;
2315 
2316 			case META_FLOATTRANSPARENT_ACTION:
2317 			{
2318 				const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
2319 
2320 				GDIMetaFile		aTmpMtf( pA->GetGDIMetaFile() );
2321 				Point			aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
2322 				const Size		aSrcSize( aTmpMtf.GetPrefSize() );
2323 				const Point		aDestPt( pA->GetPoint() );
2324 				const Size		aDestSize( pA->GetSize() );
2325 				const double	fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
2326 				const double	fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
2327 				long			nMoveX, nMoveY;
2328 
2329 				if( fScaleX != 1.0 || fScaleY != 1.0 )
2330 				{
2331 					aTmpMtf.Scale( fScaleX, fScaleY );
2332 					aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2333 				}
2334 
2335 				nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
2336 
2337 				if( nMoveX || nMoveY )
2338 					aTmpMtf.Move( nMoveX, nMoveY );
2339 
2340 				WriteOrders( &aTmpMtf );
2341 			}
2342 			break;
2343 
2344 	  }
2345 
2346 	  nWrittenActions++;
2347 	  MayCallback();
2348 
2349 	  if( pMET->GetError() )
2350 		bStatus=sal_False;
2351 
2352 	  if( bStatus == sal_False )
2353 		break;
2354 	}
2355 }
2356 
WriteObjectEnvironmentGroup(const GDIMetaFile * pMTF)2357 void METWriter::WriteObjectEnvironmentGroup(const GDIMetaFile * pMTF)
2358 {
2359 	sal_uLong i, nId;
2360 
2361 	//--- Das Feld 'Begin Object Environment Group':
2362 	WriteFieldIntroducer(16,BegObjEnvMagic,0,0);
2363 	WriteFieldId(7);
2364 
2365 	//--- Das Feld 'Map Color Attribute Table':
2366 	WriteFieldIntroducer(22,MapColAtrMagic,0,0);
2367 	WriteBigEndianShort(0x000e);
2368 	*pMET << (sal_uInt8)0x0c << (sal_uInt8)0x02 << (sal_uInt8)0x84 << (sal_uInt8)0x00;
2369 	WriteFieldId(4);
2370 
2371 	//--- Das erste Feld 'Map Coded Font':
2372 	WriteFieldIntroducer(32,MapCodFntMagic,0,0);
2373 	WriteBigEndianShort(0x0018);
2374 	*pMET << (sal_uInt8)0x0c << (sal_uInt8)0x02 << (sal_uInt8)0x84 << (sal_uInt8)0x00;
2375 	*pMET << (sal_uInt8)0xff << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
2376 	*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00 << (sal_uInt8)0x00;
2377 	*pMET << (sal_uInt8)0x04 << (sal_uInt8)0x24 << (sal_uInt8)0x05 << (sal_uInt8)0x00;
2378 	*pMET << (sal_uInt8)0x06 << (sal_uInt8)0x20;
2379 	*pMET << (sal_uInt8)0x03 << (sal_uInt8)0x97 << (sal_uInt8)0x01 << (sal_uInt8)0xb5;
2380 
2381 	//--- Die weiteren Felder 'Map Coded Font':
2382 	CreateChrSets(pMTF);
2383 	WriteChrSets();
2384 
2385 	//--- Die Felder 'Map Data Resource':
2386 	nId=nActBitmapId;
2387 	for (i=0; i<nNumberOfBitmaps; i++)
2388 	{
2389 		WriteFieldIntroducer(29,MapDatResMagic,0,0);
2390 		WriteBigEndianShort(0x0015);
2391 		*pMET << (sal_uInt8)0x0c << (sal_uInt8)0x02 << (sal_uInt8)0x84 << (sal_uInt8)0x00;
2392 		WriteFieldId(nId);
2393 		*pMET << (sal_uInt8)0x07 << (sal_uInt8)0x22 << (sal_uInt8)0x10;
2394 		*pMET << (sal_uInt32)nId;
2395 		nId++;
2396 	}
2397 
2398 	//--- Das Feld 'End Object Environment Group':
2399 	WriteFieldIntroducer(16,EndObjEnvMagic,0,0);
2400 	WriteFieldId(7);
2401 }
2402 
2403 
WriteGraphicsObject(const GDIMetaFile * pMTF)2404 void METWriter::WriteGraphicsObject(const GDIMetaFile * pMTF)
2405 {
2406 	sal_uLong nSegmentSize,nPos,nDataFieldsStartPos;
2407 
2408 	if( bStatus==sal_False )
2409 		return;
2410 
2411 	//--- Das Feld 'Begin Graphics Object':
2412 	WriteFieldIntroducer(16,BegGrfObjMagic,0,0);
2413 	WriteFieldId(7);
2414 
2415 	// Map Color Attribute Table, Fonts und anderes:
2416 	WriteObjectEnvironmentGroup(pMTF);
2417 
2418 	//--- Das Feld 'Graphics Data Descriptor':
2419 	WriteDataDescriptor(pMTF);
2420 
2421 	// Zaehler fuer Data Fields initialisieren:
2422 	nNumberOfDataFields=0;
2423 
2424 	// Und Position des ersten Data Fields merken:
2425 	nDataFieldsStartPos=pMET->Tell();
2426 
2427 	//--- Anfang des ersten Feldes 'Graphics Data'
2428 	WriteFieldIntroducer(0,DatGrfObjMagic,0,0);
2429 	nNumberOfDataFields++;
2430 
2431 	// Nun schreiben wir zunaechst den Kopf des Segments:
2432 	*pMET << (sal_uInt8)0x70 << (sal_uInt8)0x0e << (sal_uInt32)0;
2433 	*pMET << (sal_uInt8)0x70 << (sal_uInt8)0x10; // Flags
2434 	*pMET << (sal_uInt16)0; // Lo-Wort der Laenge der Segementdaten (Big Endian)
2435 	*pMET << (sal_uInt32)0;  // Reserved
2436 	*pMET << (sal_uInt16)0; // Hi-Wort der Laenge der Segementdaten (Big Endian) (Ohh Ohh OS2)
2437 	// Anmerkung: die richtige Daten-Laenge schreiben wir weiter unten nochmal
2438 
2439 	// Jetzt werden alle Orders rausgeschrieben:
2440 	// (wobei die Sache ggf. in mehrere 'Graphics Data Fields' aufgeteilt
2441 	// wird, per Methode WillWriteOrder(..))
2442 	WriteOrders(pMTF);
2443 
2444 	//--- Das letzte Feld 'Graphic Data' beenden:
2445 	UpdateFieldSize();
2446 
2447 	//--- Und schliesslich die Segmentgroesse richtigstellen:
2448 	nPos=pMET->Tell();
2449 	nSegmentSize=nPos-nDataFieldsStartPos;
2450 	nSegmentSize-=nNumberOfDataFields*8; // Structured Field Introducers zaehlen nicht mit
2451 	pMET->Seek(nDataFieldsStartPos+16); // Zum Lo-Wort der Segmentgroesse seeken
2452 	WriteBigEndianShort((sal_uInt16)(nSegmentSize&0x0000ffff)); // Und schreiben
2453 	pMET->Seek(nDataFieldsStartPos+22); // Zum Hi-Wort der Segmentgroesse seeken
2454 	WriteBigEndianShort((sal_uInt16)(nSegmentSize>>16)); // Und schreiben
2455 	pMET->Seek(nPos); // Zurueck zur Tagesordnung
2456 
2457 	//--- Das Feld 'End Graphic Objects':
2458 	WriteFieldIntroducer(16,EndGrfObjMagic,0,0);
2459 	WriteFieldId(7);
2460 
2461 	if( pMET->GetError() )
2462 		bStatus=sal_False;
2463 }
2464 
2465 
WriteResourceGroup(const GDIMetaFile * pMTF)2466 void METWriter::WriteResourceGroup(const GDIMetaFile * pMTF)
2467 {
2468 	if( bStatus==sal_False )
2469 		return;
2470 
2471 	//--- Das Feld 'Begin Resource Group':
2472 	WriteFieldIntroducer(16,BegResGrpMagic,0,0);
2473 	WriteFieldId(2);
2474 
2475 	//--- Der Inhalt:
2476 	WriteColorAttributeTable();
2477 	nActBitmapId=0x77777700;
2478 	WriteImageObjects(pMTF);
2479 	nActBitmapId=0x77777700;
2480 	WriteGraphicsObject(pMTF);
2481 
2482 	//--- Das Feld 'End Resource Group':
2483 	WriteFieldIntroducer(16,EndResGrpMagic,0,0);
2484 	WriteFieldId(2);
2485 
2486 	if( pMET->GetError() )
2487 		bStatus=sal_False;
2488 }
2489 
2490 
WriteDocument(const GDIMetaFile * pMTF)2491 void METWriter::WriteDocument(const GDIMetaFile * pMTF)
2492 {
2493 	if( bStatus==sal_False )
2494 		return;
2495 
2496 	//--- Das Feld 'Begin Document':
2497 	WriteFieldIntroducer(0,BegDocumnMagic,0,0);
2498 	WriteFieldId(1);
2499 	*pMET << (sal_uInt8)0x00 << (sal_uInt8)0x00;
2500 	*pMET << (sal_uInt8)0x05 << (sal_uInt8)0x18 << (sal_uInt8)0x03 << (sal_uInt8)0x0c << (sal_uInt8)0x00;
2501 	*pMET << (sal_uInt8)0x06 << (sal_uInt8)0x01 << (sal_uInt8)0x03 << (sal_uInt8)0xd4 << (sal_uInt8)0x03 << (sal_uInt8)0x52;
2502 	*pMET << (sal_uInt8)0x03 << (sal_uInt8)0x65 << (sal_uInt8)0x00;
2503 	UpdateFieldSize();
2504 
2505 	//--- Der Inhalt:
2506 	WriteResourceGroup(pMTF);
2507 
2508 	//--- Das Feld 'End Document':
2509 	WriteFieldIntroducer(16,EndDocumnMagic,0,0);
2510 	WriteFieldId(1);
2511 
2512 	if( pMET->GetError() )
2513 		bStatus=sal_False;
2514 }
2515 
WriteMET(const GDIMetaFile & rMTF,SvStream & rTargetStream,FilterConfigItem * pFilterConfigItem)2516 sal_Bool METWriter::WriteMET( const GDIMetaFile& rMTF, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem )
2517 {
2518 	if ( pFilterConfigItem )
2519 	{
2520 		xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
2521 		if ( xStatusIndicator.is() )
2522 		{
2523 			rtl::OUString aMsg;
2524 			xStatusIndicator->start( aMsg, 100 );
2525 		}
2526 	}
2527 
2528 	METChrSet*			pCS;
2529 	METGDIStackMember*	pGS;
2530 
2531 	bStatus=sal_True;
2532 	nLastPercent=0;
2533 
2534 	pMET=&rTargetStream;
2535 	pMET->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2536 
2537 	aPictureRect = Rectangle( Point(), rMTF.GetPrefSize() );
2538 	aTargetMapMode = aPictureMapMode = rMTF.GetPrefMapMode();
2539 
2540 	aGDILineColor=Color( COL_BLACK );
2541 	aGDIFillColor=Color( COL_WHITE );
2542 	eGDIRasterOp=ROP_OVERPAINT;
2543 	aGDIFont=Font();
2544 	aGDIMapMode=MapMode();
2545 	aGDIClipRect=Rectangle();
2546 	pGDIStack=NULL;
2547 	aMETColor=Color(COL_BLACK);
2548 	aMETBackgroundColor=Color(COL_WHITE);
2549 	eMETMix=ROP_OVERPAINT;
2550 	nMETStrokeLineWidth=1;
2551 	aMETChrCellSize=Size(0,0);
2552 	nMETChrAngle=0;
2553 	nMETChrSet=0x00;
2554 	pChrSetList=NULL;
2555 	nNextChrSetId=1;
2556 	nNumberOfActions=0;
2557 	nNumberOfBitmaps=0;
2558 	nWrittenActions=0;
2559 	nWrittenBitmaps=0;
2560 	nActBitmapPercent=0;
2561 
2562 	CountActionsAndBitmaps(&rMTF);
2563 
2564 	WriteDocument(&rMTF);
2565 
2566 	while( pChrSetList )
2567 	{
2568 		pCS=pChrSetList;
2569 		pChrSetList=pCS->pSucc;
2570 		delete pCS;
2571 	}
2572 
2573 	while( pGDIStack )
2574 	{
2575 		pGS=pGDIStack;
2576 		pGDIStack=pGS->pSucc;
2577 		delete pGS;
2578 	}
2579 
2580 	if ( xStatusIndicator.is() )
2581 		xStatusIndicator->end();
2582 
2583 	return bStatus;
2584 }
2585 
2586 //================== GraphicExport - die exportierte Funktion ================
2587 
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)2588 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool )
2589 {
2590     METWriter aMETWriter;
2591 
2592     // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
2593     GDIMetaFile aMetafile(rGraphic.GetGDIMetaFile());
2594 
2595     if(usesClipActions(aMetafile))
2596     {
2597         // #121267# It is necessary to prepare the metafile since the export does *not* support
2598         // clip regions. This tooling method clips the geometry content of the metafile internally
2599         // against it's own clip regions, so that the export is safe to ignore clip regions
2600         clipMetafileContentAgainstOwnRegions(aMetafile);
2601     }
2602 
2603     // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
2604     return aMETWriter.WriteMET( aMetafile, rStream, pFilterConfigItem );
2605 }
2606