xref: /AOO41X/main/filter/source/graphicfilter/eos2met/eos2met.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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