xref: /AOO41X/main/filter/source/graphicfilter/epict/epict.cxx (revision 87bc88d3ed834c36654f277ed18005c290f77bdd)
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