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