Bump version to 5.0-14
[LibreOffice.git] / filter / source / graphicfilter / eos2met / eos2met.cxx
blob3acff99057c51463f7621980e755ce83df2fc2ee
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/fltcall.hxx>
22 #include <math.h>
23 #include <tools/stream.hxx>
24 #include <tools/bigint.hxx>
25 #include <vcl/metaact.hxx>
26 #include <vcl/salbtype.hxx>
27 #include <tools/poly.hxx>
28 #include <tools/fract.hxx>
29 #include <vcl/graph.hxx>
30 #include <vcl/gradient.hxx>
31 #include <vcl/hatch.hxx>
32 #include <vcl/metric.hxx>
33 #include <vcl/font.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <svl/solar.hrc>
38 #include <vcl/gdimetafiletools.hxx>
39 #include <vcl/dibtools.hxx>
40 #include <boost/scoped_array.hpp>
42 // -----------------------------Field Types-------------------------------
44 #define BegDocumnMagic 0xA8A8 /* Begin Document */
45 #define EndDocumnMagic 0xA8A9 /* End Document */
47 #define BegResGrpMagic 0xC6A8 /* Begin Resource Group */
48 #define EndResGrpMagic 0xC6A9 /* End Resource Group */
50 #define BegColAtrMagic 0x77A8 /* Begin Color Attribute Table */
51 #define EndColAtrMagic 0x77A9 /* End Color Attribute Table */
52 #define BlkColAtrMagic 0x77B0 /* Color Attribute Table */
53 #define MapColAtrMagic 0x77AB /* Map Color Attribute Table */
55 #define BegImgObjMagic 0xFBA8 /* Begin Image Object */
56 #define EndImgObjMagic 0xFBA9 /* End Image Object */
57 #define DscImgObjMagic 0xFBA6 /* Image Data Descriptor */
58 #define DatImgObjMagic 0xFBEE /* Image Picture Data */
60 #define BegObjEnvMagic 0xC7A8 /* Begin Object Environment Group */
61 #define EndObjEnvMagic 0xC7A9 /* End Object Environment Group */
63 #define BegGrfObjMagic 0xBBA8 /* Begin Graphics Object */
64 #define EndGrfObjMagic 0xBBA9 /* End Graphics Object */
65 #define DscGrfObjMagic 0xBBA6 /* Graphics Data Descritor */
66 #define DatGrfObjMagic 0xBBEE /* Graphics Data */
68 #define MapCodFntMagic 0x8AAB /* Map Coded Font */
69 #define MapDatResMagic 0xC3AB /* Map Data Resource */
71 // Struktur des Metafiles
72 // BegDocumn
73 // BegResGrp
74 // BegColAtr
75 // BlkColAtr
76 // EndColAtr
77 // BegImgObj[0..n]
78 // BegResGrp[]
79 // BegColAtr[]
80 // BlkColAtr
81 // EndColAtr
82 // EndResGrp
83 // BegObjEnv[]
84 // MapColAtr
85 // EndObjEnv
86 // DscImgObj
87 // DatImgOb1
88 // DatImgOb2[1..n]
89 // EndImgObj
90 // BegGrfObj
91 // BegObjEnv[]
92 // MapColAtr
93 // MapCodFnt1
94 // MapCodFnt2[0..n]
95 // MapDatRes[0..n]
96 // EndObjEnv
97 // DscGrfObj
98 // DatGrfObj[0..n]
99 // EndGrfObj
100 // EndResGrp
101 // EndDocumn
103 //============================== METWriter ===================================
105 struct METChrSet
107 struct METChrSet * pSucc;
108 sal_uInt8 nSet;
109 OUString aName;
110 FontWeight eWeight;
113 struct METGDIStackMember
115 struct METGDIStackMember * pSucc;
116 Color aLineColor;
117 Color aFillColor;
118 RasterOp eRasterOp;
119 vcl::Font aFont;
120 MapMode aMapMode;
121 Rectangle aClipRect;
124 class METWriter
126 private:
128 bool bStatus;
129 sal_uInt32 nLastPercent; // with which number pCallback has been called the last time
130 SvStream* pMET;
131 Rectangle aPictureRect;
132 MapMode aPictureMapMode;
133 MapMode aTargetMapMode;
134 sal_uInt32 nActualFieldStartPos; // start position of the current 'Field'
135 sal_uInt32 nNumberOfDataFields; // number of commenced 'Graphcis Data Fields'
136 Color aGDILineColor;
137 Color aGDIFillColor;
138 RasterOp eGDIRasterOp;
139 vcl::Font aGDIFont;
140 MapMode aGDIMapMode; // currently ununsed!
141 Rectangle aGDIClipRect; // currently ununsed!
142 METGDIStackMember* pGDIStack;
143 Color aMETColor;
144 Color aMETBackgroundColor;
145 RasterOp eMETMix ;
146 long nMETStrokeLineWidth;
147 Size aMETChrCellSize;
148 short nMETChrAngle;
149 sal_uInt8 nMETChrSet;
150 METChrSet* pChrSetList; // list of Character-Sets
151 sal_uInt8 nNextChrSetId; // the first unused ChrSet-Id
152 sal_uInt32 nActBitmapId; // Field-Id of the next Bitmap
153 sal_uInt32 nNumberOfActions; // number of Actions in the GDIMetafile
154 sal_uInt32 nNumberOfBitmaps; // number of Bitmaps
155 sal_uInt32 nWrittenActions; // number of already processed actions during the writing of the orders
156 sal_uInt32 nWrittenBitmaps; // number of already written Bitmaps
157 sal_uInt32 nActBitmapPercent; // percentage of the next bitmap that's already written
159 ScopedVclPtr<VirtualDevice> apDummyVDev;
160 VclPtr<OutputDevice> pCompDev;
162 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
164 void MayCallback();
165 // calculates a percentage based on the 5 parameters above and then does a
166 // Callback as the case may be. Sets bStatus to sal_False if the user wants to cancel
168 void CountActionsAndBitmaps(const GDIMetaFile * pMTF);
169 // Counts the bitmaps and actions (nNumberOfActions and nNumberOfBitmaps have to
170 // be set to 0 at the beginning, since this method is recursive)
172 void WriteBigEndianShort(sal_uInt16 nWord);
173 void WriteBigEndianLong(sal_uInt32 nLong);
175 void WritePoint(Point aPt);
176 void WriteClipRect( const Rectangle& rRect );
177 void WriteFieldIntroducer(sal_uInt16 nFieldSize, sal_uInt16 nFieldType,
178 sal_uInt8 nFlags, sal_uInt16 nSegSeqNum);
179 void UpdateFieldSize();
181 void WriteFieldId(sal_uInt32 nId);
183 void CreateChrSets(const GDIMetaFile * pMTF);
184 void CreateChrSet(const vcl::Font & rFont);
185 void WriteChrSets();
186 sal_uInt8 FindChrSet(const vcl::Font & rFont);
188 void WriteColorAttributeTable(sal_uInt32 nFieldId=4, BitmapPalette* pPalette=NULL,
189 sal_uInt8 nBasePartFlags=0x40, sal_uInt8 nBasePartLCTID=0);
191 void WriteImageObject(const Bitmap & rBitmap);
192 void WriteImageObjects(const GDIMetaFile * pMTF);
194 void WriteDataDescriptor(const GDIMetaFile * pMTF);
196 void WillWriteOrder(sal_uInt32 nNextOrderMaximumLength);
198 void METSetAndPushLineInfo( const LineInfo& rLineInfo );
199 void METPopLineInfo( const LineInfo& rLineInfo );
200 void METBitBlt(Point aPt, Size aSize, const Size& rSizePixel);
201 void METBeginArea(bool bBoundaryLine);
202 void METEndArea();
203 void METBeginPath(sal_uInt32 nPathId);
204 void METEndPath();
205 void METFillPath(sal_uInt32 nPathId);
206 void METOutlinePath(sal_uInt32 nPathId);
207 void METCloseFigure();
208 void METMove(Point aPt);
209 void METLine(Point aPt1, Point aPt2);
210 void METLine(const Polygon & rPolygon);
211 void METLine(const tools::PolyPolygon & rPolyPolygon);
212 void METLineAtCurPos(Point aPt);
213 void METBox(bool bFill, bool bBoundary,
214 const Rectangle& rRect, sal_uInt32 nHAxis, sal_uInt32 nVAxis);
215 void METFullArc(Point aCenter, double fMultiplier);
216 void METPartialArcAtCurPos(Point aCenter, double fMultiplier,
217 double fStartAngle, double fSweepAngle);
218 void METChrStr(Point aPt, const OUString& aStr);
219 void METSetArcParams(sal_Int32 nP, sal_Int32 nQ, sal_Int32 nR, sal_Int32 nS);
220 void METSetColor(Color aColor);
221 void METSetBackgroundColor(Color aColor);
222 void METSetMix(RasterOp eROP);
223 void METSetChrCellSize(Size aSize);
224 void METSetChrAngle(short nAngle);
225 void METSetChrSet(sal_uInt8 nSet);
227 void WriteOrders(const GDIMetaFile * pMTF);
229 void WriteObjectEnvironmentGroup(const GDIMetaFile * pMTF);
231 void WriteGraphicsObject(const GDIMetaFile * pMTF);
233 void WriteResourceGroup(const GDIMetaFile * pMTF);
235 void WriteDocument(const GDIMetaFile * pMTF);
237 public:
239 METWriter()
240 : bStatus(false)
241 , nLastPercent( 0 )
242 , pMET(NULL)
243 , nActualFieldStartPos( 0 )
244 , nNumberOfDataFields( 0 )
245 , eGDIRasterOp( ROP_OVERPAINT )
246 , pGDIStack(NULL)
247 , eMETMix( ROP_OVERPAINT )
248 , nMETStrokeLineWidth(0)
249 , nMETChrAngle(0)
250 , nMETChrSet( 0 )
251 , pChrSetList(NULL)
252 , nNextChrSetId( 0 )
253 , nActBitmapId( 0 )
254 , nNumberOfActions( 0 )
255 , nNumberOfBitmaps( 0 )
256 , nWrittenActions( 0 )
257 , nWrittenBitmaps( 0 )
258 , nActBitmapPercent( 0 )
259 , pCompDev(NULL)
261 pCompDev = reinterpret_cast< OutputDevice* >( Application::GetAppWindow() );
262 if( !pCompDev )
264 apDummyVDev.disposeAndClear();
265 apDummyVDev.reset( VclPtr<VirtualDevice>::Create() );
266 pCompDev = apDummyVDev.get();
270 bool WriteMET( const GDIMetaFile & rMTF, SvStream & rTargetStream,
271 FilterConfigItem* pConfigItem );
275 //========================== Methods of METWriter ==========================
277 void METWriter::MayCallback()
279 if ( xStatusIndicator.is() )
281 sal_uInt32 nPercent;
282 nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
283 *100/((nNumberOfBitmaps<<14)+nNumberOfActions);
285 if (nPercent>=nLastPercent+3)
287 nLastPercent = nPercent;
288 if ( nPercent <= 100 )
289 xStatusIndicator->setValue( nPercent );
294 void METWriter::WriteClipRect( const Rectangle& rRect )
296 aGDIClipRect = rRect;
297 sal_uInt32 nPathId = ( rRect.IsEmpty() ) ? 0 : 1;
298 if ( nPathId )
300 Polygon aPoly( rRect );
301 METBeginPath( nPathId );
302 METLine( aPoly );
303 METEndPath();
305 WillWriteOrder(8);
306 pMET->WriteUChar( 0xb4 ).WriteUChar( 6 )
307 .WriteUChar( 0x00 ).WriteUChar( 0 ).WriteUInt32( nPathId );
310 void METWriter::CountActionsAndBitmaps(const GDIMetaFile * pMTF)
312 for( size_t nAction = 0, nActionCount=pMTF->GetActionSize(); nAction < nActionCount; nAction++ )
314 const MetaAction* pMA = pMTF->GetAction(nAction);
316 switch (pMA->GetType())
318 case MetaActionType::EPS :
320 const GDIMetaFile aGDIMetaFile( static_cast<const MetaEPSAction*>(pMA)->GetSubstitute() );
321 size_t nCount = aGDIMetaFile.GetActionSize();
322 size_t i;
323 for ( i = 0; i < nCount; i++ )
324 if ( ((const MetaAction*)aGDIMetaFile.GetAction( i ))->GetType() == MetaActionType::BMPSCALE )
325 break;
326 if ( i == nCount)
327 break;
329 case MetaActionType::BMP:
330 case MetaActionType::BMPSCALE:
331 case MetaActionType::BMPSCALEPART:
332 case MetaActionType::BMPEX:
333 case MetaActionType::BMPEXSCALE:
334 case MetaActionType::BMPEXSCALEPART:
335 nNumberOfBitmaps++;
336 break;
337 default: break;
339 nNumberOfActions++;
344 void METWriter::WriteBigEndianShort(sal_uInt16 nWord)
346 pMET->WriteUChar( nWord>>8 ).WriteUChar( nWord&0x00ff );
350 void METWriter::WriteBigEndianLong(sal_uInt32 nLong)
352 WriteBigEndianShort((sal_uInt16)(nLong>>16));
353 WriteBigEndianShort((sal_uInt16)(nLong&0x0000ffff));
357 void METWriter::WritePoint(Point aPt)
359 Point aNewPt = OutputDevice::LogicToLogic( aPt, aPictureMapMode, aTargetMapMode );
361 pMET->WriteInt32( aNewPt.X() - aPictureRect.Left() )
362 .WriteInt32( aPictureRect.Bottom() - aNewPt.Y() );
366 void METWriter::WriteFieldIntroducer(sal_uInt16 nFieldSize, sal_uInt16 nFieldType,
367 sal_uInt8 nFlags, sal_uInt16 nSegSeqNum)
369 nActualFieldStartPos=pMET->Tell();
370 WriteBigEndianShort(nFieldSize);
371 pMET->WriteUChar( 0xd3 ).WriteUInt16( nFieldType ).WriteUChar( nFlags ).WriteUInt16( nSegSeqNum );
375 void METWriter::UpdateFieldSize()
377 sal_uInt32 nPos;
379 nPos=pMET->Tell();
380 pMET->Seek(nActualFieldStartPos);
381 WriteBigEndianShort((sal_uInt16)(nPos-nActualFieldStartPos));
382 pMET->Seek(nPos);
386 void METWriter::WriteFieldId(sal_uInt32 nId)
388 sal_uInt8 nbyte;
389 short i;
391 for (i=1; i<=8; i++) {
392 nbyte= '0' + (sal_uInt8)((nId >> (32-i*4)) & 0x0f);
393 pMET->WriteUChar( nbyte );
398 void METWriter::CreateChrSets(const GDIMetaFile * pMTF)
400 size_t nAction, nActionCount;
402 if (!bStatus)
403 return;
405 nActionCount = pMTF->GetActionSize();
407 for (nAction = 0; nAction < nActionCount; nAction++)
409 const MetaAction * pMA = pMTF->GetAction(nAction);
411 switch (pMA->GetType())
413 case MetaActionType::FONT:
415 const MetaFontAction* pA = static_cast<const MetaFontAction*>(pMA);
416 CreateChrSet( pA->GetFont() );
418 break;
419 default: break;
425 void METWriter::CreateChrSet(const vcl::Font & rFont)
427 METChrSet * pCS;
429 if ( FindChrSet( rFont ) == 0 )
431 pCS = new METChrSet;
432 pCS->pSucc = pChrSetList; pChrSetList=pCS;
433 pCS->nSet = nNextChrSetId++;
434 pCS->aName = rFont.GetName();
435 pCS->eWeight = rFont.GetWeight();
440 sal_uInt8 METWriter::FindChrSet(const vcl::Font & rFont)
442 METChrSet* pCS;
444 for (pCS=pChrSetList; pCS!=NULL; pCS=pCS->pSucc)
446 if (pCS->aName==rFont.GetName() && pCS->eWeight==rFont.GetWeight() )
447 return pCS->nSet;
450 return 0;
454 void METWriter::WriteChrSets()
456 sal_uInt16 i;
457 char c = 0;
458 METChrSet * pCS;
459 sal_uInt8 nbyte;
461 for (pCS=pChrSetList; pCS!=NULL; pCS=pCS->pSucc)
464 WriteFieldIntroducer(0x58,MapCodFntMagic,0,0);
466 WriteBigEndianShort(0x0050);
468 pMET->WriteUChar( 0x0c ).WriteUChar( 0x02 ).WriteUChar( 0x84 ).WriteUChar( 0x00 );
469 pMET->WriteUChar( 0xa4 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x01 );
470 pMET->WriteUChar( 0x01 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
472 pMET->WriteUChar( 0x04 ).WriteUChar( 0x24 ).WriteUChar( 0x05 ).WriteUChar( pCS->nSet );
474 pMET->WriteUChar( 0x14 ).WriteUChar( 0x1f );
475 switch (pCS->eWeight)
477 case WEIGHT_THIN: nbyte=1; break;
478 case WEIGHT_ULTRALIGHT: nbyte=2; break;
479 case WEIGHT_LIGHT: nbyte=3; break;
480 case WEIGHT_SEMILIGHT: nbyte=4; break;
481 case WEIGHT_NORMAL: nbyte=5; break;
482 case WEIGHT_SEMIBOLD: nbyte=6; break;
483 case WEIGHT_BOLD: nbyte=7; break;
484 case WEIGHT_ULTRABOLD: nbyte=8; break;
485 case WEIGHT_BLACK: nbyte=9; break;
486 default: nbyte=5;
488 pMET->WriteUChar( nbyte );
489 pMET->WriteUChar( 0x05 );
490 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
491 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
492 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
493 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x0c );
495 pMET->WriteUChar( 0x06 ).WriteUChar( 0x20 ).WriteUChar( 0x03 ).WriteUChar( 0xd4 );
496 pMET->WriteUChar( 0x03 ).WriteUChar( 0x52 );
498 pMET->WriteUChar( 0x24 ).WriteUChar( 0x02 ).WriteUChar( 0x08 ).WriteUChar( 0x00 );
499 OString n(OUStringToOString(pCS->aName,
500 osl_getThreadTextEncoding()));
501 for (i=0; i<32; i++)
503 if ( i == 0 || c != 0 )
504 c = n[i];
505 pMET->WriteChar( c );
511 void METWriter::WriteColorAttributeTable(sal_uInt32 nFieldId, BitmapPalette* pPalette, sal_uInt8 nBasePartFlags, sal_uInt8 nBasePartLCTID)
513 sal_uInt16 nIndex,nNumI,i;
515 if (!bStatus) return;
517 //--- The Field 'Begin Color Attribute Table':
518 WriteFieldIntroducer(16,BegColAtrMagic,0,0);
519 WriteFieldId(nFieldId);
521 //--- The Field 'Color Attribute Table':
522 WriteFieldIntroducer(0,BlkColAtrMagic,0,0);
523 pMET->WriteUChar( nBasePartFlags ).WriteUChar( 0x00 ).WriteUChar( nBasePartLCTID ); // 'Base Part'
524 if (pPalette!=NULL)
526 nIndex=0;
527 while (nIndex<pPalette->GetEntryCount())
529 nNumI=pPalette->GetEntryCount()-nIndex;
530 if (nNumI>81) nNumI=81;
531 pMET->WriteUChar( (11+nNumI*3) ); // length of the parameter
532 pMET->WriteUChar( 1 ).WriteUChar( 0 ).WriteUChar( 1 ); // typ: element list, Reserved, Format: RGB
533 pMET->WriteUChar( 0 ); WriteBigEndianShort(nIndex); // start-Index (3 Bytes)
534 pMET->WriteUChar( 8 ).WriteUChar( 8 ).WriteUChar( 8 ); // Bits per component R,G,B
535 pMET->WriteUChar( 3 ); // number of bytes per entry
536 for (i=0; i<nNumI; i++)
538 const BitmapColor& rCol = (*pPalette)[ nIndex ];
540 pMET->WriteUChar( rCol.GetRed() );
541 pMET->WriteUChar( rCol.GetGreen() );
542 pMET->WriteUChar( rCol.GetBlue() );
543 nIndex++;
547 else
549 // 'Trible Generating'
550 pMET->WriteUChar( 0x0a ).WriteUChar( 0x02 ).WriteUChar( 0x00 ).WriteUChar( 0x01 ).WriteUChar( 0x00 );
551 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x08 ).WriteUChar( 0x08 ).WriteUChar( 0x08 );
553 UpdateFieldSize();
555 //--- The Field 'End Color Attribute Table':
556 WriteFieldIntroducer(16,EndColAtrMagic,0,0);
557 WriteFieldId(nFieldId);
559 if (pMET->GetError())
560 bStatus=false;
564 void METWriter::WriteImageObject(const Bitmap & rBitmap)
566 SvMemoryStream aTemp(0x00010000,0x00010000);
567 sal_uInt32 nWidth,nHeight,nResX,nResY;
568 sal_uInt32 nBytesPerLine,i,j,nNumColors,ny,nLines;
569 sal_uInt32 nActColMapId;
570 sal_uInt16 nBitsPerPixel;
571 sal_uInt8 nbyte;
573 if (!bStatus)
574 return;
576 nActColMapId=((nActBitmapId>>24)&0x000000ff) | ((nActBitmapId>> 8)&0x0000ff00) |
577 ((nActBitmapId<< 8)&0x00ff0000) | ((nActBitmapId<<24)&0xff000000);
579 //--- The Field 'Begin Image Object':
580 WriteFieldIntroducer(16,BegImgObjMagic,0,0);
581 WriteFieldId(nActBitmapId);
583 // generate Windows-BMP file
584 WriteDIB(rBitmap, aTemp, false, true);
586 // read header of the Windows-BMP file:
587 aTemp.SetEndian(SvStreamEndian::LITTLE);
588 aTemp.Seek(18);
589 aTemp.ReadUInt32( nWidth ).ReadUInt32( nHeight );
590 aTemp.SeekRel(2);
591 aTemp.ReadUInt16( nBitsPerPixel );
592 aTemp.SeekRel(8);
593 aTemp.ReadUInt32( nResX ).ReadUInt32( nResY );
594 aTemp.SeekRel(8);
596 nNumColors=1<<nBitsPerPixel;
597 nBytesPerLine=((nWidth*nBitsPerPixel+0x0000001f) & 0xffffffe0 ) >> 3;
599 // read color palette as the case may be and write it to the MET file:
600 if (nBitsPerPixel<=8)
602 BitmapPalette aPal( (sal_uInt16) nNumColors );
603 sal_uInt8 nr,ng,nb;
605 for (i=0; i<nNumColors; i++)
607 aTemp.ReadUChar( nb ).ReadUChar( ng ).ReadUChar( nr ); aTemp.SeekRel(1);
608 aPal[ (sal_uInt16) i ] = BitmapColor( nr, ng, nb );
611 //--- The Field 'Begin Resource Group':
612 WriteFieldIntroducer(16,BegResGrpMagic,0,0);
613 WriteFieldId(nActColMapId);
615 //--- writer color table:
616 WriteColorAttributeTable(nActColMapId,&aPal,0,1);
618 //--- The Field 'End Resource Group':
619 WriteFieldIntroducer(16,EndResGrpMagic,0,0);
620 WriteFieldId(nActColMapId);
622 //--- The Field 'Begin Object Environment Group':
623 WriteFieldIntroducer(16,BegObjEnvMagic,0,0);
624 WriteFieldId(nActBitmapId);
626 //--- The Field 'Map Color Attribute Table':
627 WriteFieldIntroducer(26,MapColAtrMagic,0,0);
628 WriteBigEndianShort(0x0012);
629 pMET->WriteUChar( 0x0c ).WriteUChar( 0x02 ).WriteUChar( 0x84 ).WriteUChar( 0x00 );
630 WriteFieldId(nActColMapId);
631 pMET->WriteUChar( 0x04 ).WriteUChar( 0x24 ).WriteUChar( 0x07 ).WriteUChar( 0x01 );
633 //--- The Field 'End Object Environment Group':
634 WriteFieldIntroducer(16,EndObjEnvMagic,0,0);
635 WriteFieldId(nActBitmapId);
638 //--- The Field 'Image Data Descriptor':
639 WriteFieldIntroducer(17,DscImgObjMagic,0,0);
640 pMET->WriteUChar( 0x01 ); // Unit of measure: tens of centimeters
641 WriteBigEndianShort((sal_uInt16)nResX);
642 WriteBigEndianShort((sal_uInt16)nResY);
643 WriteBigEndianShort((sal_uInt16)nWidth);
644 WriteBigEndianShort((sal_uInt16)nHeight);
646 //--- The first Field 'Image Picture Data':
647 WriteFieldIntroducer(0,DatImgObjMagic,0,0);
649 // Begin Segment:
650 pMET->WriteUChar( 0x70 ).WriteUChar( 0x00 );
652 // Begin Image Content:
653 pMET->WriteUChar( 0x91 ).WriteUChar( 0x01 ).WriteUChar( 0xff );
655 // Image Size:
656 pMET->WriteUChar( 0x94 ).WriteUChar( 0x09 ).WriteUChar( 0x02 );
657 pMET->WriteUInt16( 0 ).WriteUInt16( 0 );
658 WriteBigEndianShort((sal_uInt16)nHeight);
659 WriteBigEndianShort((sal_uInt16)nWidth);
661 // Image Encoding:
662 pMET->WriteUChar( 0x95 ).WriteUChar( 0x02 ).WriteUChar( 0x03 ).WriteUChar( 0x03 );
664 // Image IDE-Size:
665 pMET->WriteUChar( 0x96 ).WriteUChar( 0x01 ).WriteUChar( nBitsPerPixel );
667 if (nBitsPerPixel<=8) {
668 // Image LUT-ID
669 pMET->WriteUChar( 0x97 ).WriteUChar( 0x01 ).WriteUChar( 0x01 );
671 else {
672 // IDE Structure
673 pMET->WriteUChar( 0x9b ).WriteUChar( 0x08 ).WriteUChar( 0x00 ).WriteUChar( 0x01 );
674 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x08 );
675 pMET->WriteUChar( 0x08 ).WriteUChar( 0x08 );
678 boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[nBytesPerLine]);
679 ny=0;
680 while (ny<nHeight) {
682 // finalize the previous field 'Image Picture Data':
683 UpdateFieldSize();
685 // and start a new field 'Image Picture Data':
686 WriteFieldIntroducer(0,DatImgObjMagic,0,0);
688 // read and write several Scanlines:
689 nLines=nHeight-ny;
690 if (nLines*nBytesPerLine>30000) nLines=30000/nBytesPerLine;
691 if (nLines<1) nLines=1;
692 WriteBigEndianShort(0xfe92);
693 WriteBigEndianShort((sal_uInt16)(nLines*nBytesPerLine));
694 for (i=0; i<nLines; i++) {
695 aTemp.Read(pBuf.get(),nBytesPerLine);
696 if (nBitsPerPixel==24) {
697 for (j=2; j<nBytesPerLine; j+=3) {
698 nbyte=pBuf[j]; pBuf[j]=pBuf[j-2]; pBuf[j-2]=nbyte;
701 pMET->Write(pBuf.get(),nBytesPerLine);
702 ny++;
704 if (aTemp.GetError() || pMET->GetError()) bStatus=false;
705 nActBitmapPercent=(ny+1)*100/nHeight;
706 MayCallback();
707 if (!bStatus) return;
709 pBuf.reset();
711 // End Image Content:
712 pMET->WriteUChar( 0x93 ).WriteUChar( 0x00 );
714 // End Segment:
715 pMET->WriteUChar( 0x71 ).WriteUChar( 0x00 );
717 // finalize the last field 'Image Picture Data':
718 UpdateFieldSize();
720 //--- The Field 'End Image Object':
721 WriteFieldIntroducer(16,EndImgObjMagic,0,0);
722 WriteFieldId(nActBitmapId);
724 // increase Ids:
725 nActBitmapId++;
727 // count Bitmaps:
728 nWrittenBitmaps++;
729 nActBitmapPercent=0;
731 if (pMET->GetError()) bStatus=false;
735 void METWriter::WriteImageObjects(const GDIMetaFile * pMTF)
737 if (!bStatus)
738 return;
740 for ( size_t nAction = 0, nActionCount = pMTF->GetActionSize(); nAction < nActionCount; nAction++)
742 const MetaAction* pMA = pMTF->GetAction(nAction);
744 switch (pMA->GetType())
746 case MetaActionType::BMP:
748 METSetMix( eGDIRasterOp );
749 WriteImageObject( static_cast<const MetaBmpAction*>(pMA)->GetBitmap() );
751 break;
753 case MetaActionType::BMPSCALE:
755 METSetMix( eGDIRasterOp );
756 WriteImageObject( static_cast<const MetaBmpScaleAction*>(pMA)->GetBitmap() );
758 break;
760 case MetaActionType::BMPSCALEPART:
762 METSetMix( eGDIRasterOp );
763 WriteImageObject( static_cast<const MetaBmpScalePartAction*>(pMA)->GetBitmap() );
765 break;
767 case MetaActionType::BMPEX:
769 METSetMix( eGDIRasterOp );
770 WriteImageObject( Graphic( static_cast<const MetaBmpExAction*>(pMA)->GetBitmapEx() ).GetBitmap() );
772 break;
774 case MetaActionType::BMPEXSCALE:
776 METSetMix( eGDIRasterOp );
777 WriteImageObject( Graphic( static_cast<const MetaBmpExScaleAction*>(pMA)->GetBitmapEx() ).GetBitmap() );
779 break;
781 case MetaActionType::BMPEXSCALEPART:
783 METSetMix( eGDIRasterOp );
784 WriteImageObject( Graphic( static_cast<const MetaBmpExScalePartAction*>(pMA)->GetBitmapEx() ).GetBitmap() );
786 break;
788 case MetaActionType::EPS :
790 const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pMA);
791 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
793 size_t nCount = aGDIMetaFile.GetActionSize();
794 for ( size_t i = 0; i < nCount; i++ )
796 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
797 if ( pMetaAct->GetType() == MetaActionType::BMPSCALE )
799 const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pMetaAct);
800 METSetMix( eGDIRasterOp );
801 WriteImageObject( pBmpScaleAction->GetBitmap() );
802 break;
806 break;
807 default: break;
810 if (!bStatus)
811 break;
814 if (pMET->GetError())
815 bStatus=false;
818 void METWriter::WriteDataDescriptor(const GDIMetaFile *)
820 if (!bStatus)
821 return;
823 WriteFieldIntroducer(0,DscGrfObjMagic,0,0);
826 // The following is the OS2 original documentation and the associated implementation
829 // Parameters (all required and in this order)
831 // 0 0xF7 Specify GVM Subset
832 // 1 Length of following data 0x07
833 // 2 0xB0 drawing order subset
834 // 3-4 0x0000
835 // 5 0x23 Level 3.2
836 // 6 0x01 Version 1
837 // 7 Length of following field 0x01
838 // 8 Coordinate types in data
839 // 0x04Intel16
840 // 0x05Intel32
841 pMET->WriteUChar( 0xf7 ).WriteUChar( 0x07 ).WriteUChar( 0xb0 ).WriteUChar( 0x00 )
842 .WriteUChar( 0x00 ).WriteUChar( 0x23 ).WriteUChar( 0x01 ).WriteUChar( 0x01 )
843 .WriteUChar( 0x05 );
845 // 0 0xF6 Set Picture Descriptor
846 // 1 Length of following data
847 // 2 Flags
848 // 0 B'0' Picture in 2D
849 // 1 Picture Dimensions
850 // B'0' Not absolute (PU_ARBITRARY PS)
851 // B'1' Absolute (example: PU_TWIPS PS)
852 // 2 Picture Elements
853 // B'0' Not pels
854 // B'1' Pels (PU_PELS PS)
855 // (Bit 1 must also be set)
856 // 3-7 B'00000'
857 // 3 0x00 Reserved
858 // 4 Picture frame size coordinate type
859 // 0x04 Intel16
860 // 0x05 Intel32
861 // 5 UnitsOfMeasure
862 // 0x00 Ten inches
863 // 0x01 Decimeter
864 // 6-11 or 6-17(2 or 4 bytes) Resolution.
865 // GPS Units / UOM on x axis
866 // GPS Units / UOM on y axis
867 // GPS Units / UOM on z axis
868 // 12-23 or 18-41(2 or 4 bytes) Window Size.
869 // GPS X left, X right
870 // GPS Y bottom, Y top
871 // GPS Z near, Z far
872 Size aUnitsPerDecimeter=OutputDevice::LogicToLogic(Size(10,10),MapMode(MAP_CM),aPictureMapMode);
873 pMET->WriteUChar( 0xf6 ).WriteUChar( 0x28 ).WriteUChar( 0x40 ).WriteUChar( 0x00 )
874 .WriteUChar( 0x05 ).WriteUChar( 0x01 )
875 .WriteUInt32( aUnitsPerDecimeter.Width() )
876 .WriteUInt32( aUnitsPerDecimeter.Height() )
877 .WriteUInt32( 0 )
878 .WriteUInt32( 0 ).WriteUInt32( aPictureRect.GetWidth() )
879 .WriteUInt32( 0 ).WriteUInt32( aPictureRect.GetHeight() )
880 .WriteUInt32( 0 ).WriteUInt32( 0 );
882 // 0 0x21 Set Current Defaults
883 // 1 Length of following data
884 // 2 Set Default Parameter Format 0x08
885 // 3-4 Mask 0xE000
886 // 5 Names 0x8F
887 // 6 Coordinates
888 // 0x00 Picture in 2D
889 // 7 Transforms
890 // 0x04 Intel16
891 // 0x05 Intel32
892 // 8 Geometrics
893 // 0x04 Intel16
894 // 0x05 Intel32
895 pMET->WriteUChar( 0x21 ).WriteUChar( 0x07 ).WriteUChar( 0x08 ).WriteUChar( 0xe0 )
896 .WriteUChar( 0x00 ).WriteUChar( 0x8f ).WriteUChar( 0x00 ).WriteUChar( 0x05 )
897 .WriteUChar( 0x05 );
899 // 0 0x21 Set Current Defaults
900 // 1 Length of following data
901 // 2 Set default viewing transform 0x07
902 // 3-4 Mask 0xCC0C
903 // 5 Names 0x8F
904 // 6-n M11, M12, M21, M22, M41, M42 Matrix elements
905 pMET->WriteUChar( 0x21 ).WriteUChar( 0x1c ).WriteUChar( 0x07 ).WriteUChar( 0xcc )
906 .WriteUChar( 0x0c ).WriteUChar( 0x8f )
907 .WriteUInt32( 0x00010000 ).WriteUInt32( 0x00000000 ).WriteUInt32( 0x00000000 )
908 .WriteUInt32( 0x00010000 ).WriteUInt32( 0x00000000 ).WriteUInt32( 0x00000000 );
910 // 0 0x21 Set Current Defaults
911 // 1 Length of following data
912 // 2 Set default line attributes 0x01
913 // 3-4 Mask - OR of as many of the following bits as are required:
914 // 0x8000 Line type
915 // 0x4000 Line width
916 // 0x2000 Line end
917 // 0x1000 Line join
918 // 0x0800 Stroke width
919 // 0x0008 Line color
920 // 0x0002 Line mix
921 // 5 Flags
923 // 0x0F Set indicated default attributes to initial values. (Data field is not present in this
924 // instance).
925 // 0x8F Set indicated default attributes to specified values.
926 // 6-n Data - data values as required, in the following order if present.
927 // No space is reserved for attributes for which the corresponding mask flag was not
928 // set.
930 // (1 byte) - Line type
931 // (1 byte) - Line width
932 // (1 byte) - Line end
933 // (1 byte) - Line join
934 // (G bytes) - Stroke width
935 // (4 bytes) - Line color
936 // (1 byte) - Line mix (G=2 or 4 depending on the Geometrics parameter of Set Default
937 // Parameter Format)
938 // Nanu! witziger-weise fehlt obiger Abschnitt in den Metadateien. Also lassen wir ihn auch weg
940 // 0 0x21 Set Current Defaults
941 // 1 Length of following data
942 // 2 Set Default Character Attributes 0x02
943 // 3-4 Mask - OR of as many of the following bits as are required:
945 // 0x8000 Character angle
946 // 0x4000 Character box
947 // 0x2000 Character direction
948 // 0x1000 Character precision
949 // 0x0800 Character set
950 // 0x0400 Character shear
951 // 0x0040 Character break extra
952 // 0x0020 Character extra
953 // 0x0008 Character color
954 // 0x0004 Character background color
955 // 0x0002 Character mix
956 // 0x0001 Character background mix
957 // 5 Flags
958 // 0x0FSet indicated default attributes to initial values. (Data field is not present in this
959 // case).
960 // 0x8FSet indicated default attributes to specified values.
961 // 6-n Data - data values as required, in the following order if present.
962 // No space is reserved for attributes for which the corresponding Mask flag was not
963 // set.
964 // (2*G bytes) - Character angle
965 // (2*G + 4 bytes)- Character box
966 // (1 byte) - Character direction
967 // (1 byte) - Character precision
968 // (1 byte) - Character set
969 // (2*G bytes) - Character shear
970 // (4 bytes) - Character break extra
971 // (4 bytes) - Character extra
972 // (4 bytes) - Character color
973 // (4 bytes) - Character background color
974 // (1 byte) - Character mix
975 // (1 byte) - Character background mix (G=2 or 4 depending on the Geometrics
976 // parameter of Set Default Parameter Format)
977 pMET->WriteUChar( 0x21 ).WriteUChar( 0x10 ).WriteUChar( 0x02 ).WriteUChar( 0x40 )
978 .WriteUChar( 0x00 ).WriteUChar( 0x8f )
979 .WriteUChar( 0xaa ).WriteUChar( 0x02 ).WriteUChar( 0x00 ).WriteUChar( 0x00 )
980 .WriteUChar( 0x44 ).WriteUChar( 0x04 ).WriteUChar( 0x00 ).WriteUChar( 0x00 )
981 .WriteUChar( 0xa8 ).WriteUChar( 0xaa ).WriteUChar( 0x40 ).WriteUChar( 0x44 );
983 // 0 0x21 Set Current Defaults
984 // 1 Length of following data
985 // 2 Set Default Marker Attributes 0x03
986 // 3-4 Mask - OR of as many of the following bits as are required:
987 // 0x4000 Marker box
988 // 0x1000 Marker precision
989 // 0x0800 Marker set
990 // 0x0100 Marker symbol
991 // 0x0008 Marker color
992 // 0x0004 Marker background color
993 // 0x0002 Marker mix
994 // 0x0001 Marker background mix
995 // 5 Flags
996 // 0x0F Set indicated default attributes to initial values.
997 // (Data field is not present in this instance)
998 // 0x8F Set indicated default attributes to specified values.
999 // 6-n Data - data values as required, in this order if present.
1000 // No space is reserved for attributes for which the corresponding Mask flag was not
1001 // set.
1002 // (2*G bytes) - Marker box
1003 // (1 byte) - Marker precision
1004 // (1 byte) - Marker set
1005 // (1 byte) - Marker symbol
1006 // (4 bytes) - Marker color
1007 // (4 bytes) - Marker background color
1008 // (1 byte) - Marker mix
1009 // (1 byte) - Marker background mix (G=2 or 4 depending on the Geometrics
1010 // parameter of Set Default Parameter Format)
1011 pMET->WriteUChar( 0x21 ).WriteUChar( 0x0c ).WriteUChar( 0x03 ).WriteUChar( 0x40 )
1012 .WriteUChar( 0x00 ).WriteUChar( 0x8f )
1013 .WriteUChar( 0x66 ).WriteUChar( 0x02 ).WriteUChar( 0x00 ).WriteUChar( 0x00 )
1014 .WriteUChar( 0x66 ).WriteUChar( 0x02 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
1016 // 0 0x21 Set Current Defaults
1017 // 1 Length of following data
1018 // 2 Set Default Pattern Attributes 0x04
1019 // 3-4 Mask - OR of as many of the following bits as are required:
1020 // 0x0800 Pattern set
1021 // 0x0100 Pattern symbol
1022 // 0x0080 Pattern reference point
1023 // 0x0008 Pattern color
1024 // 0x0004 Pattern background color
1025 // 0x0002 Pattern mix
1026 // 0x0001 Pattern background mix
1027 // 5 Flags
1029 // 0x0F Set indicated default attributes to initial values.
1030 // (Data field is not present in this instance)
1031 // 0x8F Set indicated default attributes to specified values.
1032 // 6-n Data - data values as required, in this order if present.
1033 // No space is reserved for attributes for which the corresponding Mask flag was
1034 // not set.
1036 // (1 byte) - Pattern set
1037 // (1 byte) - Pattern symbol
1038 // (2*G bytes) - Pattern reference point
1039 // (4 bytes) - Pattern color
1040 // (4 bytes) - Pattern background color
1041 // (1 byte) - Pattern mix
1042 // (1 byte) - Pattern background mix (G=2 or 4 depending on the Geometrics
1043 // parameter of Set Default Parameter Format)
1044 // 0 0x21 Set Current Defaults
1045 // 1 Length of following data
1046 // 2 Set Default Image Attributes 0x06
1047 // 3-4 Mask - OR of as many of these bits as are required:
1048 // 0x0008 Image color
1049 // 0x0004 Image background color
1050 // 0x0002 Image mix
1051 // 0x0001 Image background mix
1052 // 5 Flags
1053 // 0x0F Set indicated default attributes to initial values. (Data field is not present in
1054 // this instance)
1055 // 0x8F Set indicated default attributes to specified values.
1056 // 6-n Data - data values as required, in this order if present.
1057 // No space is reserved for attributes for which the corresponding Mask flag was
1058 // not set.
1059 // (4 bytes) - Image color
1060 // (4 bytes) - Image background color
1061 // (1 byte) - Image mix
1062 // (1 byte) - Image background mix
1063 // 0 0x21 Set Current Defaults
1064 // 1 Length of following data
1065 // 2 Set Default Viewing Window 0x05
1066 // 3-4 Mask - OR of as many of the following bits as are required:
1067 // 0x8000 x left limit
1068 // 0x4000 x right limit
1069 // 0x2000 y bottom limit
1070 // 0x1000 y top limit
1071 // 5 Flags
1072 // 0x0F Set indicated default attributes to initial values.
1073 // (Data field is not present in this case).
1074 // 0x8F Set indicated default attributes to specified values.
1075 // 6-n Data - data values as required, in the following order if present.
1076 // No space is reserved for attributes for which the corresponding Mask flag was
1077 // not set.
1078 // (2*G bytes) - x left limit
1079 // (2*G bytes) - x right limit
1080 // (2*G bytes) - y bottom limit
1081 // (2*G bytes) - y top limit (G=2 or 4 depending on the Geometrics parameter of Set
1082 // Default Parameter Format)
1083 // 0 0x21 Set Current Defaults
1084 // 1 Length of following data
1085 // 2 Set Default Arc Parameters 0x0B
1086 // 3-4 Mask - OR of as many of the following bits as are required:
1087 // 0x8000 P value
1088 // 0x4000 Q value
1089 // 0x2000 R value
1090 // 0x1000 S value
1091 // 5 Flags
1092 // 0x0F Set indicated default attributes to initial values.
1093 // (Data field is not present in this case).
1094 // 0x8F Set indicated default attributes to specified values.
1095 // 6-n Data - data values as required, in the following order if present.
1096 // No space is reserved for attributes for which the corresponding Mask flag was
1097 // not set.
1098 // (G bytes) - P value
1099 // (G bytes) - Q value
1100 // (G bytes) - R value
1101 // (G bytes) - S value (G=2 or 4 depending on the Geometrics parameter of Set
1102 // Default Parameter Format)
1103 // 0 0x21 Set Current Defaults
1104 // 1 Length of following data
1105 // 2 Set Default Pick Identifier 0x0C
1106 // 3-4 Mask - OR of as many of the following bits as are required:
1107 // 0x8000 Pick identifier
1108 // 5 Flags
1109 // 0x0F Set indicated default attributes to initial values.
1110 // (Data field is not present in this case).
1111 // 0x8F Set indicated default attributes to specified values.
1112 // 6-n Data - data values as required, in the following order if present.
1113 // No space is reserved for attributes for which the corresponding Mask flag was
1114 // not set.
1115 // (4 bytes) - Pick identifier
1117 // 0 0xE7 Set Bit-map Identifier
1118 // 1 Length of following data 0x07
1119 // 2-3 Usage Flags 0x8000
1120 // 4-7 Bit-map handle
1121 // 8 Lcid
1122 if (nNumberOfBitmaps>0) {
1123 pMET->WriteUChar( 0xe7 ).WriteUChar( 0x07 ).WriteUChar( 0x80 ).WriteUChar( 0x00 );
1124 WriteBigEndianLong(nActBitmapId);
1125 pMET->WriteUChar( 0xfe );
1128 UpdateFieldSize();
1130 if (pMET->GetError()) bStatus=false;
1134 void METWriter::WillWriteOrder(sal_uInt32 nNextOrderMaximumLength)
1136 // The parameters of a 'Graphics Data Fields' can be (according to OS2
1137 // documentation) at most 32759 bytes long. Meant by this is the size
1138 // of the field minus the 'Structured Field Introducer' (size 8).
1139 // So the size of the whole field can be at most 8+32759=32767=0x7fff.
1140 // To be on the safe side whe use 30000 as the limit.
1141 if (pMET->Tell()-nActualFieldStartPos+nNextOrderMaximumLength>30000)
1143 UpdateFieldSize();
1144 WriteFieldIntroducer(0,DatGrfObjMagic,0,0);
1145 nNumberOfDataFields++;
1151 void METWriter::METBitBlt(Point aPt, Size aSize, const Size& rBmpSizePixel)
1153 WillWriteOrder(46);
1154 pMET->WriteUChar( 0xd6 ).WriteUChar( 44 ).WriteUInt16( 0 ).WriteUInt16( 0x00cc );
1155 WriteBigEndianLong(nActBitmapId++);
1156 pMET->WriteUChar( 0x02 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
1157 WritePoint(Point(aPt.X(),aPt.Y()+aSize.Height()));
1158 WritePoint(Point(aPt.X()+aSize.Width(),aPt.Y()));
1159 pMET->WriteUInt32( 0 ).WriteUInt32( 0 )
1160 .WriteUInt32( rBmpSizePixel.Width() )
1161 .WriteUInt32( rBmpSizePixel.Height() );
1164 void METWriter::METSetAndPushLineInfo( const LineInfo& rLineInfo )
1166 sal_Int32 nWidth = OutputDevice::LogicToLogic( Size( rLineInfo.GetWidth(),0 ), aPictureMapMode, aTargetMapMode ).Width();
1168 WillWriteOrder( 8 ); // set stroke linewidth
1169 pMET ->WriteUChar( 0x15 )
1170 .WriteUChar( 6 )
1171 .WriteUChar( 0 ) // Flags
1172 .WriteUChar( 0 )
1173 .WriteInt32( nWidth );
1175 if ( rLineInfo.GetStyle() != LINE_SOLID )
1177 sal_uInt8 nStyle = 0; // LineDefault;
1179 switch ( rLineInfo.GetStyle() )
1181 case LINE_NONE :
1182 nStyle = 8;
1183 break;
1185 case LINE_DASH :
1187 if ( rLineInfo.GetDotCount() )
1189 if ( !rLineInfo.GetDashCount() )
1190 nStyle = 1; // LINE_DOT
1191 else
1192 nStyle = 3; // LINE_DASH_DOT
1194 else
1195 nStyle = 2; // LINE_DASH
1197 break;
1198 case LineStyle_SOLID:
1199 case LineStyle_FORCE_EQUAL_SIZE:
1200 break; // not handled -Wall
1202 WillWriteOrder( 2 );
1203 pMET->WriteUChar( 0x18 ).WriteUChar( nStyle ); // set LineType
1207 void METWriter::METPopLineInfo( const LineInfo& rLineInfo )
1209 WillWriteOrder( 8 ); // set stroke linewidth
1210 pMET ->WriteUChar( 0x15 )
1211 .WriteUChar( 6 )
1212 .WriteUChar( 0 ) // Flags
1213 .WriteUChar( 0 )
1214 .WriteUInt32( 1 );
1216 if ( rLineInfo.GetStyle() != LINE_SOLID )
1218 WillWriteOrder( 2 );
1219 pMET->WriteUChar( 0x18 ).WriteUChar( 0 ); // set LineType
1223 void METWriter::METBeginArea(bool bBoundaryLine)
1225 WillWriteOrder(2);
1226 pMET->WriteUChar( 0x68 );
1227 if (bBoundaryLine) pMET->WriteUChar( 0xc0 );
1228 else pMET->WriteUChar( 0x80 );
1232 void METWriter::METEndArea()
1234 WillWriteOrder(2);
1235 pMET->WriteUChar( 0x60 ).WriteUChar( 0 );
1239 void METWriter::METBeginPath(sal_uInt32 nPathId)
1241 WillWriteOrder(8);
1242 pMET->WriteUChar( 0xd0 ).WriteUChar( 6 ).WriteUInt16( 0 ).WriteUInt32( nPathId );
1246 void METWriter::METEndPath()
1248 WillWriteOrder(2);
1249 pMET->WriteUChar( 0x7f ).WriteUChar( 0 );
1253 void METWriter::METFillPath(sal_uInt32 nPathId)
1255 WillWriteOrder(8);
1256 pMET->WriteUChar( 0xd7 ).WriteUChar( 6 )
1257 .WriteUChar( 0x00 ).WriteUChar( 0 ).WriteUInt32( nPathId );
1261 void METWriter::METOutlinePath(sal_uInt32 nPathId)
1263 WillWriteOrder(8);
1264 pMET->WriteUChar( 0xd4 ).WriteUChar( 6 )
1265 .WriteUChar( 0 ).WriteUChar( 0 ).WriteUInt32( nPathId );
1269 void METWriter::METCloseFigure()
1271 WillWriteOrder(2);
1272 pMET->WriteUChar( 0x7d ).WriteUChar( 0 );
1276 void METWriter::METMove(Point aPt)
1278 WillWriteOrder(10);
1279 pMET->WriteUChar( 0x21 ).WriteUChar( 8 );
1280 WritePoint(aPt);
1284 void METWriter::METLine(Point aPt1, Point aPt2)
1286 WillWriteOrder(18);
1287 pMET->WriteUChar( 0xc1 ).WriteUChar( 16 );
1288 WritePoint(aPt1); WritePoint(aPt2);
1292 void METWriter::METLine(const Polygon & rPolygon)
1294 sal_uInt16 nNumPoints,i,j,nOrderPoints;
1295 bool bFirstOrder;
1297 bFirstOrder=true;
1298 i=0; nNumPoints=rPolygon.GetSize();
1299 while (i<nNumPoints) {
1300 nOrderPoints=nNumPoints-i;
1301 if (nOrderPoints>30) nOrderPoints=30;
1302 WillWriteOrder(nOrderPoints*8+2);
1303 if (bFirstOrder) {
1304 pMET->WriteUChar( 0xc1 ); // Line at given pos
1305 bFirstOrder=false;
1307 else {
1308 pMET->WriteUChar( 0x81 ); // Line at current pos
1310 pMET->WriteUChar( nOrderPoints*8 );
1311 for (j=0; j<nOrderPoints; j++) WritePoint(rPolygon.GetPoint(i++));
1316 void METWriter::METLine(const tools::PolyPolygon & rPolyPolygon)
1318 sal_uInt16 i,nCount;
1319 nCount=rPolyPolygon.Count();
1320 for (i=0; i<nCount; i++) {
1321 METLine(rPolyPolygon.GetObject(i));
1322 METCloseFigure();
1326 void METWriter::METLineAtCurPos(Point aPt)
1328 WillWriteOrder(10);
1329 pMET->WriteUChar( 0x81 ).WriteUChar( 8 );
1330 WritePoint(aPt);
1333 void METWriter::METBox(bool bFill, bool bBoundary,
1334 const Rectangle& rRect, sal_uInt32 nHAxis, sal_uInt32 nVAxis)
1336 sal_uInt8 nFlags=0;
1337 if (bFill) nFlags|=0x40;
1338 if (bBoundary) nFlags|=0x20;
1340 WillWriteOrder(28);
1341 pMET->WriteUChar( 0xc0 ).WriteUChar( 26 ).WriteUChar( nFlags ).WriteUChar( 0 );
1342 WritePoint(rRect.BottomLeft());
1343 WritePoint(rRect.TopRight());
1344 pMET->WriteUInt32( nHAxis ).WriteUInt32( nVAxis );
1347 void METWriter::METFullArc(Point aCenter, double fMultiplier)
1349 WillWriteOrder(14);
1350 pMET->WriteUChar( 0xc7 ).WriteUChar( 12 );
1351 WritePoint(aCenter);
1352 pMET->WriteInt32( fMultiplier*65536.0+0.5 );
1355 void METWriter::METPartialArcAtCurPos(Point aCenter, double fMultiplier,
1356 double fStartAngle, double fSweepAngle)
1358 fStartAngle*=180.0/3.14159265359;
1359 while (fStartAngle>360.0) fStartAngle-=360.0;
1360 while (fStartAngle<0.0) fStartAngle+=360.0;
1361 fSweepAngle*=180.0/3.14159265359;
1362 while (fSweepAngle>360.0) fSweepAngle-=360.0;
1363 while (fSweepAngle<.00) fSweepAngle+=360.0;
1364 WillWriteOrder(22);
1365 pMET->WriteUChar( 0xa3 ).WriteUChar( 20 );
1366 WritePoint(aCenter);
1367 pMET->WriteInt32( fMultiplier*65536.0+0.5 );
1368 pMET->WriteInt32( fStartAngle*65536.0+0.5 );
1369 pMET->WriteInt32( fSweepAngle*65536.0+0.5 );
1373 void METWriter::METChrStr( Point aPt, const OUString& aUniStr )
1375 OString aStr(OUStringToOString(aUniStr,
1376 osl_getThreadTextEncoding()));
1377 sal_uInt16 nLen = aStr.getLength();
1378 WillWriteOrder( 11 + nLen );
1379 pMET->WriteUChar( 0xc3 ).WriteUChar( 9 + nLen );
1380 WritePoint(aPt);
1381 for (sal_uInt16 i = 0; i < nLen; ++i)
1382 pMET->WriteChar( aStr[i] );
1383 pMET->WriteUChar( 0 );
1387 void METWriter::METSetArcParams(sal_Int32 nP, sal_Int32 nQ, sal_Int32 nR, sal_Int32 nS)
1389 WillWriteOrder(18);
1390 pMET->WriteUChar( 0x22 ).WriteUChar( 16 ).WriteInt32( nP ).WriteInt32( nQ ).WriteInt32( nR ).WriteInt32( nS );
1394 void METWriter::METSetColor(Color aColor)
1396 if (aColor==aMETColor) return;
1397 aMETColor=aColor;
1399 WillWriteOrder(6);
1400 pMET->WriteUChar( 0xa6 ).WriteUChar( 4 ).WriteUChar( 0 )
1401 .WriteUChar( aColor.GetBlue() )
1402 .WriteUChar( aColor.GetGreen() )
1403 .WriteUChar( aColor.GetRed() );
1407 void METWriter::METSetBackgroundColor(Color aColor)
1409 if (aColor==aMETBackgroundColor) return;
1410 aMETBackgroundColor=aColor;
1412 WillWriteOrder(6);
1413 pMET->WriteUChar( 0xa7 ).WriteUChar( 4 ).WriteUChar( 0 )
1414 .WriteUChar( aColor.GetBlue() )
1415 .WriteUChar( aColor.GetGreen() )
1416 .WriteUChar( aColor.GetRed() );
1419 void METWriter::METSetMix(RasterOp eROP)
1421 sal_uInt8 nMix;
1423 if (eMETMix==eROP)
1424 return;
1426 eMETMix=eROP;
1428 switch (eROP)
1430 case ROP_INVERT: nMix=0x0c; break;
1431 case ROP_XOR: nMix=0x04; break;
1432 default: nMix=0x02;
1435 WillWriteOrder(2);
1436 pMET->WriteUChar( 0x0c ).WriteUChar( nMix );
1440 void METWriter::METSetChrCellSize(Size aSize)
1442 if (aMETChrCellSize==aSize)
1443 return;
1445 aMETChrCellSize=aSize;
1446 WillWriteOrder(10);
1447 if (aSize.Width()==0) aSize.Width()=aSize.Height();
1448 pMET->WriteUChar( 0x33 ).WriteUChar( 8 ).WriteInt32( aSize.Width() ).WriteInt32( aSize.Height() );
1452 void METWriter::METSetChrAngle(short nAngle)
1454 sal_Int32 nax, nay;
1456 if (nMETChrAngle==nAngle) return;
1457 nMETChrAngle=nAngle;
1459 if (nAngle==0)
1461 nax=256;
1462 nay=0;
1464 else
1466 double fa=((double)nAngle)/1800.0*3.14159265359;
1467 nax=(long)(256.0*cos(fa)+0.5);
1468 nay=(long)(256.0*sin(fa)+0.5);
1471 WillWriteOrder(10);
1472 pMET->WriteUChar( 0x34 ).WriteUChar( 8 ).WriteInt32( nax ).WriteInt32( nay );
1476 void METWriter::METSetChrSet(sal_uInt8 nSet)
1478 if (nMETChrSet==nSet)
1479 return;
1481 nMETChrSet=nSet;
1482 WillWriteOrder(2);
1483 pMET->WriteUChar( 0x38 ).WriteUChar( nSet );
1487 void METWriter::WriteOrders( const GDIMetaFile* pMTF )
1489 if(!bStatus)
1490 return;
1492 for( size_t nA = 0, nACount = pMTF->GetActionSize(); nA < nACount; nA++ )
1494 const MetaAction* pMA = pMTF->GetAction( nA );
1496 switch (pMA->GetType())
1498 case MetaActionType::PIXEL:
1500 const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pMA);
1501 METSetMix( eGDIRasterOp );
1502 METSetColor( pA->GetColor() );
1503 METLine( pA->GetPoint(),pA->GetPoint() );
1505 break;
1507 case MetaActionType::POINT:
1509 const MetaPointAction* pA = static_cast<const MetaPointAction*>(pMA);
1511 METSetArcParams(1,1,0,0);
1512 METSetMix(eGDIRasterOp);
1513 METSetColor(aGDILineColor);
1514 METBeginArea(false);
1515 METFullArc(pA->GetPoint(),0.5);
1516 METEndArea();
1518 break;
1520 case MetaActionType::LINE:
1522 const MetaLineAction* pA = static_cast<const MetaLineAction*>(pMA);
1524 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1526 LineInfo aLineInfo( pA->GetLineInfo() );
1527 if ( ! ( aLineInfo.IsDefault() ) )
1528 METSetAndPushLineInfo( aLineInfo );
1530 METSetMix( eGDIRasterOp );
1531 METSetColor(aGDILineColor);
1532 METBeginPath( 1 );
1533 METLine( pA->GetStartPoint(), pA->GetEndPoint() );
1534 METEndPath();
1535 METOutlinePath( 1 );
1537 if ( ! ( aLineInfo.IsDefault() ) )
1538 METPopLineInfo( aLineInfo );
1541 break;
1543 case MetaActionType::RECT:
1545 const MetaRectAction* pA = static_cast<const MetaRectAction*>(pMA);
1547 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1549 METSetMix( eGDIRasterOp );
1550 METSetColor( aGDIFillColor );
1551 METSetBackgroundColor( aGDIFillColor );
1552 METBox( true, false, pA->GetRect(), 0, 0 );
1555 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1557 METSetMix( eGDIRasterOp );
1558 METSetColor( aGDILineColor );
1559 METBox( false, true, pA->GetRect(), 0, 0 );
1562 break;
1564 case MetaActionType::ROUNDRECT:
1566 const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pMA);
1568 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1570 METSetMix( eGDIRasterOp );
1571 METSetColor( aGDIFillColor );
1572 METSetBackgroundColor( aGDIFillColor );
1573 METBox( true, false, pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1576 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1578 METSetMix( eGDIRasterOp );
1579 METSetColor( aGDILineColor );
1580 METBox( false, true, pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1583 break;
1585 case MetaActionType::ELLIPSE:
1587 const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pMA);
1588 Point aCenter;
1590 aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1591 aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1593 METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1595 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1597 METSetMix( eGDIRasterOp );
1598 METSetColor( aGDIFillColor );
1599 METSetBackgroundColor( aGDIFillColor );
1600 METBeginArea(false);
1601 METFullArc(aCenter,0.5);
1602 METEndArea();
1605 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1607 METSetMix( eGDIRasterOp );
1608 METSetColor( aGDILineColor );
1609 METFullArc( aCenter,0.5 );
1612 break;
1614 case MetaActionType::ARC:
1616 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pMA);
1617 Point aStartPos,aCenter;
1618 double fdx,fdy,fa1,fa2;
1620 aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1621 aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1622 fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1623 fdy=(double)(pA->GetStartPoint().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 fa1=atan2(-fdy,fdx);
1628 fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1629 fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1630 fdx*=(double)pA->GetRect().GetHeight();
1631 fdy*=(double)pA->GetRect().GetWidth();
1632 if (fdx==0.0 && fdy==0.0) fdx=1.0;
1633 fa2=atan2(-fdy,fdx);
1634 aStartPos.X()=aCenter.X()+(long)(((double)pA->GetRect().GetWidth())*cos(fa1)/2.0+0.5);
1635 aStartPos.Y()=aCenter.Y()-(long)(((double)pA->GetRect().GetHeight())*sin(fa1)/2.0+0.5);
1637 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1639 METSetMix( eGDIRasterOp );
1640 METSetColor( aGDILineColor );
1641 METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1642 METBeginPath(1);
1643 METMove(aStartPos);
1644 METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1645 METEndPath();
1646 METOutlinePath(1);
1649 break;
1651 case MetaActionType::PIE:
1653 const MetaPieAction* pA = static_cast<const MetaPieAction*>(pMA);
1654 Point aCenter;
1655 double fdx,fdy,fa1,fa2;
1657 aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1658 aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1659 fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1660 fdy=(double)(pA->GetStartPoint().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 fa1=atan2(-fdy,fdx);
1665 fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1666 fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1667 fdx*=(double)pA->GetRect().GetHeight();
1668 fdy*=(double)pA->GetRect().GetWidth();
1669 if (fdx==0.0 && fdy==0.0) fdx=1.0;
1670 fa2=atan2(-fdy,fdx);
1672 METSetArcParams(pA->GetRect().GetWidth(), pA->GetRect().GetHeight(),0,0);
1674 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1676 METSetMix( eGDIRasterOp );
1677 METSetColor( aGDIFillColor );
1678 METSetBackgroundColor( aGDIFillColor );
1679 METBeginPath(1);
1680 METMove(aCenter);
1681 METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1682 METLineAtCurPos(aCenter);
1683 METEndPath();
1684 METFillPath(1);
1687 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1689 METSetMix( eGDIRasterOp );
1690 METSetColor( aGDILineColor );
1691 METBeginPath(1);
1692 METMove(aCenter);
1693 METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1694 METLineAtCurPos(aCenter);
1695 METEndPath();
1696 METOutlinePath(1);
1699 break;
1701 case MetaActionType::CHORD:
1703 const MetaChordAction* pA = static_cast<const MetaChordAction*>(pMA);
1704 Point aStartPos,aCenter;
1705 double fdx,fdy,fa1,fa2;
1707 aCenter.X()=(pA->GetRect().Left()+pA->GetRect().Right())/2;
1708 aCenter.Y()=(pA->GetRect().Top()+pA->GetRect().Bottom())/2;
1709 fdx=(double)(pA->GetStartPoint().X()-aCenter.X());
1710 fdy=(double)(pA->GetStartPoint().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 fa1=atan2(-fdy,fdx);
1715 fdx=(double)(pA->GetEndPoint().X()-aCenter.X());
1716 fdy=(double)(pA->GetEndPoint().Y()-aCenter.Y());
1717 fdx*=(double)pA->GetRect().GetHeight();
1718 fdy*=(double)pA->GetRect().GetWidth();
1719 if (fdx==0.0 && fdy==0.0) fdx=1.0;
1720 fa2=atan2(-fdy,fdx);
1721 aStartPos.X()=aCenter.X()+(long)(((double)pA->GetRect().GetWidth())*cos(fa1)/2.0+0.5);
1722 aStartPos.Y()=aCenter.Y()-(long)(((double)pA->GetRect().GetHeight())*sin(fa1)/2.0+0.5);
1724 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1726 METSetMix( eGDIRasterOp );
1727 METSetColor( aGDIFillColor );
1728 METSetBackgroundColor( aGDIFillColor );
1729 METBeginPath(1);
1730 METMove(aStartPos);
1731 METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1732 METLineAtCurPos(aStartPos);
1733 METEndPath();
1734 METFillPath(1);
1737 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1739 METSetMix( eGDIRasterOp );
1740 METSetColor( aGDILineColor );
1741 METBeginPath(1);
1742 METMove(aStartPos);
1743 METPartialArcAtCurPos(aCenter,0.5,fa1,fa2-fa1);
1744 METLineAtCurPos(aStartPos);
1745 METEndPath();
1746 METOutlinePath(1);
1749 break;
1751 case MetaActionType::POLYLINE:
1753 const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pMA);
1755 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1757 LineInfo aLineInfo( pA->GetLineInfo() );
1758 if ( ! ( aLineInfo.IsDefault() ) )
1759 METSetAndPushLineInfo( aLineInfo );
1761 METSetMix(eGDIRasterOp);
1762 METSetColor(aGDILineColor);
1763 METBeginPath(1);
1764 Polygon aSimplePoly;
1765 const Polygon& rPoly = pA->GetPolygon();
1766 if ( rPoly.HasFlags() )
1767 rPoly.AdaptiveSubdivide( aSimplePoly );
1768 else
1769 aSimplePoly = rPoly;
1770 METLine( aSimplePoly );
1771 METEndPath();
1772 METOutlinePath(1);
1774 if ( ! ( aLineInfo.IsDefault() ) )
1775 METPopLineInfo( aLineInfo );
1778 break;
1780 case MetaActionType::POLYGON:
1782 const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pMA);
1783 Polygon aSimplePoly;
1784 const Polygon& rPoly = pA->GetPolygon();
1785 if ( rPoly.HasFlags() )
1786 rPoly.AdaptiveSubdivide( aSimplePoly );
1787 else
1788 aSimplePoly = rPoly;
1789 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1791 METSetMix(eGDIRasterOp);
1792 METSetColor(aGDIFillColor );
1793 METSetBackgroundColor(aGDIFillColor );
1794 METBeginPath(1);
1795 METLine( aSimplePoly );
1796 METEndPath();
1797 METFillPath(1);
1800 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1802 METSetMix(eGDIRasterOp);
1803 METSetColor(aGDILineColor );
1804 METBeginPath(1);
1805 METLine( aSimplePoly );
1806 METEndPath();
1807 METOutlinePath(1);
1810 break;
1812 case MetaActionType::POLYPOLYGON:
1814 const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pMA);
1816 tools::PolyPolygon aSimplePolyPoly( pA->GetPolyPolygon() );
1817 sal_uInt16 i, nCount = aSimplePolyPoly.Count();
1818 for ( i = 0; i < nCount; i++ )
1820 if ( aSimplePolyPoly[ i ].HasFlags() )
1822 Polygon aSimplePoly;
1823 aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
1824 aSimplePolyPoly[ i ] = aSimplePoly;
1827 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
1829 METSetMix(eGDIRasterOp);
1830 METSetColor(aGDIFillColor);
1831 METSetBackgroundColor(aGDIFillColor);
1832 METBeginPath(1);
1833 METLine( aSimplePolyPoly );
1834 METEndPath();
1835 METFillPath(1);
1838 if( aGDILineColor != Color( COL_TRANSPARENT ) )
1840 METSetMix(eGDIRasterOp);
1841 METSetColor(aGDILineColor);
1842 METBeginPath(1);
1843 METLine( aSimplePolyPoly );
1844 METEndPath();
1845 METOutlinePath(1);
1848 break;
1850 case MetaActionType::TEXT:
1852 const MetaTextAction* pA = static_cast<const MetaTextAction*>(pMA);
1853 Point aPt( pA->GetPoint() );
1855 if( aGDIFont.GetAlign() != ALIGN_BASELINE)
1857 ScopedVclPtrInstance< VirtualDevice > pVDev;
1859 if( aGDIFont.GetAlign()==ALIGN_TOP )
1860 aPt.Y()+=(long)pVDev->GetFontMetric( aGDIFont ).GetAscent();
1861 else
1862 aPt.Y()-=(long)pVDev->GetFontMetric( aGDIFont ).GetDescent();
1865 METSetMix(eGDIRasterOp);
1866 METSetColor(aGDIFont.GetColor());
1867 METSetBackgroundColor(aGDIFont.GetFillColor());
1868 METSetChrCellSize(aGDIFont.GetSize());
1869 METSetChrAngle(aGDIFont.GetOrientation());
1870 METSetChrSet(FindChrSet(aGDIFont));
1871 METChrStr(aPt, pA->GetText().copy(pA->GetIndex(),pA->GetLen()));
1873 break;
1875 case MetaActionType::TEXTARRAY:
1877 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pMA);
1878 sal_uInt16 i;
1879 OUString aStr;
1880 Polygon aPolyDummy(1);
1881 short nOrientation;
1882 Point aPt( pA->GetPoint() );
1884 if( aGDIFont.GetAlign() != ALIGN_BASELINE )
1886 ScopedVclPtrInstance< VirtualDevice > pVDev;
1887 if( aGDIFont.GetAlign() == ALIGN_TOP )
1888 aPt.Y()+=(long)pVDev->GetFontMetric(aGDIFont).GetAscent();
1889 else
1890 aPt.Y()-=(long)pVDev->GetFontMetric(aGDIFont).GetDescent();
1893 METSetMix(eGDIRasterOp);
1894 METSetColor(aGDIFont.GetColor());
1895 METSetBackgroundColor(aGDIFont.GetFillColor());
1896 METSetChrCellSize(aGDIFont.GetSize());
1897 METSetChrAngle( nOrientation = aGDIFont.GetOrientation() );
1898 METSetChrSet(FindChrSet(aGDIFont));
1899 aStr = pA->GetText().copy(pA->GetIndex(),pA->GetLen());
1901 if( pA->GetDXArray()!=NULL )
1903 Point aPt2;
1905 for( i=0; i < aStr.getLength(); i++ )
1907 aPt2 = aPt;
1908 if ( i > 0 )
1910 aPt2.X() += pA->GetDXArray()[i-1];
1911 if ( nOrientation )
1913 aPolyDummy.SetPoint( aPt2, 0 );
1914 aPolyDummy.Rotate( aPt, nOrientation );
1915 aPt2 = aPolyDummy.GetPoint( 0 );
1918 METChrStr( aPt2, OUString( aStr[ i ] ) );
1921 else
1922 METChrStr( aPt, aStr );
1924 break;
1926 case MetaActionType::STRETCHTEXT:
1928 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pMA);
1929 ScopedVclPtrInstance< VirtualDevice > pVDev;
1930 sal_uInt16 i;
1931 sal_Int32 nNormSize;
1932 OUString aStr;
1933 Polygon aPolyDummy(1);
1934 short nOrientation;
1935 Point aPt( pA->GetPoint() );
1936 Point aPt2;
1938 pVDev->SetFont( aGDIFont );
1940 if( aGDIFont.GetAlign() != ALIGN_BASELINE)
1942 if( aGDIFont.GetAlign() == ALIGN_TOP )
1943 aPt.Y()+=(long)pVDev->GetFontMetric().GetAscent();
1944 else
1945 aPt.Y()-=(long)pVDev->GetFontMetric().GetDescent();
1948 METSetMix(eGDIRasterOp);
1949 METSetColor(aGDIFont.GetColor());
1950 METSetBackgroundColor(aGDIFont.GetFillColor());
1951 METSetChrCellSize(aGDIFont.GetSize());
1952 METSetChrAngle( nOrientation = aGDIFont.GetOrientation() );
1953 METSetChrSet(FindChrSet(aGDIFont));
1954 aStr = pA->GetText().copy(pA->GetIndex(),pA->GetLen());
1955 boost::scoped_array<long> pDXAry(new long[aStr.getLength()]);
1956 nNormSize = pVDev->GetTextArray( aStr, pDXAry.get() );
1958 for ( i = 0; i < aStr.getLength(); i++ )
1960 aPt2 = aPt;
1961 if (i > 0 && nNormSize)
1963 aPt2.X() += pDXAry[i-1]*((long)pA->GetWidth())/ nNormSize;
1964 if ( nOrientation )
1966 aPolyDummy.SetPoint( aPt2, 0 );
1967 aPolyDummy.Rotate( aPt, nOrientation );
1968 aPt2 = aPolyDummy.GetPoint( 0 );
1971 METChrStr( aPt2, OUString( aStr[ i ] ) );
1974 break;
1976 case MetaActionType::TEXTRECT:
1978 // OSL_FAIL( "Unsupported MET-Action: MetaActionType::TEXTRECT!" );
1980 break;
1982 case MetaActionType::BMP:
1984 const MetaBmpAction* pA = static_cast<const MetaBmpAction*>(pMA);
1985 const Size aSizePixel( pA->GetBitmap().GetSizePixel() );
1987 METSetMix(eGDIRasterOp);
1988 METBitBlt( pA->GetPoint(), pCompDev->PixelToLogic( aSizePixel, aPictureMapMode ), aSizePixel );
1990 break;
1992 case MetaActionType::BMPSCALE:
1994 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pMA);
1996 METSetMix(eGDIRasterOp);
1997 METBitBlt( pA->GetPoint(), pA->GetSize(), pA->GetBitmap().GetSizePixel() );
1999 break;
2001 case MetaActionType::BMPSCALEPART:
2003 const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pMA);
2004 Bitmap aTmp( pA->GetBitmap() );
2006 aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
2007 METSetMix( eGDIRasterOp );
2008 METBitBlt( pA->GetDestPoint(), pA->GetDestSize(), pA->GetBitmap().GetSizePixel() );
2010 break;
2012 case MetaActionType::BMPEX:
2014 const MetaBmpExAction* pA = static_cast<const MetaBmpExAction*>(pMA);
2015 const Size aSizePixel( pA->GetBitmapEx().GetSizePixel() );
2017 METSetMix( eGDIRasterOp );
2018 METBitBlt( pA->GetPoint(), pCompDev->PixelToLogic( aSizePixel, aPictureMapMode ), aSizePixel );
2020 break;
2022 case MetaActionType::BMPEXSCALE:
2024 const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pMA);
2025 const Size aSizePixel( pA->GetBitmapEx().GetSizePixel() );
2027 METSetMix( eGDIRasterOp );
2028 METBitBlt( pA->GetPoint(), pA->GetSize(), aSizePixel );
2030 break;
2032 case MetaActionType::BMPEXSCALEPART:
2034 const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pMA);
2035 Bitmap aTmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
2037 aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
2038 METSetMix( eGDIRasterOp );
2039 METBitBlt( pA->GetDestPoint(), pA->GetDestSize(), aTmp.GetSizePixel() );
2041 break;
2043 case MetaActionType::EPS :
2045 const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pMA);
2046 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
2048 size_t nCount = aGDIMetaFile.GetActionSize();
2049 for ( size_t i = 0; i < nCount; i++ )
2051 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
2052 if ( pMetaAct->GetType() == MetaActionType::BMPSCALE )
2054 const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pMetaAct);
2055 METSetMix(eGDIRasterOp);
2056 METBitBlt( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap().GetSizePixel() );
2057 break;
2061 break;
2063 case MetaActionType::MASK:
2064 break;
2066 case MetaActionType::MASKSCALE:
2067 break;
2069 case MetaActionType::MASKSCALEPART:
2070 break;
2072 case MetaActionType::GRADIENT:
2074 ScopedVclPtrInstance< VirtualDevice > pVDev;
2075 GDIMetaFile aTmpMtf;
2076 const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pMA);
2078 pVDev->SetMapMode( aTargetMapMode );
2079 pVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
2080 WriteOrders( &aTmpMtf );
2082 break;
2084 case MetaActionType::HATCH:
2086 ScopedVclPtrInstance< VirtualDevice > pVDev;
2087 GDIMetaFile aTmpMtf;
2088 const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pMA);
2090 pVDev->SetMapMode( aTargetMapMode );
2091 pVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
2092 WriteOrders( &aTmpMtf );
2094 break;
2096 case MetaActionType::WALLPAPER:
2097 break;
2099 case MetaActionType::CLIPREGION:
2100 break;
2102 case MetaActionType::ISECTRECTCLIPREGION:
2104 const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pMA);
2105 WriteClipRect( pA->GetRect() );
2107 break;
2109 case MetaActionType::ISECTREGIONCLIPREGION:
2110 break;
2112 case MetaActionType::MOVECLIPREGION:
2113 break;
2115 case MetaActionType::LINECOLOR:
2117 const MetaLineColorAction* pA = static_cast<const MetaLineColorAction*>(pMA);
2119 if( pA->IsSetting() )
2120 aGDILineColor = pA->GetColor();
2121 else
2122 aGDILineColor = Color( COL_TRANSPARENT );
2124 break;
2126 case MetaActionType::FILLCOLOR:
2128 const MetaFillColorAction* pA = static_cast<const MetaFillColorAction*>(pMA);
2130 if( pA->IsSetting() )
2131 aGDIFillColor = pA->GetColor();
2132 else
2133 aGDIFillColor = Color( COL_TRANSPARENT );
2135 break;
2137 case MetaActionType::TEXTCOLOR:
2139 const MetaTextColorAction* pA = static_cast<const MetaTextColorAction*>(pMA);
2140 aGDIFont.SetColor( pA->GetColor() );
2142 break;
2144 case MetaActionType::TEXTFILLCOLOR:
2146 const MetaTextFillColorAction* pA = static_cast<const MetaTextFillColorAction*>(pMA);
2148 if( pA->IsSetting() )
2149 aGDIFont.SetFillColor( pA->GetColor() );
2150 else
2151 aGDIFont.SetFillColor( Color( COL_TRANSPARENT ) );
2153 break;
2155 case MetaActionType::TEXTALIGN:
2156 break;
2158 case MetaActionType::MAPMODE:
2160 const MetaMapModeAction* pA = static_cast<const MetaMapModeAction*>(pMA);
2162 if( aPictureMapMode != pA->GetMapMode() )
2164 if ( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
2166 MapMode aMM = pA->GetMapMode();
2167 Fraction aScaleX = aMM.GetScaleX();
2168 Fraction aScaleY = aMM.GetScaleY();
2170 Point aOrigin = aPictureMapMode.GetOrigin();
2171 BigInt aX( aOrigin.X() );
2172 aX *= BigInt( aScaleX.GetDenominator() );
2174 if( aOrigin.X() >= 0 )
2176 if( aScaleX.GetNumerator() >= 0 )
2177 aX += BigInt( aScaleX.GetNumerator()/2 );
2178 else
2179 aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
2181 else
2183 if( aScaleX.GetNumerator() >= 0 )
2184 aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
2185 else
2186 aX += BigInt( aScaleX.GetNumerator()/2 );
2189 aX /= BigInt( aScaleX.GetNumerator() );
2190 aOrigin.X() = (long) aX + aMM.GetOrigin().X();
2192 BigInt aY( aOrigin.Y() );
2193 aY *= BigInt( aScaleY.GetDenominator() );
2195 if( aOrigin.Y() >= 0 )
2197 if( aScaleY.GetNumerator() >= 0 )
2198 aY += BigInt( aScaleY.GetNumerator()/2 );
2199 else
2200 aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
2202 else
2204 if( aScaleY.GetNumerator() >= 0 )
2205 aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
2206 else
2207 aY += BigInt( aScaleY.GetNumerator()/2 );
2210 aY /= BigInt( aScaleY.GetNumerator() );
2211 aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
2212 aPictureMapMode.SetOrigin( aOrigin );
2214 aScaleX *= aPictureMapMode.GetScaleX();
2215 aScaleY *= aPictureMapMode.GetScaleY();
2216 aPictureMapMode.SetScaleX( aScaleX );
2217 aPictureMapMode.SetScaleY( aScaleY );
2219 else
2220 aPictureMapMode=pA->GetMapMode();
2223 break;
2225 case MetaActionType::FONT:
2227 aGDIFont = static_cast<const MetaFontAction*>(pMA)->GetFont();
2229 break;
2231 case MetaActionType::PUSH:
2233 METGDIStackMember* pGS = new METGDIStackMember;
2235 pGS->pSucc=pGDIStack; pGDIStack=pGS;
2236 pGS->aLineColor=aGDILineColor;
2237 pGS->aFillColor=aGDIFillColor;
2238 pGS->eRasterOp=eGDIRasterOp;
2239 pGS->aFont=aGDIFont;
2240 pGS->aMapMode=aPictureMapMode;
2241 pGS->aClipRect=aGDIClipRect;
2243 break;
2245 case MetaActionType::POP:
2247 METGDIStackMember* pGS;
2249 if( pGDIStack )
2251 pGS=pGDIStack; pGDIStack=pGS->pSucc;
2252 aGDILineColor=pGS->aLineColor;
2253 aGDIFillColor=pGS->aFillColor;
2254 eGDIRasterOp=pGS->eRasterOp;
2255 aGDIFont=pGS->aFont;
2256 if ( pGS->aClipRect != aGDIClipRect )
2257 WriteClipRect( pGS->aClipRect );
2258 aPictureMapMode=pGS->aMapMode;
2259 delete pGS;
2262 break;
2264 case MetaActionType::RASTEROP:
2266 eGDIRasterOp = static_cast<const MetaRasterOpAction*>(pMA)->GetRasterOp();
2268 break;
2270 case MetaActionType::Transparent:
2272 if( aGDIFillColor != Color( COL_TRANSPARENT ) )
2274 METSetMix(eGDIRasterOp);
2275 METSetColor(aGDIFillColor);
2276 METSetBackgroundColor(aGDIFillColor);
2277 METBeginPath(1);
2278 METLine( static_cast<const MetaTransparentAction*>(pMA)->GetPolyPolygon());
2279 METEndPath();
2280 METFillPath(1);
2283 if( aGDILineColor != Color( COL_TRANSPARENT ) )
2285 METSetMix(eGDIRasterOp);
2286 METSetColor(aGDILineColor);
2287 METBeginPath(1);
2288 METLine( static_cast<const MetaTransparentAction*>(pMA)->GetPolyPolygon());
2289 METEndPath();
2290 METOutlinePath(1);
2293 break;
2295 case MetaActionType::FLOATTRANSPARENT:
2297 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pMA);
2299 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
2300 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
2301 const Size aSrcSize( aTmpMtf.GetPrefSize() );
2302 const Point aDestPt( pA->GetPoint() );
2303 const Size aDestSize( pA->GetSize() );
2304 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
2305 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
2306 long nMoveX, nMoveY;
2308 if( fScaleX != 1.0 || fScaleY != 1.0 )
2310 aTmpMtf.Scale( fScaleX, fScaleY );
2311 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2314 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
2316 if( nMoveX || nMoveY )
2317 aTmpMtf.Move( nMoveX, nMoveY );
2319 WriteOrders( &aTmpMtf );
2321 break;
2322 default: break;
2325 nWrittenActions++;
2326 MayCallback();
2328 if( pMET->GetError() )
2329 bStatus=false;
2331 if( !bStatus )
2332 break;
2336 void METWriter::WriteObjectEnvironmentGroup(const GDIMetaFile * pMTF)
2338 sal_uInt32 i, nId;
2340 //--- The Field 'Begin Object Environment Group':
2341 WriteFieldIntroducer(16,BegObjEnvMagic,0,0);
2342 WriteFieldId(7);
2344 //--- The Field 'Map Color Attribute Table':
2345 WriteFieldIntroducer(22,MapColAtrMagic,0,0);
2346 WriteBigEndianShort(0x000e);
2347 pMET->WriteUChar( 0x0c ).WriteUChar( 0x02 ).WriteUChar( 0x84 ).WriteUChar( 0x00 );
2348 WriteFieldId(4);
2350 //--- The first Field 'Map Coded Font':
2351 WriteFieldIntroducer(32,MapCodFntMagic,0,0);
2352 WriteBigEndianShort(0x0018);
2353 pMET->WriteUChar( 0x0c ).WriteUChar( 0x02 ).WriteUChar( 0x84 ).WriteUChar( 0x00 );
2354 pMET->WriteUChar( 0xff ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
2355 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
2356 pMET->WriteUChar( 0x04 ).WriteUChar( 0x24 ).WriteUChar( 0x05 ).WriteUChar( 0x00 );
2357 pMET->WriteUChar( 0x06 ).WriteUChar( 0x20 );
2358 pMET->WriteUChar( 0x03 ).WriteUChar( 0x97 ).WriteUChar( 0x01 ).WriteUChar( 0xb5 );
2360 //--- The additional Fields 'Map Coded Font':
2361 CreateChrSets(pMTF);
2362 WriteChrSets();
2364 //--- The Fields 'Map Data Resource':
2365 nId=nActBitmapId;
2366 for (i=0; i<nNumberOfBitmaps; i++)
2368 WriteFieldIntroducer(29,MapDatResMagic,0,0);
2369 WriteBigEndianShort(0x0015);
2370 pMET->WriteUChar( 0x0c ).WriteUChar( 0x02 ).WriteUChar( 0x84 ).WriteUChar( 0x00 );
2371 WriteFieldId(nId);
2372 pMET->WriteUChar( 0x07 ).WriteUChar( 0x22 ).WriteUChar( 0x10 );
2373 pMET->WriteUInt32( nId );
2374 nId++;
2377 //--- Das Feld 'End Object Environment Group':
2378 WriteFieldIntroducer(16,EndObjEnvMagic,0,0);
2379 WriteFieldId(7);
2383 void METWriter::WriteGraphicsObject(const GDIMetaFile * pMTF)
2385 sal_uInt32 nSegmentSize,nPos,nDataFieldsStartPos;
2387 if( !bStatus )
2388 return;
2390 //--- Das Feld 'Begin Graphics Object':
2391 WriteFieldIntroducer(16,BegGrfObjMagic,0,0);
2392 WriteFieldId(7);
2394 // Map Color Attribute Table, Fonts and other stuff:
2395 WriteObjectEnvironmentGroup(pMTF);
2397 //--- The Field 'Graphics Data Descriptor':
2398 WriteDataDescriptor(pMTF);
2400 // initialise the counter for Data Fields:
2401 nNumberOfDataFields=0;
2403 // and remember the position of the first Data Field:
2404 nDataFieldsStartPos=pMET->Tell();
2406 //--- start of the first Field 'Graphics Data'
2407 WriteFieldIntroducer(0,DatGrfObjMagic,0,0);
2408 nNumberOfDataFields++;
2410 // now at first we write the head of the segment:
2411 pMET->WriteUChar( 0x70 ).WriteUChar( 0x0e ).WriteUInt32( 0 );
2412 pMET->WriteUChar( 0x70 ).WriteUChar( 0x10 ); // Flags
2413 pMET->WriteUInt16( 0 ); // Lo-Word of the length of the segment data (Big Endian)
2414 pMET->WriteUInt32( 0 ); // Reserved
2415 pMET->WriteUInt16( 0 ); // Hi-Word of the length of the segment (Big Endian) (Ohh Ohh OS2)
2416 // Annotation: we're writing the correct data length again below
2418 // now all orders are being written out:
2419 // (wobei die Sache ggf. in mehrere 'Graphics Data Fields' aufgeteilt
2420 // wird, per Methode WillWriteOrder(..))
2421 WriteOrders(pMTF);
2423 //--- terminate the last Field 'Graphic Data':
2424 UpdateFieldSize();
2426 //--- and finally correct the segment size:
2427 nPos=pMET->Tell();
2428 nSegmentSize=nPos-nDataFieldsStartPos;
2429 nSegmentSize-=nNumberOfDataFields*8; // Structured Field Introducers are not counted
2430 pMET->Seek(nDataFieldsStartPos+16); // seek to the Lo-Word of the segment size
2431 WriteBigEndianShort((sal_uInt16)(nSegmentSize&0x0000ffff)); // Und schreiben
2432 pMET->Seek(nDataFieldsStartPos+22); // seek to the Hi-Word of the segment size
2433 WriteBigEndianShort((sal_uInt16)(nSegmentSize>>16)); // and writing it
2434 pMET->Seek(nPos); // back to business as usual
2436 //--- The Field 'End Graphic Objects':
2437 WriteFieldIntroducer(16,EndGrfObjMagic,0,0);
2438 WriteFieldId(7);
2440 if( pMET->GetError() )
2441 bStatus=false;
2445 void METWriter::WriteResourceGroup(const GDIMetaFile * pMTF)
2447 if( !bStatus )
2448 return;
2450 //--- The Field 'Begin Resource Group':
2451 WriteFieldIntroducer(16,BegResGrpMagic,0,0);
2452 WriteFieldId(2);
2454 //--- The Content:
2455 WriteColorAttributeTable();
2456 nActBitmapId=0x77777700;
2457 WriteImageObjects(pMTF);
2458 nActBitmapId=0x77777700;
2459 WriteGraphicsObject(pMTF);
2461 //--- The Field 'End Resource Group':
2462 WriteFieldIntroducer(16,EndResGrpMagic,0,0);
2463 WriteFieldId(2);
2465 if( pMET->GetError() )
2466 bStatus=false;
2470 void METWriter::WriteDocument(const GDIMetaFile * pMTF)
2472 if( !bStatus )
2473 return;
2475 //--- The Field 'Begin Document':
2476 WriteFieldIntroducer(0,BegDocumnMagic,0,0);
2477 WriteFieldId(1);
2478 pMET->WriteUChar( 0x00 ).WriteUChar( 0x00 );
2479 pMET->WriteUChar( 0x05 ).WriteUChar( 0x18 ).WriteUChar( 0x03 ).WriteUChar( 0x0c ).WriteUChar( 0x00 );
2480 pMET->WriteUChar( 0x06 ).WriteUChar( 0x01 ).WriteUChar( 0x03 ).WriteUChar( 0xd4 ).WriteUChar( 0x03 ).WriteUChar( 0x52 );
2481 pMET->WriteUChar( 0x03 ).WriteUChar( 0x65 ).WriteUChar( 0x00 );
2482 UpdateFieldSize();
2484 //--- The Content:
2485 WriteResourceGroup(pMTF);
2487 //--- The Field 'End Document':
2488 WriteFieldIntroducer(16,EndDocumnMagic,0,0);
2489 WriteFieldId(1);
2491 if( pMET->GetError() )
2492 bStatus=false;
2495 bool METWriter::WriteMET( const GDIMetaFile& rMTF, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem )
2497 if ( pFilterConfigItem )
2499 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
2500 if ( xStatusIndicator.is() )
2502 OUString aMsg;
2503 xStatusIndicator->start( aMsg, 100 );
2507 METChrSet* pCS;
2508 METGDIStackMember* pGS;
2510 bStatus=true;
2511 nLastPercent=0;
2513 pMET=&rTargetStream;
2514 pMET->SetEndian(SvStreamEndian::LITTLE);
2516 aPictureRect = Rectangle( Point(), rMTF.GetPrefSize() );
2517 aTargetMapMode = aPictureMapMode = rMTF.GetPrefMapMode();
2519 aGDILineColor=Color( COL_BLACK );
2520 aGDIFillColor=Color( COL_WHITE );
2521 eGDIRasterOp=ROP_OVERPAINT;
2522 aGDIFont=vcl::Font();
2523 aGDIMapMode=MapMode();
2524 aGDIClipRect=Rectangle();
2525 pGDIStack=NULL;
2526 aMETColor=Color(COL_BLACK);
2527 aMETBackgroundColor=Color(COL_WHITE);
2528 eMETMix=ROP_OVERPAINT;
2529 nMETStrokeLineWidth=1;
2530 aMETChrCellSize=Size(0,0);
2531 nMETChrAngle=0;
2532 nMETChrSet=0x00;
2533 pChrSetList=NULL;
2534 nNextChrSetId=1;
2535 nNumberOfActions=0;
2536 nNumberOfBitmaps=0;
2537 nWrittenActions=0;
2538 nWrittenBitmaps=0;
2539 nActBitmapPercent=0;
2541 CountActionsAndBitmaps(&rMTF);
2543 WriteDocument(&rMTF);
2545 while( pChrSetList )
2547 pCS=pChrSetList;
2548 pChrSetList=pCS->pSucc;
2549 delete pCS;
2552 while( pGDIStack )
2554 pGS=pGDIStack;
2555 pGDIStack=pGS->pSucc;
2556 delete pGS;
2559 if ( xStatusIndicator.is() )
2560 xStatusIndicator->end();
2562 return bStatus;
2565 //================== GraphicExport - the exported Function ================
2567 // this needs to be kept in sync with
2568 // ImpFilterLibCacheEntry::GetImportFunction() from
2569 // vcl/source/filter/graphicfilter.cxx
2570 #if defined(DISABLE_DYNLOADING)
2571 #define GraphicExport emeGraphicExport
2572 #endif
2574 extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
2575 GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem )
2577 METWriter aMETWriter;
2579 // #119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
2580 GDIMetaFile aMetafile(rGraphic.GetGDIMetaFile());
2582 if(usesClipActions(aMetafile))
2584 // #i121267# It is necessary to prepare the metafile since the export does *not* support
2585 // clip regions. This tooling method clips the geometry content of the metafile internally
2586 // against it's own clip regions, so that the export is safe to ignore clip regions
2587 clipMetafileContentAgainstOwnRegions(aMetafile);
2590 return aMETWriter.WriteMET( aMetafile, rStream, pFilterConfigItem );
2593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */