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