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
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26
27 #include <vcl/metaact.hxx>
28 #include <svtools/filter.hxx>
29 #include <svl/solar.hrc>
30 #include <svtools/fltcall.hxx>
31
32 #include <math.h>
33 #include <vcl/bmpacc.hxx>
34 #include <vcl/metaact.hxx>
35 #include <vcl/graph.hxx>
36 #include <vcl/bmpacc.hxx>
37 #include <vcl/gradient.hxx>
38 #include <vcl/hatch.hxx>
39 #include <vcl/metric.hxx>
40 #include <vcl/font.hxx>
41 #include <vcl/virdev.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <vcl/gdimtf.hxx>
45
46 #include <tools/bigint.hxx>
47
48 #include <basegfx/polygon/b2dpolygon.hxx>
49 #include <basegfx/polygon/b2dpolypolygon.hxx>
50
51 //============================== PictWriter ===================================
52
53 struct PictWriterAttrStackMember {
54 struct PictWriterAttrStackMember * pSucc;
55 Color aLineColor;
56 Color aFillColor;
57 RasterOp eRasterOp;
58 Font aFont;
59 MapMode aMapMode;
60 Rectangle aClipRect;
61 };
62
63
64 enum PictDrawingMethod {
65 PDM_FRAME, PDM_PAINT, PDM_ERASE, PDM_INVERT, PDM_FILL
66 };
67
68
69 struct PictPattern {
70 sal_uInt32 nLo, nHi;
71 };
72
73 class PictWriter {
74
75 private:
76
77 sal_Bool bStatus;
78 sal_uLong nLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde.
79 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
80
81 SvStream * pPict;
82
83 // Aktuelle Attribute im Quell-Metafile:
84 Color aLineColor;
85 Color aFillColor;
86 RasterOp eSrcRasterOp;
87 Font aSrcFont;
88 MapMode aSrcMapMode;
89 MapMode aTargetMapMode;
90 Rectangle aClipRect;
91 PictWriterAttrStackMember * pAttrStack;
92
93 // Aktuelle Attribute im Ziel-Metafile, und ob sie gueltig sind
94 sal_Bool bDstBkPatVisible; sal_Bool bDstBkPatValid;
95 sal_uInt8 nDstTxFace; sal_Bool bDstTxFaceValid;
96 RasterOp eDstTxMode; sal_Bool bDstTxModeValid;
97 sal_uInt16 nDstPnSize; sal_Bool bDstPnSizeValid;
98 RasterOp eDstPnMode; sal_Bool bDstPnModeValid;
99 PictPattern aDstPnPat; sal_Bool bDstPnPatValid;
100 sal_Bool bDstFillPatVisible; sal_Bool bDstFillPatValid;
101 sal_uInt16 nDstTxSize; sal_Bool bDstTxSizeValid;
102 Color aDstFgCol; sal_Bool bDstFgColValid;
103 Color aDstBkCol; sal_Bool bDstBkColValid;
104 Point aDstPenPosition; sal_Bool bDstPenPositionValid;
105 Point aDstTextPosition; sal_Bool bDstTextPositionValid;
106 String aDstFontName; sal_uInt16 nDstFontNameId; sal_Bool bDstFontNameValid;
107
108 sal_uLong nNumberOfActions; // Anzahl der Actions im GDIMetafile
109 sal_uLong nNumberOfBitmaps; // Anzahl der Bitmaps
110 sal_uLong nWrittenActions; // Anzahl der bereits verarbeiteten Actions beim Schreiben der Opcodes
111 sal_uLong nWrittenBitmaps; // Anzahl der bereits geschriebenen Bitmaps
112 sal_uLong nActBitmapPercent; // Wieviel Prozent die naechste Bitmap schon geschrieben ist.
113
114 void MayCallback();
115 // Berechnet anhand der obigen 5 Parameter eine Prozentzahl
116 // und macht dann ggf. einen Callback. Setzt bStatus auf sal_False wenn User abbrechen
117 // moechte.
118
119 void CountActionsAndBitmaps(const GDIMetaFile & rMTF);
120 // Zaehlt die Bitmaps und Actions (nNumberOfActions und nNumberOfBitmaps muessen
121 // zu Anfang auf 0 gesetzt werden, weil diese Methode rekursiv ist)
122
123 Polygon PolyPolygonToPolygon(const PolyPolygon & rPoly);
124 // Macht aus einem PolyPolygon ein halbwegs vernuenftiges Polygon
125
126 Rectangle MapRectangle( const Rectangle& rRect );
127 void WritePoint(const Point & rPoint);
128 void WriteSize(const Size & rSize);
129 void WriteRGBColor(const Color & rColor);
130 void WriteString( const String & rString );
131 void WriteRectangle(const Rectangle & rRect);
132 void WritePolygon(const Polygon & rPoly);
133 void WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
134
135 void ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible);
136 void ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible);
137
138 void WriteOpcode_TxFace(const Font & rFont);
139 void WriteOpcode_TxMode(RasterOp eMode);
140 void WriteOpcode_PnSize(sal_uInt16 nSize);
141 void WriteOpcode_PnMode(RasterOp eMode);
142 void WriteOpcode_PnLinePat(sal_Bool bVisible);
143 void WriteOpcode_PnFillPat(sal_Bool bVisible);
144 void WriteOpcode_OvSize(const Size & rSize);
145 void WriteOpcode_TxSize(sal_uInt16 nSize);
146 void WriteOpcode_RGBFgCol(const Color & rColor);
147 void WriteOpcode_RGBBkCol(const Color & rColor);
148 void WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt);
149 void WriteOpcode_LineFrom(const Point & rNewPt);
150 void WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta);
151 void WriteOpcode_FontName(const Font & rFont);
152 void WriteOpcode_ClipRect( const Rectangle& rRect );
153 void WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect);
154 void WriteOpcode_SameRect(PictDrawingMethod eMethod);
155 void WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect);
156 void WriteOpcode_SameRRect(PictDrawingMethod eMethod);
157 void WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect);
158 void WriteOpcode_SameOval(PictDrawingMethod eMethod);
159 void WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect,
160 const Point & rStartPt, const Point & rEndPt);
161 void WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect,
162 const Point & rStartPt, const Point & rEndPt);
163 void WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly);
164 void WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap);
165 void WriteOpcode_EndOfFile();
166
167 void SetAttrForPaint();
168 void SetAttrForFrame();
169 void SetAttrForText();
170
171 void WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry);
172
173 void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
174 void WriteOpcodes(const GDIMetaFile & rMTF);
175
176 void WriteHeader(const GDIMetaFile & rMTF);
177 void UpdateHeader();
178
179 public:
180
181 sal_Bool WritePict( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem );
182 };
183
184
185 //========================== Methoden von PictWriter ==========================
186
187
MayCallback()188 void PictWriter::MayCallback()
189 {
190 if ( xStatusIndicator.is() )
191 {
192 sal_uLong nPercent;
193 nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
194 *100
195 /((nNumberOfBitmaps<<14)+nNumberOfActions);
196
197 if (nPercent>=nLastPercent+3)
198 {
199 nLastPercent=nPercent;
200 if( nPercent<=100 )
201 xStatusIndicator->setValue( nPercent );
202 }
203 }
204 }
205
CountActionsAndBitmaps(const GDIMetaFile & rMTF)206 void PictWriter::CountActionsAndBitmaps(const GDIMetaFile & rMTF)
207 {
208 sal_uLong nAction, nActionCount;
209 const MetaAction* pMA;
210
211 nActionCount = rMTF.GetActionCount();
212
213 for (nAction=0; nAction<nActionCount; nAction++)
214 {
215 pMA = rMTF.GetAction( nAction );
216
217 switch( pMA->GetType() )
218 {
219 case META_BMP_ACTION:
220 case META_BMPSCALE_ACTION:
221 case META_BMPSCALEPART_ACTION:
222 case META_BMPEX_ACTION:
223 case META_BMPEXSCALE_ACTION:
224 case META_BMPEXSCALEPART_ACTION:
225 nNumberOfBitmaps++;
226 break;
227 }
228
229 nNumberOfActions++;
230 }
231 }
232
233
PolyPolygonToPolygon(const PolyPolygon & rPolyPoly)234 Polygon PictWriter::PolyPolygonToPolygon(const PolyPolygon & rPolyPoly)
235 {
236 sal_uInt16 nCount,nSize1,nSize2,np,i1,i2,i3,nBestIdx1,nBestIdx2;
237 long nDistSqr,nBestDistSqr, nCountdownTests;
238 Point aP1,aPRel;
239 Polygon aPoly1, aPoly2, aPoly3;
240
241 nCount=rPolyPoly.Count();
242 if (nCount==0) return Polygon(0);
243
244 aPoly1=rPolyPoly.GetObject(0);
245 for (np=1; np<nCount; np++) {
246 aPoly2=rPolyPoly.GetObject(np);
247
248 //-----------------Folgendes verschmilzt aPoly1 und aPoly2 zu aPoly1-----------------
249
250 nSize1=aPoly1.GetSize();
251 nSize2=aPoly2.GetSize();
252
253 // Zunaechst werden ein Punkt in aPoly1 (referenziert durch nBestIdx1) und ein
254 // Punkt in aPoly2 (referenziert durch nBestIdx2) gesucht, die moeglichst dicht
255 // beieinander liegen. Da dies mit quadratischem Aufwand einher geht, und somit
256 // manche Bilder Ewigkeiten benoetigen, um exportiert zu werden, begrenzen wir
257 // die Anzahl der Tests auf 1000, und brechen die Suche ggf. schon vorher ab.
258 // Dadruch wird das Ergebnis nicht falsch, sondern eventuell nicht so schoen.
259 nCountdownTests=1000;
260 nBestDistSqr=0x7fffffff;
261 nBestIdx1=0;
262 nBestIdx2=0;
263 for (i1=0; i1<nSize1; i1++) {
264 aP1=aPoly1.GetPoint(i1);
265 for (i2=0; i2<nSize2; i2++) {
266 aPRel=aPoly2.GetPoint(i2); aPRel-=aP1;
267 nDistSqr=aPRel.X()*aPRel.X()+aPRel.Y()*aPRel.Y();
268 if (nDistSqr<nBestDistSqr) {
269 nBestIdx1=i1;
270 nBestIdx2=i2;
271 nBestDistSqr=nDistSqr;
272 }
273 if (nCountdownTests<=0) break;
274 nCountdownTests--;
275 }
276 if (nCountdownTests<=0) break;
277 }
278
279 // Nun werden aPoly1 und aPoly2 zu einem Polygon aPoly3 (spaeter aPoly1) zusammengefuegt.
280 // Die beiden Polygone werden verbunden durch zwei zusaetzliche Kanten zwischen den oben
281 // gefundenen Punkten.
282 aPoly3.Clear();
283 aPoly3.SetSize(nSize1+nSize2+2);
284 i3=0;
285 for (i1=nBestIdx1; i1<nSize1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
286 for (i1=0; i1<=nBestIdx1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
287 for (i2=nBestIdx2; i2<nSize2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
288 for (i2=0; i2<=nBestIdx2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
289
290 aPoly1=aPoly3;
291
292 //-----------------------------------------------------------------------------------
293
294 }
295 return aPoly1;
296 }
297
298
WritePoint(const Point & rPoint)299 void PictWriter::WritePoint(const Point & rPoint)
300 {
301 Point aPoint = OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode );
302 *pPict << ((short)aPoint.Y()) << ((short)aPoint.X());
303 }
304
305
WriteSize(const Size & rSize)306 void PictWriter::WriteSize(const Size & rSize)
307 {
308 OutputDevice::LogicToLogic( rSize, aSrcMapMode, aTargetMapMode ); // -Wall is this needed.
309 *pPict << ((short)rSize.Height()) << ((short)rSize.Width());
310 }
311
312
WriteRGBColor(const Color & rColor)313 void PictWriter::WriteRGBColor(const Color & rColor)
314 {
315 const sal_uInt16 nR = ( (sal_uInt16) rColor.GetRed() << 8 ) | (sal_uInt16) rColor.GetRed();
316 const sal_uInt16 nG = ( (sal_uInt16) rColor.GetGreen() << 8 ) | (sal_uInt16) rColor.GetGreen();
317 const sal_uInt16 nB = ( (sal_uInt16) rColor.GetBlue() << 8 ) | (sal_uInt16) rColor.GetBlue();
318
319 *pPict << nR << nG << nB;
320 }
321
322
WriteString(const String & rString)323 void PictWriter::WriteString( const String & rString )
324 {
325 sal_uInt16 i,nLen;
326
327 ByteString aByteString( rString, gsl_getSystemTextEncoding() );
328 nLen = aByteString.Len();
329 if ( nLen > 255 )
330 nLen = 255;
331 *pPict << ( (sal_uInt8)nLen );
332 for ( i = 0; i < nLen; i++ )
333 *pPict << aByteString.GetChar( i );
334 }
335
MapRectangle(const Rectangle & rRect)336 Rectangle PictWriter::MapRectangle( const Rectangle& rRect )
337 {
338 Point aPoint = OutputDevice::LogicToLogic( rRect.TopLeft(), aSrcMapMode, aTargetMapMode );
339 Size aSize = OutputDevice::LogicToLogic( rRect.GetSize(), aSrcMapMode, aTargetMapMode );
340 Rectangle aRect( aPoint, aSize );
341 aRect.Justify();
342 aRect.nBottom++;
343 aRect.nRight++;
344 return aRect;
345 }
346
WriteRectangle(const Rectangle & rRect)347 void PictWriter::WriteRectangle(const Rectangle & rRect)
348 {
349 Rectangle aRect( MapRectangle( rRect ) );
350 *pPict << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
351 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
352 }
353
WritePolygon(const Polygon & rPoly)354 void PictWriter::WritePolygon(const Polygon & rPoly)
355 {
356 sal_uInt16 nDataSize,i,nSize;
357 short nMinX = 0, nMinY = 0, nMaxX = 0, nMaxY = 0;
358 short nx,ny;
359 Polygon aPoly(rPoly);
360
361 nSize=aPoly.GetSize();
362
363 if (aPoly.GetPoint(0) != aPoly.GetPoint(nSize-1))
364 {
365 nSize++;
366 aPoly.SetSize(nSize);
367 aPoly.SetPoint(aPoly.GetPoint(0),nSize-1);
368 }
369
370 nDataSize=nSize*4+10;
371 for (i=0; i<nSize; i++)
372 {
373 Point aPoint = OutputDevice::LogicToLogic( aPoly.GetPoint( i ),
374 aSrcMapMode,
375 aTargetMapMode );
376
377 nx = (short) aPoint.X();
378 ny = (short) aPoint.Y();
379
380 if ( i==0 || nMinX>nx )
381 nMinX=nx;
382 if ( i==0 || nMinY>ny )
383 nMinY=ny;
384 if ( i==0 || nMaxX<nx )
385 nMaxX=nx;
386 if ( i==0 || nMaxY<ny )
387 nMaxY=ny;
388 }
389
390 *pPict << nDataSize << nMinY << nMinX << nMaxY << nMaxX;
391
392 for (i=0; i<nSize; i++)
393 WritePoint( aPoly.GetPoint(i) );
394 }
395
396
WriteArcAngles(const Rectangle & rRect,const Point & rStartPt,const Point & rEndPt)397 void PictWriter::WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
398 {
399 Point aStartPt = OutputDevice::LogicToLogic( rStartPt,
400 aSrcMapMode,
401 aTargetMapMode );
402 Point aEndPt = OutputDevice::LogicToLogic( rEndPt,
403 aSrcMapMode,
404 aTargetMapMode );
405 Rectangle aRect( OutputDevice::LogicToLogic( rRect.TopLeft(),
406 aSrcMapMode,
407 aTargetMapMode ),
408 OutputDevice::LogicToLogic( rRect.GetSize(),
409 aSrcMapMode,
410 aTargetMapMode ) );
411 Point aCenter;
412 double fAngS, fAngE, fdx, fdy;
413 short nStartAngle, nArcAngle;
414
415
416 aCenter=Point( ( aRect.Left() + aRect.Right() ) >> 1,
417 ( aRect.Top() + aRect.Bottom() ) >> 1 );
418
419 fdx=(double)(aStartPt.X()-aCenter.X());
420 fdy=(double)(aStartPt.Y()-aCenter.Y());
421 if ( fdx==0.0 && fdy==0.0 )
422 fdx=1.0;
423 fAngE=atan2(fdx,-fdy);
424
425 fdx=(double)(aEndPt.X()-aCenter.X());
426 fdy=(double)(aEndPt.Y()-aCenter.Y());
427 if ( fdx==0.0 && fdy==0.0 )
428 fdx=1.0;
429 fAngS=atan2(fdx,-fdy);
430
431 nStartAngle=(short)(fAngS*180.0/3.14159265359);
432 nArcAngle=((short)(fAngE*180.0/3.14159265359))-nStartAngle;
433 if (nArcAngle<0)
434 nArcAngle += 360;
435 *pPict << nStartAngle << nArcAngle;
436 }
437
438
ConvertLinePattern(PictPattern & rPat,sal_Bool bVisible)439 void PictWriter::ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible)
440 {
441 if( bVisible )
442 {
443 rPat.nHi=0xffffffff;
444 rPat.nLo=0xffffffff;
445 }
446 else
447 {
448 rPat.nHi=0x00000000;
449 rPat.nLo=0x00000000;
450 }
451 }
452
ConvertFillPattern(PictPattern & rPat,sal_Bool bVisible)453 void PictWriter::ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible)
454 {
455 if( bVisible )
456 {
457 rPat.nHi=0xffffffff;
458 rPat.nLo=0xffffffff;
459 }
460 else
461 {
462 rPat.nHi=0x00000000;
463 rPat.nLo=0x00000000;
464 }
465 }
466
467
WriteOpcode_TxFace(const Font & rFont)468 void PictWriter::WriteOpcode_TxFace(const Font & rFont)
469 {
470 sal_uInt8 nFace;
471 FontWeight eWeight;
472
473 nFace=0;
474 eWeight=rFont.GetWeight();
475 if (eWeight==WEIGHT_BOLD ||
476 eWeight==WEIGHT_SEMIBOLD ||
477 eWeight==WEIGHT_ULTRABOLD ||
478 eWeight==WEIGHT_BLACK) nFace|=0x01;
479 if (rFont.GetItalic()!=ITALIC_NONE) nFace|=0x02;
480 if (rFont.GetUnderline()!=UNDERLINE_NONE) nFace|=0x04;
481 if (rFont.IsOutline()==sal_True) nFace|=0x08;
482 if (rFont.IsShadow()==sal_True) nFace|=0x10;
483
484 if (bDstTxFaceValid==sal_False || nDstTxFace!=nFace) {
485 *pPict << (sal_uInt16)0x0004 << nFace << (sal_uInt8)0;
486 nDstTxFace=nFace;
487 bDstTxFaceValid=sal_True;
488 }
489 }
490
491
WriteOpcode_TxMode(RasterOp eMode)492 void PictWriter::WriteOpcode_TxMode(RasterOp eMode)
493 {
494 sal_uInt16 nVal;
495
496 if (bDstTxModeValid==sal_False || eDstTxMode!=eMode) {
497 switch (eMode) {
498 case ROP_INVERT: nVal=0x000c; break;
499 case ROP_XOR: nVal=0x000a; break;
500 default: nVal=0x0008;
501 }
502 *pPict << (sal_uInt16)0x0005 << nVal;
503 eDstTxMode=eMode;
504 bDstTxModeValid=sal_True;
505 }
506 }
507
508
WriteOpcode_PnSize(sal_uInt16 nSize)509 void PictWriter::WriteOpcode_PnSize(sal_uInt16 nSize)
510 {
511 if (nSize==0) nSize=1;
512 if (bDstPnSizeValid==sal_False || nDstPnSize!=nSize) {
513 *pPict << (sal_uInt16)0x0007 << nSize << nSize;
514 nDstPnSize=nSize;
515 bDstPnSizeValid=sal_True;
516 }
517 }
518
519
WriteOpcode_PnMode(RasterOp eMode)520 void PictWriter::WriteOpcode_PnMode(RasterOp eMode)
521 {
522 sal_uInt16 nVal;
523
524 if (bDstPnModeValid==sal_False || eDstPnMode!=eMode) {
525 switch (eMode)
526 {
527 case ROP_INVERT: nVal=0x000c; break;
528 case ROP_XOR: nVal=0x000a; break;
529 default: nVal=0x0008;
530 }
531 *pPict << (sal_uInt16)0x0008 << nVal;
532 eDstPnMode=eMode;
533 bDstPnModeValid=sal_True;
534 }
535 }
536
537
WriteOpcode_PnLinePat(sal_Bool bVisible)538 void PictWriter::WriteOpcode_PnLinePat(sal_Bool bVisible)
539 {
540 PictPattern aPat;
541
542 ConvertLinePattern(aPat,bVisible);
543 if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
544 *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
545 aDstPnPat=aPat;
546 bDstPnPatValid=sal_True;
547 }
548 }
549
550
WriteOpcode_PnFillPat(sal_Bool bVisible)551 void PictWriter::WriteOpcode_PnFillPat(sal_Bool bVisible)
552 {
553 PictPattern aPat;
554
555 ConvertFillPattern(aPat,bVisible);
556 if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
557 *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
558 aDstPnPat=aPat;
559 bDstPnPatValid=sal_True;
560 }
561 }
562
563
WriteOpcode_OvSize(const Size & rSize)564 void PictWriter::WriteOpcode_OvSize(const Size & rSize)
565 {
566 *pPict << (sal_uInt16)0x000b;
567 WriteSize(rSize);
568 }
569
570
WriteOpcode_TxSize(sal_uInt16 nSize)571 void PictWriter::WriteOpcode_TxSize(sal_uInt16 nSize)
572 {
573 if (bDstTxSizeValid==sal_False || nDstTxSize!=nSize) {
574
575 nDstTxSize = (sal_uInt16) OutputDevice::LogicToLogic( Size( 0, nSize ),
576 aSrcMapMode, aTargetMapMode ).Height();
577
578 *pPict << (sal_uInt16)0x000d << nDstTxSize;
579 bDstTxSizeValid=sal_True;
580 }
581 }
582
583
WriteOpcode_RGBFgCol(const Color & rColor)584 void PictWriter::WriteOpcode_RGBFgCol(const Color & rColor)
585 {
586 if (bDstFgColValid==sal_False || aDstFgCol!=rColor) {
587 *pPict << (sal_uInt16)0x001a;
588 WriteRGBColor(rColor);
589 aDstFgCol=rColor;
590 bDstFgColValid=sal_True;
591 }
592 }
593
594
WriteOpcode_RGBBkCol(const Color & rColor)595 void PictWriter::WriteOpcode_RGBBkCol(const Color & rColor)
596 {
597 if (bDstBkColValid==sal_False || aDstBkCol!=rColor) {
598 *pPict << (sal_uInt16)0x001b;
599 WriteRGBColor(rColor);
600 aDstBkCol=rColor;
601 bDstBkColValid=sal_True;
602 }
603 }
604
605
WriteOpcode_Line(const Point & rLocPt,const Point & rNewPt)606 void PictWriter::WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt)
607 {
608 Point aLocPt = OutputDevice::LogicToLogic( rLocPt,
609 aSrcMapMode,
610 aTargetMapMode );
611 Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
612 aSrcMapMode,
613 aTargetMapMode );
614 long dh,dv;
615
616 dh=aNewPt.X()-aLocPt.X();
617 dv=aNewPt.Y()-aLocPt.Y();
618 if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
619 { // ShortLine
620 *pPict << (sal_uInt16)0x0022;
621 WritePoint(rLocPt);
622 *pPict << (char)dh << (char)dv;
623 }
624 else
625 {
626 *pPict << (sal_uInt16)0x0020;
627 WritePoint(rLocPt);
628 WritePoint(rNewPt);
629 }
630 aDstPenPosition=rNewPt;
631 bDstPenPositionValid=sal_True;
632 }
633
634
WriteOpcode_LineFrom(const Point & rNewPt)635 void PictWriter::WriteOpcode_LineFrom(const Point & rNewPt)
636 {
637 Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
638 aSrcMapMode,
639 aTargetMapMode );
640 long dh,dv;
641
642 dh = aNewPt.X()-aDstPenPosition.X();
643 dv = aNewPt.Y()-aDstPenPosition.Y();
644
645 if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
646 { // ShortLine
647 *pPict << (sal_uInt16)0x0023;
648 *pPict << (char)dh << (char)dv;
649 }
650 else
651 {
652 *pPict << (sal_uInt16)0x0021;
653 WritePoint(rNewPt);
654 }
655 aDstPenPosition=rNewPt;
656 bDstPenPositionValid=sal_True;
657 }
658
659
WriteOpcode_Text(const Point & rPoint,const String & rString,sal_Bool bDelta)660 void PictWriter::WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta)
661 {
662 Point aPoint = OutputDevice::LogicToLogic( rPoint,
663 aSrcMapMode,
664 aTargetMapMode );
665 long dh,dv;
666 sal_uLong nPos;
667
668 nPos = pPict->Tell();
669 dh = aPoint.X()-aDstTextPosition.X();
670 dv = aPoint.Y()-aDstTextPosition.Y();
671
672 if (bDstTextPositionValid==sal_False || dh<0 || dh>255 || dv<0 || dv>0 || bDelta==sal_False)
673 {
674 *pPict << (sal_uInt16)0x0028;
675 WritePoint(rPoint);
676 }
677 else if (dv==0)
678 {
679 *pPict << (sal_uInt16)0x0029 << (sal_uInt8)dh;
680 }
681 else if (dh==0)
682 {
683 *pPict << (sal_uInt16)0x002a << (sal_uInt8)dv;
684 }
685 else
686 {
687 *pPict << (sal_uInt16)0x002b << (sal_uInt8)dh << (sal_uInt8)dv;
688 }
689
690 WriteString( rString );
691 if (((pPict->Tell()-nPos)&1)!=0)
692 *pPict << (sal_uInt8)0;
693
694 aDstTextPosition = aPoint;
695 bDstTextPositionValid=sal_True;
696 }
697
698
WriteOpcode_FontName(const Font & rFont)699 void PictWriter::WriteOpcode_FontName(const Font & rFont)
700 {
701 sal_uInt16 nDataLen,nFontId;
702
703 switch (rFont.GetFamily()) {
704 case FAMILY_MODERN: nFontId=22; break;
705 case FAMILY_ROMAN: nFontId=20; break;
706 case FAMILY_SWISS: nFontId=21; break;
707 default: nFontId=1;
708 }
709
710 if (bDstFontNameValid==sal_False || nDstFontNameId!=nFontId || aDstFontName!=rFont.GetName())
711 {
712 ByteString aByteString( rFont.GetName(), gsl_getSystemTextEncoding() );
713 sal_uInt16 nFontNameLen = aByteString.Len();
714 if ( nFontNameLen )
715 {
716 nDataLen = 3 + nFontNameLen;
717 *pPict << (sal_uInt16)0x002c << nDataLen << nFontId;
718 WriteString( rFont.GetName() );
719 if ( ( nFontNameLen & 1 ) == 0 )
720 *pPict << (sal_uInt8)0;
721 }
722 *pPict << (sal_uInt16)0x0003 << nFontId;
723 aDstFontName=rFont.GetName();
724 nDstFontNameId=nFontId;
725 bDstFontNameValid=sal_True;
726 }
727 }
728
WriteOpcode_ClipRect(const Rectangle & rRect)729 void PictWriter::WriteOpcode_ClipRect( const Rectangle& rRect )
730 {
731 Rectangle aRect( MapRectangle( rRect ) );
732 aRect.nBottom++;
733 aRect.nRight++;
734 *pPict << (sal_uInt16)1 // opcode 1
735 << (sal_uInt16)10 // data size
736 << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
737 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
738 aClipRect = aRect;
739 }
740
WriteOpcode_Rect(PictDrawingMethod eMethod,const Rectangle & rRect)741 void PictWriter::WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect)
742 {
743 sal_uInt16 oc;
744 switch (eMethod) {
745 case PDM_FRAME: oc=0x0030; break;
746 case PDM_PAINT: oc=0x0031; break;
747 case PDM_ERASE: oc=0x0032; break;
748 case PDM_INVERT: oc=0x0033; break;
749 case PDM_FILL: oc=0x0034; break;
750 default: oc=0; break; // -Wall a default for oc...
751 }
752 *pPict << oc;
753 WriteRectangle(rRect);
754 }
755
756
WriteOpcode_SameRect(PictDrawingMethod eMethod)757 void PictWriter::WriteOpcode_SameRect(PictDrawingMethod eMethod)
758 {
759 sal_uInt16 oc;
760 switch (eMethod) {
761 case PDM_FRAME: oc=0x0038; break;
762 case PDM_PAINT: oc=0x0039; break;
763 case PDM_ERASE: oc=0x003a; break;
764 case PDM_INVERT: oc=0x003b; break;
765 case PDM_FILL: oc=0x003c; break;
766 default: oc=0; break; // -Wall a default for oc...
767 }
768 *pPict << oc;
769 }
770
771
WriteOpcode_RRect(PictDrawingMethod eMethod,const Rectangle & rRect)772 void PictWriter::WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect)
773 {
774 sal_uInt16 oc;
775 switch (eMethod) {
776 case PDM_FRAME: oc=0x0040; break;
777 case PDM_PAINT: oc=0x0041; break;
778 case PDM_ERASE: oc=0x0042; break;
779 case PDM_INVERT: oc=0x0043; break;
780 case PDM_FILL: oc=0x0044; break;
781 default: oc=0; break; // -Wall a default for oc...
782 }
783 *pPict << oc;
784 WriteRectangle(rRect);
785 }
786
787
WriteOpcode_SameRRect(PictDrawingMethod eMethod)788 void PictWriter::WriteOpcode_SameRRect(PictDrawingMethod eMethod)
789 {
790 sal_uInt16 oc;
791 switch (eMethod) {
792 case PDM_FRAME: oc=0x0048; break;
793 case PDM_PAINT: oc=0x0049; break;
794 case PDM_ERASE: oc=0x004a; break;
795 case PDM_INVERT: oc=0x004b; break;
796 case PDM_FILL: oc=0x004c; break;
797 default: oc=0; break; // -Wall a default for oc...
798 }
799 *pPict << oc;
800 }
801
802
WriteOpcode_Oval(PictDrawingMethod eMethod,const Rectangle & rRect)803 void PictWriter::WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect)
804 {
805 sal_uInt16 oc;
806 switch (eMethod) {
807 case PDM_FRAME: oc=0x0050; break;
808 case PDM_PAINT: oc=0x0051; break;
809 case PDM_ERASE: oc=0x0052; break;
810 case PDM_INVERT: oc=0x0053; break;
811 case PDM_FILL: oc=0x0054; break;
812 default: oc=0; break; // -Wall a default for oc...
813 }
814 *pPict << oc;
815 WriteRectangle(rRect);
816 }
817
818
WriteOpcode_SameOval(PictDrawingMethod eMethod)819 void PictWriter::WriteOpcode_SameOval(PictDrawingMethod eMethod)
820 {
821 sal_uInt16 oc;
822 switch (eMethod) {
823 case PDM_FRAME: oc=0x0058; break;
824 case PDM_PAINT: oc=0x0059; break;
825 case PDM_ERASE: oc=0x005a; break;
826 case PDM_INVERT: oc=0x005b; break;
827 case PDM_FILL: oc=0x005c; break;
828 default: oc=0; break; // -Wall a default for oc...
829 }
830 *pPict << oc;
831 }
832
833
WriteOpcode_Arc(PictDrawingMethod eMethod,const Rectangle & rRect,const Point & rStartPt,const Point & rEndPt)834 void PictWriter::WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect,
835 const Point & rStartPt, const Point & rEndPt)
836 {
837 sal_uInt16 oc;
838 switch (eMethod) {
839 case PDM_FRAME: oc=0x0060; break;
840 case PDM_PAINT: oc=0x0061; break;
841 case PDM_ERASE: oc=0x0062; break;
842 case PDM_INVERT: oc=0x0063; break;
843 case PDM_FILL: oc=0x0064; break;
844 default: oc=0; break; // -Wall a default for oc...
845 }
846 *pPict << oc;
847 WriteRectangle(rRect);
848 WriteArcAngles(rRect,rStartPt,rEndPt);
849 }
850
851
WriteOpcode_SameArc(PictDrawingMethod eMethod,const Rectangle & rRect,const Point & rStartPt,const Point & rEndPt)852 void PictWriter::WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect,
853 const Point & rStartPt, const Point & rEndPt)
854 {
855 sal_uInt16 oc;
856 switch (eMethod) {
857 case PDM_FRAME: oc=0x0068; break;
858 case PDM_PAINT: oc=0x0069; break;
859 case PDM_ERASE: oc=0x006a; break;
860 case PDM_INVERT: oc=0x006b; break;
861 case PDM_FILL: oc=0x006c; break;
862 default: oc=0; break; // -Wall a default for oc...
863 }
864 *pPict << oc;
865 WriteArcAngles(rRect,rStartPt,rEndPt);
866 }
867
868
WriteOpcode_Poly(PictDrawingMethod eMethod,const Polygon & rPoly)869 void PictWriter::WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly)
870 {
871 sal_uInt16 oc;
872
873 if (rPoly.GetSize()<3) return;
874 switch (eMethod) {
875 case PDM_FRAME: oc=0x0070; break;
876 case PDM_PAINT: oc=0x0071; break;
877 case PDM_ERASE: oc=0x0072; break;
878 case PDM_INVERT: oc=0x0073; break;
879 case PDM_FILL: oc=0x0074; break;
880 default: oc=0; break; // -Wall a default for oc...
881 }
882 *pPict << oc;
883 WritePolygon(rPoly);
884 }
885
886
WriteOpcode_BitsRect(const Point & rPoint,const Size & rSize,const Bitmap & rBitmap)887 void PictWriter::WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap)
888 {
889 BitmapReadAccess* pAcc = NULL;
890 Bitmap aBitmap( rBitmap );
891
892 sal_uLong nWidth, nHeight, nDstRowBytes, nx, nc, ny, nCount, nColTabSize, i;
893 sal_uLong nDstRowPos, nSrcRowBytes, nEqu3, nPos, nDstMapPos;
894 sal_uInt16 nBitsPerPixel, nPackType;
895 sal_uInt8 *pComp[4], *pPix, *pTemp;
896 sal_uInt8 nEquData = 0;
897 sal_uInt8 nFlagCounterByte, nRed, nGreen, nBlue;
898
899 SetAttrForPaint();
900
901 // temopraere Windows-BMP-Datei erzeugen:
902 nActBitmapPercent=30;
903 MayCallback();
904
905 if ( bStatus == sal_False )
906 return;
907 if ( ( pAcc = aBitmap.AcquireReadAccess() ) == NULL )
908 return;
909
910 nBitsPerPixel = aBitmap.GetBitCount();
911
912 // export code below only handles four discrete cases
913 nBitsPerPixel =
914 nBitsPerPixel <= 1 ? 1 : nBitsPerPixel <= 4 ? 4 : nBitsPerPixel <= 8 ? 8 : 24;
915
916 nWidth = pAcc->Width();
917 nHeight = pAcc->Height();
918
919 // Wenn 24-Bit, dann den Opcode 'DirectBitsRect' erzeugen:
920 if ( nBitsPerPixel == 24 )
921 {
922
923 // Anzahl Bytes einer (ungepackten) Zeile in Quelle und Ziel berechnen:
924 nSrcRowBytes =( ( 3 * nWidth ) + 0x0003 ) & 0xfffc;
925 nDstRowBytes = nWidth * 4;
926
927 // Opcode und BaseAddr (?) schreiben:
928 *pPict << (sal_uInt16)0x009a << (sal_uInt32)0x000000ff;
929
930 // Normalerweise wollen wir den Packing-Type 4 (Run length encoding
931 // for 32-Bit Pixels) erzeugen. Wenn aber RowBytes<8 gilt, sind die Daten
932 // grundsaetzlich ungepackt, auch wenn der Packing-Type 4 angegeben ist,
933 // was etwas komisch erscheint. Daher wollen wir in so einem Fall lieber
934 // gleich den Packing-Type 1 (ungepackt) angeben:
935
936 if ( nDstRowBytes < 8 )
937 nPackType = 1;
938 else
939 nPackType = 4;
940
941 // PixMap-Struktur schreiben:
942 *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes pro Zeile und dass es eine 'PixMap' ist
943 << (sal_uInt16)0x0000 // Y1-Position der Bitmap in der Quelle
944 << (sal_uInt16)0x0000 // X1-Position der Bitmap in der Quelle
945 << (sal_uInt16)nHeight // Y2-Position der Bitmap in der Quelle
946 << (sal_uInt16)nWidth // X2-Position der Bitmap in der Quelle
947 << (sal_uInt16)0x0000 // Version
948 << (sal_uInt16)nPackType // Packing type
949 << (sal_uInt32) 0x00000000 // Packing size (?)
950 << (sal_uInt32) 0x00480000 // H-Res
951 << (sal_uInt32) 0x00480000 // V-Res
952 << (sal_uInt16)0x0010 // Pixel type (?)
953 << (sal_uInt16)0x0020 // Pixel size: 32 bit
954 << (sal_uInt16)0x0004 // CmpCount: 4 Komponenten
955 << (sal_uInt16)0x0008 // CmpSize: 8 Bits
956 << (sal_uInt32) 0x00000000 // PlaneBytes (?)
957 << (sal_uInt32) 0x00000000 // (?)
958 << (sal_uInt32) 0x00000000; // (?)
959
960 // Source-Rectangle schreiben:
961 *pPict << (sal_uInt16)0x0000 // Y1-Position auf der Bitmap
962 << (sal_uInt16)0x0000 // X1-Position auf der Bitmap
963 << (sal_uInt16)nHeight // Y2-Position auf der Bitmap
964 << (sal_uInt16)nWidth; // X2-Position auf der Bitmap
965
966 // Destination-Rectangle schreiben:
967 WritePoint( rPoint );
968 WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
969
970 // Transfer mode schreiben:
971 *pPict << (sal_uInt16)0x0000; // (?)
972
973 // Position der Map-Daten in Ziel merken:
974 nDstMapPos=pPict->Tell();
975
976 if ( nPackType == 1 ) // bei 24 bits nWidth == 1 !!
977 { // nicht packen
978 for ( ny = 0; ny < nHeight; ny++ )
979 {
980 *pPict << (sal_uInt8)0;
981 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetRed();
982 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetGreen();
983 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetBlue();
984 // Prozente zaehlen, Callback, Fehler pruefen:
985 nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus)
986 MayCallback();
987 }
988 }
989 else // packen ( PackType == 4 )
990 {
991 // Speicher fuer Zeilen-Zwischen-Datenstruktur allozieren:
992 for ( nc = 0; nc < 4; nc++ )
993 pComp[ nc ] = new sal_uInt8[ nWidth ];
994
995 // Schleife ueber Zeilen:
996 for ( ny = 0; ny < nHeight; ny++ )
997 {
998 // Zeil ny der Quelle in die Zwischen-Datenstrktur einlesen:
999
1000 for ( nx = 0; nx < nWidth; nx++ )
1001 {
1002 pComp[ 1 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetRed();
1003 pComp[ 2 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetGreen();
1004 pComp[ 3 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetBlue();
1005 pComp[ 0 ][ nx ] = 0;
1006 }
1007
1008 // Anfang der Zeile im Ziel merken:
1009 nDstRowPos = pPict->Tell();
1010
1011 // ByteCount (das ist die Groesse der gepackten Zeile) zunaechst 0 (wird spaeter berichtigt):
1012 if ( nDstRowBytes > 250 )
1013 *pPict << (sal_uInt16)0;
1014 else
1015 *pPict << (sal_uInt8)0;
1016
1017 // Schleife ueber Componenten:
1018 for ( nc = 0; nc < 4; nc++ )
1019 {
1020 // Schleife ueber x:
1021 nx = 0;
1022 while ( nx < nWidth )
1023 {
1024 // Die Position von 3 gleichen Bytes suchen und in nEqu3 merken.
1025 // wenn nicht gefunden, dann nEqu3=nWidth setzten.
1026 // Wenn doch gefunden, dann in nEquData den Wert der Bytes merken.
1027 nEqu3 = nx;
1028 for (;;)
1029 {
1030 if ( nEqu3 + 2 >= nWidth )
1031 {
1032 nEqu3 = nWidth;
1033 break;
1034 }
1035 nEquData = pComp[nc][nEqu3];
1036 if ( nEquData == pComp[nc][nEqu3+1] && nEquData==pComp[nc][nEqu3+2] )
1037 break;
1038 nEqu3++;
1039 }
1040
1041 // Die Daten von nx bis nEqu3 unkomprimiert schreiben (ggf. in mehreren Records):
1042 while ( nEqu3 > nx )
1043 {
1044 nCount = nEqu3 - nx;
1045 if ( nCount > 128 )
1046 nCount=128;
1047 nFlagCounterByte = (sal_uInt8)(nCount-1);
1048 *pPict << nFlagCounterByte;
1049 do
1050 {
1051 *pPict << pComp[nc][nx++];
1052 nCount--;
1053 }
1054 while ( nCount > 0 );
1055 }
1056
1057 // Jetzt einen Komprimierungs-Record erzeugen (falls oben mindestens 3
1058 // gleiche Bytes gefunden):
1059 if ( nx < nWidth )
1060 { // Hinweis: es gilt nx==nEqu3 (hoffentlich)
1061 nCount=3; // Drei Bytes sind gleich, wie weiter oben herausgefunden.
1062 // Pruefen, ob es weitere gleiche Bytes gibts (dabei Max.-Record-Groesse beachten):
1063 while ( nx + nCount < nWidth && nCount < 128 )
1064 {
1065 if ( nEquData != pComp[ nc ][ nx + nCount ] )
1066 break;
1067 nCount++;
1068 }
1069 // nCount gleiche Bytes komprimiert schreiben:
1070 nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1071 *pPict << nFlagCounterByte << nEquData;
1072 nx += nCount;
1073 }
1074 }
1075 }
1076 // ByteCount berichtigen:
1077 nPos = pPict->Tell();
1078 pPict->Seek( nDstRowPos );
1079 if ( nDstRowBytes > 250 )
1080 *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1081 else
1082 *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1083 pPict->Seek( nPos );
1084
1085 // Prozente zaehlen, Callback, Fehler pruefen:
1086 nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus)
1087 MayCallback();
1088 }
1089 // Aufraeumen:
1090 for ( nc = 0; nc < 4; nc++ )
1091 delete pComp[ nc ];
1092 }
1093 }
1094 else
1095 { // nicht 24-Bit also Opcode 'PackBitsRect' erzeugen:
1096
1097 // Bei 1-Bit-Bildern ignorieren manche Import-Filter die Palette und nehmen statt
1098 // dessen die Vorder- und Hintergrundfarbe:
1099 if ( nBitsPerPixel == 1 )
1100 {
1101 WriteOpcode_RGBBkCol( pAcc->GetPaletteColor( 0 ) );
1102 WriteOpcode_RGBFgCol( pAcc->GetPaletteColor( 1 ) );
1103 }
1104 else
1105 {
1106 WriteOpcode_RGBBkCol( Color( COL_BLACK ) );
1107 WriteOpcode_RGBFgCol( Color( COL_WHITE ) );
1108 }
1109
1110 // Anzahl Bytes einer (ungepackten) Zeile in Ziel und Quelle berechnen:
1111 nDstRowBytes = ( nWidth * nBitsPerPixel + 7 ) >> 3;
1112 nSrcRowBytes = ( nDstRowBytes + 3 ) & 0xfffffffc;
1113
1114 // Opcode schreiben:
1115 *pPict << (sal_uInt16)0x0098;
1116
1117 // Normalerweise wollen wir den Packing-Type 0 (default Packing) erzeugen.
1118 // Wenn aber RowBytes<8 gilt, sind die Daten grundsaetzlich ungepackt,
1119 // auch wenn der Packing-Type 0 angegeben ist, was etwas komisch erscheint.
1120 // Daher wollen wir in so einem Fall lieber gleich den Packing-Type 1 (ungepackt)
1121 // angeben:
1122 if ( nDstRowBytes < 8 )
1123 nPackType = 1;
1124 else
1125 nPackType = 0;
1126
1127 // PixMap-Struktur schreiben:
1128 *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes pro Zeile und dass es eine 'PixMap' ist
1129 << (sal_uInt16)0x0000 // Y1-Position der Bitmap in der Quelle
1130 << (sal_uInt16)0x0000 // X1-Position der Bitmap in der Quelle
1131 << (sal_uInt16)nHeight // Y2-Position der Bitmap in der Quelle
1132 << (sal_uInt16)nWidth // X2-Position der Bitmap in der Quelle
1133 << (sal_uInt16)0x0000 // Version
1134 << (sal_uInt16)nPackType // Packing type
1135 << (sal_uInt32) 0x00000000 // Packing size (?)
1136 << (sal_uInt32) 0x00480000 // H-Res
1137 << (sal_uInt32) 0x00480000 // V-Res
1138 << (sal_uInt16)0x0000 // Pixel type (?)
1139 << (sal_uInt16)nBitsPerPixel // Pixel size
1140 << (sal_uInt16)0x0001 // CmpCount: 1 Komponente
1141 << (sal_uInt16)nBitsPerPixel // CmpSize
1142 << (sal_uInt32) 0x00000000 // PlaneBytes (?)
1143 << (sal_uInt32) 0x00000000 // (?)
1144 << (sal_uInt32) 0x00000000; // (?)
1145
1146 // Palette lesen und schreiben:
1147 nColTabSize = pAcc->GetPaletteEntryCount();
1148 *pPict << (sal_uInt32)0 << (sal_uInt16)0x8000 << (sal_uInt16)( nColTabSize - 1 );
1149
1150 for ( i = 0; i < nColTabSize; i++ )
1151 {
1152 nRed = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetRed();
1153 nGreen = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetGreen();
1154 nBlue = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetBlue();
1155 *pPict << (sal_uInt16)0 << nRed << nRed << nGreen << nGreen << nBlue << nBlue;
1156 }
1157
1158 // Source-Rectangle schreiben:
1159 *pPict << (sal_uInt16)0 << (sal_uInt16)0 << (sal_uInt16)nHeight << (sal_uInt16)nWidth;
1160
1161 // Destination-Rectangle schreiben:
1162 WritePoint( rPoint );
1163 WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
1164
1165 // Transfer mode schreiben:
1166 *pPict << (sal_uInt16)0; // (?)
1167
1168 // Speicher fuer eine Zeile allozieren:
1169 pPix = new sal_uInt8[ nSrcRowBytes ];
1170
1171 // Position der Map-Daten in Ziel merken:
1172 nDstMapPos=pPict->Tell();
1173
1174 // Schleife ueber Zeilen:
1175 for ( ny = 0; ny < nHeight; ny++ )
1176 {
1177
1178 // Zeile ny der Quelle in den Zwischenspeicher einlesen:
1179
1180 switch ( nBitsPerPixel )
1181 {
1182 case 1 :
1183 for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1184 *pTemp++ = (sal_uInt8)0;
1185 for ( i = 0; i < nWidth; i++ )
1186 pPix[ ( i >> 3 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 1) << ((i & 7) ^ 7);
1187 break;
1188 case 4 :
1189 for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1190 *pTemp++ = (sal_uInt8)0;
1191 for ( i = 0; i < nWidth; i++ )
1192 pPix[ ( i >> 1 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 15) << ((i & 1) << 2);
1193 break;
1194 case 8 :
1195 for ( i = 0; i < nWidth; i++ )
1196 pPix[ i ] = pAcc->GetPixelIndex( ny, i );
1197 break;
1198 }
1199
1200 if ( nPackType == 1 )
1201 { // nicht packen
1202 pPict->Write( pPix, nDstRowBytes );
1203 }
1204 else
1205 { // Packen (nPackType==0)
1206
1207 // Anfang der Zeile im Ziel merken:
1208 nDstRowPos = pPict->Tell();
1209
1210 // ByteCount (das ist die Groesse der gepackten Zeile) zunaechst 0 (wird spaeter berichtigt):
1211 if ( nDstRowBytes > 250 )
1212 *pPict << (sal_uInt16)0;
1213 else
1214 *pPict << (sal_uInt8)0;
1215
1216 // Schleife ueber Bytes der Zeile:
1217 nx=0;
1218 while ( nx < nDstRowBytes && bStatus )
1219 {
1220 // Die Position von 3 gleichen Bytes suchen und in nEqu3 merken.
1221 // wenn nicht gefunden, dann nEqu3=nDstRowBytes setzten.
1222 // Wenn doch gefunden, dann in nEquData den Wert der Bytes merken.
1223 nEqu3 = nx;
1224 for (;;)
1225 {
1226 if ( nEqu3 + 2 >= nDstRowBytes )
1227 {
1228 nEqu3 = nDstRowBytes;
1229 break;
1230 }
1231 nEquData = pPix[ nEqu3 ];
1232 if ( nEquData == pPix[ nEqu3 + 1 ] && nEquData == pPix[ nEqu3 + 2 ] )
1233 break;
1234 nEqu3++;
1235 }
1236
1237 // Die Daten von nx bis nEqu3 unkomprimiert schreiben (ggf. in mehreren Records):
1238 while ( nEqu3 > nx )
1239 {
1240 nCount = nEqu3 - nx;
1241 if ( nCount > 128 )
1242 nCount = 128;
1243 nFlagCounterByte = (sal_uInt8)( nCount - 1 );
1244 *pPict << nFlagCounterByte;
1245 do
1246 {
1247 *pPict << pPix[ nx++ ];
1248 nCount--;
1249 } while ( nCount > 0 );
1250 }
1251
1252 // Jetzt einen Komprimierungs-Record erzeugen (falls oben mindestens 3
1253 // gleiche Bytes gefunden):
1254 if ( nx < nDstRowBytes )
1255 { // Hinweis: es gilt nx==nEqu3 (hoffentlich)
1256 nCount = 3; // Drei Bytes sind gleich, wie weiter oben herausgefunden.
1257 // Pruefen, ob es weitere gleiche Bytes gibts (dabei Max.-Record-Groesse beachten):
1258 while ( nx + nCount < nDstRowBytes && nCount < 128 )
1259 {
1260 if ( nEquData != pPix[ nx + nCount ] )
1261 break;
1262 nCount++;
1263 }
1264 // nCount gleiche Bytes komprimiert schreiben:
1265 nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1266 *pPict << nFlagCounterByte << nEquData;
1267 nx += nCount;
1268 }
1269 }
1270
1271 // ByteCount berichtigen:
1272 nPos = pPict->Tell();
1273 pPict->Seek( nDstRowPos );
1274 if ( nDstRowBytes > 250 )
1275 *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1276 else
1277 *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1278 pPict->Seek( nPos );
1279 }
1280
1281 // Prozente zaehlen, Callback, Fehler pruefen:
1282 nActBitmapPercent =( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus)
1283 MayCallback();
1284 if ( pPict->GetError() )
1285 bStatus = sal_False;
1286 }
1287 // Aufraeumen:
1288 delete[] pPix;
1289 }
1290
1291 // Map-Daten muessen gerade Anzahl von Bytes sein:
1292 if ( ( ( pPict->Tell() - nDstMapPos ) & 1 ) != 0 )
1293 *pPict << (sal_uInt8)0;
1294
1295 // Bitmaps zaehlen:
1296 nWrittenBitmaps++;
1297 nActBitmapPercent = 0;
1298 if ( pAcc )
1299 aBitmap.ReleaseAccess( pAcc );
1300 }
1301
WriteOpcode_EndOfFile()1302 void PictWriter::WriteOpcode_EndOfFile()
1303 {
1304 *pPict << (sal_uInt16)0x00ff;
1305 }
1306
1307
SetAttrForPaint()1308 void PictWriter::SetAttrForPaint()
1309 {
1310 WriteOpcode_PnMode(eSrcRasterOp);
1311 WriteOpcode_RGBFgCol(aFillColor);
1312 WriteOpcode_RGBBkCol(aFillColor);
1313 WriteOpcode_PnFillPat(aFillColor!=Color( COL_TRANSPARENT ));
1314 }
1315
1316
SetAttrForFrame()1317 void PictWriter::SetAttrForFrame()
1318 {
1319 WriteOpcode_PnMode(eSrcRasterOp);
1320 WriteOpcode_PnSize(0);
1321 WriteOpcode_RGBFgCol(aLineColor);
1322 WriteOpcode_PnLinePat(aLineColor!=Color( COL_TRANSPARENT ));
1323 }
1324
1325
SetAttrForText()1326 void PictWriter::SetAttrForText()
1327 {
1328 WriteOpcode_RGBFgCol(aSrcFont.GetColor());
1329 WriteOpcode_RGBBkCol(aSrcFont.GetFillColor());
1330 WriteOpcode_PnLinePat(sal_True);
1331 WriteOpcode_FontName(aSrcFont);
1332 WriteOpcode_TxSize((sal_uInt16)(aSrcFont.GetSize().Height()));
1333 WriteOpcode_TxMode(eSrcRasterOp);
1334 WriteOpcode_TxFace(aSrcFont);
1335 }
1336
1337
WriteTextArray(Point & rPoint,const String & rString,const sal_Int32 * pDXAry)1338 void PictWriter::WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry)
1339 {
1340 sal_uInt16 i,nLen;
1341 sal_Unicode c;
1342 sal_Bool bDelta;
1343 Point aPt;
1344
1345 if ( pDXAry == NULL )
1346 WriteOpcode_Text( rPoint, rString, sal_False );
1347 else
1348 {
1349 bDelta = sal_False;
1350 nLen = rString.Len();
1351 for ( i = 0; i < nLen; i++ )
1352 {
1353 c = rString.GetChar( i );
1354 if ( c && ( c != 0x20 ) )
1355 {
1356 aPt = rPoint;
1357 if ( i > 0 )
1358 aPt.X() += pDXAry[ i - 1 ];
1359
1360 WriteOpcode_Text( aPt, String( c ), bDelta );
1361 bDelta = sal_True;
1362 }
1363 }
1364 }
1365 }
1366
HandleLineInfoPolyPolygons(const LineInfo & rInfo,const basegfx::B2DPolygon & rLinePolygon)1367 void PictWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
1368 {
1369 if(rLinePolygon.count())
1370 {
1371 basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
1372 basegfx::B2DPolyPolygon aFillPolyPolygon;
1373
1374 rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
1375
1376 if(aLinePolyPolygon.count())
1377 {
1378 aLinePolyPolygon = aLinePolyPolygon.getDefaultAdaptiveSubdivision();
1379 const sal_uInt32 nPolyCount(aLinePolyPolygon.count());
1380 SetAttrForFrame();
1381
1382 for(sal_uInt32 a(0); a < nPolyCount; a++)
1383 {
1384 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
1385 const sal_uInt32 nPointCount(aCandidate.count());
1386
1387 if(nPointCount)
1388 {
1389 const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount);
1390 const basegfx::B2DPoint aCurr(aCandidate.getB2DPoint(0));
1391 Point nCurr(basegfx::fround(aCurr.getX()), basegfx::fround(aCurr.getY()));
1392
1393 for(sal_uInt32 b(0); b < nEdgeCount; b++)
1394 {
1395 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1396 const basegfx::B2DPoint aNext(aCandidate.getB2DPoint(nNextIndex));
1397 const Point nNext(basegfx::fround(aNext.getX()), basegfx::fround(aNext.getY()));
1398
1399 WriteOpcode_Line(nCurr, nNext);
1400 nCurr = nNext;
1401 }
1402 }
1403 }
1404 }
1405
1406 if(aFillPolyPolygon.count())
1407 {
1408 const Color aOldLineColor(aLineColor);
1409 const Color aOldFillColor(aFillColor);
1410
1411 aLineColor = Color( COL_TRANSPARENT );
1412 aFillColor = aOldLineColor;
1413 SetAttrForPaint();
1414
1415 for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
1416 {
1417 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a).getDefaultAdaptiveSubdivision());
1418 WriteOpcode_Poly(PDM_PAINT, aPolygon);
1419 }
1420
1421 aLineColor = aOldLineColor;
1422 aFillColor = aOldFillColor;
1423 }
1424 }
1425 }
1426
WriteOpcodes(const GDIMetaFile & rMTF)1427 void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
1428 {
1429 sal_uLong nA, nACount;
1430 const MetaAction* pMA;
1431
1432 if( !bStatus)
1433 return;
1434
1435 nACount=rMTF.GetActionCount();
1436
1437 for (nA=0; nA<nACount; nA++)
1438 {
1439 pMA = rMTF.GetAction(nA);
1440
1441 switch (pMA->GetType())
1442 {
1443 case META_PIXEL_ACTION:
1444 {
1445 const MetaPixelAction* pA = (const MetaPixelAction*) pMA;
1446 WriteOpcode_PnMode(eSrcRasterOp);
1447 WriteOpcode_PnSize(1);
1448 WriteOpcode_RGBFgCol(pA->GetColor());
1449 WriteOpcode_PnLinePat(sal_True);
1450 WriteOpcode_Line(pA->GetPoint(),pA->GetPoint());
1451 }
1452 break;
1453
1454 case META_POINT_ACTION:
1455 {
1456 const MetaPointAction* pA = (const MetaPointAction*) pMA;
1457
1458 if( aLineColor != Color( COL_TRANSPARENT ) )
1459 {
1460 SetAttrForFrame();
1461 WriteOpcode_Line( pA->GetPoint(),pA->GetPoint() );
1462 }
1463 }
1464 break;
1465
1466 case META_LINE_ACTION:
1467 {
1468 const MetaLineAction* pA = (const MetaLineAction*) pMA;
1469
1470 if( aLineColor != Color( COL_TRANSPARENT ) )
1471 {
1472 if(pA->GetLineInfo().IsDefault())
1473 {
1474 SetAttrForFrame();
1475 WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() );
1476 }
1477 else
1478 {
1479 // LineInfo used; handle Dash/Dot and fat lines
1480 basegfx::B2DPolygon aPolygon;
1481 aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1482 aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1483 HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
1484 }
1485 }
1486 break;
1487 }
1488
1489 case META_RECT_ACTION:
1490 {
1491 const MetaRectAction* pA = (const MetaRectAction*) pMA;
1492
1493 if (aFillColor!=Color( COL_TRANSPARENT ))
1494 {
1495 SetAttrForPaint();
1496 WriteOpcode_Rect(PDM_PAINT,pA->GetRect());
1497 if (aLineColor!=Color( COL_TRANSPARENT ))
1498 {
1499 SetAttrForFrame();
1500 WriteOpcode_SameRect(PDM_FRAME);
1501 }
1502 }
1503 else if (aLineColor!=Color( COL_TRANSPARENT ))
1504 {
1505 SetAttrForFrame();
1506 WriteOpcode_Rect(PDM_FRAME,pA->GetRect());
1507 }
1508 }
1509 break;
1510
1511 case META_ROUNDRECT_ACTION:
1512 {
1513 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1514
1515 WriteOpcode_OvSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
1516
1517 if (aFillColor!=Color( COL_TRANSPARENT ))
1518 {
1519 SetAttrForPaint();
1520 WriteOpcode_RRect(PDM_PAINT,pA->GetRect());
1521 if (aLineColor!=Color( COL_TRANSPARENT ))
1522 {
1523 SetAttrForFrame();
1524 WriteOpcode_SameRRect(PDM_FRAME);
1525 }
1526 }
1527 else if (aLineColor!=Color( COL_TRANSPARENT ))
1528 {
1529 SetAttrForFrame();
1530 WriteOpcode_RRect(PDM_FRAME,pA->GetRect());
1531 }
1532 }
1533 break;
1534
1535 case META_ELLIPSE_ACTION:
1536 {
1537 const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
1538
1539 if (aFillColor!=Color( COL_TRANSPARENT ))
1540 {
1541 SetAttrForPaint();
1542 WriteOpcode_Oval(PDM_PAINT,pA->GetRect());
1543 if (aLineColor!=Color( COL_TRANSPARENT ))
1544 {
1545 SetAttrForFrame();
1546 WriteOpcode_SameOval(PDM_FRAME);
1547 }
1548 }
1549 else if (aLineColor!=Color( COL_TRANSPARENT ))
1550 {
1551 SetAttrForFrame();
1552 WriteOpcode_Oval(PDM_FRAME,pA->GetRect());
1553 }
1554 }
1555 break;
1556
1557 case META_ARC_ACTION:
1558 {
1559 const MetaArcAction* pA = (const MetaArcAction*) pMA;
1560
1561 if (aLineColor!=Color( COL_TRANSPARENT ))
1562 {
1563 SetAttrForFrame();
1564 WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1565 }
1566 }
1567 break;
1568
1569 case META_PIE_ACTION:
1570 {
1571 const MetaPieAction* pA = (const MetaPieAction *) pMA;
1572
1573 if (aFillColor!=Color( COL_TRANSPARENT ))
1574 {
1575 SetAttrForPaint();
1576 WriteOpcode_Arc(PDM_PAINT,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1577
1578 if (aLineColor!=Color( COL_TRANSPARENT ))
1579 {
1580 SetAttrForFrame();
1581 WriteOpcode_SameArc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1582 }
1583 }
1584 else if (aLineColor!=Color( COL_TRANSPARENT ))
1585 {
1586 SetAttrForFrame();
1587 WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1588 }
1589
1590 if (aLineColor!=Color( COL_TRANSPARENT ))
1591 {
1592 double fxc,fyc,fxr,fyr,fx1,fy1,fx2,fy2,l1,l2;
1593
1594 fxc=((double)(pA->GetRect().Left()+pA->GetRect().Right()))/2.0;
1595 fyc=((double)(pA->GetRect().Top()+pA->GetRect().Bottom()))/2.0;
1596 fxr=((double)pA->GetRect().GetWidth())/2.0;
1597 fyr=((double)pA->GetRect().GetHeight())/2.0;
1598 fx1=((double)pA->GetStartPoint().X())-fxc;
1599 fy1=((double)pA->GetStartPoint().Y())-fyc;
1600 fx2=((double)pA->GetEndPoint().X())-fxc;
1601 fy2=((double)pA->GetEndPoint().Y())-fyc;
1602 l1=sqrt(fx1*fx1+fy1*fy1);
1603 l2=sqrt(fx2*fx2+fy2*fy2);
1604
1605 if (l1>0)
1606 {
1607 fx1=fx1/l1*fxr;
1608 fy1=fy1/l1*fyr;
1609 }
1610
1611 if (l2>0)
1612 {
1613 fx2=fx2/l2*fxr;
1614 fy2=fy2/l2*fyr;
1615 }
1616 fx1+=fxc; fy1+=fyc; fx2+=fxc; fy2+=fyc;
1617 WriteOpcode_Line(Point((long)(fx1+0.5),(long)(fy1+0.5)), Point((long)(fxc+0.5),(long)(fyc+0.5)));
1618 WriteOpcode_LineFrom(Point((long)(fx2+0.5),(long)(fy2+0.5)));
1619 }
1620 }
1621 break;
1622
1623 case META_CHORD_ACTION:
1624 {
1625 // DBG_ERROR( "Unsupported PICT-Action: META_CHORD_ACTION!" );
1626 }
1627 break;
1628
1629 case META_POLYLINE_ACTION:
1630 {
1631 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1632
1633 if( aLineColor!=Color( COL_TRANSPARENT ) )
1634 {
1635 const Polygon& rPoly = pA->GetPolygon();
1636
1637 if( rPoly.GetSize() )
1638 {
1639 if(pA->GetLineInfo().IsDefault())
1640 {
1641 Polygon aSimplePoly;
1642 if ( rPoly.HasFlags() )
1643 rPoly.AdaptiveSubdivide( aSimplePoly );
1644 else
1645 aSimplePoly = rPoly;
1646
1647 const sal_uInt16 nSize = aSimplePoly.GetSize();
1648 Point aLast;
1649
1650 if ( nSize )
1651 {
1652 SetAttrForFrame();
1653 aLast = aSimplePoly[0];
1654
1655 for ( sal_uInt16 i = 1; i < nSize; i++ )
1656 {
1657 WriteOpcode_Line( aLast, aSimplePoly[i] );
1658 aLast = aSimplePoly[i];
1659 }
1660 }
1661 }
1662 else
1663 {
1664 // LineInfo used; handle Dash/Dot and fat lines
1665 HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1666 }
1667 }
1668 }
1669 }
1670 break;
1671
1672 case META_POLYGON_ACTION:
1673 {
1674 const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1675
1676 const Polygon& rPoly = pA->GetPolygon();
1677
1678 Polygon aSimplePoly;
1679 if ( rPoly.HasFlags() )
1680 rPoly.AdaptiveSubdivide( aSimplePoly );
1681 else
1682 aSimplePoly = rPoly;
1683
1684 if (aFillColor!=Color( COL_TRANSPARENT ))
1685 {
1686 SetAttrForPaint();
1687 WriteOpcode_Poly( PDM_PAINT, aSimplePoly );
1688 }
1689 if (aLineColor!=Color( COL_TRANSPARENT ))
1690 {
1691 SetAttrForFrame();
1692 WriteOpcode_Poly( PDM_FRAME, aSimplePoly );
1693 }
1694 }
1695 break;
1696
1697 case META_POLYPOLYGON_ACTION:
1698 {
1699 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1700
1701 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1702 sal_uInt16 nPolyCount = rPolyPoly.Count();
1703 PolyPolygon aSimplePolyPoly( rPolyPoly );
1704 for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
1705 {
1706 if ( aSimplePolyPoly[ i ].HasFlags() )
1707 {
1708 Polygon aSimplePoly;
1709 aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
1710 aSimplePolyPoly[ i ] = aSimplePoly;
1711 }
1712 }
1713 if (aFillColor!=Color( COL_TRANSPARENT ))
1714 {
1715 SetAttrForPaint();
1716 WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( aSimplePolyPoly ));
1717 }
1718
1719 if (aLineColor!=Color( COL_TRANSPARENT ))
1720 {
1721 sal_uInt16 nCount,i;
1722 SetAttrForFrame();
1723 nCount = aSimplePolyPoly.Count();
1724 for ( i = 0; i < nCount; i++ )
1725 WriteOpcode_Poly( PDM_FRAME, aSimplePolyPoly.GetObject( i ) );
1726 }
1727 }
1728 break;
1729
1730 case META_TEXT_ACTION:
1731 {
1732 const MetaTextAction* pA = (const MetaTextAction*) pMA;
1733 Point aPt( pA->GetPoint() );
1734
1735 if ( aSrcFont.GetAlign() != ALIGN_BASELINE )
1736 {
1737 VirtualDevice aVirDev;
1738
1739 if (aSrcFont.GetAlign()==ALIGN_TOP)
1740 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1741 else
1742 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1743 }
1744
1745 SetAttrForText();
1746 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1747 WriteOpcode_Text( aPt, aStr, sal_False );
1748 }
1749 break;
1750
1751 case META_TEXTARRAY_ACTION:
1752 {
1753 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
1754 Point aPt( pA->GetPoint() );
1755
1756 if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1757 {
1758 VirtualDevice aVirDev;
1759
1760 if (aSrcFont.GetAlign()==ALIGN_TOP)
1761 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1762 else
1763 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1764 }
1765 SetAttrForText();
1766 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1767 WriteTextArray( aPt, aStr, pA->GetDXArray() );
1768 break;
1769 }
1770
1771 case META_STRETCHTEXT_ACTION:
1772 {
1773 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pMA;
1774 Point aPt( pA->GetPoint() );
1775 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1776 VirtualDevice aVirDev;
1777 sal_Int32* pDXAry = new sal_Int32[ aStr.Len() ];
1778 sal_Int32 nNormSize( aVirDev.GetTextArray( aStr,pDXAry ) );
1779 sal_uInt16 i;
1780
1781 if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1782 {
1783 if (aSrcFont.GetAlign()==ALIGN_TOP)
1784 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1785 else
1786 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1787 }
1788
1789 for ( i = 0; i < aStr.Len() - 1; i++ )
1790 pDXAry[ i ] = pDXAry[ i ] * ( (long)pA->GetWidth() ) / nNormSize;
1791
1792 SetAttrForText();
1793 WriteTextArray( aPt, aStr, pDXAry );
1794 delete[] pDXAry;
1795 }
1796 break;
1797
1798 case META_TEXTRECT_ACTION:
1799 {
1800 // DBG_ERROR( "Unsupported PICT-Action: META_TEXTRECT_ACTION!" );
1801 }
1802 break;
1803
1804 case META_BMP_ACTION:
1805 {
1806 const MetaBmpAction* pA = (const MetaBmpAction*) pMA;
1807 const Bitmap aBmp( pA->GetBitmap() );
1808 VirtualDevice aVirDev;
1809
1810 WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1811 }
1812 break;
1813
1814 case META_BMPSCALE_ACTION:
1815 {
1816 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1817 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1818 }
1819 break;
1820
1821 case META_BMPSCALEPART_ACTION:
1822 {
1823 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
1824 Bitmap aBmp( pA->GetBitmap() );
1825
1826 aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1827 WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1828 }
1829 break;
1830
1831 case META_BMPEX_ACTION:
1832 {
1833 const MetaBmpExAction* pA = (const MetaBmpExAction*) pMA;
1834 const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1835 VirtualDevice aVirDev;
1836
1837 WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1838 }
1839 break;
1840
1841 case META_BMPEXSCALE_ACTION:
1842 {
1843 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
1844 const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1845
1846 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), aBmp );
1847 }
1848 break;
1849
1850 case META_BMPEXSCALEPART_ACTION:
1851 {
1852 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
1853 Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1854
1855 aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1856 WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1857 }
1858 break;
1859
1860 case META_EPS_ACTION :
1861 {
1862 const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
1863 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1864
1865 sal_Int32 nCount = aGDIMetaFile.GetActionCount();
1866 for ( sal_Int32 i = 0; i < nCount; i++ )
1867 {
1868 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1869 if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
1870 {
1871 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
1872 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1873 break;
1874 }
1875 }
1876 }
1877 break;
1878
1879 case META_MASK_ACTION:
1880 case META_MASKSCALE_ACTION:
1881 case META_MASKSCALEPART_ACTION:
1882 {
1883 // DBG_ERROR( "Unsupported PICT-Action: META_MASK..._ACTION!" );
1884 }
1885 break;
1886
1887 case META_GRADIENT_ACTION:
1888 {
1889 VirtualDevice aVDev;
1890 GDIMetaFile aTmpMtf;
1891 const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
1892
1893 aVDev.SetMapMode( aTargetMapMode );
1894 aVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1895 WriteOpcodes( aTmpMtf );
1896 }
1897 break;
1898
1899 case META_HATCH_ACTION:
1900 {
1901 VirtualDevice aVDev;
1902 GDIMetaFile aTmpMtf;
1903 const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
1904
1905 aVDev.SetMapMode( aTargetMapMode );
1906 aVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1907 WriteOpcodes( aTmpMtf );
1908 }
1909 break;
1910
1911 case META_WALLPAPER_ACTION:
1912 {
1913 // DBG_ERROR( "Unsupported PICT-Action: META_WALLPAPER_ACTION!" );
1914 }
1915 break;
1916
1917 case META_CLIPREGION_ACTION:
1918 {
1919 // DBG_ERROR( "Unsupported PICT-Action: META_CLIPREGION_ACTION!" );
1920 }
1921 break;
1922
1923 case META_ISECTRECTCLIPREGION_ACTION:
1924 {
1925 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
1926 WriteOpcode_ClipRect( pA->GetRect() );
1927 }
1928 break;
1929
1930 case META_ISECTREGIONCLIPREGION_ACTION:
1931 {
1932 // DBG_ERROR( "Unsupported PICT-Action: META_ISECTREGIONCLIPREGION_ACTION!" );
1933 }
1934 break;
1935
1936 case META_MOVECLIPREGION_ACTION:
1937 {
1938 // DBG_ERROR( "Unsupported PICT-Action: META_MOVECLIPREGION_ACTION!" );
1939 }
1940 break;
1941
1942 case META_LINECOLOR_ACTION:
1943 {
1944 const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
1945
1946 if( pA->IsSetting() )
1947 aLineColor = pA->GetColor();
1948 else
1949 aLineColor = Color( COL_TRANSPARENT );
1950 }
1951 break;
1952
1953 case META_FILLCOLOR_ACTION:
1954 {
1955 const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
1956
1957 if( pA->IsSetting() )
1958 aFillColor = pA->GetColor();
1959 else
1960 aFillColor = Color( COL_TRANSPARENT );
1961 }
1962 break;
1963
1964 case META_TEXTCOLOR_ACTION:
1965 {
1966 const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
1967 aSrcFont.SetColor( pA->GetColor() );
1968 }
1969 break;
1970
1971 case META_TEXTFILLCOLOR_ACTION:
1972 {
1973 const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
1974
1975 if( pA->IsSetting() )
1976 aSrcFont.SetFillColor( pA->GetColor() );
1977 else
1978 aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
1979 }
1980 break;
1981
1982 case META_TEXTALIGN_ACTION:
1983 {
1984 // DBG_ERROR( "Unsupported PICT-Action: META_TEXTALIGN_ACTION!" );
1985 }
1986 break;
1987
1988 case META_MAPMODE_ACTION:
1989 {
1990 const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
1991
1992 if (aSrcMapMode!=pA->GetMapMode())
1993 {
1994 if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
1995 {
1996 MapMode aMM = pA->GetMapMode();
1997 Fraction aScaleX = aMM.GetScaleX();
1998 Fraction aScaleY = aMM.GetScaleY();
1999
2000 Point aOrigin = aSrcMapMode.GetOrigin();
2001 BigInt aX( aOrigin.X() );
2002 aX *= BigInt( aScaleX.GetDenominator() );
2003 if( aOrigin.X() >= 0 )
2004 {
2005 if( aScaleX.GetNumerator() >= 0 )
2006 aX += BigInt( aScaleX.GetNumerator()/2 );
2007 else
2008 aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
2009 }
2010 else
2011 {
2012 if( aScaleX.GetNumerator() >= 0 )
2013 aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
2014 else
2015 aX += BigInt( aScaleX.GetNumerator()/2 );
2016 }
2017
2018 aX /= BigInt( aScaleX.GetNumerator() );
2019 aOrigin.X() = (long)aX + aMM.GetOrigin().X();
2020 BigInt aY( aOrigin.Y() );
2021 aY *= BigInt( aScaleY.GetDenominator() );
2022
2023 if( aOrigin.Y() >= 0 )
2024 {
2025 if( aScaleY.GetNumerator() >= 0 )
2026 aY += BigInt( aScaleY.GetNumerator()/2 );
2027 else
2028 aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
2029 }
2030 else
2031 {
2032 if( aScaleY.GetNumerator() >= 0 )
2033 aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
2034 else
2035 aY += BigInt( aScaleY.GetNumerator()/2 );
2036 }
2037
2038 aY /= BigInt( aScaleY.GetNumerator() );
2039 aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
2040 aSrcMapMode.SetOrigin( aOrigin );
2041
2042 aScaleX *= aSrcMapMode.GetScaleX();
2043 aScaleY *= aSrcMapMode.GetScaleY();
2044 aSrcMapMode.SetScaleX( aScaleX );
2045 aSrcMapMode.SetScaleY( aScaleY );
2046 }
2047 else
2048 aSrcMapMode = pA->GetMapMode();
2049 }
2050 }
2051 break;
2052
2053 case META_FONT_ACTION:
2054 {
2055 const MetaFontAction* pA = (const MetaFontAction*) pMA;
2056 aSrcFont=pA->GetFont();
2057 }
2058 break;
2059
2060 case META_PUSH_ACTION:
2061 {
2062 PictWriterAttrStackMember * pAt = new PictWriterAttrStackMember;
2063 pAt->aLineColor=aLineColor;
2064 pAt->aFillColor=aFillColor;
2065 pAt->eRasterOp=eSrcRasterOp;
2066 pAt->aFont=aSrcFont;
2067 pAt->aMapMode=aSrcMapMode;
2068 pAt->aClipRect=aClipRect;
2069 pAt->pSucc=pAttrStack;
2070 pAttrStack=pAt;
2071 }
2072 break;
2073
2074 case META_POP_ACTION:
2075 {
2076 PictWriterAttrStackMember* pAt=pAttrStack;
2077
2078 if( pAt )
2079 {
2080 aLineColor=pAt->aLineColor;
2081 aFillColor=pAt->aFillColor;
2082 eSrcRasterOp=pAt->eRasterOp;
2083 aSrcFont=pAt->aFont;
2084 aSrcMapMode=pAt->aMapMode;
2085 if ( pAt->aClipRect != aClipRect )
2086 {
2087 Rectangle aRect( pAt->aClipRect );
2088 *pPict << (sal_uInt16)1 // opcode 1
2089 << (sal_uInt16)10 // data size
2090 << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
2091 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
2092 }
2093 aClipRect=pAt->aClipRect;
2094 pAttrStack=pAt->pSucc;
2095 delete pAt;
2096 }
2097 }
2098 break;
2099
2100 case META_RASTEROP_ACTION:
2101 {
2102 const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
2103 eSrcRasterOp=pA->GetRasterOp();
2104 }
2105 break;
2106
2107 case META_TRANSPARENT_ACTION:
2108 {
2109 const PolyPolygon& rPolyPoly = ( (const MetaTransparentAction*) pMA )->GetPolyPolygon();
2110
2111 if (aFillColor!=Color( COL_TRANSPARENT ))
2112 {
2113 SetAttrForPaint();
2114 WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( rPolyPoly ) );
2115 }
2116
2117 if (aLineColor!=Color( COL_TRANSPARENT ))
2118 {
2119 SetAttrForFrame();
2120 for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
2121 WriteOpcode_Poly( PDM_FRAME, rPolyPoly.GetObject( i ) );
2122 }
2123 }
2124 break;
2125
2126 case META_FLOATTRANSPARENT_ACTION:
2127 {
2128 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
2129
2130 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
2131 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
2132 const Size aSrcSize( aTmpMtf.GetPrefSize() );
2133 const Point aDestPt( pA->GetPoint() );
2134 const Size aDestSize( pA->GetSize() );
2135 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
2136 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
2137 long nMoveX, nMoveY;
2138
2139 if( fScaleX != 1.0 || fScaleY != 1.0 )
2140 {
2141 aTmpMtf.Scale( fScaleX, fScaleY );
2142 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2143 }
2144
2145 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
2146
2147 if( nMoveX || nMoveY )
2148 aTmpMtf.Move( nMoveX, nMoveY );
2149
2150 WriteOpcodes( aTmpMtf );
2151 }
2152 break;
2153
2154 }
2155
2156 nWrittenActions++;
2157 MayCallback();
2158
2159 if (pPict->GetError())
2160 bStatus=sal_False;
2161
2162 if (bStatus==sal_False)
2163 break;
2164 }
2165 }
2166
2167
WriteHeader(const GDIMetaFile & rMTF)2168 void PictWriter::WriteHeader(const GDIMetaFile & rMTF)
2169 {
2170 sal_uInt16 i;
2171 Size aSize( rMTF.GetPrefSize() );
2172 Point aPoint;
2173 Rectangle aRect( aPoint, aSize );
2174
2175 // 512 Bytes "Muell" am Anfang:
2176 for (i=0;i<128;i++) *pPict << (sal_uInt32)0;
2177
2178 // Lo-16-Bits der Groesse der Datei ohne die 512 Bytes Muell:
2179 *pPict << (sal_uInt16)0; // wird spaeter durch UpdateHeader() berichtigt
2180
2181 // Das Bounding-Rectangle (y1,x1,y2,x2 !):
2182 WriteRectangle( aRect );
2183
2184 // Version 2:
2185 *pPict << (sal_uInt32)0x001102ff;
2186
2187 // Extended-Version-2-Header:
2188 *pPict << (sal_uInt16)0x0c00 // Opcode
2189 << (sal_uInt16)0xfffe // Version (?)
2190 << (sal_uInt16)0x0000 // Reserved
2191 << (sal_uInt32) 0x00480000 // hRes
2192 << (sal_uInt32) 0x00480000;
2193 WriteRectangle( aRect );
2194 *pPict << (sal_uInt32)0x00000000; // Reserved
2195
2196 // viele Import-Filter verlangen die Angabe eines
2197 // Clipping-Bereichs am Anfang
2198
2199 WriteOpcode_ClipRect( aRect );
2200 }
2201
2202
UpdateHeader()2203 void PictWriter::UpdateHeader()
2204 {
2205 sal_uLong nPos;
2206
2207 // Lo-16-Bits der Groesse der Datei ohne die 512 Bytes Muell berichtigen:
2208 nPos=pPict->Tell();
2209 pPict->Seek(512);
2210 *pPict << (sal_uInt16)((nPos-512)&0x0000ffff);
2211 pPict->Seek(nPos);
2212 }
2213
2214
WritePict(const GDIMetaFile & rMTF,SvStream & rTargetStream,FilterConfigItem * pFilterConfigItem)2215 sal_Bool PictWriter::WritePict(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem )
2216 {
2217 PictWriterAttrStackMember* pAt;
2218 MapMode aMap72( MAP_INCH );
2219 Fraction aDPIFrac( 1, 72 );
2220
2221 bStatus=sal_True;
2222 nLastPercent=0;
2223
2224 if ( pFilterConfigItem )
2225 {
2226 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
2227 if ( xStatusIndicator.is() )
2228 {
2229 rtl::OUString aMsg;
2230 xStatusIndicator->start( aMsg, 100 );
2231 }
2232 }
2233
2234 pPict=&rTargetStream;
2235 pPict->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
2236
2237 aLineColor=Color( COL_BLACK );
2238 aFillColor=Color( COL_WHITE );
2239 eSrcRasterOp=ROP_OVERPAINT;
2240 aSrcFont=Font();
2241 aSrcMapMode = rMTF.GetPrefMapMode();
2242
2243 aMap72.SetScaleX( aDPIFrac );
2244 aMap72.SetScaleY( aDPIFrac );
2245 aTargetMapMode = aMap72;
2246
2247 pAttrStack=NULL;
2248
2249 bDstBkPatValid=sal_False;
2250 bDstTxFaceValid=sal_False;
2251 bDstTxModeValid=sal_False;
2252 bDstPnSizeValid=sal_False;
2253 bDstPnModeValid=sal_False;
2254 bDstPnPatValid=sal_False;
2255 bDstFillPatValid=sal_False;
2256 bDstTxSizeValid=sal_False;
2257 bDstFgColValid=sal_False;
2258 bDstBkColValid=sal_False;
2259 bDstPenPositionValid=sal_False;
2260 bDstTextPositionValid=sal_False;
2261 bDstFontNameValid=sal_False;
2262
2263 nNumberOfActions=0;
2264 nNumberOfBitmaps=0;
2265 nWrittenActions=0;
2266 nWrittenBitmaps=0;
2267 nActBitmapPercent=0;
2268
2269 CountActionsAndBitmaps(rMTF);
2270
2271 WriteHeader(rMTF);
2272 WriteOpcodes(rMTF);
2273 WriteOpcode_EndOfFile();
2274 UpdateHeader();
2275
2276 while (pAttrStack!=NULL) {
2277 pAt=pAttrStack;
2278 pAttrStack=pAt->pSucc;
2279 delete pAt;
2280 }
2281
2282 if ( xStatusIndicator.is() )
2283 xStatusIndicator->end();
2284
2285 return bStatus;
2286 }
2287
2288 //================== GraphicExport - die exportierte Funktion ================
2289
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)2290 extern "C" sal_Bool __LOADONCALLAPI GraphicExport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool)
2291 {
2292 PictWriter aPictWriter;
2293
2294 // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
2295 GDIMetaFile aScaledMtf( rGraphic.GetGDIMetaFile() );
2296
2297 return aPictWriter.WritePict( aScaledMtf, rStream, pFilterConfigItem );
2298 }
2299
2300