1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
103 //============================== METWriter ===================================
107 struct METChrSet
* pSucc
;
113 struct METGDIStackMember
115 struct METGDIStackMember
* pSucc
;
129 sal_uInt32 nLastPercent
; // with which number pCallback has been called the last time
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'
138 RasterOp eGDIRasterOp
;
140 MapMode aGDIMapMode
; // currently ununsed!
141 Rectangle aGDIClipRect
; // currently ununsed!
142 METGDIStackMember
* pGDIStack
;
144 Color aMETBackgroundColor
;
146 long nMETStrokeLineWidth
;
147 Size aMETChrCellSize
;
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
;
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
);
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
);
203 void METBeginPath(sal_uInt32 nPathId
);
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
);
243 , nActualFieldStartPos( 0 )
244 , nNumberOfDataFields( 0 )
245 , eGDIRasterOp( ROP_OVERPAINT
)
247 , eMETMix( ROP_OVERPAINT
)
248 , nMETStrokeLineWidth(0)
254 , nNumberOfActions( 0 )
255 , nNumberOfBitmaps( 0 )
256 , nWrittenActions( 0 )
257 , nWrittenBitmaps( 0 )
258 , nActBitmapPercent( 0 )
261 pCompDev
= reinterpret_cast< OutputDevice
* >( Application::GetAppWindow() );
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() )
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;
300 Polygon
aPoly( rRect
);
301 METBeginPath( nPathId
);
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();
323 for ( i
= 0; i
< nCount
; i
++ )
324 if ( ((const MetaAction
*)aGDIMetaFile
.GetAction( i
))->GetType() == MetaActionType::BMPSCALE
)
329 case MetaActionType::BMP
:
330 case MetaActionType::BMPSCALE
:
331 case MetaActionType::BMPSCALEPART
:
332 case MetaActionType::BMPEX
:
333 case MetaActionType::BMPEXSCALE
:
334 case MetaActionType::BMPEXSCALEPART
:
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()
380 pMET
->Seek(nActualFieldStartPos
);
381 WriteBigEndianShort((sal_uInt16
)(nPos
-nActualFieldStartPos
));
386 void METWriter::WriteFieldId(sal_uInt32 nId
)
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
;
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() );
425 void METWriter::CreateChrSet(const vcl::Font
& rFont
)
429 if ( FindChrSet( rFont
) == 0 )
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
)
444 for (pCS
=pChrSetList
; pCS
!=NULL
; pCS
=pCS
->pSucc
)
446 if (pCS
->aName
==rFont
.GetName() && pCS
->eWeight
==rFont
.GetWeight() )
454 void METWriter::WriteChrSets()
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;
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()));
503 if ( i
== 0 || c
!= 0 )
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'
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() );
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 );
555 //--- The Field 'End Color Attribute Table':
556 WriteFieldIntroducer(16,EndColAtrMagic
,0,0);
557 WriteFieldId(nFieldId
);
559 if (pMET
->GetError())
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
;
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
);
589 aTemp
.ReadUInt32( nWidth
).ReadUInt32( nHeight
);
591 aTemp
.ReadUInt16( nBitsPerPixel
);
593 aTemp
.ReadUInt32( nResX
).ReadUInt32( nResY
);
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
);
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);
650 pMET
->WriteUChar( 0x70 ).WriteUChar( 0x00 );
652 // Begin Image Content:
653 pMET
->WriteUChar( 0x91 ).WriteUChar( 0x01 ).WriteUChar( 0xff );
656 pMET
->WriteUChar( 0x94 ).WriteUChar( 0x09 ).WriteUChar( 0x02 );
657 pMET
->WriteUInt16( 0 ).WriteUInt16( 0 );
658 WriteBigEndianShort((sal_uInt16
)nHeight
);
659 WriteBigEndianShort((sal_uInt16
)nWidth
);
662 pMET
->WriteUChar( 0x95 ).WriteUChar( 0x02 ).WriteUChar( 0x03 ).WriteUChar( 0x03 );
665 pMET
->WriteUChar( 0x96 ).WriteUChar( 0x01 ).WriteUChar( nBitsPerPixel
);
667 if (nBitsPerPixel
<=8) {
669 pMET
->WriteUChar( 0x97 ).WriteUChar( 0x01 ).WriteUChar( 0x01 );
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
]);
682 // finalize the previous field 'Image Picture Data':
685 // and start a new field 'Image Picture Data':
686 WriteFieldIntroducer(0,DatImgObjMagic
,0,0);
688 // read and write several Scanlines:
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
);
704 if (aTemp
.GetError() || pMET
->GetError()) bStatus
=false;
705 nActBitmapPercent
=(ny
+1)*100/nHeight
;
707 if (!bStatus
) return;
711 // End Image Content:
712 pMET
->WriteUChar( 0x93 ).WriteUChar( 0x00 );
715 pMET
->WriteUChar( 0x71 ).WriteUChar( 0x00 );
717 // finalize the last field 'Image Picture Data':
720 //--- The Field 'End Image Object':
721 WriteFieldIntroducer(16,EndImgObjMagic
,0,0);
722 WriteFieldId(nActBitmapId
);
731 if (pMET
->GetError()) bStatus
=false;
735 void METWriter::WriteImageObjects(const GDIMetaFile
* pMTF
)
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() );
753 case MetaActionType::BMPSCALE
:
755 METSetMix( eGDIRasterOp
);
756 WriteImageObject( static_cast<const MetaBmpScaleAction
*>(pMA
)->GetBitmap() );
760 case MetaActionType::BMPSCALEPART
:
762 METSetMix( eGDIRasterOp
);
763 WriteImageObject( static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetBitmap() );
767 case MetaActionType::BMPEX
:
769 METSetMix( eGDIRasterOp
);
770 WriteImageObject( Graphic( static_cast<const MetaBmpExAction
*>(pMA
)->GetBitmapEx() ).GetBitmap() );
774 case MetaActionType::BMPEXSCALE
:
776 METSetMix( eGDIRasterOp
);
777 WriteImageObject( Graphic( static_cast<const MetaBmpExScaleAction
*>(pMA
)->GetBitmapEx() ).GetBitmap() );
781 case MetaActionType::BMPEXSCALEPART
:
783 METSetMix( eGDIRasterOp
);
784 WriteImageObject( Graphic( static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetBitmapEx() ).GetBitmap() );
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() );
814 if (pMET
->GetError())
818 void METWriter::WriteDataDescriptor(const GDIMetaFile
*)
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
837 // 7 Length of following field 0x01
838 // 8 Coordinate types in data
841 pMET
->WriteUChar( 0xf7 ).WriteUChar( 0x07 ).WriteUChar( 0xb0 ).WriteUChar( 0x00 )
842 .WriteUChar( 0x00 ).WriteUChar( 0x23 ).WriteUChar( 0x01 ).WriteUChar( 0x01 )
845 // 0 0xF6 Set Picture Descriptor
846 // 1 Length of following data
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
854 // B'1' Pels (PU_PELS PS)
855 // (Bit 1 must also be set)
858 // 4 Picture frame size coordinate type
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
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() )
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
888 // 0x00 Picture in 2D
895 pMET
->WriteUChar( 0x21 ).WriteUChar( 0x07 ).WriteUChar( 0x08 ).WriteUChar( 0xe0 )
896 .WriteUChar( 0x00 ).WriteUChar( 0x8f ).WriteUChar( 0x00 ).WriteUChar( 0x05 )
899 // 0 0x21 Set Current Defaults
900 // 1 Length of following data
901 // 2 Set default viewing transform 0x07
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:
918 // 0x0800 Stroke width
923 // 0x0F Set indicated default attributes to initial values. (Data field is not present in this
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
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
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
958 // 0x0FSet indicated default attributes to initial values. (Data field is not present in this
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
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:
988 // 0x1000 Marker precision
990 // 0x0100 Marker symbol
991 // 0x0008 Marker color
992 // 0x0004 Marker background color
994 // 0x0001 Marker background mix
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
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
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
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
1051 // 0x0001 Image background mix
1053 // 0x0F Set indicated default attributes to initial values. (Data field is not present in
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
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
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
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:
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
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
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
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
1122 if (nNumberOfBitmaps
>0) {
1123 pMET
->WriteUChar( 0xe7 ).WriteUChar( 0x07 ).WriteUChar( 0x80 ).WriteUChar( 0x00 );
1124 WriteBigEndianLong(nActBitmapId
);
1125 pMET
->WriteUChar( 0xfe );
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)
1144 WriteFieldIntroducer(0,DatGrfObjMagic
,0,0);
1145 nNumberOfDataFields
++;
1151 void METWriter::METBitBlt(Point aPt
, Size aSize
, const Size
& rBmpSizePixel
)
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 )
1171 .WriteUChar( 0 ) // Flags
1173 .WriteInt32( nWidth
);
1175 if ( rLineInfo
.GetStyle() != LINE_SOLID
)
1177 sal_uInt8 nStyle
= 0; // LineDefault;
1179 switch ( rLineInfo
.GetStyle() )
1187 if ( rLineInfo
.GetDotCount() )
1189 if ( !rLineInfo
.GetDashCount() )
1190 nStyle
= 1; // LINE_DOT
1192 nStyle
= 3; // LINE_DASH_DOT
1195 nStyle
= 2; // LINE_DASH
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 )
1212 .WriteUChar( 0 ) // Flags
1216 if ( rLineInfo
.GetStyle() != LINE_SOLID
)
1218 WillWriteOrder( 2 );
1219 pMET
->WriteUChar( 0x18 ).WriteUChar( 0 ); // set LineType
1223 void METWriter::METBeginArea(bool bBoundaryLine
)
1226 pMET
->WriteUChar( 0x68 );
1227 if (bBoundaryLine
) pMET
->WriteUChar( 0xc0 );
1228 else pMET
->WriteUChar( 0x80 );
1232 void METWriter::METEndArea()
1235 pMET
->WriteUChar( 0x60 ).WriteUChar( 0 );
1239 void METWriter::METBeginPath(sal_uInt32 nPathId
)
1242 pMET
->WriteUChar( 0xd0 ).WriteUChar( 6 ).WriteUInt16( 0 ).WriteUInt32( nPathId
);
1246 void METWriter::METEndPath()
1249 pMET
->WriteUChar( 0x7f ).WriteUChar( 0 );
1253 void METWriter::METFillPath(sal_uInt32 nPathId
)
1256 pMET
->WriteUChar( 0xd7 ).WriteUChar( 6 )
1257 .WriteUChar( 0x00 ).WriteUChar( 0 ).WriteUInt32( nPathId
);
1261 void METWriter::METOutlinePath(sal_uInt32 nPathId
)
1264 pMET
->WriteUChar( 0xd4 ).WriteUChar( 6 )
1265 .WriteUChar( 0 ).WriteUChar( 0 ).WriteUInt32( nPathId
);
1269 void METWriter::METCloseFigure()
1272 pMET
->WriteUChar( 0x7d ).WriteUChar( 0 );
1276 void METWriter::METMove(Point aPt
)
1279 pMET
->WriteUChar( 0x21 ).WriteUChar( 8 );
1284 void METWriter::METLine(Point aPt1
, Point aPt2
)
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
;
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);
1304 pMET
->WriteUChar( 0xc1 ); // Line at given pos
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
));
1326 void METWriter::METLineAtCurPos(Point aPt
)
1329 pMET
->WriteUChar( 0x81 ).WriteUChar( 8 );
1333 void METWriter::METBox(bool bFill
, bool bBoundary
,
1334 const Rectangle
& rRect
, sal_uInt32 nHAxis
, sal_uInt32 nVAxis
)
1337 if (bFill
) nFlags
|=0x40;
1338 if (bBoundary
) nFlags
|=0x20;
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
)
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;
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
);
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
)
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;
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
;
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
)
1430 case ROP_INVERT
: nMix
=0x0c; break;
1431 case ROP_XOR
: nMix
=0x04; break;
1436 pMET
->WriteUChar( 0x0c ).WriteUChar( nMix
);
1440 void METWriter::METSetChrCellSize(Size aSize
)
1442 if (aMETChrCellSize
==aSize
)
1445 aMETChrCellSize
=aSize
;
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
)
1456 if (nMETChrAngle
==nAngle
) return;
1457 nMETChrAngle
=nAngle
;
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);
1472 pMET
->WriteUChar( 0x34 ).WriteUChar( 8 ).WriteInt32( nax
).WriteInt32( nay
);
1476 void METWriter::METSetChrSet(sal_uInt8 nSet
)
1478 if (nMETChrSet
==nSet
)
1483 pMET
->WriteUChar( 0x38 ).WriteUChar( nSet
);
1487 void METWriter::WriteOrders( const GDIMetaFile
* pMTF
)
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() );
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);
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
);
1533 METLine( pA
->GetStartPoint(), pA
->GetEndPoint() );
1535 METOutlinePath( 1 );
1537 if ( ! ( aLineInfo
.IsDefault() ) )
1538 METPopLineInfo( aLineInfo
);
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 );
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() );
1585 case MetaActionType::ELLIPSE
:
1587 const MetaEllipseAction
* pA
= static_cast<const MetaEllipseAction
*>(pMA
);
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);
1605 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
1607 METSetMix( eGDIRasterOp
);
1608 METSetColor( aGDILineColor
);
1609 METFullArc( aCenter
,0.5 );
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);
1644 METPartialArcAtCurPos(aCenter
,0.5,fa1
,fa2
-fa1
);
1651 case MetaActionType::PIE
:
1653 const MetaPieAction
* pA
= static_cast<const MetaPieAction
*>(pMA
);
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
);
1681 METPartialArcAtCurPos(aCenter
,0.5,fa1
,fa2
-fa1
);
1682 METLineAtCurPos(aCenter
);
1687 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
1689 METSetMix( eGDIRasterOp
);
1690 METSetColor( aGDILineColor
);
1693 METPartialArcAtCurPos(aCenter
,0.5,fa1
,fa2
-fa1
);
1694 METLineAtCurPos(aCenter
);
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
);
1731 METPartialArcAtCurPos(aCenter
,0.5,fa1
,fa2
-fa1
);
1732 METLineAtCurPos(aStartPos
);
1737 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
1739 METSetMix( eGDIRasterOp
);
1740 METSetColor( aGDILineColor
);
1743 METPartialArcAtCurPos(aCenter
,0.5,fa1
,fa2
-fa1
);
1744 METLineAtCurPos(aStartPos
);
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
);
1764 Polygon aSimplePoly
;
1765 const Polygon
& rPoly
= pA
->GetPolygon();
1766 if ( rPoly
.HasFlags() )
1767 rPoly
.AdaptiveSubdivide( aSimplePoly
);
1769 aSimplePoly
= rPoly
;
1770 METLine( aSimplePoly
);
1774 if ( ! ( aLineInfo
.IsDefault() ) )
1775 METPopLineInfo( aLineInfo
);
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
);
1788 aSimplePoly
= rPoly
;
1789 if( aGDIFillColor
!= Color( COL_TRANSPARENT
) )
1791 METSetMix(eGDIRasterOp
);
1792 METSetColor(aGDIFillColor
);
1793 METSetBackgroundColor(aGDIFillColor
);
1795 METLine( aSimplePoly
);
1800 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
1802 METSetMix(eGDIRasterOp
);
1803 METSetColor(aGDILineColor
);
1805 METLine( aSimplePoly
);
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
);
1833 METLine( aSimplePolyPoly
);
1838 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
1840 METSetMix(eGDIRasterOp
);
1841 METSetColor(aGDILineColor
);
1843 METLine( aSimplePolyPoly
);
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();
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()));
1875 case MetaActionType::TEXTARRAY
:
1877 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pMA
);
1880 Polygon
aPolyDummy(1);
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();
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
)
1905 for( i
=0; i
< aStr
.getLength(); i
++ )
1910 aPt2
.X() += pA
->GetDXArray()[i
-1];
1913 aPolyDummy
.SetPoint( aPt2
, 0 );
1914 aPolyDummy
.Rotate( aPt
, nOrientation
);
1915 aPt2
= aPolyDummy
.GetPoint( 0 );
1918 METChrStr( aPt2
, OUString( aStr
[ i
] ) );
1922 METChrStr( aPt
, aStr
);
1926 case MetaActionType::STRETCHTEXT
:
1928 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pMA
);
1929 ScopedVclPtrInstance
< VirtualDevice
> pVDev
;
1931 sal_Int32 nNormSize
;
1933 Polygon
aPolyDummy(1);
1935 Point
aPt( pA
->GetPoint() );
1938 pVDev
->SetFont( aGDIFont
);
1940 if( aGDIFont
.GetAlign() != ALIGN_BASELINE
)
1942 if( aGDIFont
.GetAlign() == ALIGN_TOP
)
1943 aPt
.Y()+=(long)pVDev
->GetFontMetric().GetAscent();
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
++ )
1961 if (i
> 0 && nNormSize
)
1963 aPt2
.X() += pDXAry
[i
-1]*((long)pA
->GetWidth())/ nNormSize
;
1966 aPolyDummy
.SetPoint( aPt2
, 0 );
1967 aPolyDummy
.Rotate( aPt
, nOrientation
);
1968 aPt2
= aPolyDummy
.GetPoint( 0 );
1971 METChrStr( aPt2
, OUString( aStr
[ i
] ) );
1976 case MetaActionType::TEXTRECT
:
1978 // OSL_FAIL( "Unsupported MET-Action: MetaActionType::TEXTRECT!" );
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
);
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() );
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() );
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
);
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
);
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() );
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() );
2063 case MetaActionType::MASK
:
2066 case MetaActionType::MASKSCALE
:
2069 case MetaActionType::MASKSCALEPART
:
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
);
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
);
2096 case MetaActionType::WALLPAPER
:
2099 case MetaActionType::CLIPREGION
:
2102 case MetaActionType::ISECTRECTCLIPREGION
:
2104 const MetaISectRectClipRegionAction
* pA
= static_cast<const MetaISectRectClipRegionAction
*>(pMA
);
2105 WriteClipRect( pA
->GetRect() );
2109 case MetaActionType::ISECTREGIONCLIPREGION
:
2112 case MetaActionType::MOVECLIPREGION
:
2115 case MetaActionType::LINECOLOR
:
2117 const MetaLineColorAction
* pA
= static_cast<const MetaLineColorAction
*>(pMA
);
2119 if( pA
->IsSetting() )
2120 aGDILineColor
= pA
->GetColor();
2122 aGDILineColor
= Color( COL_TRANSPARENT
);
2126 case MetaActionType::FILLCOLOR
:
2128 const MetaFillColorAction
* pA
= static_cast<const MetaFillColorAction
*>(pMA
);
2130 if( pA
->IsSetting() )
2131 aGDIFillColor
= pA
->GetColor();
2133 aGDIFillColor
= Color( COL_TRANSPARENT
);
2137 case MetaActionType::TEXTCOLOR
:
2139 const MetaTextColorAction
* pA
= static_cast<const MetaTextColorAction
*>(pMA
);
2140 aGDIFont
.SetColor( pA
->GetColor() );
2144 case MetaActionType::TEXTFILLCOLOR
:
2146 const MetaTextFillColorAction
* pA
= static_cast<const MetaTextFillColorAction
*>(pMA
);
2148 if( pA
->IsSetting() )
2149 aGDIFont
.SetFillColor( pA
->GetColor() );
2151 aGDIFont
.SetFillColor( Color( COL_TRANSPARENT
) );
2155 case MetaActionType::TEXTALIGN
:
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 );
2179 aX
-= BigInt( (aScaleX
.GetNumerator()+1)/2 );
2183 if( aScaleX
.GetNumerator() >= 0 )
2184 aX
-= BigInt( (aScaleX
.GetNumerator()-1)/2 );
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 );
2200 aY
-= BigInt( (aScaleY
.GetNumerator()+1)/2 );
2204 if( aScaleY
.GetNumerator() >= 0 )
2205 aY
-= BigInt( (aScaleY
.GetNumerator()-1)/2 );
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
);
2220 aPictureMapMode
=pA
->GetMapMode();
2225 case MetaActionType::FONT
:
2227 aGDIFont
= static_cast<const MetaFontAction
*>(pMA
)->GetFont();
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
;
2245 case MetaActionType::POP
:
2247 METGDIStackMember
* pGS
;
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
;
2264 case MetaActionType::RASTEROP
:
2266 eGDIRasterOp
= static_cast<const MetaRasterOpAction
*>(pMA
)->GetRasterOp();
2270 case MetaActionType::Transparent
:
2272 if( aGDIFillColor
!= Color( COL_TRANSPARENT
) )
2274 METSetMix(eGDIRasterOp
);
2275 METSetColor(aGDIFillColor
);
2276 METSetBackgroundColor(aGDIFillColor
);
2278 METLine( static_cast<const MetaTransparentAction
*>(pMA
)->GetPolyPolygon());
2283 if( aGDILineColor
!= Color( COL_TRANSPARENT
) )
2285 METSetMix(eGDIRasterOp
);
2286 METSetColor(aGDILineColor
);
2288 METLine( static_cast<const MetaTransparentAction
*>(pMA
)->GetPolyPolygon());
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
);
2328 if( pMET
->GetError() )
2336 void METWriter::WriteObjectEnvironmentGroup(const GDIMetaFile
* pMTF
)
2340 //--- The Field 'Begin Object Environment Group':
2341 WriteFieldIntroducer(16,BegObjEnvMagic
,0,0);
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 );
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
);
2364 //--- The Fields 'Map Data Resource':
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 );
2372 pMET
->WriteUChar( 0x07 ).WriteUChar( 0x22 ).WriteUChar( 0x10 );
2373 pMET
->WriteUInt32( nId
);
2377 //--- Das Feld 'End Object Environment Group':
2378 WriteFieldIntroducer(16,EndObjEnvMagic
,0,0);
2383 void METWriter::WriteGraphicsObject(const GDIMetaFile
* pMTF
)
2385 sal_uInt32 nSegmentSize
,nPos
,nDataFieldsStartPos
;
2390 //--- Das Feld 'Begin Graphics Object':
2391 WriteFieldIntroducer(16,BegGrfObjMagic
,0,0);
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(..))
2423 //--- terminate the last Field 'Graphic Data':
2426 //--- and finally correct the segment size:
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);
2440 if( pMET
->GetError() )
2445 void METWriter::WriteResourceGroup(const GDIMetaFile
* pMTF
)
2450 //--- The Field 'Begin Resource Group':
2451 WriteFieldIntroducer(16,BegResGrpMagic
,0,0);
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);
2465 if( pMET
->GetError() )
2470 void METWriter::WriteDocument(const GDIMetaFile
* pMTF
)
2475 //--- The Field 'Begin Document':
2476 WriteFieldIntroducer(0,BegDocumnMagic
,0,0);
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 );
2485 WriteResourceGroup(pMTF
);
2487 //--- The Field 'End Document':
2488 WriteFieldIntroducer(16,EndDocumnMagic
,0,0);
2491 if( pMET
->GetError() )
2495 bool METWriter::WriteMET( const GDIMetaFile
& rMTF
, SvStream
& rTargetStream
, FilterConfigItem
* pFilterConfigItem
)
2497 if ( pFilterConfigItem
)
2499 xStatusIndicator
= pFilterConfigItem
->GetStatusIndicator();
2500 if ( xStatusIndicator
.is() )
2503 xStatusIndicator
->start( aMsg
, 100 );
2508 METGDIStackMember
* pGS
;
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();
2526 aMETColor
=Color(COL_BLACK
);
2527 aMETBackgroundColor
=Color(COL_WHITE
);
2528 eMETMix
=ROP_OVERPAINT
;
2529 nMETStrokeLineWidth
=1;
2530 aMETChrCellSize
=Size(0,0);
2539 nActBitmapPercent
=0;
2541 CountActionsAndBitmaps(&rMTF
);
2543 WriteDocument(&rMTF
);
2545 while( pChrSetList
)
2548 pChrSetList
=pCS
->pSucc
;
2555 pGDIStack
=pGS
->pSucc
;
2559 if ( xStatusIndicator
.is() )
2560 xStatusIndicator
->end();
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
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: */