xref: /AOO41X/main/vcl/source/gdi/cvtsvm.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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_vcl.hxx"
26 
27 #define ENABLE_BYTESTRING_STREAM_OPERATORS
28 
29 #include <algorithm>
30 #include <string.h>
31 #include <tools/stack.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/stream.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/graph.hxx>
36 #include <vcl/lineinfo.hxx>
37 #include <vcl/salbtype.hxx>
38 #include <vcl/cvtsvm.hxx>
39 #include <vcl/dibtools.hxx>
40 
41 // -----------
42 // - Defines -
43 // -----------
44 
45 #define CVTSVM_WRITE_SUBACTIONCOUNT 1
46 
47 // -----------
48 // - Inlines -
49 // -----------
50 
ImplReadRect(SvStream & rIStm,Rectangle & rRect)51 void ImplReadRect( SvStream& rIStm, Rectangle& rRect )
52 {
53     Point aTL;
54     Point aBR;
55 
56     rIStm >> aTL;
57     rIStm >> aBR;
58 
59     rRect = Rectangle( aTL, aBR );
60 }
61 
62 // ------------------------------------------------------------------------
63 
ImplWriteRect(SvStream & rOStm,const Rectangle & rRect)64 void ImplWriteRect( SvStream& rOStm, const Rectangle& rRect )
65 {
66     rOStm << rRect.TopLeft();
67     rOStm << rRect.BottomRight();
68 }
69 
70 // ------------------------------------------------------------------------
71 
ImplReadPoly(SvStream & rIStm,Polygon & rPoly)72 void ImplReadPoly( SvStream& rIStm, Polygon& rPoly )
73 {
74     sal_Int32   nSize;
75 
76     rIStm >> nSize;
77     rPoly = Polygon( (sal_uInt16) nSize );
78 
79     for( sal_uInt16 i = 0; i < (sal_uInt16) nSize; i++ )
80         rIStm >> rPoly[ i ];
81 }
82 
83 // ------------------------------------------------------------------------
84 
ImplReadPolyPoly(SvStream & rIStm,PolyPolygon & rPolyPoly)85 void ImplReadPolyPoly( SvStream& rIStm, PolyPolygon& rPolyPoly )
86 {
87     Polygon aPoly;
88     sal_Int32   nPolyCount;
89 
90     rIStm >> nPolyCount;
91 
92     for( sal_uInt16 i = 0; i < (sal_uInt16) nPolyCount; i++ )
93     {
94         ImplReadPoly( rIStm, aPoly );
95         rPolyPoly.Insert( aPoly );
96     }
97 }
98 
99 // ------------------------------------------------------------------------
100 
ImplWritePolyPolyAction(SvStream & rOStm,const PolyPolygon & rPolyPoly)101 void ImplWritePolyPolyAction( SvStream& rOStm, const PolyPolygon& rPolyPoly )
102 {
103     const sal_uInt16    nPoly = rPolyPoly.Count();
104     sal_uInt16          nPoints = 0;
105     sal_uInt16          n;
106 
107     for( n = 0; n < nPoly; n++ )
108         nPoints = sal::static_int_cast<sal_uInt16>(nPoints + rPolyPoly[ n ].GetSize());
109 
110     rOStm << (sal_Int16) GDI_POLYPOLYGON_ACTION;
111     rOStm << (sal_Int32) ( 8 + ( nPoly << 2 ) + ( nPoints << 3 ) );
112     rOStm << (sal_Int32) nPoly;
113 
114     for( n = 0; n < nPoly; n++ )
115     {
116         // #i102224# Here the evtl. curved nature of Polygon was
117         // ignored (for all those Years). Adapted to at least write
118         // a polygon representing the curve as good as possible
119         Polygon aSimplePoly;
120         rPolyPoly[n].AdaptiveSubdivide(aSimplePoly);
121         const sal_uInt16 nSize(aSimplePoly.GetSize());
122 
123         rOStm << (sal_Int32) nSize;
124 
125         for( sal_uInt16 j = 0; j < nSize; j++ )
126             rOStm << aSimplePoly[ j ];
127     }
128 }
129 
130 // ------------------------------------------------------------------------
131 
ImplReadColor(SvStream & rIStm,Color & rColor)132 void ImplReadColor( SvStream& rIStm, Color& rColor )
133 {
134     sal_Int16 nVal;
135 
136     rIStm >> nVal; rColor.SetRed( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
137     rIStm >> nVal; rColor.SetGreen( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
138     rIStm >> nVal; rColor.SetBlue( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
139 }
140 
141 // ------------------------------------------------------------------------
142 
ImplWriteColor(SvStream & rOStm,const Color & rColor)143 void ImplWriteColor( SvStream& rOStm, const Color& rColor )
144 {
145     sal_Int16 nVal;
146 
147     nVal = ( (sal_Int16) rColor.GetRed() << 8 ) | rColor.GetRed();
148     rOStm << nVal;
149 
150     nVal = ( (sal_Int16) rColor.GetGreen() << 8 ) | rColor.GetGreen();
151     rOStm << nVal;
152 
153     nVal = ( (sal_Int16) rColor.GetBlue() << 8 ) | rColor.GetBlue();
154     rOStm << nVal;
155 }
156 
157 // ------------------------------------------------------------------------
158 
ImplReadMapMode(SvStream & rIStm,MapMode & rMapMode)159 void ImplReadMapMode( SvStream& rIStm, MapMode& rMapMode )
160 {
161     Point   aOrg;
162     sal_Int32   nXNum;
163     sal_Int32   nXDenom;
164     sal_Int32   nYNum;
165     sal_Int32   nYDenom;
166     sal_Int16   nUnit;
167 
168     rIStm >> nUnit >> aOrg >> nXNum >> nXDenom >> nYNum >> nYDenom;
169     rMapMode = MapMode( (MapUnit) nUnit, aOrg, Fraction( nXNum, nXDenom ), Fraction( nYNum, nYDenom ) );
170 }
171 
172 // ------------------------------------------------------------------------
173 
ImplWriteMapMode(SvStream & rOStm,const MapMode & rMapMode)174 void ImplWriteMapMode( SvStream& rOStm, const MapMode& rMapMode )
175 {
176     rOStm << (sal_Int16) rMapMode.GetMapUnit();
177     rOStm << rMapMode.GetOrigin();
178     rOStm << (sal_Int32) rMapMode.GetScaleX().GetNumerator();
179     rOStm << (sal_Int32) rMapMode.GetScaleX().GetDenominator();
180     rOStm << (sal_Int32) rMapMode.GetScaleY().GetNumerator();
181     rOStm << (sal_Int32) rMapMode.GetScaleY().GetDenominator();
182 }
183 
184 // ------------------------------------------------------------------------
185 
ImplWritePushAction(SvStream & rOStm)186 void ImplWritePushAction( SvStream& rOStm )
187 {
188     rOStm << (sal_Int16) GDI_PUSH_ACTION;
189     rOStm << (sal_Int32) 4;
190 }
191 
192 // ------------------------------------------------------------------------
193 
ImplWritePopAction(SvStream & rOStm)194 void ImplWritePopAction( SvStream& rOStm )
195 {
196     rOStm << (sal_Int16) GDI_POP_ACTION;
197     rOStm << (sal_Int32) 4;
198 }
199 
200 // ------------------------------------------------------------------------
201 
ImplWriteLineColor(SvStream & rOStm,const Color & rColor,sal_Int16 nStyle,sal_Int32 nWidth=0L)202 void ImplWriteLineColor( SvStream& rOStm, const Color& rColor, sal_Int16 nStyle, sal_Int32 nWidth = 0L )
203 {
204     if( rColor.GetTransparency() > 127 )
205         nStyle = 0;
206 
207     rOStm << (sal_Int16) GDI_PEN_ACTION;
208     rOStm << (sal_Int32) 16;
209     ImplWriteColor( rOStm, rColor );
210     rOStm << nWidth;
211     rOStm << nStyle;
212 }
213 
214 // ------------------------------------------------------------------------
215 
ImplWriteFillColor(SvStream & rOStm,const Color & rColor,sal_Int16 nStyle)216 void ImplWriteFillColor( SvStream& rOStm, const Color& rColor, sal_Int16 nStyle )
217 {
218     rOStm << (sal_Int16) GDI_FILLBRUSH_ACTION;
219     rOStm << (sal_Int32) 20;
220     ImplWriteColor( rOStm, rColor );
221 
222     if( rColor.GetTransparency() > 127 )
223         nStyle = 0;
224 
225     if( nStyle > 1 )
226     {
227         ImplWriteColor( rOStm, COL_WHITE );
228         rOStm << nStyle;
229         rOStm << (sal_Int16) 1;
230     }
231     else
232     {
233         ImplWriteColor( rOStm, COL_BLACK );
234         rOStm << nStyle;
235         rOStm << (sal_Int16) 0;
236     }
237 }
238 
239 // ------------------------------------------------------------------------
240 
ImplWriteFont(SvStream & rOStm,const Font & rFont,rtl_TextEncoding & rActualCharSet)241 void ImplWriteFont( SvStream& rOStm, const Font& rFont,
242                     rtl_TextEncoding& rActualCharSet )
243 {
244     char    aName[32];
245     short   nWeight;
246 
247     ByteString aByteName( rFont.GetName(), rOStm.GetStreamCharSet() );
248     strncpy( aName, aByteName.GetBuffer(), 32 );
249 
250     switch ( rFont.GetWeight() )
251     {
252         case WEIGHT_THIN:
253         case WEIGHT_ULTRALIGHT:
254         case WEIGHT_LIGHT:
255             nWeight = 1;
256         break;
257 
258         case WEIGHT_NORMAL:
259         case WEIGHT_MEDIUM:
260             nWeight = 2;
261         break;
262 
263         case WEIGHT_BOLD:
264         case WEIGHT_ULTRABOLD:
265         case WEIGHT_BLACK:
266             nWeight = 3;
267         break;
268 
269         default:
270             nWeight = 0;
271         break;
272     }
273 
274     rOStm << (sal_Int16) GDI_FONT_ACTION;
275     rOStm << (sal_Int32) 78;
276 
277     rActualCharSet = GetStoreCharSet( rFont.GetCharSet() );
278     ImplWriteColor( rOStm, rFont.GetColor() );
279     ImplWriteColor( rOStm, rFont.GetFillColor() );
280     rOStm.Write( aName, 32 );
281     rOStm << rFont.GetSize();
282     rOStm << (sal_Int16) 0; // no character orientation anymore
283     rOStm << (sal_Int16) rFont.GetOrientation();
284     rOStm << (sal_Int16) rActualCharSet;
285     rOStm << (sal_Int16) rFont.GetFamily();
286     rOStm << (sal_Int16) rFont.GetPitch();
287     rOStm << (sal_Int16) rFont.GetAlign();
288     rOStm << (sal_Int16) nWeight;
289     rOStm << (sal_Int16) rFont.GetUnderline();
290     rOStm << (sal_Int16) rFont.GetStrikeout();
291     rOStm << (sal_Bool) ( rFont.GetItalic() != ITALIC_NONE );
292     rOStm << rFont.IsOutline();
293     rOStm << rFont.IsShadow();
294     rOStm << rFont.IsTransparent();
295     if ( rActualCharSet == RTL_TEXTENCODING_DONTKNOW )
296         rActualCharSet = gsl_getSystemTextEncoding();
297 }
298 
299 // ------------------------------------------------------------------------
300 
ImplWriteRasterOpAction(SvStream & rOStm,sal_Int16 nRasterOp)301 void ImplWriteRasterOpAction( SvStream& rOStm, sal_Int16 nRasterOp )
302 {
303     rOStm << (sal_Int16) GDI_RASTEROP_ACTION << (sal_Int32) 6 << nRasterOp;
304 }
305 
306 // ------------------------------------------------------------------------
307 
ImplWriteUnicodeComment(SvStream & rOStm,const String & rString)308 sal_Bool ImplWriteUnicodeComment( SvStream& rOStm, const String& rString )
309 {
310     xub_StrLen i, nStringLen = rString.Len();
311     if ( nStringLen )
312     {
313         sal_uInt32  nSize = ( nStringLen << 1 ) + 4;
314         sal_uInt16  nType = GDI_UNICODE_COMMENT;
315 
316         rOStm << nType << nSize;
317         for ( i = 0; i < nStringLen; i++ )
318         {
319             sal_Unicode nUni = rString.GetChar( i );
320             rOStm << nUni;
321         }
322     }
323     return nStringLen != 0;
324 }
325 
326 // ------------------------------------------------------------------------
327 
ImplReadUnicodeComment(sal_uInt32 nStrmPos,SvStream & rIStm,String & rString)328 void ImplReadUnicodeComment( sal_uInt32 nStrmPos, SvStream& rIStm, String& rString )
329 {
330     sal_uInt32 nOld = rIStm.Tell();
331     if ( nStrmPos )
332     {
333         sal_uInt16  nType;
334         sal_uInt32  nActionSize;
335         xub_StrLen  nStringLen;
336 
337         rIStm.Seek( nStrmPos );
338         rIStm   >> nType
339                 >> nActionSize;
340 
341         nStringLen = sal::static_int_cast<xub_StrLen>(( nActionSize - 4 ) >> 1);
342 
343         if ( nStringLen && ( nType == GDI_UNICODE_COMMENT ) )
344         {
345             sal_Unicode* pBuffer = rString.AllocBuffer( nStringLen );
346             while ( nStringLen-- )
347                 rIStm >> *pBuffer++;
348         }
349     }
350     rIStm.Seek( nOld );
351 }
352 
353 // ------------------------------------------------------------------------
354 
ImplSkipActions(SvStream & rIStm,sal_uLong nSkipCount)355 void ImplSkipActions( SvStream& rIStm, sal_uLong nSkipCount )
356 {
357     sal_Int32 nActionSize;
358     sal_Int16 nType;
359 
360     for( sal_uLong i = 0UL; i < nSkipCount; i++ )
361     {
362         rIStm >> nType >> nActionSize;
363         rIStm.SeekRel( nActionSize - 4L );
364     }
365 }
366 
367 // ------------------------------------------------------------------------
368 
ImplWriteExtendedPolyPolygonAction(SvStream & rOStm,const PolyPolygon & rPolyPolygon,bool bOnlyWhenCurve)369 bool ImplWriteExtendedPolyPolygonAction(SvStream& rOStm, const PolyPolygon& rPolyPolygon, bool bOnlyWhenCurve)
370 {
371     const sal_uInt16 nPolygonCount(rPolyPolygon.Count());
372 
373     if(nPolygonCount)
374     {
375         sal_uInt32 nAllPolygonCount(0);
376         sal_uInt32 nAllPointCount(0);
377         sal_uInt32 nAllFlagCount(0);
378         sal_uInt16 a(0);
379 
380         for(a = 0; a < nPolygonCount; a++)
381         {
382             const Polygon& rCandidate = rPolyPolygon.GetObject(a);
383             const sal_uInt16 nPointCount(rCandidate.GetSize());
384 
385             if(nPointCount)
386             {
387                 nAllPolygonCount++;
388                 nAllPointCount += nPointCount;
389 
390                 if(rCandidate.HasFlags())
391                 {
392                     nAllFlagCount += nPointCount;
393                 }
394             }
395         }
396 
397         if((bOnlyWhenCurve && nAllFlagCount) || (!bOnlyWhenCurve && nAllPointCount))
398         {
399             rOStm << (sal_Int16) GDI_EXTENDEDPOLYGON_ACTION;
400 
401             const sal_Int32 nActionSize(
402                 4 +                         // Action size
403                 2 +                         // PolygonCount
404                 (nAllPolygonCount * 2) +    // Points per polygon
405                 (nAllPointCount << 3) +     // Points themselves
406                 nAllPolygonCount +          // Bool if (when poly has points) it has flags, too
407                 nAllFlagCount);             // Flags themselves
408 
409             rOStm << nActionSize;
410             rOStm << (sal_uInt16)nAllPolygonCount;
411 
412             for(a = 0; a < nPolygonCount; a++)
413             {
414                 const Polygon& rCandidate = rPolyPolygon.GetObject(a);
415                 const sal_uInt16 nPointCount(rCandidate.GetSize());
416 
417                 if(nPointCount)
418                 {
419                     rOStm << nPointCount;
420 
421                     for(sal_uInt16 b(0); b < nPointCount; b++)
422                     {
423                         rOStm << rCandidate[b];
424                     }
425 
426                     if(rCandidate.HasFlags())
427                     {
428                         rOStm << (sal_uInt8)true;
429 
430                         for(sal_uInt16 c(0); c < nPointCount; c++)
431                         {
432                             rOStm << (sal_uInt8)rCandidate.GetFlags(c);
433                         }
434                     }
435                     else
436                     {
437                         rOStm << (sal_uInt8)false;
438                     }
439                 }
440             }
441 
442             return true;
443         }
444     }
445 
446     return false;
447 }
448 
449 // ------------------------------------------------------------------------
450 
ImplReadExtendedPolyPolygonAction(SvStream & rIStm,PolyPolygon & rPolyPoly)451 void ImplReadExtendedPolyPolygonAction(SvStream& rIStm, PolyPolygon& rPolyPoly)
452 {
453     rPolyPoly.Clear();
454     sal_uInt16 nPolygonCount(0);
455     rIStm >> nPolygonCount;
456 
457     for(sal_uInt16 a(0); a < nPolygonCount; a++)
458     {
459         sal_uInt16 nPointCount(0);
460         rIStm >> nPointCount;
461         Polygon aCandidate(nPointCount);
462 
463         if(nPointCount)
464         {
465             for(sal_uInt16 b(0); b < nPointCount; b++)
466             {
467                 rIStm >> aCandidate[b];
468             }
469 
470             sal_uInt8 bHasFlags(false);
471             rIStm >> bHasFlags;
472 
473             if(bHasFlags)
474             {
475                 sal_uInt8 aPolyFlags(0);
476 
477                 for(sal_uInt16 c(0); c < nPointCount; c++)
478                 {
479                     rIStm >> aPolyFlags;
480                     aCandidate.SetFlags(c, (PolyFlags)aPolyFlags);
481                 }
482             }
483         }
484 
485         rPolyPoly.Insert(aCandidate);
486     }
487 }
488 
489 // ----------------
490 // - SVMConverter -
491 // ----------------
492 
SVMConverter(SvStream & rStm,GDIMetaFile & rMtf,sal_uLong nConvertMode)493 SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf, sal_uLong nConvertMode )
494 {
495     if( !rStm.GetError() )
496     {
497         if( CONVERT_FROM_SVM1 == nConvertMode )
498             ImplConvertFromSVM1( rStm, rMtf );
499         else if( CONVERT_TO_SVM1 == nConvertMode )
500             ImplConvertToSVM1( rStm, rMtf );
501     }
502 }
503 
504 // ------------------------------------------------------------------------
505 
ImplConvertFromSVM1(SvStream & rIStm,GDIMetaFile & rMtf)506 void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
507 {
508     const sal_uLong         nPos = rIStm.Tell();
509     const sal_uInt16        nOldFormat = rIStm.GetNumberFormatInt();
510 
511     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
512 
513     char    aCode[ 5 ];
514     Size    aPrefSz;
515     sal_Int16   nSize;
516     sal_Int16   nVersion;
517 
518     // read header
519     rIStm.Read( (char*) &aCode, sizeof( aCode ) );  // Kennung
520     rIStm >> nSize;                                 // Size
521     rIStm >> nVersion;                              // Version
522     rIStm >> aPrefSz.Width();                       // PrefSize.Width()
523     rIStm >> aPrefSz.Height();                      // PrefSize.Height()
524 
525     // check header-magic and version
526     if( rIStm.GetError()
527         || ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 )
528         || ( nVersion != 200 ) )
529     {
530         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
531         rIStm.SetNumberFormatInt( nOldFormat );
532         rIStm.Seek( nPos );
533         return;
534     }
535 
536     LineInfo            aLineInfo( LINE_NONE, 0 );
537     Stack               aLIStack;
538     VirtualDevice       aFontVDev;
539     rtl_TextEncoding    eActualCharSet = gsl_getSystemTextEncoding();
540     sal_Bool                bFatLine = sal_False;
541 
542     // TODO: fix reindentation below if you can accept being blamed by the SCM
543         MapMode     aMapMode;
544         Polygon     aActionPoly;
545         Rectangle   aRect;
546         Point       aPt, aPt1;
547         Size        aSz;
548         Color       aActionColor;
549         sal_Int32       nTmp, nTmp1, nActionSize;
550         sal_Int32       nActions;
551         sal_Int16       nType;
552 
553         sal_uInt32  nUnicodeCommentStreamPos = 0;
554         sal_Int32       nUnicodeCommentActionNumber = 0;
555 
556         ImplReadMapMode( rIStm, aMapMode );             // MapMode
557         rIStm >> nActions;                              // Action count
558 
559         rMtf.SetPrefSize( aPrefSz );
560         rMtf.SetPrefMapMode( aMapMode );
561         sal_uInt32 nLastPolygonAction(0);
562 
563         for( sal_Int32 i = 0L; i < nActions; i++ )
564         {
565             rIStm >> nType;
566             sal_Int32 nActBegin = rIStm.Tell();
567             rIStm >> nActionSize;
568 
569             DBG_ASSERT( ( nType <= 33 ) || ( nType >= 1024 ), "Unknown GDIMetaAction while converting!" );
570 
571             switch( nType )
572             {
573                 case( GDI_PIXEL_ACTION ):
574                 {
575                     rIStm >> aPt;
576                     ImplReadColor( rIStm, aActionColor );
577                     rMtf.AddAction( new MetaPixelAction( aPt, aActionColor ) );
578                 }
579                 break;
580 
581                 case( GDI_POINT_ACTION ):
582                 {
583                     rIStm >> aPt;
584                     rMtf.AddAction( new MetaPointAction( aPt ) );
585                 }
586                 break;
587 
588                 case( GDI_LINE_ACTION ):
589                 {
590                     rIStm >> aPt >> aPt1;
591                     rMtf.AddAction( new MetaLineAction( aPt, aPt1, aLineInfo ) );
592                 }
593                 break;
594 
595                 case (GDI_LINEJOIN_ACTION) :
596                 {
597                     sal_Int16 nLineJoin(0);
598                     rIStm >> nLineJoin;
599                     aLineInfo.SetLineJoin((basegfx::B2DLineJoin)nLineJoin);
600                 }
601                 break;
602 
603                 case (GDI_LINECAP_ACTION) :
604                 {
605                     sal_Int16 nLineCap(0);
606                     rIStm >> nLineCap;
607                     aLineInfo.SetLineCap((com::sun::star::drawing::LineCap)nLineCap);
608                 }
609                 break;
610 
611                 case (GDI_LINEDASHDOT_ACTION) :
612                 {
613                     sal_Int16 a(0);
614                     sal_Int32 b(0);
615 
616                     rIStm >> a; aLineInfo.SetDashCount(a);
617                     rIStm >> b; aLineInfo.SetDashLen(b);
618                     rIStm >> a; aLineInfo.SetDotCount(a);
619                     rIStm >> b; aLineInfo.SetDotLen(b);
620                     rIStm >> b; aLineInfo.SetDistance(b);
621 
622                     if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
623                         || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
624                         && aLineInfo.GetDistance())
625                     {
626                         aLineInfo.SetStyle(LINE_DASH);
627                     }
628                 }
629                 break;
630 
631                 case (GDI_EXTENDEDPOLYGON_ACTION) :
632                 {
633                     // read the PolyPolygon in every case
634                     PolyPolygon aInputPolyPolygon;
635                     ImplReadExtendedPolyPolygonAction(rIStm, aInputPolyPolygon);
636 
637                     // now check if it can be set somewhere
638                     if(nLastPolygonAction < rMtf.GetActionCount())
639                     {
640                         MetaPolyLineAction* pPolyLineAction = dynamic_cast< MetaPolyLineAction* >(rMtf.GetAction(nLastPolygonAction));
641 
642                         if(pPolyLineAction)
643                         {
644                             // replace MetaPolyLineAction when we have a single polygon. Do not rely on the
645                             // same point count; the originally written GDI_POLYLINE_ACTION may have been
646                             // Subdivided for better quality for older usages
647                             if(1 == aInputPolyPolygon.Count())
648                             {
649                                 rMtf.ReplaceAction(
650                                     new MetaPolyLineAction(
651                                         aInputPolyPolygon.GetObject(0),
652                                         pPolyLineAction->GetLineInfo()),
653                                     nLastPolygonAction);
654                                 pPolyLineAction->Delete();
655                             }
656                         }
657                         else
658                         {
659                             MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast< MetaPolyPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
660 
661                             if(pPolyPolygonAction)
662                             {
663                                 // replace MetaPolyPolygonAction when we have a curved polygon. Do rely on the
664                                 // same sub-polygon count
665                                 if(pPolyPolygonAction->GetPolyPolygon().Count() == aInputPolyPolygon.Count())
666                                 {
667                                     rMtf.ReplaceAction(
668                                         new MetaPolyPolygonAction(
669                                             aInputPolyPolygon),
670                                         nLastPolygonAction);
671                                     pPolyPolygonAction->Delete();
672                                 }
673                             }
674                             else
675                             {
676                                 MetaPolygonAction* pPolygonAction = dynamic_cast< MetaPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
677 
678                                 if(pPolygonAction)
679                                 {
680                                     // replace MetaPolygonAction
681                                     if(1 == aInputPolyPolygon.Count())
682                                     {
683                                         rMtf.ReplaceAction(
684                                             new MetaPolygonAction(
685                                                 aInputPolyPolygon.GetObject(0)),
686                                             nLastPolygonAction);
687                                         pPolygonAction->Delete();
688                                     }
689                                 }
690                             }
691                         }
692                     }
693                 }
694                 break;
695 
696                 case( GDI_RECT_ACTION ):
697                 {
698                     ImplReadRect( rIStm, aRect );
699                     rIStm >> nTmp >> nTmp1;
700 
701                     if( nTmp || nTmp1 )
702                         rMtf.AddAction( new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
703                     else
704                     {
705                         rMtf.AddAction( new MetaRectAction( aRect ) );
706 
707                         if( bFatLine )
708                             rMtf.AddAction( new MetaPolyLineAction( aRect, aLineInfo ) );
709                     }
710                 }
711                 break;
712 
713                 case( GDI_ELLIPSE_ACTION ):
714                 {
715                     ImplReadRect( rIStm, aRect );
716 
717                     if( bFatLine )
718                     {
719                         const Polygon aPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
720 
721                         rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
722                         rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, sal_False ) );
723                         rMtf.AddAction( new MetaPolygonAction( aPoly ) );
724                         rMtf.AddAction( new MetaPopAction() );
725                         rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
726                     }
727                     else
728                         rMtf.AddAction( new MetaEllipseAction( aRect ) );
729                 }
730                 break;
731 
732                 case( GDI_ARC_ACTION ):
733                 {
734                     ImplReadRect( rIStm, aRect );
735                     rIStm >> aPt >> aPt1;
736 
737                     if( bFatLine )
738                     {
739                         const Polygon aPoly( aRect, aPt, aPt1, POLY_ARC );
740 
741                         rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
742                         rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, sal_False ) );
743                         rMtf.AddAction( new MetaPolygonAction( aPoly ) );
744                         rMtf.AddAction( new MetaPopAction() );
745                         rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
746                     }
747                     else
748                         rMtf.AddAction( new MetaArcAction( aRect, aPt, aPt1 ) );
749                 }
750                 break;
751 
752                 case( GDI_PIE_ACTION ):
753                 {
754                     ImplReadRect( rIStm, aRect );
755                     rIStm >> aPt >> aPt1;
756 
757                     if( bFatLine )
758                     {
759                         const Polygon aPoly( aRect, aPt, aPt1, POLY_PIE );
760 
761                         rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
762                         rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, sal_False ) );
763                         rMtf.AddAction( new MetaPolygonAction( aPoly ) );
764                         rMtf.AddAction( new MetaPopAction() );
765                         rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
766                     }
767                     else
768                         rMtf.AddAction( new MetaPieAction( aRect, aPt, aPt1 ) );
769                 }
770                 break;
771 
772                 case( GDI_INVERTRECT_ACTION ):
773                 case( GDI_HIGHLIGHTRECT_ACTION ):
774                 {
775                     ImplReadRect( rIStm, aRect );
776                     rMtf.AddAction( new MetaPushAction( PUSH_RASTEROP ) );
777                     rMtf.AddAction( new MetaRasterOpAction( ROP_INVERT ) );
778                     rMtf.AddAction( new MetaRectAction( aRect ) );
779                     rMtf.AddAction( new MetaPopAction() );
780                 }
781                 break;
782 
783                 case( GDI_POLYLINE_ACTION ):
784                 {
785                     ImplReadPoly( rIStm, aActionPoly );
786                     nLastPolygonAction = rMtf.GetActionCount();
787 
788                     if( bFatLine )
789                         rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
790                     else
791                         rMtf.AddAction( new MetaPolyLineAction( aActionPoly ) );
792                 }
793                 break;
794 
795                 case( GDI_POLYGON_ACTION ):
796                 {
797                     ImplReadPoly( rIStm, aActionPoly );
798 
799                     if( bFatLine )
800                     {
801                         rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
802                         rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, sal_False ) );
803                         rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
804                         rMtf.AddAction( new MetaPopAction() );
805                         rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
806                     }
807                     else
808                     {
809                         nLastPolygonAction = rMtf.GetActionCount();
810                         rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
811                     }
812                 }
813                 break;
814 
815                 case( GDI_POLYPOLYGON_ACTION ):
816                 {
817                     PolyPolygon aPolyPoly;
818 
819                     ImplReadPolyPoly( rIStm, aPolyPoly );
820 
821                     if( bFatLine )
822                     {
823                         rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
824                         rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, sal_False ) );
825                         rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
826                         rMtf.AddAction( new MetaPopAction() );
827 
828                         for( sal_uInt16 nPoly = 0, nCount = aPolyPoly.Count(); nPoly < nCount; nPoly++ )
829                             rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
830                     }
831                     else
832                     {
833                         nLastPolygonAction = rMtf.GetActionCount();
834                         rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
835                     }
836                 }
837                 break;
838 
839                 case( GDI_FONT_ACTION ):
840                 {
841                     Font    aFont;
842                     char    aName[ 32 ];
843                     sal_Int32   nWidth, nHeight;
844                     sal_Int16   nCharSet, nFamily, nPitch, nAlign, nWeight, nUnderline, nStrikeout;
845                     sal_Int16   nCharOrient, nLineOrient;
846                     sal_Bool    bItalic, bOutline, bShadow, bTransparent;
847 
848                     ImplReadColor( rIStm, aActionColor ); aFont.SetColor( aActionColor );
849                     ImplReadColor( rIStm, aActionColor ); aFont.SetFillColor( aActionColor );
850                     rIStm.Read( aName, 32 );
851                     aFont.SetName( UniString( aName, rIStm.GetStreamCharSet() ) );
852                     rIStm >> nWidth >> nHeight;
853                     rIStm >> nCharOrient >> nLineOrient;
854                     rIStm >> nCharSet >> nFamily >> nPitch >> nAlign >> nWeight >> nUnderline >> nStrikeout;
855                     rIStm >> bItalic >> bOutline >> bShadow >> bTransparent;
856 
857                     aFont.SetSize( Size( nWidth, nHeight ) );
858                     aFont.SetCharSet( (CharSet) nCharSet );
859                     aFont.SetFamily( (FontFamily) nFamily );
860                     aFont.SetPitch( (FontPitch) nPitch );
861                     aFont.SetAlign( (FontAlign) nAlign );
862                     aFont.SetWeight( ( nWeight == 1 ) ? WEIGHT_LIGHT : ( nWeight == 2 ) ? WEIGHT_NORMAL :
863                                      ( nWeight == 3 ) ? WEIGHT_BOLD : WEIGHT_DONTKNOW );
864                     aFont.SetUnderline( (FontUnderline) nUnderline );
865                     aFont.SetStrikeout( (FontStrikeout) nStrikeout );
866                     aFont.SetItalic( bItalic ? ITALIC_NORMAL : ITALIC_NONE );
867                     aFont.SetOutline( bOutline );
868                     aFont.SetShadow( bShadow );
869                     aFont.SetOrientation( nLineOrient );
870                     aFont.SetTransparent( bTransparent );
871 
872                     eActualCharSet = aFont.GetCharSet();
873                     if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
874                         eActualCharSet = gsl_getSystemTextEncoding();
875 
876                     rMtf.AddAction( new MetaFontAction( aFont ) );
877                     rMtf.AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
878                     rMtf.AddAction( new MetaTextColorAction( aFont.GetColor() ) );
879                     rMtf.AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
880 
881                     // #106172# Track font relevant data in shadow VDev
882                     aFontVDev.SetFont( aFont );
883                 }
884                 break;
885 
886                 case( GDI_TEXT_ACTION ):
887                 {
888                     ByteString  aByteStr;
889                     sal_Int32       nIndex, nLen;
890 
891                     rIStm >> aPt >> nIndex >> nLen >> nTmp;
892                     if ( nTmp && ( static_cast< sal_uInt32 >( nTmp ) < ( SAL_MAX_UINT16 - 1 ) ) )
893                                         {
894                         rIStm.Read( aByteStr.AllocBuffer( (sal_uInt16)nTmp ), nTmp + 1 );
895                         UniString aStr( aByteStr, eActualCharSet );
896                         if ( nUnicodeCommentActionNumber == i )
897                             ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
898                         rMtf.AddAction( new MetaTextAction( aPt, aStr, (sal_uInt16) nIndex, (sal_uInt16) nLen ) );
899                     }
900                             rIStm.Seek( nActBegin + nActionSize );
901                 }
902                 break;
903 
904                 case( GDI_TEXTARRAY_ACTION ):
905                 {
906                     ByteString  aByteStr;
907                     sal_Int32*  pDXAry = NULL;
908                     sal_Int32       nIndex, nLen, nAryLen;
909 
910                     rIStm >> aPt >> nIndex >> nLen >> nTmp >> nAryLen;
911                     if ( nTmp && ( static_cast< sal_uInt32 >( nTmp ) < ( SAL_MAX_UINT16 - 1 ) ) )
912                     {
913                         rIStm.Read( aByteStr.AllocBuffer( (sal_uInt16)nTmp ), nTmp + 1 );
914                         UniString aStr( aByteStr, eActualCharSet );
915 
916                         if( nAryLen > 0L )
917                         {
918                             sal_Int32 nStrLen( aStr.Len() );
919 
920                             pDXAry = new sal_Int32[ Max( nAryLen, nStrLen ) ];
921 
922                             for( long j = 0L; j < nAryLen; j++ )
923                                 rIStm >> nTmp, pDXAry[ j ] = nTmp;
924 
925                             // #106172# Add last DX array elem, if missing
926                             if( nAryLen != nStrLen )
927                             {
928                                 if( nAryLen+1 == nStrLen )
929                                 {
930                                     sal_Int32* pTmpAry = new sal_Int32[nStrLen];
931 
932                                     aFontVDev.GetTextArray( aStr, pTmpAry, (sal_uInt16) nIndex, (sal_uInt16) nLen );
933 
934                                     // now, the difference between the
935                                     // last and the second last DX array
936                                     // is the advancement for the last
937                                     // glyph. Thus, to complete our meta
938                                     // action's DX array, just add that
939                                     // difference to last elem and store
940                                     // in very last.
941                                     if( nStrLen > 1 )
942                                         pDXAry[ nStrLen-1 ] = pDXAry[ nStrLen-2 ] + pTmpAry[ nStrLen-1 ] - pTmpAry[ nStrLen-2 ];
943                                     else
944                                         pDXAry[ nStrLen-1 ] = pTmpAry[ nStrLen-1 ]; // len=1: 0th position taken to be 0
945 
946                                     delete[] pTmpAry;
947                                 }
948     #ifdef DBG_UTIL
949                                 else
950                                     DBG_ERROR("More than one DX array element missing on SVM import");
951     #endif
952                             }
953                         }
954                         if ( nUnicodeCommentActionNumber == i )
955                             ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
956                         rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, pDXAry, (sal_uInt16) nIndex, (sal_uInt16) nLen ) );
957 
958                         if( pDXAry )
959                             delete[] pDXAry;
960                     }
961                             rIStm.Seek( nActBegin + nActionSize );
962                 }
963                 break;
964 
965                 case( GDI_STRETCHTEXT_ACTION ):
966                 {
967                     ByteString  aByteStr;
968                     sal_Int32       nIndex, nLen, nWidth;
969 
970                     rIStm >> aPt >> nIndex >> nLen >> nTmp >> nWidth;
971                     if ( nTmp && ( static_cast< sal_uInt32 >( nTmp ) < ( SAL_MAX_INT16 - 1 ) ) )
972                     {
973                         rIStm.Read( aByteStr.AllocBuffer( (sal_uInt16)nTmp ), nTmp + 1 );
974                         UniString aStr( aByteStr, eActualCharSet );
975                         if ( nUnicodeCommentActionNumber == i )
976                             ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
977                         rMtf.AddAction( new MetaStretchTextAction( aPt, nWidth, aStr, (sal_uInt16) nIndex, (sal_uInt16) nLen ) );
978                     }
979                                         rIStm.Seek( nActBegin + nActionSize );
980                 }
981                 break;
982 
983                 case( GDI_BITMAP_ACTION ):
984                 {
985                     Bitmap aBmp;
986 
987                     rIStm >> aPt;
988                     ReadDIB(aBmp, rIStm, true);
989                     rMtf.AddAction( new MetaBmpAction( aPt, aBmp ) );
990                 }
991                 break;
992 
993                 case( GDI_BITMAPSCALE_ACTION ):
994                 {
995                     Bitmap aBmp;
996 
997                     rIStm >> aPt >> aSz;
998                     ReadDIB(aBmp, rIStm, true);
999                     rMtf.AddAction( new MetaBmpScaleAction( aPt, aSz, aBmp ) );
1000                 }
1001                 break;
1002 
1003                 case( GDI_BITMAPSCALEPART_ACTION ):
1004                 {
1005                     Bitmap  aBmp;
1006                     Size    aSz2;
1007 
1008                     rIStm >> aPt >> aSz >> aPt1 >> aSz2;
1009                     ReadDIB(aBmp, rIStm, true);
1010                     rMtf.AddAction( new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
1011                 }
1012                 break;
1013 
1014                 case( GDI_PEN_ACTION ):
1015                 {
1016                     sal_Int32 nPenWidth;
1017                     sal_Int16 nPenStyle;
1018 
1019                     ImplReadColor( rIStm, aActionColor );
1020                     rIStm >> nPenWidth >> nPenStyle;
1021 
1022                     aLineInfo.SetStyle( nPenStyle ? LINE_SOLID : LINE_NONE );
1023                     aLineInfo.SetWidth( nPenWidth );
1024                     bFatLine = nPenStyle && !aLineInfo.IsDefault();
1025 
1026                     rMtf.AddAction( new MetaLineColorAction( aActionColor, nPenStyle != 0 ) );
1027                 }
1028                 break;
1029 
1030                 case( GDI_FILLBRUSH_ACTION ):
1031                 {
1032                     sal_Int16 nBrushStyle;
1033 
1034                     ImplReadColor( rIStm, aActionColor );
1035                     rIStm.SeekRel( 6L );
1036                     rIStm >> nBrushStyle;
1037                     rMtf.AddAction( new MetaFillColorAction( aActionColor, nBrushStyle != 0 ) );
1038                     rIStm.SeekRel( 2L );
1039                 }
1040                 break;
1041 
1042                 case( GDI_MAPMODE_ACTION ):
1043                 {
1044                     ImplReadMapMode( rIStm, aMapMode );
1045                     rMtf.AddAction( new MetaMapModeAction( aMapMode ) );
1046 
1047                     // #106172# Track font relevant data in shadow VDev
1048                     aFontVDev.SetMapMode( aMapMode );
1049                 }
1050                 break;
1051 
1052                 case( GDI_CLIPREGION_ACTION ):
1053                 {
1054                     Region  aRegion;
1055                     sal_Int16   nRegType;
1056                     sal_Int16   bIntersect;
1057                     sal_Bool    bClip = sal_False;
1058 
1059                     rIStm >> nRegType >> bIntersect;
1060                     ImplReadRect( rIStm, aRect );
1061 
1062                     switch( nRegType )
1063                     {
1064                         case( 0 ):
1065                         break;
1066 
1067                         case( 1 ):
1068                         {
1069                             Rectangle aRegRect;
1070 
1071                             ImplReadRect( rIStm, aRegRect );
1072                             aRegion = Region( aRegRect );
1073                             bClip = sal_True;
1074                         }
1075                         break;
1076 
1077                         case( 2 ):
1078                         {
1079                             ImplReadPoly( rIStm, aActionPoly );
1080                             aRegion = Region( aActionPoly );
1081                             bClip = sal_True;
1082                         }
1083                         break;
1084 
1085                         case( 3 ):
1086                         {
1087                             PolyPolygon aPolyPoly;
1088                             sal_Int32       nPolyCount;
1089 
1090                             rIStm >> nPolyCount;
1091 
1092                             for( sal_uInt16 j = 0; j < (sal_uInt16) nPolyCount; j++ )
1093                             {
1094                                 ImplReadPoly( rIStm, aActionPoly );
1095                                 aPolyPoly.Insert( aActionPoly );
1096                             }
1097 
1098                             aRegion = Region( aPolyPoly );
1099                             bClip = sal_True;
1100                         }
1101                         break;
1102                     }
1103 
1104                     if( bIntersect )
1105                         aRegion.Intersect( aRect );
1106 
1107                     rMtf.AddAction( new MetaClipRegionAction( aRegion, bClip ) );
1108                 }
1109                 break;
1110 
1111                 case( GDI_MOVECLIPREGION_ACTION ):
1112                 {
1113                     rIStm >> nTmp >> nTmp1;
1114                     rMtf.AddAction( new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
1115                 }
1116                 break;
1117 
1118                 case( GDI_ISECTCLIPREGION_ACTION ):
1119                 {
1120                     ImplReadRect( rIStm, aRect );
1121                     rMtf.AddAction( new MetaISectRectClipRegionAction( aRect ) );
1122                 }
1123                 break;
1124 
1125                 case( GDI_RASTEROP_ACTION ):
1126                 {
1127                     RasterOp    eRasterOp;
1128                     sal_Int16       nRasterOp;
1129 
1130                     rIStm >> nRasterOp;
1131 
1132                     switch( nRasterOp )
1133                     {
1134                         case( 1 ):
1135                             eRasterOp = ROP_INVERT;
1136                         break;
1137 
1138                         case( 4 ):
1139                         case( 5 ):
1140                             eRasterOp = ROP_XOR;
1141                         break;
1142 
1143                         default:
1144                             eRasterOp = ROP_OVERPAINT;
1145                         break;
1146                     }
1147 
1148                     rMtf.AddAction( new MetaRasterOpAction( eRasterOp ) );
1149                 }
1150                 break;
1151 
1152                 case( GDI_PUSH_ACTION ):
1153                 {
1154                     aLIStack.Push( new LineInfo( aLineInfo ) );
1155                     rMtf.AddAction( new MetaPushAction( PUSH_ALL ) );
1156 
1157                     // #106172# Track font relevant data in shadow VDev
1158                     aFontVDev.Push();
1159                 }
1160                 break;
1161 
1162                 case( GDI_POP_ACTION ):
1163                 {
1164 
1165                     LineInfo* pLineInfo = (LineInfo*) aLIStack.Pop();
1166 
1167                     // restore line info
1168                     if( pLineInfo )
1169                     {
1170                         aLineInfo = *pLineInfo;
1171                         delete pLineInfo;
1172                         bFatLine = ( LINE_NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
1173                     }
1174 
1175                     rMtf.AddAction( new MetaPopAction() );
1176 
1177                     // #106172# Track font relevant data in shadow VDev
1178                     aFontVDev.Pop();
1179                 }
1180                 break;
1181 
1182                 case( GDI_GRADIENT_ACTION ):
1183                 {
1184                     Color   aStartCol;
1185                     Color   aEndCol;
1186                     sal_Int16   nStyle;
1187                     sal_Int16   nAngle;
1188                     sal_Int16   nBorder;
1189                     sal_Int16   nOfsX;
1190                     sal_Int16   nOfsY;
1191                     sal_Int16   nIntensityStart;
1192                     sal_Int16   nIntensityEnd;
1193 
1194                     ImplReadRect( rIStm, aRect );
1195                     rIStm >> nStyle;
1196                     ImplReadColor( rIStm, aStartCol );
1197                     ImplReadColor( rIStm, aEndCol );
1198                     rIStm >> nAngle >> nBorder >> nOfsX >> nOfsY >> nIntensityStart >> nIntensityEnd;
1199 
1200                     Gradient aGrad( (GradientStyle) nStyle, aStartCol, aEndCol );
1201 
1202                     aGrad.SetAngle( nAngle );
1203                     aGrad.SetBorder( nBorder );
1204                     aGrad.SetOfsX( nOfsX );
1205                     aGrad.SetOfsY( nOfsY );
1206                     aGrad.SetStartIntensity( nIntensityStart );
1207                     aGrad.SetEndIntensity( nIntensityEnd );
1208                     rMtf.AddAction( new MetaGradientAction( aRect, aGrad ) );
1209                 }
1210                 break;
1211 
1212                 case( GDI_TRANSPARENT_COMMENT ):
1213                 {
1214                     PolyPolygon aPolyPoly;
1215                     sal_Int32       nFollowingActionCount;
1216                     sal_Int16       nTrans;
1217 
1218                     rIStm >> aPolyPoly >> nTrans >> nFollowingActionCount;
1219                     ImplSkipActions( rIStm, nFollowingActionCount );
1220                     rMtf.AddAction( new MetaTransparentAction( aPolyPoly, nTrans ) );
1221 
1222 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1223                     i += nFollowingActionCount;
1224 #endif
1225                 }
1226                 break;
1227 
1228                 case( GDI_FLOATTRANSPARENT_COMMENT ):
1229                 {
1230                     GDIMetaFile aMtf;
1231                     Point       aPos;
1232                     Size        aSize;
1233                     Gradient    aGradient;
1234                     sal_Int32       nFollowingActionCount;
1235 
1236                     rIStm >> aMtf >> aPos >> aSize >> aGradient >> nFollowingActionCount;
1237                     ImplSkipActions( rIStm, nFollowingActionCount );
1238                     rMtf.AddAction( new MetaFloatTransparentAction( aMtf, aPos, aSize, aGradient ) );
1239 
1240 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1241                     i += nFollowingActionCount;
1242 #endif
1243                 }
1244                 break;
1245 
1246                 case( GDI_HATCH_COMMENT ):
1247                 {
1248                     PolyPolygon aPolyPoly;
1249                     Hatch       aHatch;
1250                     sal_Int32       nFollowingActionCount;
1251 
1252                     rIStm >> aPolyPoly >> aHatch >> nFollowingActionCount;
1253                     ImplSkipActions( rIStm, nFollowingActionCount );
1254                     rMtf.AddAction( new MetaHatchAction( aPolyPoly, aHatch ) );
1255 
1256 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1257                     i += nFollowingActionCount;
1258 #endif
1259                 }
1260                 break;
1261 
1262                 case( GDI_REFPOINT_COMMENT ):
1263                 {
1264                     Point   aRefPoint;
1265                     sal_Bool    bSet;
1266                     sal_Int32   nFollowingActionCount;
1267 
1268                     rIStm >> aRefPoint >> bSet >> nFollowingActionCount;
1269                     ImplSkipActions( rIStm, nFollowingActionCount );
1270                     rMtf.AddAction( new MetaRefPointAction( aRefPoint, bSet ) );
1271 
1272 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1273                     i += nFollowingActionCount;
1274 #endif
1275 
1276                     // #106172# Track font relevant data in shadow VDev
1277                     if( bSet )
1278                         aFontVDev.SetRefPoint( aRefPoint );
1279                     else
1280                         aFontVDev.SetRefPoint();
1281                 }
1282                 break;
1283 
1284                 case( GDI_TEXTLINECOLOR_COMMENT ):
1285                 {
1286                     Color   aColor;
1287                     sal_Bool    bSet;
1288                     sal_Int32   nFollowingActionCount;
1289 
1290                     rIStm >> aColor >> bSet >> nFollowingActionCount;
1291                     ImplSkipActions( rIStm, nFollowingActionCount );
1292                     rMtf.AddAction( new MetaTextLineColorAction( aColor, bSet ) );
1293 
1294 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1295                     i += nFollowingActionCount;
1296 #endif
1297                 }
1298                 break;
1299 
1300                 case( GDI_TEXTLINE_COMMENT ):
1301                 {
1302                     Point   aStartPt;
1303                     long    nWidth;
1304                     sal_uInt32 nStrikeout;
1305                     sal_uInt32 nUnderline;
1306                     sal_Int32   nFollowingActionCount;
1307 
1308                     rIStm >> aStartPt >> nWidth >> nStrikeout >> nUnderline >> nFollowingActionCount;
1309                     ImplSkipActions( rIStm, nFollowingActionCount );
1310                     rMtf.AddAction( new MetaTextLineAction( aStartPt, nWidth,
1311                                                             (FontStrikeout) nStrikeout,
1312                                                             (FontUnderline) nUnderline,
1313                                                             UNDERLINE_NONE ) );
1314 
1315 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1316                     i += nFollowingActionCount;
1317 #endif
1318                 }
1319                 break;
1320 
1321                 case( GDI_GRADIENTEX_COMMENT ):
1322                 {
1323                     PolyPolygon aPolyPoly;
1324                     Gradient    aGradient;
1325                     sal_Int32       nFollowingActionCount;
1326 
1327                     rIStm >> aPolyPoly >> aGradient >> nFollowingActionCount;
1328                     ImplSkipActions( rIStm, nFollowingActionCount );
1329                     rMtf.AddAction( new MetaGradientExAction( aPolyPoly, aGradient ) );
1330 
1331 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1332                     i += nFollowingActionCount;
1333 #endif
1334                 }
1335                 break;
1336 
1337                 case( GDI_COMMENT_COMMENT ):
1338                 {
1339                     ByteString  aComment;
1340                     sal_Int32   nValue;
1341                     sal_uInt32  nDataSize;
1342                     sal_uInt8*      pData;
1343                     sal_Int32       nFollowingActionCount;
1344 
1345                     rIStm >> aComment >> nValue >> nDataSize;
1346 
1347                     if( nDataSize )
1348                     {
1349                         pData = new sal_uInt8[ nDataSize ];
1350                         rIStm.Read( pData, nDataSize );
1351                     }
1352                     else
1353                         pData = NULL;
1354 
1355                     rIStm >> nFollowingActionCount;
1356                     ImplSkipActions( rIStm, nFollowingActionCount );
1357                     rMtf.AddAction( new MetaCommentAction( aComment, nValue, pData, nDataSize ) );
1358 
1359 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
1360                     i += nFollowingActionCount;
1361 #endif
1362                 }
1363                 break;
1364 
1365                 case ( GDI_UNICODE_COMMENT ):
1366                 {
1367                     nUnicodeCommentActionNumber = i + 1;
1368                     nUnicodeCommentStreamPos = rIStm.Tell() - 6;
1369                     rIStm.SeekRel( nActionSize - 4 );
1370                 }
1371                 break;
1372 
1373                 default:
1374                     rIStm.SeekRel( nActionSize - 4L );
1375                 break;
1376             }
1377                 }
1378 
1379         // cleanup push-pop stack if neccessary
1380         for( void* pLineInfo = aLIStack.Pop(); pLineInfo; pLineInfo = aLIStack.Pop() )
1381             delete (LineInfo*) pLineInfo;
1382 
1383     rIStm.SetNumberFormatInt( nOldFormat );
1384 }
1385 
1386 // ------------------------------------------------------------------------
1387 
ImplConvertToSVM1(SvStream & rOStm,GDIMetaFile & rMtf)1388 void SVMConverter::ImplConvertToSVM1( SvStream& rOStm, GDIMetaFile& rMtf )
1389 {
1390     sal_uLong               nPos;
1391     sal_uLong               nCountPos;
1392     Font                aSaveFont;
1393     const sal_uInt16        nOldFormat = rOStm.GetNumberFormatInt();
1394     rtl_TextEncoding    eActualCharSet = gsl_getSystemTextEncoding();
1395     const Size          aPrefSize( rMtf.GetPrefSize() );
1396     sal_Bool                bRop_0_1 = sal_False;
1397     VirtualDevice       aSaveVDev;
1398     Color               aLineCol( COL_BLACK );
1399     Stack               aLineColStack;
1400 
1401     rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1402 
1403     //MagicCode schreiben
1404     rOStm << "SVGDI";                                   // Kennung
1405     nPos = rOStm.Tell();
1406     rOStm << (sal_Int16) 42;                                // HeaderSize
1407     rOStm << (sal_Int16) 200;                               // VERSION
1408     rOStm << (sal_Int32) aPrefSize.Width();
1409     rOStm << (sal_Int32) aPrefSize.Height();
1410     ImplWriteMapMode( rOStm, rMtf.GetPrefMapMode() );
1411 
1412     // ActionCount wird spaeter geschrieben
1413     nCountPos = rOStm.Tell();
1414     rOStm.SeekRel( 4L );
1415 
1416     const sal_Int32 nActCount = ImplWriteActions( rOStm, rMtf, aSaveVDev, bRop_0_1, aLineCol, aLineColStack, eActualCharSet );
1417     const sal_uLong nActPos = rOStm.Tell();
1418 
1419     rOStm.Seek( nCountPos );
1420     rOStm << nActCount;
1421     rOStm.Seek( nActPos );
1422     rOStm.SetNumberFormatInt( nOldFormat );
1423 
1424     // cleanup push-pop stack if neccessary
1425     for( void* pCol = aLineColStack.Pop(); pCol; pCol = aLineColStack.Pop() )
1426         delete (Color*) pCol;
1427 }
1428 
1429 // ------------------------------------------------------------------------
1430 
ImplWriteActions(SvStream & rOStm,GDIMetaFile & rMtf,VirtualDevice & rSaveVDev,sal_Bool & rRop_0_1,Color & rLineCol,Stack & rLineColStack,rtl_TextEncoding & rActualCharSet)1431 sal_uLong SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
1432                                       VirtualDevice& rSaveVDev, sal_Bool& rRop_0_1,
1433                                       Color& rLineCol, Stack& rLineColStack,
1434                                       rtl_TextEncoding& rActualCharSet )
1435 {
1436     sal_uLong nCount = 0;
1437     for( sal_uLong i = 0, nActionCount = rMtf.GetActionCount(); i < nActionCount; i++ )
1438     {
1439         const MetaAction* pAction = rMtf.GetAction( i );
1440 
1441         switch( pAction->GetType() )
1442         {
1443             case( META_PIXEL_ACTION ):
1444             {
1445                 MetaPixelAction* pAct = (MetaPixelAction*) pAction;
1446 
1447                 rOStm << (sal_Int16) GDI_PIXEL_ACTION;
1448                 rOStm << (sal_Int32) 18;
1449                 rOStm << pAct->GetPoint();
1450                 ImplWriteColor( rOStm, pAct->GetColor() );
1451                 nCount++;
1452             }
1453             break;
1454 
1455             case( META_POINT_ACTION ):
1456             {
1457                 MetaPointAction* pAct = (MetaPointAction*) pAction;
1458 
1459                 rOStm << (sal_Int16) GDI_POINT_ACTION;
1460                 rOStm << (sal_Int32) 12;
1461                 rOStm << pAct->GetPoint();
1462                 nCount++;
1463             }
1464             break;
1465 
1466             case( META_LINE_ACTION ):
1467             {
1468                 MetaLineAction* pAct = (MetaLineAction*) pAction;
1469                 const LineInfo& rInfo = pAct->GetLineInfo();
1470                 const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
1471                 const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
1472                 const bool bLineCap(bFatLine && com::sun::star::drawing::LineCap_BUTT != rInfo.GetLineCap());
1473                 const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
1474 
1475                 if( bFatLine )
1476                 {
1477                     ImplWritePushAction( rOStm );
1478                     ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
1479 
1480                     if(bLineJoin)
1481                     {
1482                         rOStm << (sal_Int16) GDI_LINEJOIN_ACTION;
1483                         rOStm << (sal_Int32) 6;
1484                         rOStm << (sal_Int16) rInfo.GetLineJoin();
1485                     }
1486 
1487                     if(bLineCap)
1488                     {
1489                         rOStm << (sal_Int16) GDI_LINECAP_ACTION;
1490                         rOStm << (sal_Int32) 6;
1491                         rOStm << (sal_Int16) rInfo.GetLineCap();
1492                     }
1493                 }
1494 
1495                 if(bLineDashDot)
1496                 {
1497                     rOStm << (sal_Int16) GDI_LINEDASHDOT_ACTION;
1498                     rOStm << (sal_Int32) 4 + 16;
1499                     rOStm << (sal_Int16)rInfo.GetDashCount();
1500                     rOStm << (sal_Int32)rInfo.GetDashLen();
1501                     rOStm << (sal_Int16)rInfo.GetDotCount();
1502                     rOStm << (sal_Int32)rInfo.GetDotLen();
1503                     rOStm << (sal_Int32)rInfo.GetDistance();
1504                 }
1505 
1506                 rOStm << (sal_Int16) GDI_LINE_ACTION;
1507                 rOStm << (sal_Int32) 20;
1508                 rOStm << pAct->GetStartPoint();
1509                 rOStm << pAct->GetEndPoint();
1510                 nCount++;
1511 
1512                 if( bFatLine )
1513                 {
1514                     ImplWritePopAction( rOStm );
1515                     nCount += 3;
1516 
1517                     if(bLineJoin)
1518                     {
1519                         nCount += 1;
1520                     }
1521 
1522                     if(bLineCap)
1523                     {
1524                         nCount += 1;
1525                     }
1526                 }
1527 
1528                 if(bLineDashDot)
1529                 {
1530                     nCount += 1;
1531                 }
1532             }
1533             break;
1534 
1535             case( META_RECT_ACTION ):
1536             {
1537                 MetaRectAction* pAct = (MetaRectAction*) pAction;
1538 
1539                 rOStm << (sal_Int16) GDI_RECT_ACTION;
1540                 rOStm << (sal_Int32) 28;
1541                 ImplWriteRect( rOStm, pAct->GetRect() );
1542                 rOStm << (sal_Int32) 0;
1543                 rOStm << (sal_Int32) 0;
1544                 nCount++;
1545             }
1546             break;
1547 
1548             case( META_ROUNDRECT_ACTION ):
1549             {
1550                 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
1551 
1552                 rOStm << (sal_Int16) GDI_RECT_ACTION;
1553                 rOStm << (sal_Int32) 28;
1554                 ImplWriteRect( rOStm, pAct->GetRect() );
1555                 rOStm << (sal_Int32) pAct->GetHorzRound();
1556                 rOStm << (sal_Int32) pAct->GetVertRound();
1557                 nCount++;
1558             }
1559             break;
1560 
1561             case( META_ELLIPSE_ACTION ):
1562             {
1563                 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
1564 
1565                 rOStm << (sal_Int16) GDI_ELLIPSE_ACTION;
1566                 rOStm << (sal_Int32) 20;
1567                 ImplWriteRect( rOStm, pAct->GetRect() );
1568                 nCount++;
1569             }
1570             break;
1571 
1572             case( META_ARC_ACTION ):
1573             {
1574                 MetaArcAction* pAct = (MetaArcAction*) pAction;
1575 
1576                 rOStm << (sal_Int16) GDI_ARC_ACTION;
1577                 rOStm << (sal_Int32) 36;
1578                 ImplWriteRect( rOStm, pAct->GetRect() );
1579                 rOStm << pAct->GetStartPoint();
1580                 rOStm << pAct->GetEndPoint();
1581                 nCount++;
1582             }
1583             break;
1584 
1585             case( META_PIE_ACTION ):
1586             {
1587                 MetaPieAction* pAct = (MetaPieAction*) pAction;
1588 
1589                 rOStm << (sal_Int16) GDI_PIE_ACTION;
1590                 rOStm << (sal_Int32) 36;
1591                 ImplWriteRect( rOStm, pAct->GetRect() );
1592                 rOStm << pAct->GetStartPoint();
1593                 rOStm << pAct->GetEndPoint();
1594                 nCount++;
1595             }
1596             break;
1597 
1598             case( META_CHORD_ACTION ):
1599             {
1600                 MetaChordAction*    pAct = (MetaChordAction*) pAction;
1601                 Polygon             aChordPoly( pAct->GetRect(), pAct->GetStartPoint(),
1602                                                 pAct->GetEndPoint(), POLY_CHORD );
1603                 const sal_uInt16        nPoints = aChordPoly.GetSize();
1604 
1605                 rOStm << (sal_Int16) GDI_POLYGON_ACTION;
1606                 rOStm << (sal_Int32) ( 8 + ( nPoints << 3 ) );
1607                 rOStm << (sal_Int32) nPoints;
1608 
1609                 for( sal_uInt16 n = 0; n < nPoints; n++ )
1610                     rOStm << aChordPoly[ n ];
1611                 nCount++;
1612             }
1613             break;
1614 
1615             case( META_POLYLINE_ACTION ):
1616             {
1617                 // #i102224#
1618                 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
1619                 // #i102224# Here the evtl. curved nature of Polygon was
1620                 // ignored (for all those Years). Adapted to at least write
1621                 // a polygon representing the curve as good as possible
1622                 Polygon aSimplePoly;
1623                 pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
1624                 const LineInfo& rInfo = pAct->GetLineInfo();
1625                 const sal_uInt16 nPoints(aSimplePoly.GetSize());
1626                 const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
1627                 const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
1628                 const bool bLineCap(bFatLine && com::sun::star::drawing::LineCap_BUTT != rInfo.GetLineCap());
1629                 const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
1630 
1631                 if( bFatLine )
1632                 {
1633                     ImplWritePushAction( rOStm );
1634                     ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
1635 
1636                     if(bLineJoin)
1637                     {
1638                         rOStm << (sal_Int16) GDI_LINEJOIN_ACTION;
1639                         rOStm << (sal_Int32) 6;
1640                         rOStm << (sal_Int16) rInfo.GetLineJoin();
1641                     }
1642 
1643                     if(bLineCap)
1644                     {
1645                         rOStm << (sal_Int16) GDI_LINECAP_ACTION;
1646                         rOStm << (sal_Int32) 6;
1647                         rOStm << (sal_Int16) rInfo.GetLineCap();
1648                     }
1649                 }
1650 
1651                 if(bLineDashDot)
1652                 {
1653                     rOStm << (sal_Int16) GDI_LINEDASHDOT_ACTION;
1654                     rOStm << (sal_Int32) 4 + 16;
1655                     rOStm << (sal_Int16)rInfo.GetDashCount();
1656                     rOStm << (sal_Int32)rInfo.GetDashLen();
1657                     rOStm << (sal_Int16)rInfo.GetDotCount();
1658                     rOStm << (sal_Int32)rInfo.GetDotLen();
1659                     rOStm << (sal_Int32)rInfo.GetDistance();
1660                 }
1661 
1662                 rOStm << (sal_Int16) GDI_POLYLINE_ACTION;
1663                 rOStm << (sal_Int32) ( 8 + ( nPoints << 3 ) );
1664                 rOStm << (sal_Int32) nPoints;
1665 
1666                 for( sal_uInt16 n = 0; n < nPoints; n++ )
1667                 {
1668                     rOStm << aSimplePoly[ n ];
1669                 }
1670 
1671                 nCount++;
1672 
1673                 const PolyPolygon aPolyPolygon(pAct->GetPolygon());
1674                 if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
1675                 {
1676                     nCount++;
1677                 }
1678 
1679                 if( bFatLine )
1680                 {
1681                     ImplWritePopAction( rOStm );
1682                     nCount += 3;
1683 
1684                     if(bLineJoin)
1685                     {
1686                         nCount += 1;
1687                     }
1688 
1689                     if(bLineCap)
1690                     {
1691                         nCount += 1;
1692                     }
1693                 }
1694 
1695                 if(bLineDashDot)
1696                 {
1697                     nCount += 1;
1698                 }
1699             }
1700             break;
1701 
1702             case( META_POLYGON_ACTION ):
1703             {
1704                 MetaPolygonAction* pAct = (MetaPolygonAction*)pAction;
1705                 // #i102224# Here the evtl. curved nature of Polygon was
1706                 // ignored (for all those Years). Adapted to at least write
1707                 // a polygon representing the curve as good as possible
1708                 Polygon aSimplePoly;
1709                 pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
1710                 const sal_uInt16 nPoints(aSimplePoly.GetSize());
1711 
1712                 rOStm << (sal_Int16) GDI_POLYGON_ACTION;
1713                 rOStm << (sal_Int32) ( 8 + ( nPoints << 3 ) );
1714                 rOStm << (sal_Int32) nPoints;
1715 
1716                 for( sal_uInt16 n = 0; n < nPoints; n++ )
1717                     rOStm << aSimplePoly[ n ];
1718 
1719                 nCount++;
1720 
1721                 const PolyPolygon aPolyPolygon(pAct->GetPolygon());
1722                 if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
1723                 {
1724                     nCount++;
1725                 }
1726             }
1727             break;
1728 
1729             case( META_POLYPOLYGON_ACTION ):
1730             {
1731                 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
1732                 ImplWritePolyPolyAction( rOStm, pAct->GetPolyPolygon() );
1733                 nCount++;
1734 
1735                 if(ImplWriteExtendedPolyPolygonAction(rOStm, pAct->GetPolyPolygon(), true))
1736                 {
1737                     nCount++;
1738                 }
1739             }
1740             break;
1741 
1742             case( META_TEXT_ACTION ):
1743             {
1744                 MetaTextAction* pAct = (MetaTextAction*) pAction;
1745                 String          aUniText( pAct->GetText() );
1746                 ByteString      aText( aUniText, rActualCharSet );
1747                 const sal_uLong     nStrLen = aText.Len();
1748 
1749                 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1750                     nCount++;
1751 
1752                 rOStm << (sal_Int16) GDI_TEXT_ACTION;
1753                 rOStm << (sal_Int32) ( 24 + ( nStrLen + 1 ) );
1754                 rOStm << pAct->GetPoint();
1755                 rOStm << (sal_Int32) pAct->GetIndex();
1756                 rOStm << (sal_Int32) pAct->GetLen();
1757                 rOStm << (sal_Int32) nStrLen;
1758                 rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
1759                 nCount++;
1760             }
1761             break;
1762 
1763             case( META_TEXTARRAY_ACTION ):
1764             {
1765                 MetaTextArrayAction*    pAct = (MetaTextArrayAction*)pAction;
1766                 ByteString              aText( pAct->GetText(), rActualCharSet );
1767                 String                  aUniText( pAct->GetText(), pAct->GetIndex(), pAct->GetLen() );
1768                 sal_uLong                   nAryLen;
1769                 sal_uLong                   nLen = pAct->GetLen();
1770                 const sal_uLong             nTextLen = aText.Len();
1771                 sal_Int32*              pDXArray = pAct->GetDXArray();
1772 
1773                 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1774                     nCount++;
1775 
1776                 if( ( nLen + pAct->GetIndex() ) > nTextLen )
1777                 {
1778                     if( pAct->GetIndex() <= nTextLen )
1779                         nLen = nTextLen - pAct->GetIndex();
1780                     else
1781                         nLen = 0UL;
1782                 }
1783 
1784                 if( !pDXArray || !nLen )
1785                     nAryLen = 0;
1786                 else
1787                     nAryLen = nLen; // #105987# Write out all of DX array
1788 
1789                 rOStm << (sal_Int16) GDI_TEXTARRAY_ACTION;
1790                 rOStm << (sal_Int32) ( 28 + ( nLen + 1 ) + ( nAryLen * 4 ) );
1791                 rOStm << pAct->GetPoint();
1792                 rOStm << (sal_Int32) 0;
1793                 rOStm << (sal_Int32) nLen;
1794                 rOStm << (sal_Int32) nLen;
1795                 rOStm << (sal_Int32) nAryLen;
1796                 rOStm.Write( aText.GetBuffer()+pAct->GetIndex(), nLen + 1 );
1797 
1798                 for( sal_uLong n = 0UL ; n < nAryLen; n++ )
1799                     rOStm << (sal_Int32) pDXArray[ n ];
1800 
1801                 nCount++;
1802             }
1803             break;
1804 
1805             case( META_STRETCHTEXT_ACTION ):
1806             {
1807                 MetaStretchTextAction*  pAct = (MetaStretchTextAction*) pAction;
1808                 String                  aUniText( pAct->GetText() );
1809                 ByteString              aText( aUniText, rActualCharSet );
1810                 const sal_uLong             nStrLen = aText.Len();
1811 
1812                 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1813                     nCount++;
1814 
1815                 rOStm << (sal_Int16) GDI_STRETCHTEXT_ACTION;
1816                 rOStm << (sal_Int32) ( 28 + ( nStrLen + 1 ) );
1817                 rOStm << pAct->GetPoint();
1818                 rOStm << (sal_Int32) pAct->GetIndex();
1819                 rOStm << (sal_Int32) pAct->GetLen();
1820                 rOStm << (sal_Int32) nStrLen;
1821                 rOStm << (sal_Int32) pAct->GetWidth();
1822                 rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
1823                 nCount++;
1824             }
1825             break;
1826 
1827             case( META_BMP_ACTION ):
1828             {
1829                 MetaBmpAction* pAct = (MetaBmpAction*) pAction;
1830 
1831                 rOStm << (sal_Int16) GDI_BITMAP_ACTION;
1832                 rOStm << (sal_Int32) 12;
1833                 rOStm << pAct->GetPoint();
1834                 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1835                 nCount++;
1836             }
1837             break;
1838 
1839             case( META_BMPSCALE_ACTION ):
1840             {
1841                 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
1842 
1843                 rOStm << (sal_Int16) GDI_BITMAPSCALE_ACTION;
1844                 rOStm << (sal_Int32) 20;
1845                 rOStm << pAct->GetPoint();
1846                 rOStm << pAct->GetSize();
1847                 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1848                 nCount++;
1849             }
1850             break;
1851 
1852             case( META_BMPSCALEPART_ACTION ):
1853             {
1854                 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
1855 
1856                 rOStm << (sal_Int16) GDI_BITMAPSCALEPART_ACTION;
1857                 rOStm << (sal_Int32) 36;
1858                 rOStm << pAct->GetDestPoint();
1859                 rOStm << pAct->GetDestSize();
1860                 rOStm << pAct->GetSrcPoint();
1861                 rOStm << pAct->GetSrcSize();
1862                 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1863                 nCount++;
1864             }
1865             break;
1866 
1867             case( META_BMPEX_ACTION ):
1868             {
1869                 MetaBmpExAction*    pAct = (MetaBmpExAction*) pAction;
1870                 const Bitmap        aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1871 
1872                 rOStm << (sal_Int16) GDI_BITMAP_ACTION;
1873                 rOStm << (sal_Int32) 12;
1874                 rOStm << pAct->GetPoint();
1875                 WriteDIB(aBmp, rOStm, false, true);
1876                 nCount++;
1877             }
1878             break;
1879 
1880             case( META_BMPEXSCALE_ACTION ):
1881             {
1882                 MetaBmpExScaleAction*   pAct = (MetaBmpExScaleAction*) pAction;
1883                 const Bitmap            aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1884 
1885                 rOStm << (sal_Int16) GDI_BITMAPSCALE_ACTION;
1886                 rOStm << (sal_Int32) 20;
1887                 rOStm << pAct->GetPoint();
1888                 rOStm << pAct->GetSize();
1889                 WriteDIB(aBmp, rOStm, false, true);
1890                 nCount++;
1891             }
1892             break;
1893 
1894             case( META_BMPEXSCALEPART_ACTION ):
1895             {
1896                 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
1897                 const Bitmap            aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1898 
1899                 rOStm << (sal_Int16) GDI_BITMAPSCALEPART_ACTION;
1900                 rOStm << (sal_Int32) 36;
1901                 rOStm << pAct->GetDestPoint();
1902                 rOStm << pAct->GetDestSize();
1903                 rOStm << pAct->GetSrcPoint();
1904                 rOStm << pAct->GetSrcSize();
1905                 WriteDIB(aBmp, rOStm, false, true);
1906                 nCount++;
1907             }
1908             break;
1909 
1910             case( META_GRADIENT_ACTION ):
1911             {
1912                 MetaGradientAction* pAct = (MetaGradientAction*) pAction;
1913                 const Gradient&     rGrad = pAct->GetGradient();
1914 
1915                 rOStm << (sal_Int16) GDI_GRADIENT_ACTION;
1916                 rOStm << (sal_Int32) 46;
1917                 ImplWriteRect( rOStm, pAct->GetRect() );
1918                 rOStm << (sal_Int16) rGrad.GetStyle();
1919                 ImplWriteColor( rOStm, rGrad.GetStartColor() );
1920                 ImplWriteColor( rOStm, rGrad.GetEndColor() );
1921                 rOStm << (sal_Int16) rGrad.GetAngle();
1922                 rOStm << (sal_Int16) rGrad.GetBorder();
1923                 rOStm << (sal_Int16) rGrad.GetOfsX();
1924                 rOStm << (sal_Int16) rGrad.GetOfsY();
1925                 rOStm << (sal_Int16) rGrad.GetStartIntensity();
1926                 rOStm << (sal_Int16) rGrad.GetEndIntensity();
1927                 nCount++;
1928             }
1929             break;
1930 
1931             case( META_GRADIENTEX_ACTION ):
1932             {
1933                 const MetaGradientExAction* pA = (MetaGradientExAction*) pAction;
1934                 sal_uLong                       nOldPos, nNewPos;
1935 
1936                 // write RefPoint comment
1937                 rOStm << (sal_Int16) GDI_GRADIENTEX_COMMENT;
1938 
1939                 // we'll write the ActionSize later
1940                 nOldPos = rOStm.Tell();
1941                 rOStm.SeekRel( 4 );
1942 
1943                 // write data
1944                 rOStm << pA->GetPolyPolygon() << pA->GetGradient();
1945                 rOStm << (sal_Int32) 0; // number of actions that follow this comment
1946 
1947                 // calculate and write ActionSize of comment
1948                 nNewPos = rOStm.Tell();
1949                 rOStm.Seek( nOldPos );
1950                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
1951                 rOStm.Seek( nNewPos );
1952 
1953                 nCount++;
1954             }
1955             break;
1956 
1957             case( META_WALLPAPER_ACTION ):
1958             {
1959                 MetaWallpaperAction*    pAct = (MetaWallpaperAction*) pAction;
1960                 const Color&            rColor = pAct->GetWallpaper().GetColor();
1961 
1962                 ImplWritePushAction( rOStm );
1963                 ImplWriteLineColor( rOStm, rColor, 1 );
1964                 ImplWriteFillColor( rOStm, rColor, 1 );
1965 
1966                 rOStm << (sal_Int16) GDI_RECT_ACTION;
1967                 rOStm << (sal_Int32) 28;
1968                 ImplWriteRect( rOStm, pAct->GetRect() );
1969                 rOStm << (sal_Int32) 0;
1970                 rOStm << (sal_Int32) 0;
1971 
1972                 ImplWritePopAction( rOStm );
1973                 nCount += 5;
1974             }
1975             break;
1976 
1977             case( META_CLIPREGION_ACTION ):
1978             {
1979                 MetaClipRegionAction*   pAct = (MetaClipRegionAction*) pAction;
1980                 const Region&           rRegion = pAct->GetRegion();
1981                 Rectangle               aClipRect;
1982 
1983                 rOStm << (sal_Int16) GDI_CLIPREGION_ACTION;
1984                 rOStm << (sal_Int32) 24;
1985 
1986                 if( pAct->IsClipping() )
1987                 {
1988                     aClipRect = rRegion.GetBoundRect();
1989                     rOStm << (sal_Int16) 1;
1990                 }
1991                 else
1992                     rOStm << (sal_Int16) 0;
1993 
1994                 rOStm << (sal_Int16) 0;
1995                 ImplWriteRect( rOStm, aClipRect );
1996 
1997                 if( pAct->IsClipping() )
1998                     ImplWriteRect( rOStm, aClipRect );
1999 
2000                 nCount++;
2001             }
2002             break;
2003 
2004             case( META_ISECTRECTCLIPREGION_ACTION ):
2005             {
2006                 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
2007 
2008                 rOStm << (sal_Int16) GDI_ISECTCLIPREGION_ACTION;
2009                 rOStm << (sal_Int32) 20;
2010                 rOStm << pAct->GetRect();
2011                 nCount++;
2012             }
2013             break;
2014 
2015             case( META_MOVECLIPREGION_ACTION ):
2016             {
2017                 MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
2018 
2019                 rOStm << (sal_Int16) GDI_MOVECLIPREGION_ACTION;
2020                 rOStm << (sal_Int32) 12;
2021                 rOStm << (sal_Int32) pAct->GetHorzMove();
2022                 rOStm << (sal_Int32) pAct->GetVertMove();
2023                 nCount++;
2024             }
2025             break;
2026 
2027             case( META_LINECOLOR_ACTION ):
2028             {
2029                 MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
2030                 ImplWriteLineColor( rOStm, rLineCol = pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
2031                 nCount++;
2032             }
2033             break;
2034 
2035             case( META_FILLCOLOR_ACTION ):
2036             {
2037                 MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
2038                 ImplWriteFillColor( rOStm, pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
2039                 nCount++;
2040             }
2041             break;
2042 
2043             case( META_FONT_ACTION ):
2044             {
2045                 rSaveVDev.SetFont( ( (MetaFontAction*) pAction )->GetFont() );
2046                 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2047                 nCount++;
2048             }
2049             break;
2050 
2051             case( META_TEXTCOLOR_ACTION ):
2052             {
2053                 Font aSaveFont( rSaveVDev.GetFont() );
2054 
2055                 aSaveFont.SetColor( ( (MetaTextColorAction*) pAction )->GetColor() );
2056                 rSaveVDev.SetFont( aSaveFont );
2057                 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2058                 nCount++;
2059             }
2060             break;
2061 
2062             case( META_TEXTFILLCOLOR_ACTION ):
2063             {
2064                 MetaTextFillColorAction*    pAct = (MetaTextFillColorAction*) pAction;
2065                 Font                        aSaveFont( rSaveVDev.GetFont() );
2066 
2067                 if( pAct->IsSetting() )
2068                     aSaveFont.SetFillColor( pAct->GetColor() );
2069                 else
2070                     aSaveFont.SetFillColor( Color( COL_TRANSPARENT ) );
2071 
2072                 rSaveVDev.SetFont( aSaveFont );
2073                 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2074                 nCount++;
2075             }
2076             break;
2077 
2078             case( META_TEXTALIGN_ACTION ):
2079             {
2080                 Font aSaveFont( rSaveVDev.GetFont() );
2081 
2082                 aSaveFont.SetAlign( ( (MetaTextAlignAction*) pAction )->GetTextAlign() );
2083                 rSaveVDev.SetFont( aSaveFont );
2084                 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2085                 nCount++;
2086             }
2087             break;
2088 
2089             case( META_MAPMODE_ACTION ):
2090             {
2091                 MetaMapModeAction* pAct = (MetaMapModeAction*) pAction;
2092 
2093                 rOStm << (sal_Int16) GDI_MAPMODE_ACTION;
2094                 rOStm << (sal_Int32) 30;
2095                 ImplWriteMapMode( rOStm, pAct->GetMapMode() );
2096                 nCount++;
2097             }
2098             break;
2099 
2100             case( META_PUSH_ACTION ):
2101             {
2102                 ImplWritePushAction( rOStm );
2103                 rLineColStack.Push( new Color( rLineCol ) );
2104                 rSaveVDev.Push();
2105                 nCount++;
2106             }
2107             break;
2108 
2109             case( META_POP_ACTION ):
2110             {
2111                 Color* pCol = (Color*) rLineColStack.Pop();
2112 
2113                 if( pCol )
2114                 {
2115                     rLineCol = *pCol;
2116                     delete pCol;
2117                 }
2118 
2119                 ImplWritePopAction( rOStm );
2120                 rSaveVDev.Pop();
2121                 nCount++;
2122             }
2123             break;
2124 
2125             case( META_RASTEROP_ACTION ):
2126             {
2127                 MetaRasterOpAction* pAct = (MetaRasterOpAction*) pAction;
2128 
2129                 if( ( pAct->GetRasterOp() != ROP_0 ) && ( pAct->GetRasterOp() != ROP_1 ) )
2130                 {
2131                     sal_Int16 nRasterOp;
2132 
2133                     // Falls vorher ROP_0/1 gesetzt war, alten
2134                     // Zustand durch Pop erst wieder herstellen
2135                     if( rRop_0_1 )
2136                     {
2137                         ImplWritePopAction( rOStm );
2138                         rSaveVDev.Pop();
2139                         rRop_0_1 = sal_False;
2140                         nCount++;
2141                     }
2142 
2143                     switch( pAct->GetRasterOp() )
2144                     {
2145                         case( ROP_OVERPAINT ) : nRasterOp = 0; break;
2146                         case( ROP_XOR ) :       nRasterOp = 4; break;
2147                         case( ROP_INVERT ):     nRasterOp = 1; break;
2148                         default:                nRasterOp = 0; break;
2149                     }
2150 
2151                     ImplWriteRasterOpAction( rOStm, nRasterOp );
2152                     nCount++;
2153                 }
2154                 else
2155                 {
2156                     ImplWritePushAction( rOStm );
2157                     rSaveVDev.Push();
2158 
2159                     if( pAct->GetRasterOp() == ROP_0 )
2160                     {
2161                         ImplWriteLineColor( rOStm, COL_BLACK, 1 );
2162                         ImplWriteFillColor( rOStm, COL_BLACK, 1 );
2163                     }
2164                     else
2165                     {
2166                         ImplWriteLineColor( rOStm, COL_WHITE, 1 );
2167                         ImplWriteFillColor( rOStm, COL_WHITE, 1 );
2168                     }
2169 
2170                     ImplWriteRasterOpAction( rOStm, 0 );
2171                     rRop_0_1 = sal_True;
2172                     nCount += 4;
2173                 }
2174             }
2175             break;
2176 
2177             case( META_TRANSPARENT_ACTION ):
2178             {
2179                 const PolyPolygon&  rPolyPoly = ( (MetaTransparentAction*) pAction )->GetPolyPolygon();
2180                 const sal_Int16         nTrans = ( (MetaTransparentAction*) pAction )->GetTransparence();
2181                 const sal_Int16         nBrushStyle = ( nTrans < 38 ) ? 8 : ( nTrans < 63 ) ? 9 : 10;
2182                 sal_uLong               nOldPos, nNewPos;
2183 
2184                 // write transparence comment
2185                 rOStm << (sal_Int16) GDI_TRANSPARENT_COMMENT;
2186 
2187                 // we'll write the ActionSize later
2188                 nOldPos = rOStm.Tell();
2189                 rOStm.SeekRel( 4 );
2190 
2191                 // write comment data
2192                 rOStm << rPolyPoly;
2193                 rOStm << nTrans;
2194                 rOStm << (sal_Int32) 15; // number of actions that follow this comment
2195 
2196                 // calculate and write ActionSize of comment
2197                 nNewPos = rOStm.Tell();
2198                 rOStm.Seek( nOldPos );
2199                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
2200                 rOStm.Seek( nNewPos );
2201 
2202                 {
2203                     // write actions for transparence
2204                     ImplWritePushAction( rOStm );
2205                     {
2206                         ImplWriteRasterOpAction( rOStm, 4 );
2207                         ImplWritePolyPolyAction( rOStm, rPolyPoly );
2208 
2209                         ImplWritePushAction( rOStm );
2210                         {
2211                             ImplWriteRasterOpAction( rOStm, 2 );
2212                             ImplWriteFillColor( rOStm, COL_BLACK, nBrushStyle );
2213                             ImplWritePolyPolyAction( rOStm, rPolyPoly );
2214                         }
2215                         ImplWritePopAction( rOStm );
2216 
2217                         ImplWriteRasterOpAction( rOStm, 4 );
2218                         ImplWritePolyPolyAction( rOStm, rPolyPoly );
2219                     }
2220                     ImplWritePopAction( rOStm );
2221 
2222                     ImplWritePushAction( rOStm );
2223                     {
2224                         ImplWriteFillColor( rOStm, Color(), 0 );
2225                         ImplWritePolyPolyAction( rOStm, rPolyPoly );
2226                     }
2227                     ImplWritePopAction( rOStm );
2228 
2229 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
2230                     nCount += 15;
2231 #endif
2232                 }
2233 
2234                 nCount++;
2235             }
2236             break;
2237 
2238             case( META_FLOATTRANSPARENT_ACTION ):
2239             {
2240                 const MetaFloatTransparentAction*   pA = (MetaFloatTransparentAction*) pAction;
2241                 const GDIMetaFile&                  rTransMtf = pA->GetGDIMetaFile();
2242                 const Point&                        rPos = pA->GetPoint();
2243                 const Size&                         rSize = pA->GetSize();
2244                 const Gradient&                     rGradient = pA->GetGradient();
2245                 sal_uLong                               nOldPos, nNewPos;
2246 
2247                 // write RefPoint comment
2248                 rOStm << (sal_Int16) GDI_FLOATTRANSPARENT_COMMENT;
2249 
2250                 // we'll write the ActionSize later
2251                 nOldPos = rOStm.Tell();
2252                 rOStm.SeekRel( 4 );
2253 
2254                 // write comment data
2255                 rOStm << rTransMtf << rPos << rSize << rGradient;
2256 
2257                 // calculate and write ActionSize of comment
2258                 nNewPos = rOStm.Tell();
2259                 rOStm.Seek( nOldPos );
2260                 rOStm << (sal_Int32) ( nNewPos - nOldPos + 4 );
2261                 rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
2262 
2263                 {
2264                     // write actions for float transparence
2265                     sal_uLong           nAddCount;
2266                     GDIMetaFile     aMtf( rTransMtf );
2267                     const Size      aSrcSize( rTransMtf.GetPrefSize() );
2268                     Point           aSrcPt( rTransMtf.GetPrefMapMode().GetOrigin() );
2269                     const double    fScaleX = aSrcSize.Width() ? (double) rSize.Width() / aSrcSize.Width() : 1.0;
2270                     const double    fScaleY = aSrcSize.Height() ? (double) rSize.Height() / aSrcSize.Height() : 1.0;
2271                     long            nMoveX, nMoveY;
2272 
2273                     if( fScaleX != 1.0 || fScaleY != 1.0 )
2274                     {
2275                         aMtf.Scale( fScaleX, fScaleY );
2276                         aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2277                     }
2278 
2279                     nMoveX = rPos.X() - aSrcPt.X(), nMoveY = rPos.Y() - aSrcPt.Y();
2280 
2281                     if( nMoveX || nMoveY )
2282                         aMtf.Move( nMoveX, nMoveY );
2283 
2284                     nAddCount = ImplWriteActions( rOStm, aMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
2285                     nNewPos = rOStm.Tell();
2286                     rOStm.Seek( nOldPos );
2287                     rOStm << (sal_Int32) nAddCount;
2288                     rOStm.Seek( nNewPos );
2289 
2290 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
2291                     nCount += nAddCount;
2292 #endif
2293                 }
2294 
2295                 nCount++;
2296             }
2297             break;
2298 
2299             case( META_HATCH_ACTION ):
2300             {
2301                 const MetaHatchAction*  pA = (MetaHatchAction*) pAction;
2302                 const PolyPolygon&      rPolyPoly = pA->GetPolyPolygon();
2303                 const Hatch&            rHatch = pA->GetHatch();
2304                 sal_uLong                   nOldPos, nNewPos, nAddCount;
2305 
2306                 // write hatch comment
2307                 rOStm << (sal_Int16) GDI_HATCH_COMMENT;
2308 
2309                 // we'll write the ActionSize later
2310                 nOldPos = rOStm.Tell();
2311                 rOStm.SeekRel( 4 );
2312 
2313                 // write comment data
2314                 rOStm << rPolyPoly;
2315                 rOStm << rHatch;
2316 
2317                 // calculate and write ActionSize of comment
2318                 nNewPos = rOStm.Tell();
2319                 rOStm.Seek( nOldPos );
2320                 rOStm << (sal_Int32) ( nNewPos - nOldPos + 4 );
2321                 rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
2322 
2323                 {
2324                     // write actions for hatch
2325                     VirtualDevice   aVDev;
2326                     GDIMetaFile     aTmpMtf;
2327 
2328                     aVDev.AddHatchActions( rPolyPoly, rHatch, aTmpMtf );
2329                     nAddCount = ImplWriteActions( rOStm, aTmpMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
2330                     nNewPos = rOStm.Tell();
2331                     rOStm.Seek( nOldPos );
2332                     rOStm << (sal_Int32) nAddCount;
2333                     rOStm.Seek( nNewPos );
2334 
2335 #ifdef CVTSVM_WRITE_SUBACTIONCOUNT
2336                     nCount += nAddCount;
2337 #endif
2338                 }
2339 
2340                 nCount++;
2341             }
2342             break;
2343 
2344             case( META_REFPOINT_ACTION ):
2345             {
2346                 const MetaRefPointAction*   pA = (MetaRefPointAction*) pAction;
2347                 const Point&                rRefPoint = pA->GetRefPoint();
2348                 const sal_Bool                  bSet = pA->IsSetting();
2349                 sal_uLong                       nOldPos, nNewPos;
2350 
2351                 // write RefPoint comment
2352                 rOStm << (sal_Int16) GDI_REFPOINT_COMMENT;
2353 
2354                 // we'll write the ActionSize later
2355                 nOldPos = rOStm.Tell();
2356                 rOStm.SeekRel( 4 );
2357 
2358                 // write data
2359                 rOStm << rRefPoint << bSet;
2360                 rOStm << (sal_Int32) 0; // number of actions that follow this comment
2361 
2362                 // calculate and write ActionSize of comment
2363                 nNewPos = rOStm.Tell();
2364                 rOStm.Seek( nOldPos );
2365                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
2366                 rOStm.Seek( nNewPos );
2367 
2368                 nCount++;
2369             }
2370             break;
2371 
2372             case( META_TEXTLINECOLOR_ACTION ):
2373             {
2374                 const MetaTextLineColorAction*  pA = (MetaTextLineColorAction*) pAction;
2375                 const Color&                    rColor = pA->GetColor();
2376                 const sal_Bool                      bSet = pA->IsSetting();
2377                 sal_uLong                           nOldPos, nNewPos;
2378 
2379                 // write RefPoint comment
2380                 rOStm << (sal_Int16) GDI_TEXTLINECOLOR_COMMENT;
2381 
2382                 // we'll write the ActionSize later
2383                 nOldPos = rOStm.Tell();
2384                 rOStm.SeekRel( 4 );
2385 
2386                 // write data
2387                 rOStm << rColor << bSet;
2388                 rOStm << (sal_Int32) 0; // number of actions that follow this comment
2389 
2390                 // calculate and write ActionSize of comment
2391                 nNewPos = rOStm.Tell();
2392                 rOStm.Seek( nOldPos );
2393                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
2394                 rOStm.Seek( nNewPos );
2395 
2396                 nCount++;
2397             }
2398             break;
2399 
2400 #if 0
2401             case( META_OVERLINECOLOR_ACTION ):
2402             break;
2403 #endif
2404 
2405             case( META_TEXTLINE_ACTION ):
2406             {
2407                 const MetaTextLineAction*   pA = (MetaTextLineAction*) pAction;
2408                 const Point&                rStartPt = pA->GetStartPoint();
2409                 const long                  nWidth = pA->GetWidth();
2410                 const FontStrikeout         eStrikeout = pA->GetStrikeout();
2411                 const FontUnderline         eUnderline = pA->GetUnderline();
2412                 sal_uLong                       nOldPos, nNewPos;
2413 
2414                 // write RefPoint comment
2415                 rOStm << (sal_Int16) GDI_TEXTLINE_COMMENT;
2416 
2417                 // we'll write the ActionSize later
2418                 nOldPos = rOStm.Tell();
2419                 rOStm.SeekRel( 4 );
2420 
2421                 // write data
2422                 rOStm << rStartPt << nWidth <<
2423                     static_cast<sal_uInt32>(eStrikeout) <<
2424                     static_cast<sal_uInt32>(eUnderline);
2425                 rOStm << (sal_Int32) 0; // number of actions that follow this comment
2426 
2427                 // calculate and write ActionSize of comment
2428                 nNewPos = rOStm.Tell();
2429                 rOStm.Seek( nOldPos );
2430                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
2431                 rOStm.Seek( nNewPos );
2432 
2433                 nCount++;
2434             }
2435             break;
2436 
2437             case( META_EPS_ACTION ):
2438             break;
2439 
2440             case( META_COMMENT_ACTION ):
2441             {
2442                 const MetaCommentAction*    pA = (MetaCommentAction*) pAction;
2443                 const sal_uInt32            nDataSize = pA->GetDataSize();
2444                 sal_uLong                       nOldPos, nNewPos;
2445 
2446                 // write RefPoint comment
2447                 rOStm << (sal_Int16) GDI_COMMENT_COMMENT;
2448 
2449                 // we'll write the ActionSize later
2450                 nOldPos = rOStm.Tell();
2451                 rOStm.SeekRel( 4 );
2452 
2453                 // write data
2454                 rOStm << pA->GetComment() << pA->GetValue() << nDataSize;
2455 
2456                 if( nDataSize )
2457                     rOStm.Write( pA->GetData(), nDataSize );
2458 
2459                 rOStm << (sal_Int32) 0; // number of actions that follow this comment
2460 
2461                 // calculate and write ActionSize of comment
2462                 nNewPos = rOStm.Tell();
2463                 rOStm.Seek( nOldPos );
2464                 rOStm << (sal_Int32) ( nNewPos - nOldPos );
2465                 rOStm.Seek( nNewPos );
2466 
2467                 nCount++;
2468             }
2469             break;
2470 
2471 #ifdef DBG_UTIL
2472             default:
2473             {
2474                 ByteString aStr( "Missing implementation for Action#: " );
2475                 aStr += ByteString::CreateFromInt32( pAction->GetType() );
2476                 aStr += '!';
2477                 DBG_ERROR( aStr.GetBuffer() );
2478             }
2479             break;
2480 #endif
2481 
2482 /*
2483             case( META_TEXTRECT_ACTION ):
2484             {
2485                 MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
2486 
2487                 rOStm << ;
2488                 rOStm << ;
2489 
2490                 nCount++;
2491             }
2492             break;
2493 */
2494 
2495 /*
2496             case( META_MASK_ACTION ):
2497             {
2498                 MetaMaskAction* pAct = (MetaMaskAction*) pAction;
2499 
2500                 rOStm << ;
2501                 rOStm << ;
2502 
2503                 nCount++;
2504             }
2505             break;
2506 */
2507 
2508 /*
2509             case( META_MASKSCALE_ACTION ):
2510             {
2511                 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
2512 
2513                 rOStm << ;
2514                 rOStm << ;
2515 
2516                 nCount++;
2517             }
2518             break;
2519 */
2520 
2521 /*
2522             case( META_MASKSCALEPART_ACTION ):
2523             {
2524                 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
2525 
2526                 rOStm << ;
2527                 rOStm << ;
2528 
2529                 nCount++;
2530             }
2531             break;
2532 */
2533 
2534 /*
2535             case( META_ISECTREGIONCLIPREGION_ACTION ):
2536             {
2537                 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
2538 
2539                 rOStm << ;
2540                 rOStm << ;
2541 
2542                 nCount++;
2543             }
2544             break;
2545 */
2546         }
2547     }
2548 
2549     return nCount;
2550 }
2551