update emoji autocorrect entries from po-files
[LibreOffice.git] / vcl / source / gdi / cvtsvm.cxx
blobba8c530f6818f15b7d63509a4a141cf9294a7cbf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <algorithm>
21 #include <string.h>
22 #include <osl/thread.h>
23 #include <tools/debug.hxx>
24 #include <tools/fract.hxx>
25 #include <tools/stream.hxx>
26 #include <tools/helpers.hxx>
27 #include <vcl/dibtools.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/graph.hxx>
30 #include <vcl/lineinfo.hxx>
31 #include <rtl/strbuf.hxx>
33 #include <cvtsvm.hxx>
34 #include <boost/scoped_array.hpp>
36 // Inlines
37 void ImplReadRect( SvStream& rIStm, Rectangle& rRect )
39 Point aTL;
40 Point aBR;
42 ReadPair( rIStm, aTL );
43 ReadPair( rIStm, aBR );
45 rRect = Rectangle( aTL, aBR );
48 void ImplWriteRect( SvStream& rOStm, const Rectangle& rRect )
50 WritePair( rOStm, rRect.TopLeft() );
51 WritePair( rOStm, rRect.BottomRight() );
54 void ImplReadPoly( SvStream& rIStm, Polygon& rPoly )
56 sal_Int32 nSize;
58 rIStm.ReadInt32( nSize );
59 rPoly = Polygon( (sal_uInt16) nSize );
61 for( sal_uInt16 i = 0; i < (sal_uInt16) nSize; i++ )
62 ReadPair( rIStm, rPoly[ i ] );
65 void ImplReadPolyPoly( SvStream& rIStm, tools::PolyPolygon& rPolyPoly )
67 Polygon aPoly;
68 sal_Int32 nPolyCount;
70 rIStm.ReadInt32( nPolyCount );
72 for( sal_uInt16 i = 0; i < (sal_uInt16) nPolyCount; i++ )
74 ImplReadPoly( rIStm, aPoly );
75 rPolyPoly.Insert( aPoly );
79 void ImplWritePolyPolyAction( SvStream& rOStm, const tools::PolyPolygon& rPolyPoly )
81 const sal_uInt16 nPoly = rPolyPoly.Count();
82 sal_uInt16 nPoints = 0;
83 sal_uInt16 n;
85 for( n = 0; n < nPoly; n++ )
86 nPoints = sal::static_int_cast<sal_uInt16>(nPoints + rPolyPoly[ n ].GetSize());
88 rOStm.WriteInt16( GDI_POLYPOLYGON_ACTION );
89 rOStm.WriteInt32( 8 + ( nPoly << 2 ) + ( nPoints << 3 ) );
90 rOStm.WriteInt32( nPoly );
92 for( n = 0; n < nPoly; n++ )
94 // #i102224# Here the possible curved nature of Polygon was
95 // ignored (for all those years). Adapted to at least write
96 // a polygon representing the curve as good as possible
97 Polygon aSimplePoly;
98 rPolyPoly[n].AdaptiveSubdivide(aSimplePoly);
99 const sal_uInt16 nSize(aSimplePoly.GetSize());
101 rOStm.WriteInt32( nSize );
103 for( sal_uInt16 j = 0; j < nSize; j++ )
104 WritePair( rOStm, aSimplePoly[ j ] );
108 void ImplReadColor( SvStream& rIStm, Color& rColor )
110 sal_Int16 nVal;
112 rIStm.ReadInt16( nVal ); rColor.SetRed( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
113 rIStm.ReadInt16( nVal ); rColor.SetGreen( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
114 rIStm.ReadInt16( nVal ); rColor.SetBlue( sal::static_int_cast<sal_uInt8>((sal_uInt16)nVal >> 8) );
117 void ImplWriteColor( SvStream& rOStm, const Color& rColor )
119 sal_Int16 nVal;
121 nVal = ( (sal_Int16) rColor.GetRed() << 8 ) | rColor.GetRed();
122 rOStm.WriteInt16( nVal );
124 nVal = ( (sal_Int16) rColor.GetGreen() << 8 ) | rColor.GetGreen();
125 rOStm.WriteInt16( nVal );
127 nVal = ( (sal_Int16) rColor.GetBlue() << 8 ) | rColor.GetBlue();
128 rOStm.WriteInt16( nVal );
131 void ImplReadMapMode( SvStream& rIStm, MapMode& rMapMode )
133 Point aOrg;
134 sal_Int32 nXNum;
135 sal_Int32 nXDenom;
136 sal_Int32 nYNum;
137 sal_Int32 nYDenom;
138 sal_Int16 nUnit;
140 rIStm.ReadInt16( nUnit );
141 ReadPair( rIStm, aOrg );
142 rIStm.ReadInt32( nXNum ).ReadInt32( nXDenom ).ReadInt32( nYNum ).ReadInt32( nYDenom );
143 rMapMode = MapMode( (MapUnit) nUnit, aOrg, Fraction( nXNum, nXDenom ), Fraction( nYNum, nYDenom ) );
146 void ImplWriteMapMode( SvStream& rOStm, const MapMode& rMapMode )
148 rOStm.WriteInt16( rMapMode.GetMapUnit() );
149 WritePair( rOStm, rMapMode.GetOrigin() );
150 rOStm.WriteInt32( rMapMode.GetScaleX().GetNumerator() );
151 rOStm.WriteInt32( rMapMode.GetScaleX().GetDenominator() );
152 rOStm.WriteInt32( rMapMode.GetScaleY().GetNumerator() );
153 rOStm.WriteInt32( rMapMode.GetScaleY().GetDenominator() );
156 void ImplWritePushAction( SvStream& rOStm )
158 rOStm.WriteInt16( GDI_PUSH_ACTION );
159 rOStm.WriteInt32( 4 );
162 void ImplWritePopAction( SvStream& rOStm )
164 rOStm.WriteInt16( GDI_POP_ACTION );
165 rOStm.WriteInt32( 4 );
168 void ImplWriteLineColor( SvStream& rOStm, const Color& rColor, sal_Int16 nStyle, sal_Int32 nWidth = 0 )
170 if( rColor.GetTransparency() > 127 )
171 nStyle = 0;
173 rOStm.WriteInt16( GDI_PEN_ACTION );
174 rOStm.WriteInt32( 16 );
175 ImplWriteColor( rOStm, rColor );
176 rOStm.WriteInt32( nWidth );
177 rOStm.WriteInt16( nStyle );
180 void ImplWriteFillColor( SvStream& rOStm, const Color& rColor, sal_Int16 nStyle )
182 rOStm.WriteInt16( GDI_FILLBRUSH_ACTION );
183 rOStm.WriteInt32( 20 );
184 ImplWriteColor( rOStm, rColor );
186 if( rColor.GetTransparency() > 127 )
187 nStyle = 0;
189 if( nStyle > 1 )
191 ImplWriteColor( rOStm, COL_WHITE );
192 rOStm.WriteInt16( nStyle );
193 rOStm.WriteInt16( 1 );
195 else
197 ImplWriteColor( rOStm, COL_BLACK );
198 rOStm.WriteInt16( nStyle );
199 rOStm.WriteInt16( 0 );
203 void ImplWriteFont( SvStream& rOStm, const vcl::Font& rFont,
204 rtl_TextEncoding& rActualCharSet )
206 char aName[33];
207 short nWeight;
209 OString aByteName(OUStringToOString(rFont.GetName(),
210 rOStm.GetStreamCharSet()));
211 strncpy( aName, aByteName.getStr(), 32 );
212 aName[32] = 0;
214 switch ( rFont.GetWeight() )
216 case WEIGHT_THIN:
217 case WEIGHT_ULTRALIGHT:
218 case WEIGHT_LIGHT:
219 nWeight = 1;
220 break;
222 case WEIGHT_NORMAL:
223 case WEIGHT_MEDIUM:
224 nWeight = 2;
225 break;
227 case WEIGHT_BOLD:
228 case WEIGHT_ULTRABOLD:
229 case WEIGHT_BLACK:
230 nWeight = 3;
231 break;
233 default:
234 nWeight = 0;
235 break;
238 rOStm.WriteInt16( GDI_FONT_ACTION );
239 rOStm.WriteInt32( 78 );
241 rActualCharSet = GetStoreCharSet( rFont.GetCharSet() );
242 ImplWriteColor( rOStm, rFont.GetColor() );
243 ImplWriteColor( rOStm, rFont.GetFillColor() );
244 rOStm.Write( aName, 32 );
245 WritePair( rOStm, rFont.GetSize() );
246 rOStm.WriteInt16( 0 ); // no character orientation anymore
247 rOStm.WriteInt16( rFont.GetOrientation() );
248 rOStm.WriteInt16( rActualCharSet );
249 rOStm.WriteInt16( rFont.GetFamily() );
250 rOStm.WriteInt16( rFont.GetPitch() );
251 rOStm.WriteInt16( rFont.GetAlign() );
252 rOStm.WriteInt16( nWeight );
253 rOStm.WriteInt16( rFont.GetUnderline() );
254 rOStm.WriteInt16( rFont.GetStrikeout() );
255 rOStm.WriteBool( rFont.GetItalic() != ITALIC_NONE );
256 rOStm.WriteBool( rFont.IsOutline() );
257 rOStm.WriteBool( rFont.IsShadow() );
258 rOStm.WriteBool( rFont.IsTransparent() );
259 if ( rActualCharSet == RTL_TEXTENCODING_DONTKNOW )
260 rActualCharSet = osl_getThreadTextEncoding();
263 void ImplWriteRasterOpAction( SvStream& rOStm, sal_Int16 nRasterOp )
265 rOStm.WriteInt16( GDI_RASTEROP_ACTION ).WriteInt32( 6 ).WriteInt16( nRasterOp );
268 bool ImplWriteUnicodeComment( SvStream& rOStm, const OUString& rString )
270 sal_Int32 nStringLen = rString.getLength();
271 if ( nStringLen )
273 sal_uInt32 nSize = ( nStringLen << 1 ) + 4;
274 sal_uInt16 nType = GDI_UNICODE_COMMENT;
276 rOStm.WriteUInt16( nType ).WriteUInt32( nSize );
277 write_uInt16s_FromOUString(rOStm, rString);
279 return nStringLen != 0;
282 void ImplReadUnicodeComment( sal_uInt32 nStrmPos, SvStream& rIStm, OUString& rString )
284 sal_uInt32 nOld = rIStm.Tell();
285 if ( nStrmPos )
287 sal_uInt16 nType;
288 sal_uInt32 nActionSize;
289 sal_Size nStringLen;
291 rIStm.Seek( nStrmPos );
292 rIStm .ReadUInt16( nType )
293 .ReadUInt32( nActionSize );
295 nStringLen = (nActionSize - 4) >> 1;
297 if ( nStringLen && ( nType == GDI_UNICODE_COMMENT ) )
298 rString = read_uInt16s_ToOUString(rIStm, nStringLen);
300 rIStm.Seek( nOld );
303 void ImplSkipActions( SvStream& rIStm, sal_uLong nSkipCount )
305 sal_Int32 nActionSize;
306 sal_Int16 nType;
308 for( sal_uLong i = 0UL; i < nSkipCount; i++ )
310 rIStm.ReadInt16( nType ).ReadInt32( nActionSize );
311 rIStm.SeekRel( nActionSize - 4L );
315 bool ImplWriteExtendedPolyPolygonAction(SvStream& rOStm, const tools::PolyPolygon& rPolyPolygon, bool bOnlyWhenCurve)
317 const sal_uInt16 nPolygonCount(rPolyPolygon.Count());
319 if(nPolygonCount)
321 sal_uInt32 nAllPolygonCount(0);
322 sal_uInt32 nAllPointCount(0);
323 sal_uInt32 nAllFlagCount(0);
324 sal_uInt16 a(0);
326 for(a = 0; a < nPolygonCount; a++)
328 const Polygon& rCandidate = rPolyPolygon.GetObject(a);
329 const sal_uInt16 nPointCount(rCandidate.GetSize());
331 if(nPointCount)
333 nAllPolygonCount++;
334 nAllPointCount += nPointCount;
336 if(rCandidate.HasFlags())
338 nAllFlagCount += nPointCount;
343 if((bOnlyWhenCurve && nAllFlagCount) || (!bOnlyWhenCurve && nAllPointCount))
345 rOStm.WriteInt16( GDI_EXTENDEDPOLYGON_ACTION );
347 const sal_Int32 nActionSize(
348 4 + // Action size
349 2 + // PolygonCount
350 (nAllPolygonCount * 2) + // Points per polygon
351 (nAllPointCount << 3) + // Points themselves
352 nAllPolygonCount + // Bool if (when poly has points) it has flags, too
353 nAllFlagCount); // Flags themselves
355 rOStm.WriteInt32( nActionSize );
356 rOStm.WriteUInt16( nAllPolygonCount );
358 for(a = 0; a < nPolygonCount; a++)
360 const Polygon& rCandidate = rPolyPolygon.GetObject(a);
361 const sal_uInt16 nPointCount(rCandidate.GetSize());
363 if(nPointCount)
365 rOStm.WriteUInt16( nPointCount );
367 for(sal_uInt16 b(0); b < nPointCount; b++)
369 WritePair( rOStm, rCandidate[b] );
372 if(rCandidate.HasFlags())
374 rOStm.WriteBool( true );
376 for(sal_uInt16 c(0); c < nPointCount; c++)
378 rOStm.WriteUChar( rCandidate.GetFlags(c) );
381 else
383 rOStm.WriteBool( false );
388 return true;
392 return false;
395 void ImplReadExtendedPolyPolygonAction(SvStream& rIStm, tools::PolyPolygon& rPolyPoly)
397 rPolyPoly.Clear();
398 sal_uInt16 nPolygonCount(0);
399 rIStm.ReadUInt16( nPolygonCount );
401 if (!nPolygonCount)
402 return;
404 const size_t nMinRecordSize = sizeof(sal_uInt16);
405 const size_t nMaxRecords = rIStm.remainingSize() / nMinRecordSize;
406 if (nPolygonCount > nMaxRecords)
408 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords <<
409 " max possible entries, but " << nPolygonCount << " claimed, truncating");
410 nPolygonCount = nMaxRecords;
413 for(sal_uInt16 a(0); a < nPolygonCount; a++)
415 sal_uInt16 nPointCount(0);
416 rIStm.ReadUInt16(nPointCount);
418 const size_t nMinPolygonSize = sizeof(sal_Int32) * 2;
419 const size_t nMaxPolygons = rIStm.remainingSize() / nMinPolygonSize;
420 if (nPointCount > nMaxPolygons)
422 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxPolygons <<
423 " max possible entries, but " << nPointCount << " claimed, truncating");
424 nPointCount = nMaxPolygons;
427 Polygon aCandidate(nPointCount);
429 if (nPointCount)
431 for(sal_uInt16 b(0); b < nPointCount; b++)
433 ReadPair( rIStm , aCandidate[b] );
436 sal_uInt8 bHasFlags(int(false));
437 rIStm.ReadUChar( bHasFlags );
439 if(bHasFlags)
441 sal_uInt8 aPolyFlags(0);
443 for(sal_uInt16 c(0); c < nPointCount; c++)
445 rIStm.ReadUChar( aPolyFlags );
446 aCandidate.SetFlags(c, (PolyFlags)aPolyFlags);
451 rPolyPoly.Insert(aCandidate);
455 SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf, sal_uLong nConvertMode )
457 if( !rStm.GetError() )
459 if( CONVERT_FROM_SVM1 == nConvertMode )
460 ImplConvertFromSVM1( rStm, rMtf );
461 else if( CONVERT_TO_SVM1 == nConvertMode )
462 ImplConvertToSVM1( rStm, rMtf );
466 void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
468 const sal_uLong nPos = rIStm.Tell();
469 const SvStreamEndian nOldFormat = rIStm.GetEndian();
471 rIStm.SetEndian( SvStreamEndian::LITTLE );
473 char aCode[ 5 ];
474 Size aPrefSz;
475 sal_Int16 nSize;
476 sal_Int16 nVersion;
478 // read header
479 rIStm.Read( aCode, sizeof( aCode ) ); // Identifier
480 rIStm.ReadInt16( nSize ); // Size
481 rIStm.ReadInt16( nVersion ); // Version
482 sal_Int32 nTmp32(0);
483 rIStm.ReadInt32( nTmp32 );
484 aPrefSz.Width() = nTmp32; // PrefSize.Width()
485 rIStm.ReadInt32( nTmp32 );
486 aPrefSz.Height() = nTmp32; // PrefSize.Height()
488 // check header-magic and version
489 if( rIStm.GetError()
490 || ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 )
491 || ( nVersion != 200 ) )
493 rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
494 rIStm.SetEndian( nOldFormat );
495 rIStm.Seek( nPos );
496 return;
499 LineInfo aLineInfo( LINE_NONE, 0 );
500 ::std::stack< LineInfo* > aLIStack;
501 ScopedVclPtrInstance< VirtualDevice > aFontVDev;
502 rtl_TextEncoding eActualCharSet = osl_getThreadTextEncoding();
503 bool bFatLine = false;
505 // TODO: fix reindentation below if you can accept being blamed by the SCM
506 MapMode aMapMode;
507 Polygon aActionPoly;
508 Rectangle aRect;
509 Point aPt, aPt1;
510 Size aSz;
511 Color aActionColor;
512 sal_Int32 nTmp, nTmp1, nActionSize;
513 sal_Int32 nActions;
514 sal_Int16 nType;
516 sal_uInt32 nUnicodeCommentStreamPos = 0;
517 sal_Int32 nUnicodeCommentActionNumber = 0;
519 ImplReadMapMode( rIStm, aMapMode ); // MapMode
520 rIStm.ReadInt32( nActions ); // Action count
522 rMtf.SetPrefSize( aPrefSz );
523 rMtf.SetPrefMapMode( aMapMode );
524 size_t nLastPolygonAction(0);
526 for (sal_Int32 i = 0; i < nActions; ++i)
528 rIStm.ReadInt16( nType );
529 sal_Int32 nActBegin = rIStm.Tell();
530 rIStm.ReadInt32( nActionSize );
532 DBG_ASSERT( ( nType <= 33 ) || ( nType >= 1024 ), "Unknown GDIMetaAction while converting!" );
534 switch( nType )
536 case( GDI_PIXEL_ACTION ):
538 ReadPair( rIStm, aPt );
539 ImplReadColor( rIStm, aActionColor );
540 rMtf.AddAction( new MetaPixelAction( aPt, aActionColor ) );
542 break;
544 case( GDI_POINT_ACTION ):
546 ReadPair( rIStm, aPt );
547 rMtf.AddAction( new MetaPointAction( aPt ) );
549 break;
551 case( GDI_LINE_ACTION ):
553 ReadPair( rIStm, aPt );
554 ReadPair( rIStm, aPt1 );
555 rMtf.AddAction( new MetaLineAction( aPt, aPt1, aLineInfo ) );
557 break;
559 case (GDI_LINEJOIN_ACTION) :
561 sal_Int16 nLineJoin(0);
562 rIStm.ReadInt16( nLineJoin );
563 aLineInfo.SetLineJoin((basegfx::B2DLineJoin)nLineJoin);
565 break;
567 case (GDI_LINECAP_ACTION) :
569 sal_Int16 nLineCap(0);
570 rIStm.ReadInt16( nLineCap );
571 aLineInfo.SetLineCap((com::sun::star::drawing::LineCap)nLineCap);
573 break;
575 case (GDI_LINEDASHDOT_ACTION) :
577 sal_Int16 a(0);
578 sal_Int32 b(0);
580 rIStm.ReadInt16( a ); aLineInfo.SetDashCount(a);
581 rIStm.ReadInt32( b ); aLineInfo.SetDashLen(b);
582 rIStm.ReadInt16( a ); aLineInfo.SetDotCount(a);
583 rIStm.ReadInt32( b ); aLineInfo.SetDotLen(b);
584 rIStm.ReadInt32( b ); aLineInfo.SetDistance(b);
586 if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
587 || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
588 && aLineInfo.GetDistance())
590 aLineInfo.SetStyle(LINE_DASH);
593 break;
595 case (GDI_EXTENDEDPOLYGON_ACTION) :
597 // read the tools::PolyPolygon in every case
598 tools::PolyPolygon aInputPolyPolygon;
599 ImplReadExtendedPolyPolygonAction(rIStm, aInputPolyPolygon);
601 // now check if it can be set somewhere
602 if(nLastPolygonAction < rMtf.GetActionSize())
604 MetaPolyLineAction* pPolyLineAction = dynamic_cast< MetaPolyLineAction* >(rMtf.GetAction(nLastPolygonAction));
606 if(pPolyLineAction)
608 // replace MetaPolyLineAction when we have a single polygon. Do not rely on the
609 // same point count; the originally written GDI_POLYLINE_ACTION may have been
610 // Subdivided for better quality for older usages
611 if(1 == aInputPolyPolygon.Count())
613 MetaAction* pAction = rMtf.ReplaceAction(
614 new MetaPolyLineAction(
615 aInputPolyPolygon.GetObject(0),
616 pPolyLineAction->GetLineInfo()),
617 nLastPolygonAction);
618 if(pAction)
619 pAction->Delete();
622 else
624 MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast< MetaPolyPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
626 if(pPolyPolygonAction)
628 // replace MetaPolyPolygonAction when we have a curved polygon. Do rely on the
629 // same sub-polygon count
630 if(pPolyPolygonAction->GetPolyPolygon().Count() == aInputPolyPolygon.Count())
632 MetaAction* pAction = rMtf.ReplaceAction(
633 new MetaPolyPolygonAction(
634 aInputPolyPolygon),
635 nLastPolygonAction);
636 if(pAction)
637 pAction->Delete();
640 else
642 MetaPolygonAction* pPolygonAction = dynamic_cast< MetaPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
644 if(pPolygonAction)
646 // replace MetaPolygonAction
647 if(1 == aInputPolyPolygon.Count())
649 MetaAction* pAction = rMtf.ReplaceAction(
650 new MetaPolygonAction(
651 aInputPolyPolygon.GetObject(0)),
652 nLastPolygonAction);
653 if(pAction)
654 pAction->Delete();
661 break;
663 case( GDI_RECT_ACTION ):
665 ImplReadRect( rIStm, aRect );
666 rIStm.ReadInt32( nTmp ).ReadInt32( nTmp1 );
668 if( nTmp || nTmp1 )
669 rMtf.AddAction( new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
670 else
672 rMtf.AddAction( new MetaRectAction( aRect ) );
674 if( bFatLine )
675 rMtf.AddAction( new MetaPolyLineAction( aRect, aLineInfo ) );
678 break;
680 case( GDI_ELLIPSE_ACTION ):
682 ImplReadRect( rIStm, aRect );
684 if( bFatLine )
686 const Polygon aPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
688 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
689 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
690 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
691 rMtf.AddAction( new MetaPopAction() );
692 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
694 else
695 rMtf.AddAction( new MetaEllipseAction( aRect ) );
697 break;
699 case( GDI_ARC_ACTION ):
701 ImplReadRect( rIStm, aRect );
702 ReadPair( rIStm, aPt );
703 ReadPair( rIStm, aPt1 );
705 if( bFatLine )
707 const Polygon aPoly( aRect, aPt, aPt1, POLY_ARC );
709 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
710 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
711 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
712 rMtf.AddAction( new MetaPopAction() );
713 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
715 else
716 rMtf.AddAction( new MetaArcAction( aRect, aPt, aPt1 ) );
718 break;
720 case( GDI_PIE_ACTION ):
722 ImplReadRect( rIStm, aRect );
723 ReadPair( rIStm, aPt );
724 ReadPair( rIStm, aPt1 );
726 if( bFatLine )
728 const Polygon aPoly( aRect, aPt, aPt1, POLY_PIE );
730 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
731 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
732 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
733 rMtf.AddAction( new MetaPopAction() );
734 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
736 else
737 rMtf.AddAction( new MetaPieAction( aRect, aPt, aPt1 ) );
739 break;
741 case( GDI_INVERTRECT_ACTION ):
742 case( GDI_HIGHLIGHTRECT_ACTION ):
744 ImplReadRect( rIStm, aRect );
745 rMtf.AddAction( new MetaPushAction( PushFlags::RASTEROP ) );
746 rMtf.AddAction( new MetaRasterOpAction( ROP_INVERT ) );
747 rMtf.AddAction( new MetaRectAction( aRect ) );
748 rMtf.AddAction( new MetaPopAction() );
750 break;
752 case( GDI_POLYLINE_ACTION ):
754 ImplReadPoly( rIStm, aActionPoly );
755 nLastPolygonAction = rMtf.GetActionSize();
757 if( bFatLine )
758 rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
759 else
760 rMtf.AddAction( new MetaPolyLineAction( aActionPoly ) );
762 break;
764 case( GDI_POLYGON_ACTION ):
766 ImplReadPoly( rIStm, aActionPoly );
768 if( bFatLine )
770 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
771 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
772 rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
773 rMtf.AddAction( new MetaPopAction() );
774 rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
776 else
778 nLastPolygonAction = rMtf.GetActionSize();
779 rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
782 break;
784 case( GDI_POLYPOLYGON_ACTION ):
786 tools::PolyPolygon aPolyPoly;
788 ImplReadPolyPoly( rIStm, aPolyPoly );
790 if( bFatLine )
792 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
793 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
794 rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
795 rMtf.AddAction( new MetaPopAction() );
797 for( sal_uInt16 nPoly = 0, nCount = aPolyPoly.Count(); nPoly < nCount; nPoly++ )
798 rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
800 else
802 nLastPolygonAction = rMtf.GetActionSize();
803 rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
806 break;
808 case( GDI_FONT_ACTION ):
810 vcl::Font aFont;
811 char aName[ 32 ];
812 sal_Int32 nWidth, nHeight;
813 sal_Int16 nCharSet, nFamily, nPitch, nAlign, nWeight, nUnderline, nStrikeout;
814 sal_Int16 nCharOrient, nLineOrient;
815 bool bItalic, bOutline, bShadow, bTransparent;
817 ImplReadColor( rIStm, aActionColor ); aFont.SetColor( aActionColor );
818 ImplReadColor( rIStm, aActionColor ); aFont.SetFillColor( aActionColor );
819 rIStm.Read( aName, 32 );
820 aFont.SetName( OUString( aName, strlen(aName), rIStm.GetStreamCharSet() ) );
821 rIStm.ReadInt32( nWidth ).ReadInt32( nHeight );
822 rIStm.ReadInt16( nCharOrient ).ReadInt16( nLineOrient );
823 rIStm.ReadInt16( nCharSet ).ReadInt16( nFamily ).ReadInt16( nPitch ).ReadInt16( nAlign ).ReadInt16( nWeight ).ReadInt16( nUnderline ).ReadInt16( nStrikeout );
824 rIStm.ReadCharAsBool( bItalic ).ReadCharAsBool( bOutline ).ReadCharAsBool( bShadow ).ReadCharAsBool( bTransparent );
826 aFont.SetSize( Size( nWidth, nHeight ) );
827 aFont.SetCharSet( (rtl_TextEncoding) nCharSet );
828 aFont.SetFamily( (FontFamily) nFamily );
829 aFont.SetPitch( (FontPitch) nPitch );
830 aFont.SetAlign( (FontAlign) nAlign );
831 aFont.SetWeight( ( nWeight == 1 ) ? WEIGHT_LIGHT : ( nWeight == 2 ) ? WEIGHT_NORMAL :
832 ( nWeight == 3 ) ? WEIGHT_BOLD : WEIGHT_DONTKNOW );
833 aFont.SetUnderline( (FontUnderline) nUnderline );
834 aFont.SetStrikeout( (FontStrikeout) nStrikeout );
835 aFont.SetItalic( bItalic ? ITALIC_NORMAL : ITALIC_NONE );
836 aFont.SetOutline( bOutline );
837 aFont.SetShadow( bShadow );
838 aFont.SetOrientation( nLineOrient );
839 aFont.SetTransparent( bTransparent );
841 eActualCharSet = aFont.GetCharSet();
842 if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
843 eActualCharSet = osl_getThreadTextEncoding();
845 rMtf.AddAction( new MetaFontAction( aFont ) );
846 rMtf.AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
847 rMtf.AddAction( new MetaTextColorAction( aFont.GetColor() ) );
848 rMtf.AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
850 // #106172# Track font relevant data in shadow VDev
851 aFontVDev->SetFont( aFont );
853 break;
855 case( GDI_TEXT_ACTION ):
857 sal_Int32 nIndex, nLen;
859 ReadPair( rIStm, aPt ).ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp );
860 if (nTmp > 0)
862 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
863 sal_uInt8 nTerminator = 0;
864 rIStm.ReadUChar( nTerminator );
865 DBG_ASSERT( nTerminator == 0, "expected string to be NULL terminated" );
867 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
868 if ( nUnicodeCommentActionNumber == i )
869 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
870 rMtf.AddAction( new MetaTextAction( aPt, aStr, nIndex, nLen ) );
872 rIStm.Seek( nActBegin + nActionSize );
874 break;
876 case( GDI_TEXTARRAY_ACTION ):
878 sal_Int32 nIndex, nLen, nAryLen;
880 ReadPair( rIStm, aPt ).ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp ).ReadInt32( nAryLen );
881 if (nTmp > 0)
883 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
884 sal_uInt8 nTerminator = 0;
885 rIStm.ReadUChar( nTerminator );
886 DBG_ASSERT( nTerminator == 0, "expected string to be NULL terminated" );
888 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
890 boost::scoped_array<long> pDXAry;
891 if (nAryLen > 0)
893 sal_Int32 nStrLen( aStr.getLength() );
895 pDXAry.reset(new long[ std::max( nAryLen, nStrLen ) ]);
897 for (sal_Int32 j = 0; j < nAryLen; ++j)
898 rIStm.ReadInt32( nTmp ), pDXAry[ j ] = nTmp;
900 // #106172# Add last DX array elem, if missing
901 if( nAryLen != nStrLen )
903 if( nAryLen+1 == nStrLen )
905 boost::scoped_array<long> pTmpAry(new long[nStrLen]);
907 aFontVDev->GetTextArray( aStr, pTmpAry.get(), nIndex, nLen );
909 // now, the difference between the
910 // last and the second last DX array
911 // is the advancement for the last
912 // glyph. Thus, to complete our meta
913 // action's DX array, just add that
914 // difference to last elem and store
915 // in very last.
916 if( nStrLen > 1 )
917 pDXAry[ nStrLen-1 ] = pDXAry[ nStrLen-2 ] + pTmpAry[ nStrLen-1 ] - pTmpAry[ nStrLen-2 ];
918 else
919 pDXAry[ nStrLen-1 ] = pTmpAry[ nStrLen-1 ]; // len=1: 0th position taken to be 0
921 #ifdef DBG_UTIL
922 else
923 OSL_FAIL("More than one DX array element missing on SVM import");
924 #endif
927 if ( nUnicodeCommentActionNumber == i )
928 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
929 rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, pDXAry.get(), nIndex, nLen ) );
931 rIStm.Seek( nActBegin + nActionSize );
933 break;
935 case( GDI_STRETCHTEXT_ACTION ):
937 sal_Int32 nIndex, nLen, nWidth;
939 ReadPair( rIStm, aPt ).ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp ).ReadInt32( nWidth );
940 if (nTmp > 0)
942 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
943 sal_uInt8 nTerminator = 0;
944 rIStm.ReadUChar( nTerminator );
945 DBG_ASSERT( nTerminator == 0, "expected string to be NULL terminated" );
947 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
948 if ( nUnicodeCommentActionNumber == i )
949 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
950 rMtf.AddAction( new MetaStretchTextAction( aPt, nWidth, aStr, nIndex, nLen ) );
952 rIStm.Seek( nActBegin + nActionSize );
954 break;
956 case( GDI_BITMAP_ACTION ):
958 Bitmap aBmp;
960 ReadPair( rIStm, aPt );
961 ReadDIB(aBmp, rIStm, true);
962 rMtf.AddAction( new MetaBmpAction( aPt, aBmp ) );
964 break;
966 case( GDI_BITMAPSCALE_ACTION ):
968 Bitmap aBmp;
970 ReadPair( rIStm, aPt );
971 ReadPair( rIStm, aSz );
972 ReadDIB(aBmp, rIStm, true);
973 rMtf.AddAction( new MetaBmpScaleAction( aPt, aSz, aBmp ) );
975 break;
977 case( GDI_BITMAPSCALEPART_ACTION ):
979 Bitmap aBmp;
980 Size aSz2;
982 ReadPair( rIStm, aPt );
983 ReadPair( rIStm, aSz );
984 ReadPair( rIStm, aPt1 );
985 ReadPair( rIStm, aSz2 );
986 ReadDIB(aBmp, rIStm, true);
987 rMtf.AddAction( new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
989 break;
991 case( GDI_PEN_ACTION ):
993 sal_Int32 nPenWidth;
994 sal_Int16 nPenStyle;
996 ImplReadColor( rIStm, aActionColor );
997 rIStm.ReadInt32( nPenWidth ).ReadInt16( nPenStyle );
999 aLineInfo.SetStyle( nPenStyle ? LINE_SOLID : LINE_NONE );
1000 aLineInfo.SetWidth( nPenWidth );
1001 bFatLine = nPenStyle && !aLineInfo.IsDefault();
1003 rMtf.AddAction( new MetaLineColorAction( aActionColor, nPenStyle != 0 ) );
1005 break;
1007 case( GDI_FILLBRUSH_ACTION ):
1009 sal_Int16 nBrushStyle;
1011 ImplReadColor( rIStm, aActionColor );
1012 rIStm.SeekRel( 6L );
1013 rIStm.ReadInt16( nBrushStyle );
1014 rMtf.AddAction( new MetaFillColorAction( aActionColor, nBrushStyle != 0 ) );
1015 rIStm.SeekRel( 2L );
1017 break;
1019 case( GDI_MAPMODE_ACTION ):
1021 ImplReadMapMode( rIStm, aMapMode );
1022 rMtf.AddAction( new MetaMapModeAction( aMapMode ) );
1024 // #106172# Track font relevant data in shadow VDev
1025 aFontVDev->SetMapMode( aMapMode );
1027 break;
1029 case( GDI_CLIPREGION_ACTION ):
1031 vcl::Region aRegion;
1032 sal_Int16 nRegType;
1033 sal_Int16 bIntersect;
1034 bool bClip = false;
1036 rIStm.ReadInt16( nRegType ).ReadInt16( bIntersect );
1037 ImplReadRect( rIStm, aRect );
1039 switch( nRegType )
1041 case( 0 ):
1042 break;
1044 case( 1 ):
1046 Rectangle aRegRect;
1048 ImplReadRect( rIStm, aRegRect );
1049 aRegion = vcl::Region( aRegRect );
1050 bClip = true;
1052 break;
1054 case( 2 ):
1056 ImplReadPoly( rIStm, aActionPoly );
1057 aRegion = vcl::Region( aActionPoly );
1058 bClip = true;
1060 break;
1062 case( 3 ):
1064 tools::PolyPolygon aPolyPoly;
1065 sal_Int32 nPolyCount;
1067 rIStm.ReadInt32( nPolyCount );
1069 for( sal_uInt16 j = 0; j < (sal_uInt16) nPolyCount; j++ )
1071 ImplReadPoly( rIStm, aActionPoly );
1072 aPolyPoly.Insert( aActionPoly );
1075 aRegion = vcl::Region( aPolyPoly );
1076 bClip = true;
1078 break;
1081 if( bIntersect )
1082 aRegion.Intersect( aRect );
1084 rMtf.AddAction( new MetaClipRegionAction( aRegion, bClip ) );
1086 break;
1088 case( GDI_MOVECLIPREGION_ACTION ):
1090 rIStm.ReadInt32( nTmp ).ReadInt32( nTmp1 );
1091 rMtf.AddAction( new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
1093 break;
1095 case( GDI_ISECTCLIPREGION_ACTION ):
1097 ImplReadRect( rIStm, aRect );
1098 rMtf.AddAction( new MetaISectRectClipRegionAction( aRect ) );
1100 break;
1102 case( GDI_RASTEROP_ACTION ):
1104 RasterOp eRasterOp;
1105 sal_Int16 nRasterOp;
1107 rIStm.ReadInt16( nRasterOp );
1109 switch( nRasterOp )
1111 case( 1 ):
1112 eRasterOp = ROP_INVERT;
1113 break;
1115 case( 4 ):
1116 case( 5 ):
1117 eRasterOp = ROP_XOR;
1118 break;
1120 default:
1121 eRasterOp = ROP_OVERPAINT;
1122 break;
1125 rMtf.AddAction( new MetaRasterOpAction( eRasterOp ) );
1127 break;
1129 case( GDI_PUSH_ACTION ):
1131 aLIStack.push( new LineInfo( aLineInfo ) );
1132 rMtf.AddAction( new MetaPushAction( PushFlags::ALL ) );
1134 // #106172# Track font relevant data in shadow VDev
1135 aFontVDev->Push();
1137 break;
1139 case( GDI_POP_ACTION ):
1142 LineInfo* pLineInfo;
1143 if (aLIStack.empty())
1144 pLineInfo = NULL;
1145 else
1147 pLineInfo = aLIStack.top();
1148 aLIStack.pop();
1151 // restore line info
1152 if( pLineInfo )
1154 aLineInfo = *pLineInfo;
1155 delete pLineInfo;
1156 bFatLine = ( LINE_NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
1159 rMtf.AddAction( new MetaPopAction() );
1161 // #106172# Track font relevant data in shadow VDev
1162 aFontVDev->Pop();
1164 break;
1166 case( GDI_GRADIENT_ACTION ):
1168 Color aStartCol;
1169 Color aEndCol;
1170 sal_Int16 nStyle;
1171 sal_Int16 nAngle;
1172 sal_Int16 nBorder;
1173 sal_Int16 nOfsX;
1174 sal_Int16 nOfsY;
1175 sal_Int16 nIntensityStart;
1176 sal_Int16 nIntensityEnd;
1178 ImplReadRect( rIStm, aRect );
1179 rIStm.ReadInt16( nStyle );
1180 ImplReadColor( rIStm, aStartCol );
1181 ImplReadColor( rIStm, aEndCol );
1182 rIStm.ReadInt16( nAngle ).ReadInt16( nBorder ).ReadInt16( nOfsX ).ReadInt16( nOfsY ).ReadInt16( nIntensityStart ).ReadInt16( nIntensityEnd );
1184 Gradient aGrad( (GradientStyle) nStyle, aStartCol, aEndCol );
1186 aGrad.SetAngle( nAngle );
1187 aGrad.SetBorder( nBorder );
1188 aGrad.SetOfsX( nOfsX );
1189 aGrad.SetOfsY( nOfsY );
1190 aGrad.SetStartIntensity( nIntensityStart );
1191 aGrad.SetEndIntensity( nIntensityEnd );
1192 rMtf.AddAction( new MetaGradientAction( aRect, aGrad ) );
1194 break;
1196 case( GDI_TRANSPARENT_COMMENT ):
1198 tools::PolyPolygon aPolyPoly;
1199 sal_Int32 nFollowingActionCount;
1200 sal_Int16 nTrans;
1202 ReadPolyPolygon( rIStm, aPolyPoly );
1203 rIStm.ReadInt16( nTrans ).ReadInt32( nFollowingActionCount );
1204 ImplSkipActions( rIStm, nFollowingActionCount );
1205 rMtf.AddAction( new MetaTransparentAction( aPolyPoly, nTrans ) );
1207 i += nFollowingActionCount;
1209 break;
1211 case( GDI_FLOATTRANSPARENT_COMMENT ):
1213 GDIMetaFile aMtf;
1214 Point aPos;
1215 Size aSize;
1216 Gradient aGradient;
1217 sal_Int32 nFollowingActionCount;
1219 ReadGDIMetaFile( rIStm, aMtf );
1220 ReadPair( rIStm, aPos );
1221 ReadPair( rIStm, aSize );
1222 ReadGradient( rIStm, aGradient );
1223 rIStm.ReadInt32( nFollowingActionCount );
1224 ImplSkipActions( rIStm, nFollowingActionCount );
1225 rMtf.AddAction( new MetaFloatTransparentAction( aMtf, aPos, aSize, aGradient ) );
1227 i += nFollowingActionCount;
1229 break;
1231 case( GDI_HATCH_COMMENT ):
1233 tools::PolyPolygon aPolyPoly;
1234 Hatch aHatch;
1235 sal_Int32 nFollowingActionCount;
1237 ReadPolyPolygon( rIStm, aPolyPoly );
1238 ReadHatch( rIStm, aHatch );
1239 rIStm.ReadInt32( nFollowingActionCount );
1240 ImplSkipActions( rIStm, nFollowingActionCount );
1241 rMtf.AddAction( new MetaHatchAction( aPolyPoly, aHatch ) );
1243 i += nFollowingActionCount;
1245 break;
1247 case( GDI_REFPOINT_COMMENT ):
1249 Point aRefPoint;
1250 bool bSet;
1251 sal_Int32 nFollowingActionCount;
1253 ReadPair( rIStm, aRefPoint );
1254 rIStm.ReadCharAsBool( bSet ).ReadInt32( nFollowingActionCount );
1255 ImplSkipActions( rIStm, nFollowingActionCount );
1256 rMtf.AddAction( new MetaRefPointAction( aRefPoint, bSet ) );
1258 i += nFollowingActionCount;
1260 // #106172# Track font relevant data in shadow VDev
1261 if( bSet )
1262 aFontVDev->SetRefPoint( aRefPoint );
1263 else
1264 aFontVDev->SetRefPoint();
1266 break;
1268 case( GDI_TEXTLINECOLOR_COMMENT ):
1270 Color aColor;
1271 bool bSet;
1272 sal_Int32 nFollowingActionCount;
1274 ReadColor( rIStm, aColor );
1275 rIStm.ReadCharAsBool( bSet ).ReadInt32( nFollowingActionCount );
1276 ImplSkipActions( rIStm, nFollowingActionCount );
1277 rMtf.AddAction( new MetaTextLineColorAction( aColor, bSet ) );
1279 i += nFollowingActionCount;
1281 break;
1283 case( GDI_TEXTLINE_COMMENT ):
1285 Point aStartPt;
1286 sal_Int32 nWidth;
1287 sal_uInt32 nStrikeout;
1288 sal_uInt32 nUnderline;
1289 sal_Int32 nFollowingActionCount;
1291 ReadPair( rIStm, aStartPt );
1292 rIStm.ReadInt32( nWidth ).ReadUInt32( nStrikeout ).ReadUInt32( nUnderline ).ReadInt32( nFollowingActionCount );
1293 ImplSkipActions( rIStm, nFollowingActionCount );
1294 rMtf.AddAction( new MetaTextLineAction( aStartPt, nWidth,
1295 (FontStrikeout) nStrikeout,
1296 (FontUnderline) nUnderline,
1297 UNDERLINE_NONE ) );
1299 i += nFollowingActionCount;
1301 break;
1303 case( GDI_GRADIENTEX_COMMENT ):
1305 tools::PolyPolygon aPolyPoly;
1306 Gradient aGradient;
1307 sal_Int32 nFollowingActionCount;
1309 ReadPolyPolygon( rIStm, aPolyPoly );
1310 ReadGradient( rIStm, aGradient );
1311 rIStm.ReadInt32( nFollowingActionCount );
1312 ImplSkipActions( rIStm, nFollowingActionCount );
1313 rMtf.AddAction( new MetaGradientExAction( aPolyPoly, aGradient ) );
1315 i += nFollowingActionCount;
1317 break;
1319 case( GDI_COMMENT_COMMENT ):
1321 sal_Int32 nValue;
1322 sal_uInt32 nDataSize;
1323 sal_uInt8* pData;
1324 sal_Int32 nFollowingActionCount;
1326 OString aComment = read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm);
1327 rIStm.ReadInt32( nValue ).ReadUInt32( nDataSize );
1329 if( nDataSize )
1331 pData = new sal_uInt8[ nDataSize ];
1332 rIStm.Read( pData, nDataSize );
1334 else
1335 pData = NULL;
1337 rIStm.ReadInt32( nFollowingActionCount );
1338 ImplSkipActions( rIStm, nFollowingActionCount );
1339 rMtf.AddAction( new MetaCommentAction( aComment, nValue, pData, nDataSize ) );
1341 i += nFollowingActionCount;
1343 break;
1345 case ( GDI_UNICODE_COMMENT ):
1347 nUnicodeCommentActionNumber = i + 1;
1348 nUnicodeCommentStreamPos = rIStm.Tell() - 6;
1349 rIStm.SeekRel( nActionSize - 4 );
1351 break;
1353 default:
1354 rIStm.SeekRel( nActionSize - 4L );
1355 break;
1359 // cleanup push-pop stack if necessary
1360 while( !aLIStack.empty() )
1362 delete aLIStack.top();
1363 aLIStack.pop();
1366 rIStm.SetEndian( nOldFormat );
1369 void SVMConverter::ImplConvertToSVM1( SvStream& rOStm, GDIMetaFile& rMtf )
1371 sal_uLong nCountPos;
1372 vcl::Font aSaveFont;
1373 const SvStreamEndian nOldFormat = rOStm.GetEndian();
1374 rtl_TextEncoding eActualCharSet = osl_getThreadTextEncoding();
1375 const Size aPrefSize( rMtf.GetPrefSize() );
1376 bool bRop_0_1 = false;
1377 ScopedVclPtrInstance< VirtualDevice > aSaveVDev;
1378 Color aLineCol( COL_BLACK );
1379 ::std::stack< Color* > aLineColStack;
1381 rOStm.SetEndian( SvStreamEndian::LITTLE );
1383 // Write MagicCode
1384 rOStm.WriteCharPtr( "SVGDI" ); // Identifier
1385 rOStm.WriteInt16( 42 ); // HeaderSize
1386 rOStm.WriteInt16( 200 ); // VERSION
1387 rOStm.WriteInt32( aPrefSize.Width() );
1388 rOStm.WriteInt32( aPrefSize.Height() );
1389 ImplWriteMapMode( rOStm, rMtf.GetPrefMapMode() );
1391 // ActionCount will be written later
1392 nCountPos = rOStm.Tell();
1393 rOStm.SeekRel( 4L );
1395 const sal_Int32 nActCount = ImplWriteActions( rOStm, rMtf, *aSaveVDev.get(), bRop_0_1, aLineCol, aLineColStack, eActualCharSet );
1396 const sal_uLong nActPos = rOStm.Tell();
1398 rOStm.Seek( nCountPos );
1399 rOStm.WriteInt32( nActCount );
1400 rOStm.Seek( nActPos );
1401 rOStm.SetEndian( nOldFormat );
1403 // cleanup push-pop stack if necessary
1404 while ( !aLineColStack.empty() )
1406 delete aLineColStack.top();
1407 aLineColStack.pop();
1411 sal_uLong SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
1412 VirtualDevice& rSaveVDev, bool& rRop_0_1,
1413 Color& rLineCol, ::std::stack< Color* >& rLineColStack,
1414 rtl_TextEncoding& rActualCharSet )
1416 sal_uLong nCount = 0;
1417 for( size_t i = 0, nActionCount = rMtf.GetActionSize(); i < nActionCount; i++ )
1419 const MetaAction* pAction = rMtf.GetAction( i );
1421 switch( pAction->GetType() )
1423 case( MetaActionType::PIXEL ):
1425 const MetaPixelAction* pAct = static_cast<const MetaPixelAction*>(pAction);
1427 rOStm.WriteInt16( GDI_PIXEL_ACTION );
1428 rOStm.WriteInt32( 18 );
1429 WritePair( rOStm, pAct->GetPoint() );
1430 ImplWriteColor( rOStm, pAct->GetColor() );
1431 nCount++;
1433 break;
1435 case( MetaActionType::POINT ):
1437 const MetaPointAction* pAct = static_cast<const MetaPointAction*>(pAction);
1439 rOStm.WriteInt16( GDI_POINT_ACTION );
1440 rOStm.WriteInt32( 12 );
1441 WritePair( rOStm, pAct->GetPoint() );
1442 nCount++;
1444 break;
1446 case( MetaActionType::LINE ):
1448 const MetaLineAction* pAct = static_cast<const MetaLineAction*>(pAction);
1449 const LineInfo& rInfo = pAct->GetLineInfo();
1450 const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
1451 const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
1452 const bool bLineCap(bFatLine && com::sun::star::drawing::LineCap_BUTT != rInfo.GetLineCap());
1453 const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
1455 if( bFatLine )
1457 ImplWritePushAction( rOStm );
1458 ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
1460 if(bLineJoin)
1462 rOStm.WriteInt16( GDI_LINEJOIN_ACTION );
1463 rOStm.WriteInt32( 6 );
1464 rOStm.WriteInt16( rInfo.GetLineJoin() );
1467 if(bLineCap)
1469 rOStm.WriteInt16( GDI_LINECAP_ACTION );
1470 rOStm.WriteInt32( 6 );
1471 rOStm.WriteInt16( rInfo.GetLineCap() );
1475 if(bLineDashDot)
1477 rOStm.WriteInt16( GDI_LINEDASHDOT_ACTION );
1478 rOStm.WriteInt32( 4 + 16 );
1479 rOStm.WriteInt16( rInfo.GetDashCount() );
1480 rOStm.WriteInt32( rInfo.GetDashLen() );
1481 rOStm.WriteInt16( rInfo.GetDotCount() );
1482 rOStm.WriteInt32( rInfo.GetDotLen() );
1483 rOStm.WriteInt32( rInfo.GetDistance() );
1486 rOStm.WriteInt16( GDI_LINE_ACTION );
1487 rOStm.WriteInt32( 20 );
1488 WritePair( rOStm, pAct->GetStartPoint() );
1489 WritePair( rOStm, pAct->GetEndPoint() );
1490 nCount++;
1492 if( bFatLine )
1494 ImplWritePopAction( rOStm );
1495 nCount += 3;
1497 if(bLineJoin)
1499 nCount += 1;
1502 if(bLineCap)
1504 nCount += 1;
1508 if(bLineDashDot)
1510 nCount += 1;
1513 break;
1515 case( MetaActionType::RECT ):
1517 const MetaRectAction* pAct = static_cast<const MetaRectAction*>(pAction);
1519 rOStm.WriteInt16( GDI_RECT_ACTION );
1520 rOStm.WriteInt32( 28 );
1521 ImplWriteRect( rOStm, pAct->GetRect() );
1522 rOStm.WriteInt32( 0 );
1523 rOStm.WriteInt32( 0 );
1524 nCount++;
1526 break;
1528 case( MetaActionType::ROUNDRECT ):
1530 const MetaRoundRectAction* pAct = static_cast<const MetaRoundRectAction*>(pAction);
1532 rOStm.WriteInt16( GDI_RECT_ACTION );
1533 rOStm.WriteInt32( 28 );
1534 ImplWriteRect( rOStm, pAct->GetRect() );
1535 rOStm.WriteInt32( pAct->GetHorzRound() );
1536 rOStm.WriteInt32( pAct->GetVertRound() );
1537 nCount++;
1539 break;
1541 case( MetaActionType::ELLIPSE ):
1543 const MetaEllipseAction* pAct = static_cast<const MetaEllipseAction*>(pAction);
1545 rOStm.WriteInt16( GDI_ELLIPSE_ACTION );
1546 rOStm.WriteInt32( 20 );
1547 ImplWriteRect( rOStm, pAct->GetRect() );
1548 nCount++;
1550 break;
1552 case( MetaActionType::ARC ):
1554 const MetaArcAction* pAct = static_cast<const MetaArcAction*>(pAction);
1556 rOStm.WriteInt16( GDI_ARC_ACTION );
1557 rOStm.WriteInt32( 36 );
1558 ImplWriteRect( rOStm, pAct->GetRect() );
1559 WritePair( rOStm, pAct->GetStartPoint() );
1560 WritePair( rOStm, pAct->GetEndPoint() );
1561 nCount++;
1563 break;
1565 case( MetaActionType::PIE ):
1567 const MetaPieAction* pAct = static_cast<const MetaPieAction*>(pAction);
1569 rOStm.WriteInt16( GDI_PIE_ACTION );
1570 rOStm.WriteInt32( 36 );
1571 ImplWriteRect( rOStm, pAct->GetRect() );
1572 WritePair( rOStm, pAct->GetStartPoint() );
1573 WritePair( rOStm, pAct->GetEndPoint() );
1574 nCount++;
1576 break;
1578 case( MetaActionType::CHORD ):
1580 const MetaChordAction* pAct = static_cast<const MetaChordAction*>(pAction);
1581 Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(),
1582 pAct->GetEndPoint(), POLY_CHORD );
1583 const sal_uInt16 nPoints = aChordPoly.GetSize();
1585 rOStm.WriteInt16( GDI_POLYGON_ACTION );
1586 rOStm.WriteInt32( 8 + ( nPoints << 3 ) );
1587 rOStm.WriteInt32( nPoints );
1589 for( sal_uInt16 n = 0; n < nPoints; n++ )
1590 WritePair( rOStm, aChordPoly[ n ] );
1591 nCount++;
1593 break;
1595 case( MetaActionType::POLYLINE ):
1597 // #i102224#
1598 const MetaPolyLineAction* pAct = static_cast<const MetaPolyLineAction*>(pAction);
1599 // #i102224# Here the possible curved nature of Polygon was
1600 // ignored (for all those years). Adapted to at least write
1601 // a polygon representing the curve as good as possible
1602 Polygon aSimplePoly;
1603 pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
1604 const LineInfo& rInfo = pAct->GetLineInfo();
1605 const sal_uInt16 nPoints(aSimplePoly.GetSize());
1606 const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
1607 const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
1608 const bool bLineCap(bFatLine && com::sun::star::drawing::LineCap_BUTT != rInfo.GetLineCap());
1609 const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
1611 if( bFatLine )
1613 ImplWritePushAction( rOStm );
1614 ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
1616 if(bLineJoin)
1618 rOStm.WriteInt16( GDI_LINEJOIN_ACTION );
1619 rOStm.WriteInt32( 6 );
1620 rOStm.WriteInt16( rInfo.GetLineJoin() );
1623 if(bLineCap)
1625 rOStm.WriteInt16( GDI_LINECAP_ACTION );
1626 rOStm.WriteInt32( 6 );
1627 rOStm.WriteInt16( rInfo.GetLineCap() );
1631 if(bLineDashDot)
1633 rOStm.WriteInt16( GDI_LINEDASHDOT_ACTION );
1634 rOStm.WriteInt32( 4 + 16 );
1635 rOStm.WriteInt16( rInfo.GetDashCount() );
1636 rOStm.WriteInt32( rInfo.GetDashLen() );
1637 rOStm.WriteInt16( rInfo.GetDotCount() );
1638 rOStm.WriteInt32( rInfo.GetDotLen() );
1639 rOStm.WriteInt32( rInfo.GetDistance() );
1642 rOStm.WriteInt16( GDI_POLYLINE_ACTION );
1643 rOStm.WriteInt32( 8 + ( nPoints << 3 ) );
1644 rOStm.WriteInt32( nPoints );
1646 for( sal_uInt16 n = 0; n < nPoints; n++ )
1648 WritePair( rOStm, aSimplePoly[ n ] );
1651 nCount++;
1653 const tools::PolyPolygon aPolyPolygon(pAct->GetPolygon());
1654 if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
1656 nCount++;
1659 if( bFatLine )
1661 ImplWritePopAction( rOStm );
1662 nCount += 3;
1664 if(bLineJoin)
1666 nCount += 1;
1669 if(bLineCap)
1671 nCount += 1;
1675 if(bLineDashDot)
1677 nCount += 1;
1680 break;
1682 case( MetaActionType::POLYGON ):
1684 const MetaPolygonAction* pAct = static_cast<const MetaPolygonAction*>(pAction);
1685 // #i102224# Here the possible curved nature of Polygon was
1686 // ignored (for all those years). Adapted to at least write
1687 // a polygon representing the curve as good as possible
1688 Polygon aSimplePoly;
1689 pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
1690 const sal_uInt16 nPoints(aSimplePoly.GetSize());
1692 rOStm.WriteInt16( GDI_POLYGON_ACTION );
1693 rOStm.WriteInt32( 8 + ( nPoints << 3 ) );
1694 rOStm.WriteInt32( nPoints );
1696 for( sal_uInt16 n = 0; n < nPoints; n++ )
1697 WritePair( rOStm, aSimplePoly[ n ] );
1699 nCount++;
1701 const tools::PolyPolygon aPolyPolygon(pAct->GetPolygon());
1702 if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
1704 nCount++;
1707 break;
1709 case( MetaActionType::POLYPOLYGON ):
1711 const MetaPolyPolygonAction* pAct = static_cast<const MetaPolyPolygonAction*>(pAction);
1712 ImplWritePolyPolyAction( rOStm, pAct->GetPolyPolygon() );
1713 nCount++;
1715 if(ImplWriteExtendedPolyPolygonAction(rOStm, pAct->GetPolyPolygon(), true))
1717 nCount++;
1720 break;
1722 case( MetaActionType::TEXT ):
1724 const MetaTextAction* pAct = static_cast<const MetaTextAction*>(pAction);
1725 OUString aUniText( pAct->GetText() );
1726 OString aText(OUStringToOString(aUniText, rActualCharSet));
1727 const sal_Int32 nStrLen = aText.getLength();
1729 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1730 nCount++;
1732 rOStm.WriteInt16( GDI_TEXT_ACTION );
1733 rOStm.WriteInt32( 24 + ( nStrLen + 1 ) );
1734 WritePair( rOStm, pAct->GetPoint() );
1735 rOStm.WriteInt32( pAct->GetIndex() );
1736 rOStm.WriteInt32( pAct->GetLen() );
1737 rOStm.WriteInt32( nStrLen );
1738 rOStm.Write( aText.getStr(), nStrLen + 1 );
1739 nCount++;
1741 break;
1743 case( MetaActionType::TEXTARRAY ):
1745 const MetaTextArrayAction* pAct = static_cast<const MetaTextArrayAction*>(pAction);
1746 OString aText(OUStringToOString(pAct->GetText(), rActualCharSet));
1747 OUString aUniText = pAct->GetText().copy(
1748 pAct->GetIndex(),
1749 std::min<sal_Int32>(pAct->GetText().getLength() - pAct->GetIndex(), pAct->GetLen()) );
1750 sal_Int32 nAryLen;
1751 sal_Int32 nLen = pAct->GetLen();
1752 const sal_Int32 nTextLen = aText.getLength();
1753 long* pDXArray = pAct->GetDXArray();
1755 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1756 nCount++;
1758 if( ( nLen + pAct->GetIndex() ) > nTextLen )
1760 if( pAct->GetIndex() <= nTextLen )
1761 nLen = nTextLen - pAct->GetIndex();
1762 else
1763 nLen = 0;
1766 if( !pDXArray || !nLen )
1767 nAryLen = 0;
1768 else
1769 nAryLen = nLen; // #105987# Write out all of DX array
1771 rOStm.WriteInt16( GDI_TEXTARRAY_ACTION );
1772 rOStm.WriteInt32( 28 + ( nLen + 1 ) + ( nAryLen * 4 ) );
1773 WritePair( rOStm, pAct->GetPoint() );
1774 rOStm.WriteInt32( 0 );
1775 rOStm.WriteInt32( nLen );
1776 rOStm.WriteInt32( nLen );
1777 rOStm.WriteInt32( nAryLen );
1778 rOStm.Write( aText.getStr()+pAct->GetIndex(), nLen + 1 );
1780 for (sal_Int32 n = 0; n < nAryLen; ++n)
1781 rOStm.WriteInt32( pDXArray[ n ] );
1783 nCount++;
1785 break;
1787 case( MetaActionType::STRETCHTEXT ):
1789 const MetaStretchTextAction* pAct = static_cast<const MetaStretchTextAction*>(pAction);
1790 OUString aUniText( pAct->GetText() );
1791 OString aText(OUStringToOString(aUniText, rActualCharSet));
1792 const sal_Int32 nStrLen = aText.getLength();
1794 if ( ImplWriteUnicodeComment( rOStm, aUniText ) )
1795 nCount++;
1797 rOStm.WriteInt16( GDI_STRETCHTEXT_ACTION );
1798 rOStm.WriteInt32( 28 + ( nStrLen + 1 ) );
1799 WritePair( rOStm, pAct->GetPoint() );
1800 rOStm.WriteInt32( pAct->GetIndex() );
1801 rOStm.WriteInt32( pAct->GetLen() );
1802 rOStm.WriteInt32( nStrLen );
1803 rOStm.WriteInt32( pAct->GetWidth() );
1804 rOStm.Write( aText.getStr(), nStrLen + 1 );
1805 nCount++;
1807 break;
1809 case( MetaActionType::BMP ):
1811 const MetaBmpAction* pAct = static_cast<const MetaBmpAction*>(pAction);
1813 rOStm.WriteInt16( GDI_BITMAP_ACTION );
1814 rOStm.WriteInt32( 12 );
1815 WritePair( rOStm, pAct->GetPoint() );
1816 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1817 nCount++;
1819 break;
1821 case( MetaActionType::BMPSCALE ):
1823 const MetaBmpScaleAction* pAct = static_cast<const MetaBmpScaleAction*>(pAction);
1825 rOStm.WriteInt16( GDI_BITMAPSCALE_ACTION );
1826 rOStm.WriteInt32( 20 );
1827 WritePair( rOStm, pAct->GetPoint() );
1828 WritePair( rOStm, pAct->GetSize() );
1829 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1830 nCount++;
1832 break;
1834 case( MetaActionType::BMPSCALEPART ):
1836 const MetaBmpScalePartAction* pAct = static_cast<const MetaBmpScalePartAction*>(pAction);
1838 rOStm.WriteInt16( GDI_BITMAPSCALEPART_ACTION );
1839 rOStm.WriteInt32( 36 );
1840 WritePair( rOStm, pAct->GetDestPoint() );
1841 WritePair( rOStm, pAct->GetDestSize() );
1842 WritePair( rOStm, pAct->GetSrcPoint() );
1843 WritePair( rOStm, pAct->GetSrcSize() );
1844 WriteDIB(pAct->GetBitmap(), rOStm, false, true);
1845 nCount++;
1847 break;
1849 case( MetaActionType::BMPEX ):
1851 const MetaBmpExAction* pAct = static_cast<const MetaBmpExAction*>(pAction);
1852 const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1854 rOStm.WriteInt16( GDI_BITMAP_ACTION );
1855 rOStm.WriteInt32( 12 );
1856 WritePair( rOStm, pAct->GetPoint() );
1857 WriteDIB(aBmp, rOStm, false, true);
1858 nCount++;
1860 break;
1862 case( MetaActionType::BMPEXSCALE ):
1864 const MetaBmpExScaleAction* pAct = static_cast<const MetaBmpExScaleAction*>(pAction);
1865 const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1867 rOStm.WriteInt16( GDI_BITMAPSCALE_ACTION );
1868 rOStm.WriteInt32( 20 );
1869 WritePair( rOStm, pAct->GetPoint() );
1870 WritePair( rOStm, pAct->GetSize() );
1871 WriteDIB(aBmp, rOStm, false, true);
1872 nCount++;
1874 break;
1876 case( MetaActionType::BMPEXSCALEPART ):
1878 const MetaBmpExScalePartAction* pAct = static_cast<const MetaBmpExScalePartAction*>(pAction);
1879 const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
1881 rOStm.WriteInt16( GDI_BITMAPSCALEPART_ACTION );
1882 rOStm.WriteInt32( 36 );
1883 WritePair( rOStm, pAct->GetDestPoint() );
1884 WritePair( rOStm, pAct->GetDestSize() );
1885 WritePair( rOStm, pAct->GetSrcPoint() );
1886 WritePair( rOStm, pAct->GetSrcSize() );
1887 WriteDIB(aBmp, rOStm, false, true);
1888 nCount++;
1890 break;
1892 case( MetaActionType::GRADIENT ):
1894 const MetaGradientAction* pAct = static_cast<const MetaGradientAction*>(pAction);
1895 const Gradient& rGrad = pAct->GetGradient();
1897 rOStm.WriteInt16( GDI_GRADIENT_ACTION );
1898 rOStm.WriteInt32( 46 );
1899 ImplWriteRect( rOStm, pAct->GetRect() );
1900 rOStm.WriteInt16( rGrad.GetStyle() );
1901 ImplWriteColor( rOStm, rGrad.GetStartColor() );
1902 ImplWriteColor( rOStm, rGrad.GetEndColor() );
1903 rOStm.WriteInt16( rGrad.GetAngle() );
1904 rOStm.WriteInt16( rGrad.GetBorder() );
1905 rOStm.WriteInt16( rGrad.GetOfsX() );
1906 rOStm.WriteInt16( rGrad.GetOfsY() );
1907 rOStm.WriteInt16( rGrad.GetStartIntensity() );
1908 rOStm.WriteInt16( rGrad.GetEndIntensity() );
1909 nCount++;
1911 break;
1913 case( MetaActionType::GRADIENTEX ):
1915 const MetaGradientExAction* pA = static_cast<const MetaGradientExAction*>(pAction);
1916 sal_uLong nOldPos, nNewPos;
1918 // write RefPoint comment
1919 rOStm.WriteInt16( GDI_GRADIENTEX_COMMENT );
1921 // we'll write the ActionSize later
1922 nOldPos = rOStm.Tell();
1923 rOStm.SeekRel( 4 );
1925 // write data
1926 WritePolyPolygon( rOStm, pA->GetPolyPolygon() );
1927 WriteGradient( rOStm, pA->GetGradient() );
1928 rOStm.WriteInt32( 0 ); // number of actions that follow this comment
1930 // calculate and write ActionSize of comment
1931 nNewPos = rOStm.Tell();
1932 rOStm.Seek( nOldPos );
1933 rOStm.WriteInt32( nNewPos - nOldPos );
1934 rOStm.Seek( nNewPos );
1936 nCount++;
1938 break;
1940 case( MetaActionType::WALLPAPER ):
1942 const MetaWallpaperAction* pAct = static_cast<const MetaWallpaperAction*>(pAction);
1943 const Color& rColor = pAct->GetWallpaper().GetColor();
1945 ImplWritePushAction( rOStm );
1946 ImplWriteLineColor( rOStm, rColor, 1 );
1947 ImplWriteFillColor( rOStm, rColor, 1 );
1949 rOStm.WriteInt16( GDI_RECT_ACTION );
1950 rOStm.WriteInt32( 28 );
1951 ImplWriteRect( rOStm, pAct->GetRect() );
1952 rOStm.WriteInt32( 0 );
1953 rOStm.WriteInt32( 0 );
1955 ImplWritePopAction( rOStm );
1956 nCount += 5;
1958 break;
1960 case( MetaActionType::CLIPREGION ):
1962 const MetaClipRegionAction* pAct = static_cast<const MetaClipRegionAction*>(pAction);
1963 const vcl::Region& rRegion = pAct->GetRegion();
1964 Rectangle aClipRect;
1966 rOStm.WriteInt16( GDI_CLIPREGION_ACTION );
1967 rOStm.WriteInt32( 24 );
1969 if( pAct->IsClipping() )
1971 aClipRect = rRegion.GetBoundRect();
1972 rOStm.WriteInt16( 1 );
1974 else
1975 rOStm.WriteInt16( 0 );
1977 rOStm.WriteInt16( 0 );
1978 ImplWriteRect( rOStm, aClipRect );
1980 if( pAct->IsClipping() )
1981 ImplWriteRect( rOStm, aClipRect );
1983 nCount++;
1985 break;
1987 case( MetaActionType::ISECTRECTCLIPREGION ):
1989 const MetaISectRectClipRegionAction* pAct = static_cast<const MetaISectRectClipRegionAction*>(pAction);
1991 rOStm.WriteInt16( GDI_ISECTCLIPREGION_ACTION );
1992 rOStm.WriteInt32( 20 );
1993 WriteRectangle( rOStm, pAct->GetRect() );
1994 nCount++;
1996 break;
1998 case( MetaActionType::MOVECLIPREGION ):
2000 const MetaMoveClipRegionAction* pAct = static_cast<const MetaMoveClipRegionAction*>(pAction);
2002 rOStm.WriteInt16( GDI_MOVECLIPREGION_ACTION );
2003 rOStm.WriteInt32( 12 );
2004 rOStm.WriteInt32( pAct->GetHorzMove() );
2005 rOStm.WriteInt32( pAct->GetVertMove() );
2006 nCount++;
2008 break;
2010 case( MetaActionType::LINECOLOR ):
2012 const MetaLineColorAction* pAct = static_cast<const MetaLineColorAction*>(pAction);
2013 ImplWriteLineColor( rOStm, rLineCol = pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
2014 nCount++;
2016 break;
2018 case( MetaActionType::FILLCOLOR ):
2020 const MetaFillColorAction* pAct = static_cast<const MetaFillColorAction*>(pAction);
2021 ImplWriteFillColor( rOStm, pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
2022 nCount++;
2024 break;
2026 case( MetaActionType::FONT ):
2028 rSaveVDev.SetFont( static_cast<const MetaFontAction*>(pAction)->GetFont() );
2029 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2030 nCount++;
2032 break;
2034 case( MetaActionType::TEXTCOLOR ):
2036 vcl::Font aSaveFont( rSaveVDev.GetFont() );
2038 aSaveFont.SetColor( static_cast<const MetaTextColorAction*>(pAction)->GetColor() );
2039 rSaveVDev.SetFont( aSaveFont );
2040 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2041 nCount++;
2043 break;
2045 case( MetaActionType::TEXTFILLCOLOR ):
2047 const MetaTextFillColorAction* pAct = static_cast<const MetaTextFillColorAction*>(pAction);
2048 vcl::Font aSaveFont( rSaveVDev.GetFont() );
2050 if( pAct->IsSetting() )
2051 aSaveFont.SetFillColor( pAct->GetColor() );
2052 else
2053 aSaveFont.SetFillColor( Color( COL_TRANSPARENT ) );
2055 rSaveVDev.SetFont( aSaveFont );
2056 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2057 nCount++;
2059 break;
2061 case( MetaActionType::TEXTALIGN ):
2063 vcl::Font aSaveFont( rSaveVDev.GetFont() );
2065 aSaveFont.SetAlign( static_cast<const MetaTextAlignAction*>(pAction)->GetTextAlign() );
2066 rSaveVDev.SetFont( aSaveFont );
2067 ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
2068 nCount++;
2070 break;
2072 case( MetaActionType::MAPMODE ):
2074 const MetaMapModeAction* pAct = static_cast<const MetaMapModeAction*>(pAction);
2076 rOStm.WriteInt16( GDI_MAPMODE_ACTION );
2077 rOStm.WriteInt32( 30 );
2078 ImplWriteMapMode( rOStm, pAct->GetMapMode() );
2079 nCount++;
2081 break;
2083 case( MetaActionType::PUSH ):
2085 ImplWritePushAction( rOStm );
2086 rLineColStack.push( new Color( rLineCol ) );
2087 rSaveVDev.Push();
2088 nCount++;
2090 break;
2092 case( MetaActionType::POP ):
2094 Color* pCol;
2095 if (rLineColStack.empty())
2096 pCol = NULL;
2097 else
2099 pCol = rLineColStack.top();
2100 rLineColStack.pop();
2103 if( pCol )
2105 rLineCol = *pCol;
2106 delete pCol;
2109 ImplWritePopAction( rOStm );
2110 rSaveVDev.Pop();
2111 nCount++;
2113 break;
2115 case( MetaActionType::RASTEROP ):
2117 const MetaRasterOpAction* pAct = static_cast<const MetaRasterOpAction*>(pAction);
2119 if( ( pAct->GetRasterOp() != ROP_0 ) && ( pAct->GetRasterOp() != ROP_1 ) )
2121 sal_Int16 nRasterOp;
2123 // If ROP_0/1 was set earlier, restore old state
2124 // via a Pop first
2125 if( rRop_0_1 )
2127 ImplWritePopAction( rOStm );
2128 rSaveVDev.Pop();
2129 rRop_0_1 = false;
2130 nCount++;
2133 switch( pAct->GetRasterOp() )
2135 case( ROP_OVERPAINT ) : nRasterOp = 0; break;
2136 case( ROP_XOR ) : nRasterOp = 4; break;
2137 case( ROP_INVERT ): nRasterOp = 1; break;
2138 default: nRasterOp = 0; break;
2141 ImplWriteRasterOpAction( rOStm, nRasterOp );
2142 nCount++;
2144 else
2146 ImplWritePushAction( rOStm );
2147 rSaveVDev.Push();
2149 if( pAct->GetRasterOp() == ROP_0 )
2151 ImplWriteLineColor( rOStm, COL_BLACK, 1 );
2152 ImplWriteFillColor( rOStm, COL_BLACK, 1 );
2154 else
2156 ImplWriteLineColor( rOStm, COL_WHITE, 1 );
2157 ImplWriteFillColor( rOStm, COL_WHITE, 1 );
2160 ImplWriteRasterOpAction( rOStm, 0 );
2161 rRop_0_1 = true;
2162 nCount += 4;
2165 break;
2167 case( MetaActionType::Transparent ):
2169 const tools::PolyPolygon& rPolyPoly = static_cast<const MetaTransparentAction*>(pAction)->GetPolyPolygon();
2170 const sal_Int16 nTrans = static_cast<const MetaTransparentAction*>(pAction)->GetTransparence();
2171 const sal_Int16 nBrushStyle = ( nTrans < 38 ) ? 8 : ( nTrans < 63 ) ? 9 : 10;
2172 sal_uLong nOldPos, nNewPos;
2174 // write transparence comment
2175 rOStm.WriteInt16( GDI_TRANSPARENT_COMMENT );
2177 // we'll write the ActionSize later
2178 nOldPos = rOStm.Tell();
2179 rOStm.SeekRel( 4 );
2181 // write comment data
2182 WritePolyPolygon( rOStm, rPolyPoly );
2183 rOStm.WriteInt16( nTrans );
2184 rOStm.WriteInt32( 15 ); // number of actions that follow this comment
2186 // calculate and write ActionSize of comment
2187 nNewPos = rOStm.Tell();
2188 rOStm.Seek( nOldPos );
2189 rOStm.WriteInt32( nNewPos - nOldPos );
2190 rOStm.Seek( nNewPos );
2193 // write actions for transparence
2194 ImplWritePushAction( rOStm );
2196 ImplWriteRasterOpAction( rOStm, 4 );
2197 ImplWritePolyPolyAction( rOStm, rPolyPoly );
2199 ImplWritePushAction( rOStm );
2201 ImplWriteRasterOpAction( rOStm, 2 );
2202 ImplWriteFillColor( rOStm, COL_BLACK, nBrushStyle );
2203 ImplWritePolyPolyAction( rOStm, rPolyPoly );
2205 ImplWritePopAction( rOStm );
2207 ImplWriteRasterOpAction( rOStm, 4 );
2208 ImplWritePolyPolyAction( rOStm, rPolyPoly );
2210 ImplWritePopAction( rOStm );
2212 ImplWritePushAction( rOStm );
2214 ImplWriteFillColor( rOStm, Color(), 0 );
2215 ImplWritePolyPolyAction( rOStm, rPolyPoly );
2217 ImplWritePopAction( rOStm );
2219 nCount += 15;
2222 nCount++;
2224 break;
2226 case( MetaActionType::FLOATTRANSPARENT ):
2228 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
2229 const GDIMetaFile& rTransMtf = pA->GetGDIMetaFile();
2230 const Point& rPos = pA->GetPoint();
2231 const Size& rSize = pA->GetSize();
2232 const Gradient& rGradient = pA->GetGradient();
2233 sal_uLong nOldPos, nNewPos;
2235 // write RefPoint comment
2236 rOStm.WriteInt16( GDI_FLOATTRANSPARENT_COMMENT );
2238 // we'll write the ActionSize later
2239 nOldPos = rOStm.Tell();
2240 rOStm.SeekRel( 4 );
2242 // write comment data
2243 WriteGDIMetaFile( rOStm, rTransMtf );
2244 WritePair( rOStm, rPos );
2245 WritePair( rOStm, rSize );
2246 WriteGradient( rOStm, rGradient );
2248 // calculate and write ActionSize of comment
2249 nNewPos = rOStm.Tell();
2250 rOStm.Seek( nOldPos );
2251 rOStm.WriteInt32( nNewPos - nOldPos + 4 );
2252 rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
2255 // write actions for float transparence
2256 sal_uLong nAddCount;
2257 GDIMetaFile aMtf( rTransMtf );
2258 const Size aSrcSize( rTransMtf.GetPrefSize() );
2259 Point aSrcPt( rTransMtf.GetPrefMapMode().GetOrigin() );
2260 const double fScaleX = aSrcSize.Width() ? (double) rSize.Width() / aSrcSize.Width() : 1.0;
2261 const double fScaleY = aSrcSize.Height() ? (double) rSize.Height() / aSrcSize.Height() : 1.0;
2262 long nMoveX, nMoveY;
2264 if( fScaleX != 1.0 || fScaleY != 1.0 )
2266 aMtf.Scale( fScaleX, fScaleY );
2267 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2270 nMoveX = rPos.X() - aSrcPt.X(), nMoveY = rPos.Y() - aSrcPt.Y();
2272 if( nMoveX || nMoveY )
2273 aMtf.Move( nMoveX, nMoveY );
2275 nAddCount = ImplWriteActions( rOStm, aMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
2276 nNewPos = rOStm.Tell();
2277 rOStm.Seek( nOldPos );
2278 rOStm.WriteInt32( nAddCount );
2279 rOStm.Seek( nNewPos );
2281 nCount += nAddCount;
2284 nCount++;
2286 break;
2288 case( MetaActionType::HATCH ):
2290 const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
2291 const tools::PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
2292 const Hatch& rHatch = pA->GetHatch();
2293 sal_uLong nOldPos, nNewPos, nAddCount;
2295 // write hatch comment
2296 rOStm.WriteInt16( GDI_HATCH_COMMENT );
2298 // we'll write the ActionSize later
2299 nOldPos = rOStm.Tell();
2300 rOStm.SeekRel( 4 );
2302 // write comment data
2303 WritePolyPolygon( rOStm, rPolyPoly );
2304 WriteHatch( rOStm, rHatch );
2306 // calculate and write ActionSize of comment
2307 nNewPos = rOStm.Tell();
2308 rOStm.Seek( nOldPos );
2309 rOStm.WriteInt32( nNewPos - nOldPos + 4 );
2310 rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
2313 // write actions for hatch
2314 ScopedVclPtrInstance< VirtualDevice > aVDev;
2315 GDIMetaFile aTmpMtf;
2317 aVDev->AddHatchActions( rPolyPoly, rHatch, aTmpMtf );
2318 nAddCount = ImplWriteActions( rOStm, aTmpMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
2319 nNewPos = rOStm.Tell();
2320 rOStm.Seek( nOldPos );
2321 rOStm.WriteInt32( nAddCount );
2322 rOStm.Seek( nNewPos );
2324 nCount += nAddCount;
2327 nCount++;
2329 break;
2331 case( MetaActionType::REFPOINT ):
2333 const MetaRefPointAction* pA = static_cast<const MetaRefPointAction*>(pAction);
2334 const Point& rRefPoint = pA->GetRefPoint();
2335 const bool bSet = pA->IsSetting();
2336 sal_uLong nOldPos, nNewPos;
2338 // write RefPoint comment
2339 rOStm.WriteInt16( GDI_REFPOINT_COMMENT );
2341 // we'll write the ActionSize later
2342 nOldPos = rOStm.Tell();
2343 rOStm.SeekRel( 4 );
2345 // write data
2346 WritePair( rOStm, rRefPoint );
2347 rOStm.WriteBool( bSet );
2348 rOStm.WriteInt32( 0 ); // number of actions that follow this comment
2350 // calculate and write ActionSize of comment
2351 nNewPos = rOStm.Tell();
2352 rOStm.Seek( nOldPos );
2353 rOStm.WriteInt32( nNewPos - nOldPos );
2354 rOStm.Seek( nNewPos );
2356 nCount++;
2358 break;
2360 case( MetaActionType::TEXTLINECOLOR ):
2362 const MetaTextLineColorAction* pA = static_cast<const MetaTextLineColorAction*>(pAction);
2363 const Color& rColor = pA->GetColor();
2364 const bool bSet = pA->IsSetting();
2365 sal_uLong nOldPos, nNewPos;
2367 // write RefPoint comment
2368 rOStm.WriteInt16( GDI_TEXTLINECOLOR_COMMENT );
2370 // we'll write the ActionSize later
2371 nOldPos = rOStm.Tell();
2372 rOStm.SeekRel( 4 );
2374 // write data
2375 WriteColor( rOStm, rColor );
2376 rOStm.WriteBool( bSet );
2377 rOStm.WriteInt32( 0 ); // number of actions that follow this comment
2379 // calculate and write ActionSize of comment
2380 nNewPos = rOStm.Tell();
2381 rOStm.Seek( nOldPos );
2382 rOStm.WriteInt32( nNewPos - nOldPos );
2383 rOStm.Seek( nNewPos );
2385 nCount++;
2387 break;
2389 case( MetaActionType::TEXTLINE ):
2391 const MetaTextLineAction* pA = static_cast<const MetaTextLineAction*>(pAction);
2392 const Point& rStartPt = pA->GetStartPoint();
2393 const sal_Int32 nWidth = (sal_Int32) pA->GetWidth();
2394 const FontStrikeout eStrikeout = pA->GetStrikeout();
2395 const FontUnderline eUnderline = pA->GetUnderline();
2396 sal_uLong nOldPos, nNewPos;
2398 // write RefPoint comment
2399 rOStm.WriteInt16( GDI_TEXTLINE_COMMENT );
2401 // we'll write the ActionSize later
2402 nOldPos = rOStm.Tell();
2403 rOStm.SeekRel( 4 );
2405 // write data
2406 WritePair( rOStm, rStartPt );
2407 rOStm.WriteInt32( nWidth ).WriteUInt32( eStrikeout ).WriteUInt32( eUnderline );
2408 rOStm.WriteInt32( 0 ); // number of actions that follow this comment
2410 // calculate and write ActionSize of comment
2411 nNewPos = rOStm.Tell();
2412 rOStm.Seek( nOldPos );
2413 rOStm.WriteInt32( nNewPos - nOldPos );
2414 rOStm.Seek( nNewPos );
2416 nCount++;
2418 break;
2420 case( MetaActionType::EPS ):
2421 break;
2423 case( MetaActionType::COMMENT ):
2425 const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
2426 const sal_uInt32 nDataSize = pA->GetDataSize();
2427 sal_uLong nOldPos, nNewPos;
2429 // write RefPoint comment
2430 rOStm.WriteInt16( GDI_COMMENT_COMMENT );
2432 // we'll write the ActionSize later
2433 nOldPos = rOStm.Tell();
2434 rOStm.SeekRel( 4 );
2436 // write data
2437 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm, pA->GetComment());
2438 rOStm.WriteInt32( pA->GetValue() ).WriteUInt32( nDataSize );
2440 if( nDataSize )
2441 rOStm.Write( pA->GetData(), nDataSize );
2443 rOStm.WriteInt32( 0 ); // number of actions that follow this comment
2445 // calculate and write ActionSize of comment
2446 nNewPos = rOStm.Tell();
2447 rOStm.Seek( nOldPos );
2448 rOStm.WriteInt32( nNewPos - nOldPos );
2449 rOStm.Seek( nNewPos );
2451 nCount++;
2453 break;
2455 default:
2456 #ifdef DBG_UTIL
2458 OStringBuffer aStr("Missing implementation for Action#: ");
2459 aStr.append(static_cast<sal_Int32>(pAction->GetType()));
2460 aStr.append('!');
2461 OSL_FAIL(aStr.getStr());
2463 #endif
2464 break;
2468 return nCount;
2471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */