1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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 "svmconverter.hxx"
36 #include <o3tl/make_unique.hxx>
39 void ImplReadRect( SvStream
& rIStm
, tools::Rectangle
& rRect
)
44 ReadPair( rIStm
, aTL
);
45 ReadPair( rIStm
, aBR
);
47 rRect
= tools::Rectangle( aTL
, aBR
);
50 void ImplWriteRect( SvStream
& rOStm
, const tools::Rectangle
& rRect
)
52 WritePair( rOStm
, rRect
.TopLeft() );
53 WritePair( rOStm
, rRect
.BottomRight() );
56 bool ImplReadPoly(SvStream
& rIStm
, tools::Polygon
& rPoly
)
59 rIStm
.ReadInt32(nSize32
);
60 sal_uInt16 nSize
= nSize32
;
62 const size_t nMaxPossiblePoints
= rIStm
.remainingSize() / 2 * sizeof(sal_Int32
);
63 if (nSize
> nMaxPossiblePoints
)
65 SAL_WARN("vcl.gdi", "svm record claims to have: " << nSize
<< " points, but only " << nMaxPossiblePoints
<< " possible");
69 rPoly
= tools::Polygon(nSize
);
71 for (sal_uInt16 i
= 0; i
< nSize
&& rIStm
.good(); ++i
)
72 ReadPair(rIStm
, rPoly
[i
]);
77 bool ImplReadPolyPoly(SvStream
& rIStm
, tools::PolyPolygon
& rPolyPoly
)
82 sal_Int32
nPolyCount32(0);
83 rIStm
.ReadInt32(nPolyCount32
);
84 sal_uInt16 nPolyCount
= (sal_uInt16
)nPolyCount32
;
86 for (sal_uInt16 i
= 0; i
< nPolyCount
&& rIStm
.good(); ++i
)
88 if (!ImplReadPoly(rIStm
, aPoly
))
93 rPolyPoly
.Insert(aPoly
);
96 return bSuccess
&& rIStm
.good();
99 void ImplWritePolyPolyAction( SvStream
& rOStm
, const tools::PolyPolygon
& rPolyPoly
)
101 const sal_uInt16 nPoly
= rPolyPoly
.Count();
102 sal_uInt16 nPoints
= 0;
105 for( n
= 0; n
< nPoly
; n
++ )
106 nPoints
= sal::static_int_cast
<sal_uInt16
>(nPoints
+ rPolyPoly
[ n
].GetSize());
108 rOStm
.WriteInt16( GDI_POLYPOLYGON_ACTION
);
109 rOStm
.WriteInt32( 8 + ( nPoly
<< 2 ) + ( nPoints
<< 3 ) );
110 rOStm
.WriteInt32( nPoly
);
112 for( n
= 0; n
< nPoly
; n
++ )
114 // #i102224# Here the possible curved nature of Polygon was
115 // ignored (for all those years). Adapted to at least write
116 // a polygon representing the curve as good as possible
117 tools::Polygon aSimplePoly
;
118 rPolyPoly
[n
].AdaptiveSubdivide(aSimplePoly
);
119 const sal_uInt16
nSize(aSimplePoly
.GetSize());
121 rOStm
.WriteInt32( nSize
);
123 for( sal_uInt16 j
= 0; j
< nSize
; j
++ )
124 WritePair( rOStm
, aSimplePoly
[ j
] );
128 void ImplReadColor( SvStream
& rIStm
, Color
& rColor
)
132 rIStm
.ReadInt16( nVal
); rColor
.SetRed( sal::static_int_cast
<sal_uInt8
>((sal_uInt16
)nVal
>> 8) );
133 rIStm
.ReadInt16( nVal
); rColor
.SetGreen( sal::static_int_cast
<sal_uInt8
>((sal_uInt16
)nVal
>> 8) );
134 rIStm
.ReadInt16( nVal
); rColor
.SetBlue( sal::static_int_cast
<sal_uInt8
>((sal_uInt16
)nVal
>> 8) );
137 void ImplWriteColor( SvStream
& rOStm
, const Color
& rColor
)
141 nVal
= ( (sal_Int16
) rColor
.GetRed() << 8 ) | rColor
.GetRed();
142 rOStm
.WriteInt16( nVal
);
144 nVal
= ( (sal_Int16
) rColor
.GetGreen() << 8 ) | rColor
.GetGreen();
145 rOStm
.WriteInt16( nVal
);
147 nVal
= ( (sal_Int16
) rColor
.GetBlue() << 8 ) | rColor
.GetBlue();
148 rOStm
.WriteInt16( nVal
);
151 bool ImplReadMapMode(SvStream
& rIStm
, MapMode
& rMapMode
)
154 rIStm
.ReadInt16(nUnit
);
157 ReadPair(rIStm
, aOrg
);
159 sal_Int32
nXNum(0), nXDenom(0), nYNum(0), nYDenom(0);
160 rIStm
.ReadInt32(nXNum
).ReadInt32(nXDenom
).ReadInt32(nYNum
).ReadInt32(nYDenom
);
162 if (!rIStm
.good() || nXDenom
<= 0 || nYDenom
<= 0 || nXNum
<= 0 || nYNum
<= 0)
164 SAL_WARN("vcl.gdi", "Parsing error: invalid mapmode fraction");
168 if (nUnit
< sal_Int16(MapUnit::Map100thMM
) || nUnit
> sal_Int16(MapUnit::LAST
))
170 SAL_WARN("vcl.gdi", "Parsing error: invalid mapmode");
174 rMapMode
= MapMode((MapUnit
) nUnit
, aOrg
, Fraction(nXNum
, nXDenom
), Fraction(nYNum
, nYDenom
));
179 void ImplWriteMapMode( SvStream
& rOStm
, const MapMode
& rMapMode
)
181 rOStm
.WriteInt16( (sal_uInt16
)rMapMode
.GetMapUnit() );
182 WritePair( rOStm
, rMapMode
.GetOrigin() );
183 rOStm
.WriteInt32( rMapMode
.GetScaleX().GetNumerator() );
184 rOStm
.WriteInt32( rMapMode
.GetScaleX().GetDenominator() );
185 rOStm
.WriteInt32( rMapMode
.GetScaleY().GetNumerator() );
186 rOStm
.WriteInt32( rMapMode
.GetScaleY().GetDenominator() );
189 void ImplWritePushAction( SvStream
& rOStm
)
191 rOStm
.WriteInt16( GDI_PUSH_ACTION
);
192 rOStm
.WriteInt32( 4 );
195 void ImplWritePopAction( SvStream
& rOStm
)
197 rOStm
.WriteInt16( GDI_POP_ACTION
);
198 rOStm
.WriteInt32( 4 );
201 void ImplWriteLineColor( SvStream
& rOStm
, const Color
& rColor
, sal_Int16 nStyle
, sal_Int32 nWidth
= 0 )
203 if( rColor
.GetTransparency() > 127 )
206 rOStm
.WriteInt16( GDI_PEN_ACTION
);
207 rOStm
.WriteInt32( 16 );
208 ImplWriteColor( rOStm
, rColor
);
209 rOStm
.WriteInt32( nWidth
);
210 rOStm
.WriteInt16( nStyle
);
213 void ImplWriteFillColor( SvStream
& rOStm
, const Color
& rColor
, sal_Int16 nStyle
)
215 rOStm
.WriteInt16( GDI_FILLBRUSH_ACTION
);
216 rOStm
.WriteInt32( 20 );
217 ImplWriteColor( rOStm
, rColor
);
219 if( rColor
.GetTransparency() > 127 )
224 ImplWriteColor( rOStm
, COL_WHITE
);
225 rOStm
.WriteInt16( nStyle
);
226 rOStm
.WriteInt16( 1 );
230 ImplWriteColor( rOStm
, COL_BLACK
);
231 rOStm
.WriteInt16( nStyle
);
232 rOStm
.WriteInt16( 0 );
236 void ImplWriteFont( SvStream
& rOStm
, const vcl::Font
& rFont
,
237 rtl_TextEncoding
& rActualCharSet
)
242 OString
aByteName(OUStringToOString(rFont
.GetFamilyName(),
243 rOStm
.GetStreamCharSet()));
244 strncpy( aName
, aByteName
.getStr(), 32 );
247 switch ( rFont
.GetWeight() )
250 case WEIGHT_ULTRALIGHT
:
261 case WEIGHT_ULTRABOLD
:
271 rOStm
.WriteInt16( GDI_FONT_ACTION
);
272 rOStm
.WriteInt32( 78 );
274 rActualCharSet
= GetStoreCharSet( rFont
.GetCharSet() );
275 ImplWriteColor( rOStm
, rFont
.GetColor() );
276 ImplWriteColor( rOStm
, rFont
.GetFillColor() );
277 rOStm
.WriteBytes( aName
, 32 );
278 WritePair( rOStm
, rFont
.GetFontSize() );
279 rOStm
.WriteInt16( 0 ); // no character orientation anymore
280 rOStm
.WriteInt16( rFont
.GetOrientation() );
281 rOStm
.WriteInt16( rActualCharSet
);
282 rOStm
.WriteInt16( rFont
.GetFamilyType() );
283 rOStm
.WriteInt16( rFont
.GetPitch() );
284 rOStm
.WriteInt16( rFont
.GetAlignment() );
285 rOStm
.WriteInt16( nWeight
);
286 rOStm
.WriteInt16( rFont
.GetUnderline() );
287 rOStm
.WriteInt16( rFont
.GetStrikeout() );
288 rOStm
.WriteBool( rFont
.GetItalic() != ITALIC_NONE
);
289 rOStm
.WriteBool( rFont
.IsOutline() );
290 rOStm
.WriteBool( rFont
.IsShadow() );
291 rOStm
.WriteBool( rFont
.IsTransparent() );
292 if ( rActualCharSet
== RTL_TEXTENCODING_DONTKNOW
)
293 rActualCharSet
= osl_getThreadTextEncoding();
296 void ImplWriteRasterOpAction( SvStream
& rOStm
, sal_Int16 nRasterOp
)
298 rOStm
.WriteInt16( GDI_RASTEROP_ACTION
).WriteInt32( 6 ).WriteInt16( nRasterOp
);
301 bool ImplWriteUnicodeComment( SvStream
& rOStm
, const OUString
& rString
)
303 sal_Int32 nStringLen
= rString
.getLength();
306 sal_uInt32 nSize
= ( nStringLen
<< 1 ) + 4;
307 sal_uInt16 nType
= GDI_UNICODE_COMMENT
;
309 rOStm
.WriteUInt16( nType
).WriteUInt32( nSize
);
310 write_uInt16s_FromOUString(rOStm
, rString
);
312 return nStringLen
!= 0;
315 void ImplReadUnicodeComment( sal_uInt32 nStrmPos
, SvStream
& rIStm
, OUString
& rString
)
317 sal_uInt32 nOld
= rIStm
.Tell();
321 sal_uInt32 nActionSize
;
322 std::size_t nStringLen
;
324 rIStm
.Seek( nStrmPos
);
325 rIStm
.ReadUInt16( nType
)
326 .ReadUInt32( nActionSize
);
328 nStringLen
= (nActionSize
- 4) >> 1;
330 if ( nStringLen
&& ( nType
== GDI_UNICODE_COMMENT
) )
331 rString
= read_uInt16s_ToOUString(rIStm
, nStringLen
);
336 void ImplSkipActions(SvStream
& rIStm
, sal_uLong nSkipCount
)
338 sal_Int32 nActionSize
;
340 for (sal_uLong i
= 0UL; i
< nSkipCount
; ++i
)
342 rIStm
.ReadInt16(nType
).ReadInt32(nActionSize
);
343 if (!rIStm
.good() || nActionSize
< 4)
345 rIStm
.SeekRel(nActionSize
- 4);
349 bool ImplWriteExtendedPolyPolygonAction(SvStream
& rOStm
, const tools::PolyPolygon
& rPolyPolygon
, bool bOnlyWhenCurve
)
351 const sal_uInt16
nPolygonCount(rPolyPolygon
.Count());
355 sal_uInt32
nAllPolygonCount(0);
356 sal_uInt32
nAllPointCount(0);
357 sal_uInt32
nAllFlagCount(0);
360 for(a
= 0; a
< nPolygonCount
; a
++)
362 const tools::Polygon
& rCandidate
= rPolyPolygon
.GetObject(a
);
363 const sal_uInt16
nPointCount(rCandidate
.GetSize());
368 nAllPointCount
+= nPointCount
;
370 if(rCandidate
.HasFlags())
372 nAllFlagCount
+= nPointCount
;
377 if((bOnlyWhenCurve
&& nAllFlagCount
) || (!bOnlyWhenCurve
&& nAllPointCount
))
379 rOStm
.WriteInt16( GDI_EXTENDEDPOLYGON_ACTION
);
381 const sal_Int32
nActionSize(
384 (nAllPolygonCount
* 2) + // Points per polygon
385 (nAllPointCount
<< 3) + // Points themselves
386 nAllPolygonCount
+ // Bool if (when poly has points) it has flags, too
387 nAllFlagCount
); // Flags themselves
389 rOStm
.WriteInt32( nActionSize
);
390 rOStm
.WriteUInt16( nAllPolygonCount
);
392 for(a
= 0; a
< nPolygonCount
; a
++)
394 const tools::Polygon
& rCandidate
= rPolyPolygon
.GetObject(a
);
395 const sal_uInt16
nPointCount(rCandidate
.GetSize());
399 rOStm
.WriteUInt16( nPointCount
);
401 for(sal_uInt16
b(0); b
< nPointCount
; b
++)
403 WritePair( rOStm
, rCandidate
[b
] );
406 if(rCandidate
.HasFlags())
408 rOStm
.WriteBool( true );
410 for(sal_uInt16
c(0); c
< nPointCount
; c
++)
412 rOStm
.WriteUChar( (sal_uInt8
)rCandidate
.GetFlags(c
) );
417 rOStm
.WriteBool( false );
429 void ImplReadExtendedPolyPolygonAction(SvStream
& rIStm
, tools::PolyPolygon
& rPolyPoly
)
432 sal_uInt16
nPolygonCount(0);
433 rIStm
.ReadUInt16( nPolygonCount
);
438 const size_t nMinRecordSize
= sizeof(sal_uInt16
);
439 const size_t nMaxRecords
= rIStm
.remainingSize() / nMinRecordSize
;
440 if (nPolygonCount
> nMaxRecords
)
442 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords
<<
443 " max possible entries, but " << nPolygonCount
<< " claimed, truncating");
444 nPolygonCount
= nMaxRecords
;
447 for(sal_uInt16
a(0); a
< nPolygonCount
; a
++)
449 sal_uInt16
nPointCount(0);
450 rIStm
.ReadUInt16(nPointCount
);
452 const size_t nMinPolygonSize
= sizeof(sal_Int32
) * 2;
453 const size_t nMaxPolygons
= rIStm
.remainingSize() / nMinPolygonSize
;
454 if (nPointCount
> nMaxPolygons
)
456 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxPolygons
<<
457 " max possible entries, but " << nPointCount
<< " claimed, truncating");
458 nPointCount
= nMaxPolygons
;
461 tools::Polygon
aCandidate(nPointCount
);
465 for(sal_uInt16
b(0); b
< nPointCount
; b
++)
467 ReadPair( rIStm
, aCandidate
[b
] );
470 sal_uInt8
bHasFlags(int(false));
471 rIStm
.ReadUChar( bHasFlags
);
475 sal_uInt8
aPolyFlags(0);
477 for(sal_uInt16
c(0); c
< nPointCount
; c
++)
479 rIStm
.ReadUChar( aPolyFlags
);
480 aCandidate
.SetFlags(c
, (PolyFlags
)aPolyFlags
);
485 rPolyPoly
.Insert(aCandidate
);
489 SVMConverter::SVMConverter( SvStream
& rStm
, GDIMetaFile
& rMtf
, sal_uLong nConvertMode
)
491 if( !rStm
.GetError() )
493 if( CONVERT_FROM_SVM1
== nConvertMode
)
494 ImplConvertFromSVM1( rStm
, rMtf
);
495 else if( CONVERT_TO_SVM1
== nConvertMode
)
496 ImplConvertToSVM1( rStm
, rMtf
);
502 sal_Int32
SkipActions(sal_Int32 i
, sal_Int32 nFollowingActionCount
, sal_Int32 nActions
)
504 sal_Int32 remainingActions
= nActions
- i
;
505 if (nFollowingActionCount
< 0)
506 nFollowingActionCount
= remainingActions
;
507 return std::min(remainingActions
, nFollowingActionCount
);
511 #define LF_FACESIZE 32
513 void SVMConverter::ImplConvertFromSVM1( SvStream
& rIStm
, GDIMetaFile
& rMtf
)
515 const sal_uLong nPos
= rIStm
.Tell();
516 const SvStreamEndian nOldFormat
= rIStm
.GetEndian();
518 rIStm
.SetEndian( SvStreamEndian::LITTLE
);
524 rIStm
.ReadBytes(aCode
, sizeof(aCode
)); // Identifier
526 rIStm
.ReadInt16( nSize
); // Size
527 sal_Int16
nVersion(0);
528 rIStm
.ReadInt16( nVersion
); // Version
530 rIStm
.ReadInt32( nTmp32
);
531 aPrefSz
.Width() = nTmp32
; // PrefSize.Width()
532 rIStm
.ReadInt32( nTmp32
);
533 aPrefSz
.Height() = nTmp32
; // PrefSize.Height()
535 // check header-magic and version
537 || ( memcmp( aCode
, "SVGDI", sizeof( aCode
) ) != 0 )
538 || ( nVersion
!= 200 ) )
540 rIStm
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
541 rIStm
.SetEndian( nOldFormat
);
546 LineInfo
aLineInfo( LineStyle::NONE
, 0 );
547 std::stack
<std::unique_ptr
<LineInfo
>> aLIStack
;
548 ScopedVclPtrInstance
< VirtualDevice
> aFontVDev
;
549 rtl_TextEncoding eActualCharSet
= osl_getThreadTextEncoding();
550 bool bFatLine
= false;
552 tools::Polygon aActionPoly
;
553 tools::Rectangle aRect
;
558 sal_uInt32 nUnicodeCommentStreamPos
= 0;
559 sal_Int32 nUnicodeCommentActionNumber
= 0;
561 rMtf
.SetPrefSize(aPrefSz
);
564 if (ImplReadMapMode(rIStm
, aMapMode
)) // MapMode
565 rMtf
.SetPrefMapMode(aMapMode
);
567 sal_Int32
nActions(0);
568 rIStm
.ReadInt32(nActions
); // Action count
571 SAL_WARN("vcl.gdi", "svm claims negative action count (" << nActions
<< ")");
575 const size_t nMinActionSize
= sizeof(sal_uInt16
) + sizeof(sal_Int32
);
576 const size_t nMaxPossibleActions
= rIStm
.remainingSize() / nMinActionSize
;
577 if (static_cast<sal_uInt32
>(nActions
) > nMaxPossibleActions
)
579 SAL_WARN("vcl.gdi", "svm claims more actions (" << nActions
<< ") than stream could provide, truncating");
580 nActions
= nMaxPossibleActions
;
583 size_t nLastPolygonAction(0);
585 for (sal_Int32 i
= 0; i
< nActions
&& rIStm
.good(); ++i
)
588 rIStm
.ReadInt16(nType
);
589 sal_Int32 nActBegin
= rIStm
.Tell();
590 sal_Int32
nActionSize(0);
591 rIStm
.ReadInt32(nActionSize
);
593 SAL_WARN_IF( ( nType
> 33 ) && ( nType
< 1024 ), "vcl.gdi", "Unknown GDIMetaAction while converting!" );
597 case GDI_PIXEL_ACTION
:
599 ReadPair( rIStm
, aPt
);
600 ImplReadColor( rIStm
, aActionColor
);
601 rMtf
.AddAction( new MetaPixelAction( aPt
, aActionColor
) );
605 case GDI_POINT_ACTION
:
607 ReadPair( rIStm
, aPt
);
608 rMtf
.AddAction( new MetaPointAction( aPt
) );
612 case GDI_LINE_ACTION
:
614 ReadPair( rIStm
, aPt
);
615 ReadPair( rIStm
, aPt1
);
616 rMtf
.AddAction( new MetaLineAction( aPt
, aPt1
, aLineInfo
) );
620 case GDI_LINEJOIN_ACTION
:
622 sal_Int16
nLineJoin(0);
623 rIStm
.ReadInt16( nLineJoin
);
624 aLineInfo
.SetLineJoin((basegfx::B2DLineJoin
)nLineJoin
);
628 case GDI_LINECAP_ACTION
:
630 sal_Int16
nLineCap(0);
631 rIStm
.ReadInt16( nLineCap
);
632 aLineInfo
.SetLineCap((css::drawing::LineCap
)nLineCap
);
636 case GDI_LINEDASHDOT_ACTION
:
641 rIStm
.ReadInt16( a
); aLineInfo
.SetDashCount(a
);
642 rIStm
.ReadInt32( b
); aLineInfo
.SetDashLen(b
);
643 rIStm
.ReadInt16( a
); aLineInfo
.SetDotCount(a
);
644 rIStm
.ReadInt32( b
); aLineInfo
.SetDotLen(b
);
645 rIStm
.ReadInt32( b
); aLineInfo
.SetDistance(b
);
647 if(((aLineInfo
.GetDashCount() && aLineInfo
.GetDashLen())
648 || (aLineInfo
.GetDotCount() && aLineInfo
.GetDotLen()))
649 && aLineInfo
.GetDistance())
651 aLineInfo
.SetStyle(LineStyle::Dash
);
656 case GDI_EXTENDEDPOLYGON_ACTION
:
658 // read the tools::PolyPolygon in every case
659 tools::PolyPolygon aInputPolyPolygon
;
660 ImplReadExtendedPolyPolygonAction(rIStm
, aInputPolyPolygon
);
662 // now check if it can be set somewhere
663 if(nLastPolygonAction
< rMtf
.GetActionSize())
665 MetaPolyLineAction
* pPolyLineAction
= dynamic_cast< MetaPolyLineAction
* >(rMtf
.GetAction(nLastPolygonAction
));
669 // replace MetaPolyLineAction when we have a single polygon. Do not rely on the
670 // same point count; the originally written GDI_POLYLINE_ACTION may have been
671 // Subdivided for better quality for older usages
672 if(1 == aInputPolyPolygon
.Count())
674 MetaAction
* pAction
= rMtf
.ReplaceAction(
675 new MetaPolyLineAction(
676 aInputPolyPolygon
.GetObject(0),
677 pPolyLineAction
->GetLineInfo()),
685 MetaPolyPolygonAction
* pPolyPolygonAction
= dynamic_cast< MetaPolyPolygonAction
* >(rMtf
.GetAction(nLastPolygonAction
));
687 if(pPolyPolygonAction
)
689 // replace MetaPolyPolygonAction when we have a curved polygon. Do rely on the
690 // same sub-polygon count
691 if(pPolyPolygonAction
->GetPolyPolygon().Count() == aInputPolyPolygon
.Count())
693 MetaAction
* pAction
= rMtf
.ReplaceAction(
694 new MetaPolyPolygonAction(
703 MetaPolygonAction
* pPolygonAction
= dynamic_cast< MetaPolygonAction
* >(rMtf
.GetAction(nLastPolygonAction
));
707 // replace MetaPolygonAction
708 if(1 == aInputPolyPolygon
.Count())
710 MetaAction
* pAction
= rMtf
.ReplaceAction(
711 new MetaPolygonAction(
712 aInputPolyPolygon
.GetObject(0)),
724 case GDI_RECT_ACTION
:
726 ImplReadRect( rIStm
, aRect
);
727 sal_Int32
nTmp(0), nTmp1(0);
728 rIStm
.ReadInt32( nTmp
).ReadInt32( nTmp1
);
731 rMtf
.AddAction( new MetaRoundRectAction( aRect
, nTmp
, nTmp1
) );
734 rMtf
.AddAction( new MetaRectAction( aRect
) );
737 rMtf
.AddAction( new MetaPolyLineAction( aRect
, aLineInfo
) );
742 case GDI_ELLIPSE_ACTION
:
744 ImplReadRect( rIStm
, aRect
);
748 const tools::Polygon
aPoly( aRect
.Center(), aRect
.GetWidth() >> 1, aRect
.GetHeight() >> 1 );
750 rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
) );
751 rMtf
.AddAction( new MetaLineColorAction( COL_TRANSPARENT
, false ) );
752 rMtf
.AddAction( new MetaPolygonAction( aPoly
) );
753 rMtf
.AddAction( new MetaPopAction() );
754 rMtf
.AddAction( new MetaPolyLineAction( aPoly
, aLineInfo
) );
757 rMtf
.AddAction( new MetaEllipseAction( aRect
) );
763 ImplReadRect( rIStm
, aRect
);
764 ReadPair( rIStm
, aPt
);
765 ReadPair( rIStm
, aPt1
);
769 const tools::Polygon
aPoly( aRect
, aPt
, aPt1
, PolyStyle::Arc
);
771 rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
) );
772 rMtf
.AddAction( new MetaLineColorAction( COL_TRANSPARENT
, false ) );
773 rMtf
.AddAction( new MetaPolygonAction( aPoly
) );
774 rMtf
.AddAction( new MetaPopAction() );
775 rMtf
.AddAction( new MetaPolyLineAction( aPoly
, aLineInfo
) );
778 rMtf
.AddAction( new MetaArcAction( aRect
, aPt
, aPt1
) );
784 ImplReadRect( rIStm
, aRect
);
785 ReadPair( rIStm
, aPt
);
786 ReadPair( rIStm
, aPt1
);
790 const tools::Polygon
aPoly( aRect
, aPt
, aPt1
, PolyStyle::Pie
);
792 rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
) );
793 rMtf
.AddAction( new MetaLineColorAction( COL_TRANSPARENT
, false ) );
794 rMtf
.AddAction( new MetaPolygonAction( aPoly
) );
795 rMtf
.AddAction( new MetaPopAction() );
796 rMtf
.AddAction( new MetaPolyLineAction( aPoly
, aLineInfo
) );
799 rMtf
.AddAction( new MetaPieAction( aRect
, aPt
, aPt1
) );
803 case GDI_INVERTRECT_ACTION
:
804 case GDI_HIGHLIGHTRECT_ACTION
:
806 ImplReadRect( rIStm
, aRect
);
807 rMtf
.AddAction( new MetaPushAction( PushFlags::RASTEROP
) );
808 rMtf
.AddAction( new MetaRasterOpAction( RasterOp::Invert
) );
809 rMtf
.AddAction( new MetaRectAction( aRect
) );
810 rMtf
.AddAction( new MetaPopAction() );
814 case GDI_POLYLINE_ACTION
:
816 if (ImplReadPoly(rIStm
, aActionPoly
))
818 nLastPolygonAction
= rMtf
.GetActionSize();
821 rMtf
.AddAction( new MetaPolyLineAction( aActionPoly
, aLineInfo
) );
823 rMtf
.AddAction( new MetaPolyLineAction( aActionPoly
) );
828 case GDI_POLYGON_ACTION
:
830 if (ImplReadPoly(rIStm
, aActionPoly
))
834 rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
) );
835 rMtf
.AddAction( new MetaLineColorAction( COL_TRANSPARENT
, false ) );
836 rMtf
.AddAction( new MetaPolygonAction( aActionPoly
) );
837 rMtf
.AddAction( new MetaPopAction() );
838 rMtf
.AddAction( new MetaPolyLineAction( aActionPoly
, aLineInfo
) );
842 nLastPolygonAction
= rMtf
.GetActionSize();
843 rMtf
.AddAction( new MetaPolygonAction( aActionPoly
) );
849 case GDI_POLYPOLYGON_ACTION
:
851 tools::PolyPolygon aPolyPoly
;
853 if (ImplReadPolyPoly(rIStm
, aPolyPoly
))
857 rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
) );
858 rMtf
.AddAction( new MetaLineColorAction( COL_TRANSPARENT
, false ) );
859 rMtf
.AddAction( new MetaPolyPolygonAction( aPolyPoly
) );
860 rMtf
.AddAction( new MetaPopAction() );
862 for( sal_uInt16 nPoly
= 0, nCount
= aPolyPoly
.Count(); nPoly
< nCount
; nPoly
++ )
863 rMtf
.AddAction( new MetaPolyLineAction( aPolyPoly
[ nPoly
], aLineInfo
) );
867 nLastPolygonAction
= rMtf
.GetActionSize();
868 rMtf
.AddAction( new MetaPolyPolygonAction( aPolyPoly
) );
874 case GDI_FONT_ACTION
:
877 char aName
[LF_FACESIZE
+1];
879 ImplReadColor( rIStm
, aActionColor
); aFont
.SetColor( aActionColor
);
880 ImplReadColor( rIStm
, aActionColor
); aFont
.SetFillColor( aActionColor
);
881 size_t nRet
= rIStm
.ReadBytes(aName
, LF_FACESIZE
);
883 aFont
.SetFamilyName( OUString( aName
, strlen(aName
), rIStm
.GetStreamCharSet() ) );
885 sal_Int32
nWidth(0), nHeight(0);
886 rIStm
.ReadInt32(nWidth
).ReadInt32(nHeight
);
887 sal_Int16
nCharOrient(0), nLineOrient(0);
888 rIStm
.ReadInt16(nCharOrient
).ReadInt16(nLineOrient
);
889 sal_Int16
nCharSet(0), nFamily(0), nPitch(0), nAlign(0), nWeight(0), nUnderline(0), nStrikeout(0);
890 rIStm
.ReadInt16(nCharSet
).ReadInt16(nFamily
).ReadInt16(nPitch
).ReadInt16(nAlign
).ReadInt16(nWeight
).ReadInt16(nUnderline
).ReadInt16(nStrikeout
);
891 bool bItalic(false), bOutline(false), bShadow(false), bTransparent(false);
892 rIStm
.ReadCharAsBool(bItalic
).ReadCharAsBool(bOutline
).ReadCharAsBool(bShadow
).ReadCharAsBool(bTransparent
);
894 aFont
.SetFontSize( Size( nWidth
, nHeight
) );
895 aFont
.SetCharSet( (rtl_TextEncoding
) nCharSet
);
896 aFont
.SetFamily( (FontFamily
) nFamily
);
897 aFont
.SetPitch( (FontPitch
) nPitch
);
898 aFont
.SetAlignment( (FontAlign
) nAlign
);
899 aFont
.SetWeight( ( nWeight
== 1 ) ? WEIGHT_LIGHT
: ( nWeight
== 2 ) ? WEIGHT_NORMAL
:
900 ( nWeight
== 3 ) ? WEIGHT_BOLD
: WEIGHT_DONTKNOW
);
901 aFont
.SetUnderline( (FontLineStyle
) nUnderline
);
902 aFont
.SetStrikeout( (FontStrikeout
) nStrikeout
);
903 aFont
.SetItalic( bItalic
? ITALIC_NORMAL
: ITALIC_NONE
);
904 aFont
.SetOutline( bOutline
);
905 aFont
.SetShadow( bShadow
);
906 aFont
.SetOrientation( nLineOrient
);
907 aFont
.SetTransparent( bTransparent
);
909 eActualCharSet
= aFont
.GetCharSet();
910 if ( eActualCharSet
== RTL_TEXTENCODING_DONTKNOW
)
911 eActualCharSet
= osl_getThreadTextEncoding();
913 rMtf
.AddAction( new MetaFontAction( aFont
) );
914 rMtf
.AddAction( new MetaTextAlignAction( aFont
.GetAlignment() ) );
915 rMtf
.AddAction( new MetaTextColorAction( aFont
.GetColor() ) );
916 rMtf
.AddAction( new MetaTextFillColorAction( aFont
.GetFillColor(), !aFont
.IsTransparent() ) );
918 // #106172# Track font relevant data in shadow VDev
919 aFontVDev
->SetFont( aFont
);
923 case GDI_TEXT_ACTION
:
925 sal_Int32
nIndex(0), nLen(0), nTmp(0);
927 ReadPair( rIStm
, aPt
).ReadInt32( nIndex
).ReadInt32( nLen
).ReadInt32( nTmp
);
930 OString aByteStr
= read_uInt8s_ToOString(rIStm
, nTmp
);
931 sal_uInt8 nTerminator
= 0;
932 rIStm
.ReadUChar( nTerminator
);
933 SAL_WARN_IF( nTerminator
!= 0, "vcl.gdi", "expected string to be NULL terminated" );
935 OUString
aStr(OStringToOUString(aByteStr
, eActualCharSet
));
936 if ( nUnicodeCommentActionNumber
== i
)
937 ImplReadUnicodeComment( nUnicodeCommentStreamPos
, rIStm
, aStr
);
938 rMtf
.AddAction( new MetaTextAction( aPt
, aStr
, nIndex
, nLen
) );
941 if (nActionSize
< 24)
942 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
944 rIStm
.Seek(nActBegin
+ nActionSize
);
948 case GDI_TEXTARRAY_ACTION
:
950 sal_Int32
nIndex(0), nLen(0), nAryLen(0), nTmp(0);
952 ReadPair( rIStm
, aPt
).ReadInt32( nIndex
).ReadInt32( nLen
).ReadInt32( nTmp
).ReadInt32( nAryLen
);
955 OString aByteStr
= read_uInt8s_ToOString(rIStm
, nTmp
);
956 sal_uInt8 nTerminator
= 0;
957 rIStm
.ReadUChar( nTerminator
);
958 SAL_WARN_IF( nTerminator
!= 0, "vcl.gdi", "expected string to be NULL terminated" );
960 OUString
aStr(OStringToOUString(aByteStr
, eActualCharSet
));
962 std::unique_ptr
<long[]> pDXAry
;
963 sal_Int32 nDXAryLen
= 0;
966 const size_t nMinRecordSize
= sizeof(sal_Int32
);
967 const size_t nMaxRecords
= rIStm
.remainingSize() / nMinRecordSize
;
968 if (static_cast<sal_uInt32
>(nAryLen
) > nMaxRecords
)
970 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords
<<
971 " max possible entries, but " << nAryLen
<< " claimed, truncating");
972 nAryLen
= nMaxRecords
;
975 sal_Int32
nStrLen( aStr
.getLength() );
977 nDXAryLen
= std::max(nAryLen
, nStrLen
);
979 if (nDXAryLen
< nLen
)
981 //MetaTextArrayAction ctor expects pDXAry to be >= nLen if set, so if this can't
982 //be achieved, don't read it, it's utterly broken.
983 SAL_WARN("vcl.gdi", "dxary too short, discarding completely");
984 rIStm
.SeekRel(sizeof(sal_Int32
) * nDXAryLen
);
990 pDXAry
.reset(new long[nDXAryLen
]);
992 for (sal_Int32 j
= 0; j
< nAryLen
; ++j
)
993 rIStm
.ReadInt32( nTmp
), pDXAry
[ j
] = nTmp
;
995 // #106172# Add last DX array elem, if missing
996 if( nAryLen
!= nStrLen
)
998 if (nAryLen
+1 == nStrLen
&& nIndex
>= 0)
1000 std::unique_ptr
<long[]> pTmpAry(new long[nStrLen
]);
1002 aFontVDev
->GetTextArray( aStr
, pTmpAry
.get(), nIndex
, nLen
);
1004 // now, the difference between the
1005 // last and the second last DX array
1006 // is the advancement for the last
1007 // glyph. Thus, to complete our meta
1008 // action's DX array, just add that
1009 // difference to last elem and store
1012 pDXAry
[ nStrLen
-1 ] = pDXAry
[ nStrLen
-2 ] + pTmpAry
[ nStrLen
-1 ] - pTmpAry
[ nStrLen
-2 ];
1014 pDXAry
[ nStrLen
-1 ] = pTmpAry
[ nStrLen
-1 ]; // len=1: 0th position taken to be 0
1018 OSL_FAIL("More than one DX array element missing on SVM import");
1023 if ( nUnicodeCommentActionNumber
== i
)
1024 ImplReadUnicodeComment( nUnicodeCommentStreamPos
, rIStm
, aStr
);
1025 rMtf
.AddAction( new MetaTextArrayAction( aPt
, aStr
, pDXAry
.get(), nIndex
, nLen
) );
1028 if (nActionSize
< 24)
1029 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
1031 rIStm
.Seek(nActBegin
+ nActionSize
);
1035 case GDI_STRETCHTEXT_ACTION
:
1037 sal_Int32
nIndex(0), nLen(0), nWidth(0), nTmp(0);
1039 ReadPair( rIStm
, aPt
).ReadInt32( nIndex
).ReadInt32( nLen
).ReadInt32( nTmp
).ReadInt32( nWidth
);
1042 OString aByteStr
= read_uInt8s_ToOString(rIStm
, nTmp
);
1043 sal_uInt8 nTerminator
= 0;
1044 rIStm
.ReadUChar( nTerminator
);
1045 SAL_WARN_IF( nTerminator
!= 0, "vcl.gdi", "expected string to be NULL terminated" );
1047 OUString
aStr(OStringToOUString(aByteStr
, eActualCharSet
));
1048 if ( nUnicodeCommentActionNumber
== i
)
1049 ImplReadUnicodeComment( nUnicodeCommentStreamPos
, rIStm
, aStr
);
1050 rMtf
.AddAction( new MetaStretchTextAction( aPt
, nWidth
, aStr
, nIndex
, nLen
) );
1053 if (nActionSize
< 28)
1054 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
1056 rIStm
.Seek(nActBegin
+ nActionSize
);
1060 case GDI_BITMAP_ACTION
:
1064 ReadPair( rIStm
, aPt
);
1065 ReadDIB(aBmp
, rIStm
, true);
1066 rMtf
.AddAction( new MetaBmpAction( aPt
, aBmp
) );
1070 case GDI_BITMAPSCALE_ACTION
:
1074 ReadPair( rIStm
, aPt
);
1075 ReadPair( rIStm
, aSz
);
1076 ReadDIB(aBmp
, rIStm
, true);
1077 rMtf
.AddAction( new MetaBmpScaleAction( aPt
, aSz
, aBmp
) );
1081 case GDI_BITMAPSCALEPART_ACTION
:
1086 ReadPair( rIStm
, aPt
);
1087 ReadPair( rIStm
, aSz
);
1088 ReadPair( rIStm
, aPt1
);
1089 ReadPair( rIStm
, aSz2
);
1090 ReadDIB(aBmp
, rIStm
, true);
1091 rMtf
.AddAction( new MetaBmpScalePartAction( aPt
, aSz
, aPt1
, aSz2
, aBmp
) );
1095 case GDI_PEN_ACTION
:
1097 sal_Int32 nPenWidth
;
1098 sal_Int16 nPenStyle
;
1100 ImplReadColor( rIStm
, aActionColor
);
1101 rIStm
.ReadInt32( nPenWidth
).ReadInt16( nPenStyle
);
1103 aLineInfo
.SetStyle( nPenStyle
? LineStyle::Solid
: LineStyle::NONE
);
1104 aLineInfo
.SetWidth( nPenWidth
);
1105 bFatLine
= nPenStyle
&& !aLineInfo
.IsDefault();
1107 rMtf
.AddAction( new MetaLineColorAction( aActionColor
, nPenStyle
!= 0 ) );
1111 case GDI_FILLBRUSH_ACTION
:
1113 sal_Int16 nBrushStyle
;
1115 ImplReadColor( rIStm
, aActionColor
);
1117 rIStm
.ReadInt16( nBrushStyle
);
1118 rMtf
.AddAction( new MetaFillColorAction( aActionColor
, nBrushStyle
!= 0 ) );
1123 case GDI_MAPMODE_ACTION
:
1125 if (ImplReadMapMode(rIStm
, aMapMode
))
1127 rMtf
.AddAction(new MetaMapModeAction(aMapMode
));
1129 // #106172# Track font relevant data in shadow VDev
1130 aFontVDev
->SetMapMode(aMapMode
);
1135 case GDI_CLIPREGION_ACTION
:
1137 vcl::Region aRegion
;
1139 sal_Int16 bIntersect
;
1142 rIStm
.ReadInt16( nRegType
).ReadInt16( bIntersect
);
1143 ImplReadRect( rIStm
, aRect
);
1152 tools::Rectangle aRegRect
;
1154 ImplReadRect( rIStm
, aRegRect
);
1155 aRegion
= vcl::Region( aRegRect
);
1162 if (ImplReadPoly(rIStm
, aActionPoly
))
1164 aRegion
= vcl::Region( aActionPoly
);
1172 bool bSuccess
= true;
1173 tools::PolyPolygon aPolyPoly
;
1174 sal_Int32
nPolyCount32(0);
1175 rIStm
.ReadInt32(nPolyCount32
);
1176 sal_uInt16
nPolyCount(nPolyCount32
);
1178 for (sal_uInt16 j
= 0; j
< nPolyCount
&& rIStm
.good(); ++j
)
1180 if (!ImplReadPoly(rIStm
, aActionPoly
))
1185 aPolyPoly
.Insert(aActionPoly
);
1190 aRegion
= vcl::Region( aPolyPoly
);
1198 aRegion
.Intersect( aRect
);
1200 rMtf
.AddAction( new MetaClipRegionAction( aRegion
, bClip
) );
1204 case GDI_MOVECLIPREGION_ACTION
:
1206 sal_Int32
nTmp(0), nTmp1(0);
1207 rIStm
.ReadInt32( nTmp
).ReadInt32( nTmp1
);
1208 rMtf
.AddAction( new MetaMoveClipRegionAction( nTmp
, nTmp1
) );
1212 case GDI_ISECTCLIPREGION_ACTION
:
1214 ImplReadRect( rIStm
, aRect
);
1215 rMtf
.AddAction( new MetaISectRectClipRegionAction( aRect
) );
1219 case GDI_RASTEROP_ACTION
:
1222 sal_Int16 nRasterOp
;
1224 rIStm
.ReadInt16( nRasterOp
);
1229 eRasterOp
= RasterOp::Invert
;
1234 eRasterOp
= RasterOp::Xor
;
1238 eRasterOp
= RasterOp::OverPaint
;
1242 rMtf
.AddAction( new MetaRasterOpAction( eRasterOp
) );
1246 case GDI_PUSH_ACTION
:
1248 aLIStack
.push(o3tl::make_unique
<LineInfo
>(aLineInfo
));
1249 rMtf
.AddAction( new MetaPushAction( PushFlags::ALL
) );
1251 // #106172# Track font relevant data in shadow VDev
1256 case GDI_POP_ACTION
:
1259 std::unique_ptr
<LineInfo
> xLineInfo
;
1260 if (!aLIStack
.empty())
1262 xLineInfo
= std::move(aLIStack
.top());
1266 // restore line info
1269 aLineInfo
= *xLineInfo
;
1271 bFatLine
= ( LineStyle::NONE
!= aLineInfo
.GetStyle() ) && !aLineInfo
.IsDefault();
1274 rMtf
.AddAction( new MetaPopAction() );
1276 // #106172# Track font relevant data in shadow VDev
1281 case GDI_GRADIENT_ACTION
:
1290 sal_Int16 nIntensityStart
;
1291 sal_Int16 nIntensityEnd
;
1293 ImplReadRect( rIStm
, aRect
);
1294 rIStm
.ReadInt16( nStyle
);
1295 ImplReadColor( rIStm
, aStartCol
);
1296 ImplReadColor( rIStm
, aEndCol
);
1297 rIStm
.ReadInt16( nAngle
).ReadInt16( nBorder
).ReadInt16( nOfsX
).ReadInt16( nOfsY
).ReadInt16( nIntensityStart
).ReadInt16( nIntensityEnd
);
1299 Gradient
aGrad( (GradientStyle
) nStyle
, aStartCol
, aEndCol
);
1301 aGrad
.SetAngle( nAngle
);
1302 aGrad
.SetBorder( nBorder
);
1303 aGrad
.SetOfsX( nOfsX
);
1304 aGrad
.SetOfsY( nOfsY
);
1305 aGrad
.SetStartIntensity( nIntensityStart
);
1306 aGrad
.SetEndIntensity( nIntensityEnd
);
1307 rMtf
.AddAction( new MetaGradientAction( aRect
, aGrad
) );
1311 case GDI_TRANSPARENT_COMMENT
:
1313 tools::PolyPolygon aPolyPoly
;
1314 sal_Int32
nFollowingActionCount(0);
1315 sal_Int16
nTrans(0);
1317 ReadPolyPolygon( rIStm
, aPolyPoly
);
1318 rIStm
.ReadInt16( nTrans
).ReadInt32( nFollowingActionCount
);
1319 ImplSkipActions( rIStm
, nFollowingActionCount
);
1320 rMtf
.AddAction( new MetaTransparentAction( aPolyPoly
, nTrans
) );
1322 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1326 case GDI_FLOATTRANSPARENT_COMMENT
:
1332 sal_Int32
nFollowingActionCount(0);
1334 ReadGDIMetaFile( rIStm
, aMtf
);
1335 ReadPair( rIStm
, aPos
);
1336 ReadPair( rIStm
, aSize
);
1337 ReadGradient( rIStm
, aGradient
);
1338 rIStm
.ReadInt32( nFollowingActionCount
);
1339 ImplSkipActions( rIStm
, nFollowingActionCount
);
1340 rMtf
.AddAction( new MetaFloatTransparentAction( aMtf
, aPos
, aSize
, aGradient
) );
1342 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1346 case GDI_HATCH_COMMENT
:
1348 tools::PolyPolygon aPolyPoly
;
1350 sal_Int32
nFollowingActionCount(0);
1352 ReadPolyPolygon( rIStm
, aPolyPoly
);
1353 ReadHatch( rIStm
, aHatch
);
1354 rIStm
.ReadInt32( nFollowingActionCount
);
1355 ImplSkipActions( rIStm
, nFollowingActionCount
);
1356 rMtf
.AddAction( new MetaHatchAction( aPolyPoly
, aHatch
) );
1358 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1362 case GDI_REFPOINT_COMMENT
:
1366 sal_Int32
nFollowingActionCount(0);
1368 ReadPair( rIStm
, aRefPoint
);
1369 rIStm
.ReadCharAsBool( bSet
).ReadInt32( nFollowingActionCount
);
1370 ImplSkipActions( rIStm
, nFollowingActionCount
);
1371 rMtf
.AddAction( new MetaRefPointAction( aRefPoint
, bSet
) );
1373 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1375 // #106172# Track font relevant data in shadow VDev
1377 aFontVDev
->SetRefPoint( aRefPoint
);
1379 aFontVDev
->SetRefPoint();
1383 case GDI_TEXTLINECOLOR_COMMENT
:
1387 sal_Int32
nFollowingActionCount(0);
1389 ReadColor( rIStm
, aColor
);
1390 rIStm
.ReadCharAsBool( bSet
).ReadInt32( nFollowingActionCount
);
1391 ImplSkipActions( rIStm
, nFollowingActionCount
);
1392 rMtf
.AddAction( new MetaTextLineColorAction( aColor
, bSet
) );
1394 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1398 case GDI_TEXTLINE_COMMENT
:
1401 sal_Int32
nWidth(0);
1402 sal_uInt32
nStrikeout(0);
1403 sal_uInt32
nUnderline(0);
1404 sal_Int32
nFollowingActionCount(0);
1406 ReadPair( rIStm
, aStartPt
);
1407 rIStm
.ReadInt32(nWidth
).ReadUInt32(nStrikeout
).ReadUInt32(nUnderline
).ReadInt32(nFollowingActionCount
);
1408 ImplSkipActions(rIStm
, nFollowingActionCount
);
1409 rMtf
.AddAction( new MetaTextLineAction( aStartPt
, nWidth
,
1410 (FontStrikeout
) nStrikeout
,
1411 (FontLineStyle
) nUnderline
,
1414 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1418 case GDI_GRADIENTEX_COMMENT
:
1420 tools::PolyPolygon aPolyPoly
;
1422 sal_Int32
nFollowingActionCount(0);
1424 ReadPolyPolygon( rIStm
, aPolyPoly
);
1425 ReadGradient( rIStm
, aGradient
);
1426 rIStm
.ReadInt32( nFollowingActionCount
);
1427 ImplSkipActions( rIStm
, nFollowingActionCount
);
1428 rMtf
.AddAction( new MetaGradientExAction( aPolyPoly
, aGradient
) );
1430 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1434 case GDI_COMMENT_COMMENT
:
1436 std::vector
<sal_uInt8
> aData
;
1438 OString aComment
= read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm
);
1439 sal_Int32
nValue(0);
1440 sal_uInt32
nDataSize(0);
1441 rIStm
.ReadInt32(nValue
).ReadUInt32(nDataSize
);
1445 const size_t nMaxPossibleData
= rIStm
.remainingSize();
1446 if (nDataSize
> nMaxPossibleActions
)
1448 SAL_WARN("vcl.gdi", "svm record claims to have: " << nDataSize
<< " data, but only " << nMaxPossibleData
<< " possible");
1449 nDataSize
= nMaxPossibleActions
;
1451 aData
.resize(nDataSize
);
1452 nDataSize
= rIStm
.ReadBytes(aData
.data(), nDataSize
);
1455 sal_Int32
nFollowingActionCount(0);
1456 rIStm
.ReadInt32(nFollowingActionCount
);
1457 ImplSkipActions( rIStm
, nFollowingActionCount
);
1458 rMtf
.AddAction(new MetaCommentAction(aComment
, nValue
, aData
.data(), nDataSize
));
1460 i
= SkipActions(i
, nFollowingActionCount
, nActions
);
1464 case GDI_UNICODE_COMMENT
:
1466 nUnicodeCommentActionNumber
= i
+ 1;
1467 nUnicodeCommentStreamPos
= rIStm
.Tell() - 6;
1468 if (nActionSize
< 4)
1469 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
1471 rIStm
.SeekRel(nActionSize
- 4);
1476 if (nActionSize
< 4)
1477 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
1479 rIStm
.SeekRel(nActionSize
- 4);
1484 rIStm
.SetEndian( nOldFormat
);
1487 void SVMConverter::ImplConvertToSVM1( SvStream
& rOStm
, GDIMetaFile
& rMtf
)
1489 sal_uLong nCountPos
;
1490 vcl::Font aSaveFont
;
1491 const SvStreamEndian nOldFormat
= rOStm
.GetEndian();
1492 rtl_TextEncoding eActualCharSet
= osl_getThreadTextEncoding();
1493 const Size
aPrefSize( rMtf
.GetPrefSize() );
1494 bool bRop_0_1
= false;
1495 ScopedVclPtrInstance
< VirtualDevice
> aSaveVDev
;
1496 Color
aLineCol( COL_BLACK
);
1497 ::std::stack
< Color
* > aLineColStack
;
1499 rOStm
.SetEndian( SvStreamEndian::LITTLE
);
1502 rOStm
.WriteCharPtr( "SVGDI" ); // Identifier
1503 rOStm
.WriteInt16( 42 ); // HeaderSize
1504 rOStm
.WriteInt16( 200 ); // VERSION
1505 rOStm
.WriteInt32( aPrefSize
.Width() );
1506 rOStm
.WriteInt32( aPrefSize
.Height() );
1507 ImplWriteMapMode( rOStm
, rMtf
.GetPrefMapMode() );
1509 // ActionCount will be written later
1510 nCountPos
= rOStm
.Tell();
1513 const sal_Int32 nActCount
= ImplWriteActions( rOStm
, rMtf
, *aSaveVDev
.get(), bRop_0_1
, aLineCol
, aLineColStack
, eActualCharSet
);
1514 const sal_uLong nActPos
= rOStm
.Tell();
1516 rOStm
.Seek( nCountPos
);
1517 rOStm
.WriteInt32( nActCount
);
1518 rOStm
.Seek( nActPos
);
1519 rOStm
.SetEndian( nOldFormat
);
1521 // cleanup push-pop stack if necessary
1522 while ( !aLineColStack
.empty() )
1524 delete aLineColStack
.top();
1525 aLineColStack
.pop();
1529 sal_uLong
SVMConverter::ImplWriteActions( SvStream
& rOStm
, GDIMetaFile
& rMtf
,
1530 VirtualDevice
& rSaveVDev
, bool& rRop_0_1
,
1531 Color
& rLineCol
, ::std::stack
< Color
* >& rLineColStack
,
1532 rtl_TextEncoding
& rActualCharSet
)
1534 sal_uLong nCount
= 0;
1535 for( size_t i
= 0, nActionCount
= rMtf
.GetActionSize(); i
< nActionCount
; i
++ )
1537 const MetaAction
* pAction
= rMtf
.GetAction( i
);
1539 switch( pAction
->GetType() )
1541 case MetaActionType::PIXEL
:
1543 const MetaPixelAction
* pAct
= static_cast<const MetaPixelAction
*>(pAction
);
1545 rOStm
.WriteInt16( GDI_PIXEL_ACTION
);
1546 rOStm
.WriteInt32( 18 );
1547 WritePair( rOStm
, pAct
->GetPoint() );
1548 ImplWriteColor( rOStm
, pAct
->GetColor() );
1553 case MetaActionType::POINT
:
1555 const MetaPointAction
* pAct
= static_cast<const MetaPointAction
*>(pAction
);
1557 rOStm
.WriteInt16( GDI_POINT_ACTION
);
1558 rOStm
.WriteInt32( 12 );
1559 WritePair( rOStm
, pAct
->GetPoint() );
1564 case MetaActionType::LINE
:
1566 const MetaLineAction
* pAct
= static_cast<const MetaLineAction
*>(pAction
);
1567 const LineInfo
& rInfo
= pAct
->GetLineInfo();
1568 const bool bFatLine(!rInfo
.IsDefault() && (LineStyle::NONE
!= rInfo
.GetStyle()));
1569 const bool bLineJoin(bFatLine
&& basegfx::B2DLineJoin::Round
!= rInfo
.GetLineJoin());
1570 const bool bLineCap(bFatLine
&& css::drawing::LineCap_BUTT
!= rInfo
.GetLineCap());
1571 const bool bLineDashDot(LineStyle::Dash
== rInfo
.GetStyle());
1575 ImplWritePushAction( rOStm
);
1576 ImplWriteLineColor( rOStm
, rLineCol
, 1, rInfo
.GetWidth() );
1580 rOStm
.WriteInt16( GDI_LINEJOIN_ACTION
);
1581 rOStm
.WriteInt32( 6 );
1582 rOStm
.WriteInt16( static_cast<sal_Int16
>(rInfo
.GetLineJoin()) );
1587 rOStm
.WriteInt16( GDI_LINECAP_ACTION
);
1588 rOStm
.WriteInt32( 6 );
1589 rOStm
.WriteInt16( (sal_Int16
)rInfo
.GetLineCap() );
1595 rOStm
.WriteInt16( GDI_LINEDASHDOT_ACTION
);
1596 rOStm
.WriteInt32( 4 + 16 );
1597 rOStm
.WriteInt16( rInfo
.GetDashCount() );
1598 rOStm
.WriteInt32( rInfo
.GetDashLen() );
1599 rOStm
.WriteInt16( rInfo
.GetDotCount() );
1600 rOStm
.WriteInt32( rInfo
.GetDotLen() );
1601 rOStm
.WriteInt32( rInfo
.GetDistance() );
1604 rOStm
.WriteInt16( GDI_LINE_ACTION
);
1605 rOStm
.WriteInt32( 20 );
1606 WritePair( rOStm
, pAct
->GetStartPoint() );
1607 WritePair( rOStm
, pAct
->GetEndPoint() );
1612 ImplWritePopAction( rOStm
);
1633 case MetaActionType::RECT
:
1635 const MetaRectAction
* pAct
= static_cast<const MetaRectAction
*>(pAction
);
1637 rOStm
.WriteInt16( GDI_RECT_ACTION
);
1638 rOStm
.WriteInt32( 28 );
1639 ImplWriteRect( rOStm
, pAct
->GetRect() );
1640 rOStm
.WriteInt32( 0 );
1641 rOStm
.WriteInt32( 0 );
1646 case MetaActionType::ROUNDRECT
:
1648 const MetaRoundRectAction
* pAct
= static_cast<const MetaRoundRectAction
*>(pAction
);
1650 rOStm
.WriteInt16( GDI_RECT_ACTION
);
1651 rOStm
.WriteInt32( 28 );
1652 ImplWriteRect( rOStm
, pAct
->GetRect() );
1653 rOStm
.WriteInt32( pAct
->GetHorzRound() );
1654 rOStm
.WriteInt32( pAct
->GetVertRound() );
1659 case MetaActionType::ELLIPSE
:
1661 const MetaEllipseAction
* pAct
= static_cast<const MetaEllipseAction
*>(pAction
);
1663 rOStm
.WriteInt16( GDI_ELLIPSE_ACTION
);
1664 rOStm
.WriteInt32( 20 );
1665 ImplWriteRect( rOStm
, pAct
->GetRect() );
1670 case MetaActionType::ARC
:
1672 const MetaArcAction
* pAct
= static_cast<const MetaArcAction
*>(pAction
);
1674 rOStm
.WriteInt16( GDI_ARC_ACTION
);
1675 rOStm
.WriteInt32( 36 );
1676 ImplWriteRect( rOStm
, pAct
->GetRect() );
1677 WritePair( rOStm
, pAct
->GetStartPoint() );
1678 WritePair( rOStm
, pAct
->GetEndPoint() );
1683 case MetaActionType::PIE
:
1685 const MetaPieAction
* pAct
= static_cast<const MetaPieAction
*>(pAction
);
1687 rOStm
.WriteInt16( GDI_PIE_ACTION
);
1688 rOStm
.WriteInt32( 36 );
1689 ImplWriteRect( rOStm
, pAct
->GetRect() );
1690 WritePair( rOStm
, pAct
->GetStartPoint() );
1691 WritePair( rOStm
, pAct
->GetEndPoint() );
1696 case MetaActionType::CHORD
:
1698 const MetaChordAction
* pAct
= static_cast<const MetaChordAction
*>(pAction
);
1699 tools::Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(),
1700 pAct
->GetEndPoint(), PolyStyle::Chord
);
1701 const sal_uInt16 nPoints
= aChordPoly
.GetSize();
1703 rOStm
.WriteInt16( GDI_POLYGON_ACTION
);
1704 rOStm
.WriteInt32( 8 + ( nPoints
<< 3 ) );
1705 rOStm
.WriteInt32( nPoints
);
1707 for( sal_uInt16 n
= 0; n
< nPoints
; n
++ )
1708 WritePair( rOStm
, aChordPoly
[ n
] );
1713 case MetaActionType::POLYLINE
:
1716 const MetaPolyLineAction
* pAct
= static_cast<const MetaPolyLineAction
*>(pAction
);
1717 // #i102224# Here the possible curved nature of Polygon was
1718 // ignored (for all those years). Adapted to at least write
1719 // a polygon representing the curve as good as possible
1720 tools::Polygon aSimplePoly
;
1721 pAct
->GetPolygon().AdaptiveSubdivide(aSimplePoly
);
1722 const LineInfo
& rInfo
= pAct
->GetLineInfo();
1723 const sal_uInt16
nPoints(aSimplePoly
.GetSize());
1724 const bool bFatLine(!rInfo
.IsDefault() && (LineStyle::NONE
!= rInfo
.GetStyle()));
1725 const bool bLineJoin(bFatLine
&& basegfx::B2DLineJoin::Round
!= rInfo
.GetLineJoin());
1726 const bool bLineCap(bFatLine
&& css::drawing::LineCap_BUTT
!= rInfo
.GetLineCap());
1727 const bool bLineDashDot(LineStyle::Dash
== rInfo
.GetStyle());
1731 ImplWritePushAction( rOStm
);
1732 ImplWriteLineColor( rOStm
, rLineCol
, 1, rInfo
.GetWidth() );
1736 rOStm
.WriteInt16( GDI_LINEJOIN_ACTION
);
1737 rOStm
.WriteInt32( 6 );
1738 rOStm
.WriteInt16( static_cast<sal_Int16
>(rInfo
.GetLineJoin()) );
1743 rOStm
.WriteInt16( GDI_LINECAP_ACTION
);
1744 rOStm
.WriteInt32( 6 );
1745 rOStm
.WriteInt16( (sal_Int16
)rInfo
.GetLineCap() );
1751 rOStm
.WriteInt16( GDI_LINEDASHDOT_ACTION
);
1752 rOStm
.WriteInt32( 4 + 16 );
1753 rOStm
.WriteInt16( rInfo
.GetDashCount() );
1754 rOStm
.WriteInt32( rInfo
.GetDashLen() );
1755 rOStm
.WriteInt16( rInfo
.GetDotCount() );
1756 rOStm
.WriteInt32( rInfo
.GetDotLen() );
1757 rOStm
.WriteInt32( rInfo
.GetDistance() );
1760 rOStm
.WriteInt16( GDI_POLYLINE_ACTION
);
1761 rOStm
.WriteInt32( 8 + ( nPoints
<< 3 ) );
1762 rOStm
.WriteInt32( nPoints
);
1764 for( sal_uInt16 n
= 0; n
< nPoints
; n
++ )
1766 WritePair( rOStm
, aSimplePoly
[ n
] );
1771 const tools::PolyPolygon
aPolyPolygon(pAct
->GetPolygon());
1772 if(ImplWriteExtendedPolyPolygonAction(rOStm
, aPolyPolygon
, true))
1779 ImplWritePopAction( rOStm
);
1800 case MetaActionType::POLYGON
:
1802 const MetaPolygonAction
* pAct
= static_cast<const MetaPolygonAction
*>(pAction
);
1803 // #i102224# Here the possible curved nature of Polygon was
1804 // ignored (for all those years). Adapted to at least write
1805 // a polygon representing the curve as good as possible
1806 tools::Polygon aSimplePoly
;
1807 pAct
->GetPolygon().AdaptiveSubdivide(aSimplePoly
);
1808 const sal_uInt16
nPoints(aSimplePoly
.GetSize());
1810 rOStm
.WriteInt16( GDI_POLYGON_ACTION
);
1811 rOStm
.WriteInt32( 8 + ( nPoints
<< 3 ) );
1812 rOStm
.WriteInt32( nPoints
);
1814 for( sal_uInt16 n
= 0; n
< nPoints
; n
++ )
1815 WritePair( rOStm
, aSimplePoly
[ n
] );
1819 const tools::PolyPolygon
aPolyPolygon(pAct
->GetPolygon());
1820 if(ImplWriteExtendedPolyPolygonAction(rOStm
, aPolyPolygon
, true))
1827 case MetaActionType::POLYPOLYGON
:
1829 const MetaPolyPolygonAction
* pAct
= static_cast<const MetaPolyPolygonAction
*>(pAction
);
1830 ImplWritePolyPolyAction( rOStm
, pAct
->GetPolyPolygon() );
1833 if(ImplWriteExtendedPolyPolygonAction(rOStm
, pAct
->GetPolyPolygon(), true))
1840 case MetaActionType::TEXT
:
1842 const MetaTextAction
* pAct
= static_cast<const MetaTextAction
*>(pAction
);
1843 OUString
aUniText( pAct
->GetText() );
1844 OString
aText(OUStringToOString(aUniText
, rActualCharSet
));
1845 const sal_Int32 nStrLen
= aText
.getLength();
1847 if ( ImplWriteUnicodeComment( rOStm
, aUniText
) )
1850 rOStm
.WriteInt16( GDI_TEXT_ACTION
);
1851 rOStm
.WriteInt32( 24 + ( nStrLen
+ 1 ) );
1852 WritePair( rOStm
, pAct
->GetPoint() );
1853 rOStm
.WriteInt32( pAct
->GetIndex() );
1854 rOStm
.WriteInt32( pAct
->GetLen() );
1855 rOStm
.WriteInt32( nStrLen
);
1856 rOStm
.WriteBytes( aText
.getStr(), nStrLen
+ 1 );
1861 case MetaActionType::TEXTARRAY
:
1863 const MetaTextArrayAction
* pAct
= static_cast<const MetaTextArrayAction
*>(pAction
);
1864 OString
aText(OUStringToOString(pAct
->GetText(), rActualCharSet
));
1865 OUString aUniText
= pAct
->GetText().copy(
1867 std::min
<sal_Int32
>(pAct
->GetText().getLength() - pAct
->GetIndex(), pAct
->GetLen()) );
1869 sal_Int32 nLen
= pAct
->GetLen();
1870 const sal_Int32 nTextLen
= aText
.getLength();
1871 long* pDXArray
= pAct
->GetDXArray();
1873 if ( ImplWriteUnicodeComment( rOStm
, aUniText
) )
1876 if( ( nLen
+ pAct
->GetIndex() ) > nTextLen
)
1878 if( pAct
->GetIndex() <= nTextLen
)
1879 nLen
= nTextLen
- pAct
->GetIndex();
1884 if( !pDXArray
|| !nLen
)
1887 nAryLen
= nLen
; // #105987# Write out all of DX array
1889 rOStm
.WriteInt16( GDI_TEXTARRAY_ACTION
);
1890 rOStm
.WriteInt32( 28 + ( nLen
+ 1 ) + ( nAryLen
* 4 ) );
1891 WritePair( rOStm
, pAct
->GetPoint() );
1892 rOStm
.WriteInt32( 0 );
1893 rOStm
.WriteInt32( nLen
);
1894 rOStm
.WriteInt32( nLen
);
1895 rOStm
.WriteInt32( nAryLen
);
1896 rOStm
.WriteBytes( aText
.getStr()+pAct
->GetIndex(), nLen
+ 1 );
1898 for (sal_Int32 n
= 0; n
< nAryLen
; ++n
)
1899 rOStm
.WriteInt32( pDXArray
[ n
] );
1905 case MetaActionType::STRETCHTEXT
:
1907 const MetaStretchTextAction
* pAct
= static_cast<const MetaStretchTextAction
*>(pAction
);
1908 OUString
aUniText( pAct
->GetText() );
1909 OString
aText(OUStringToOString(aUniText
, rActualCharSet
));
1910 const sal_Int32 nStrLen
= aText
.getLength();
1912 if ( ImplWriteUnicodeComment( rOStm
, aUniText
) )
1915 rOStm
.WriteInt16( GDI_STRETCHTEXT_ACTION
);
1916 rOStm
.WriteInt32( 28 + ( nStrLen
+ 1 ) );
1917 WritePair( rOStm
, pAct
->GetPoint() );
1918 rOStm
.WriteInt32( pAct
->GetIndex() );
1919 rOStm
.WriteInt32( pAct
->GetLen() );
1920 rOStm
.WriteInt32( nStrLen
);
1921 rOStm
.WriteInt32( pAct
->GetWidth() );
1922 rOStm
.WriteBytes( aText
.getStr(), nStrLen
+ 1 );
1927 case MetaActionType::BMP
:
1929 const MetaBmpAction
* pAct
= static_cast<const MetaBmpAction
*>(pAction
);
1931 rOStm
.WriteInt16( GDI_BITMAP_ACTION
);
1932 rOStm
.WriteInt32( 12 );
1933 WritePair( rOStm
, pAct
->GetPoint() );
1934 WriteDIB(pAct
->GetBitmap(), rOStm
, false, true);
1939 case MetaActionType::BMPSCALE
:
1941 const MetaBmpScaleAction
* pAct
= static_cast<const MetaBmpScaleAction
*>(pAction
);
1943 rOStm
.WriteInt16( GDI_BITMAPSCALE_ACTION
);
1944 rOStm
.WriteInt32( 20 );
1945 WritePair( rOStm
, pAct
->GetPoint() );
1946 WritePair( rOStm
, pAct
->GetSize() );
1947 WriteDIB(pAct
->GetBitmap(), rOStm
, false, true);
1952 case MetaActionType::BMPSCALEPART
:
1954 const MetaBmpScalePartAction
* pAct
= static_cast<const MetaBmpScalePartAction
*>(pAction
);
1956 rOStm
.WriteInt16( GDI_BITMAPSCALEPART_ACTION
);
1957 rOStm
.WriteInt32( 36 );
1958 WritePair( rOStm
, pAct
->GetDestPoint() );
1959 WritePair( rOStm
, pAct
->GetDestSize() );
1960 WritePair( rOStm
, pAct
->GetSrcPoint() );
1961 WritePair( rOStm
, pAct
->GetSrcSize() );
1962 WriteDIB(pAct
->GetBitmap(), rOStm
, false, true);
1967 case MetaActionType::BMPEX
:
1969 const MetaBmpExAction
* pAct
= static_cast<const MetaBmpExAction
*>(pAction
);
1970 const Bitmap
aBmp( Graphic( pAct
->GetBitmapEx() ).GetBitmap() );
1972 rOStm
.WriteInt16( GDI_BITMAP_ACTION
);
1973 rOStm
.WriteInt32( 12 );
1974 WritePair( rOStm
, pAct
->GetPoint() );
1975 WriteDIB(aBmp
, rOStm
, false, true);
1980 case MetaActionType::BMPEXSCALE
:
1982 const MetaBmpExScaleAction
* pAct
= static_cast<const MetaBmpExScaleAction
*>(pAction
);
1983 const Bitmap
aBmp( Graphic( pAct
->GetBitmapEx() ).GetBitmap() );
1985 rOStm
.WriteInt16( GDI_BITMAPSCALE_ACTION
);
1986 rOStm
.WriteInt32( 20 );
1987 WritePair( rOStm
, pAct
->GetPoint() );
1988 WritePair( rOStm
, pAct
->GetSize() );
1989 WriteDIB(aBmp
, rOStm
, false, true);
1994 case MetaActionType::BMPEXSCALEPART
:
1996 const MetaBmpExScalePartAction
* pAct
= static_cast<const MetaBmpExScalePartAction
*>(pAction
);
1997 const Bitmap
aBmp( Graphic( pAct
->GetBitmapEx() ).GetBitmap() );
1999 rOStm
.WriteInt16( GDI_BITMAPSCALEPART_ACTION
);
2000 rOStm
.WriteInt32( 36 );
2001 WritePair( rOStm
, pAct
->GetDestPoint() );
2002 WritePair( rOStm
, pAct
->GetDestSize() );
2003 WritePair( rOStm
, pAct
->GetSrcPoint() );
2004 WritePair( rOStm
, pAct
->GetSrcSize() );
2005 WriteDIB(aBmp
, rOStm
, false, true);
2010 case MetaActionType::GRADIENT
:
2012 const MetaGradientAction
* pAct
= static_cast<const MetaGradientAction
*>(pAction
);
2013 const Gradient
& rGrad
= pAct
->GetGradient();
2015 rOStm
.WriteInt16( GDI_GRADIENT_ACTION
);
2016 rOStm
.WriteInt32( 46 );
2017 ImplWriteRect( rOStm
, pAct
->GetRect() );
2018 rOStm
.WriteInt16( (sal_Int16
)rGrad
.GetStyle() );
2019 ImplWriteColor( rOStm
, rGrad
.GetStartColor() );
2020 ImplWriteColor( rOStm
, rGrad
.GetEndColor() );
2021 rOStm
.WriteInt16( rGrad
.GetAngle() );
2022 rOStm
.WriteInt16( rGrad
.GetBorder() );
2023 rOStm
.WriteInt16( rGrad
.GetOfsX() );
2024 rOStm
.WriteInt16( rGrad
.GetOfsY() );
2025 rOStm
.WriteInt16( rGrad
.GetStartIntensity() );
2026 rOStm
.WriteInt16( rGrad
.GetEndIntensity() );
2031 case MetaActionType::GRADIENTEX
:
2033 const MetaGradientExAction
* pA
= static_cast<const MetaGradientExAction
*>(pAction
);
2034 sal_uLong nOldPos
, nNewPos
;
2036 // write RefPoint comment
2037 rOStm
.WriteInt16( GDI_GRADIENTEX_COMMENT
);
2039 // we'll write the ActionSize later
2040 nOldPos
= rOStm
.Tell();
2044 WritePolyPolygon( rOStm
, pA
->GetPolyPolygon() );
2045 WriteGradient( rOStm
, pA
->GetGradient() );
2046 rOStm
.WriteInt32( 0 ); // number of actions that follow this comment
2048 // calculate and write ActionSize of comment
2049 nNewPos
= rOStm
.Tell();
2050 rOStm
.Seek( nOldPos
);
2051 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2052 rOStm
.Seek( nNewPos
);
2058 case MetaActionType::WALLPAPER
:
2060 const MetaWallpaperAction
* pAct
= static_cast<const MetaWallpaperAction
*>(pAction
);
2061 const Color
& rColor
= pAct
->GetWallpaper().GetColor();
2063 ImplWritePushAction( rOStm
);
2064 ImplWriteLineColor( rOStm
, rColor
, 1 );
2065 ImplWriteFillColor( rOStm
, rColor
, 1 );
2067 rOStm
.WriteInt16( GDI_RECT_ACTION
);
2068 rOStm
.WriteInt32( 28 );
2069 ImplWriteRect( rOStm
, pAct
->GetRect() );
2070 rOStm
.WriteInt32( 0 );
2071 rOStm
.WriteInt32( 0 );
2073 ImplWritePopAction( rOStm
);
2078 case MetaActionType::CLIPREGION
:
2080 const MetaClipRegionAction
* pAct
= static_cast<const MetaClipRegionAction
*>(pAction
);
2081 const vcl::Region
& rRegion
= pAct
->GetRegion();
2082 tools::Rectangle aClipRect
;
2084 rOStm
.WriteInt16( GDI_CLIPREGION_ACTION
);
2085 rOStm
.WriteInt32( 24 );
2087 if( pAct
->IsClipping() )
2089 aClipRect
= rRegion
.GetBoundRect();
2090 rOStm
.WriteInt16( 1 );
2093 rOStm
.WriteInt16( 0 );
2095 rOStm
.WriteInt16( 0 );
2096 ImplWriteRect( rOStm
, aClipRect
);
2098 if( pAct
->IsClipping() )
2099 ImplWriteRect( rOStm
, aClipRect
);
2105 case MetaActionType::ISECTRECTCLIPREGION
:
2107 const MetaISectRectClipRegionAction
* pAct
= static_cast<const MetaISectRectClipRegionAction
*>(pAction
);
2109 rOStm
.WriteInt16( GDI_ISECTCLIPREGION_ACTION
);
2110 rOStm
.WriteInt32( 20 );
2111 WriteRectangle( rOStm
, pAct
->GetRect() );
2116 case MetaActionType::MOVECLIPREGION
:
2118 const MetaMoveClipRegionAction
* pAct
= static_cast<const MetaMoveClipRegionAction
*>(pAction
);
2120 rOStm
.WriteInt16( GDI_MOVECLIPREGION_ACTION
);
2121 rOStm
.WriteInt32( 12 );
2122 rOStm
.WriteInt32( pAct
->GetHorzMove() );
2123 rOStm
.WriteInt32( pAct
->GetVertMove() );
2128 case MetaActionType::LINECOLOR
:
2130 const MetaLineColorAction
* pAct
= static_cast<const MetaLineColorAction
*>(pAction
);
2131 ImplWriteLineColor( rOStm
, rLineCol
= pAct
->GetColor(), pAct
->IsSetting() ? 1 : 0 );
2136 case MetaActionType::FILLCOLOR
:
2138 const MetaFillColorAction
* pAct
= static_cast<const MetaFillColorAction
*>(pAction
);
2139 ImplWriteFillColor( rOStm
, pAct
->GetColor(), pAct
->IsSetting() ? 1 : 0 );
2144 case MetaActionType::FONT
:
2146 rSaveVDev
.SetFont( static_cast<const MetaFontAction
*>(pAction
)->GetFont() );
2147 ImplWriteFont( rOStm
, rSaveVDev
.GetFont(), rActualCharSet
);
2152 case MetaActionType::TEXTCOLOR
:
2154 vcl::Font
aSaveFont( rSaveVDev
.GetFont() );
2156 aSaveFont
.SetColor( static_cast<const MetaTextColorAction
*>(pAction
)->GetColor() );
2157 rSaveVDev
.SetFont( aSaveFont
);
2158 ImplWriteFont( rOStm
, rSaveVDev
.GetFont(), rActualCharSet
);
2163 case MetaActionType::TEXTFILLCOLOR
:
2165 const MetaTextFillColorAction
* pAct
= static_cast<const MetaTextFillColorAction
*>(pAction
);
2166 vcl::Font
aSaveFont( rSaveVDev
.GetFont() );
2168 if( pAct
->IsSetting() )
2169 aSaveFont
.SetFillColor( pAct
->GetColor() );
2171 aSaveFont
.SetFillColor( Color( COL_TRANSPARENT
) );
2173 rSaveVDev
.SetFont( aSaveFont
);
2174 ImplWriteFont( rOStm
, rSaveVDev
.GetFont(), rActualCharSet
);
2179 case MetaActionType::TEXTALIGN
:
2181 vcl::Font
aSaveFont( rSaveVDev
.GetFont() );
2183 aSaveFont
.SetAlignment( static_cast<const MetaTextAlignAction
*>(pAction
)->GetTextAlign() );
2184 rSaveVDev
.SetFont( aSaveFont
);
2185 ImplWriteFont( rOStm
, rSaveVDev
.GetFont(), rActualCharSet
);
2190 case MetaActionType::MAPMODE
:
2192 const MetaMapModeAction
* pAct
= static_cast<const MetaMapModeAction
*>(pAction
);
2194 rOStm
.WriteInt16( GDI_MAPMODE_ACTION
);
2195 rOStm
.WriteInt32( 30 );
2196 ImplWriteMapMode( rOStm
, pAct
->GetMapMode() );
2201 case MetaActionType::PUSH
:
2203 ImplWritePushAction( rOStm
);
2204 rLineColStack
.push( new Color( rLineCol
) );
2210 case MetaActionType::POP
:
2213 if (rLineColStack
.empty())
2217 pCol
= rLineColStack
.top();
2218 rLineColStack
.pop();
2227 ImplWritePopAction( rOStm
);
2233 case MetaActionType::RASTEROP
:
2235 const MetaRasterOpAction
* pAct
= static_cast<const MetaRasterOpAction
*>(pAction
);
2237 if( ( pAct
->GetRasterOp() != RasterOp::N0
) && ( pAct
->GetRasterOp() != RasterOp::N1
) )
2239 sal_Int16 nRasterOp
;
2241 // If RasterOp::N0/1 was set earlier, restore old state
2245 ImplWritePopAction( rOStm
);
2251 switch( pAct
->GetRasterOp() )
2253 case RasterOp::OverPaint
: nRasterOp
= 0; break;
2254 case RasterOp::Xor
: nRasterOp
= 4; break;
2255 case RasterOp::Invert
: nRasterOp
= 1; break;
2256 default: nRasterOp
= 0; break;
2259 ImplWriteRasterOpAction( rOStm
, nRasterOp
);
2264 ImplWritePushAction( rOStm
);
2267 if( pAct
->GetRasterOp() == RasterOp::N0
)
2269 ImplWriteLineColor( rOStm
, COL_BLACK
, 1 );
2270 ImplWriteFillColor( rOStm
, COL_BLACK
, 1 );
2274 ImplWriteLineColor( rOStm
, COL_WHITE
, 1 );
2275 ImplWriteFillColor( rOStm
, COL_WHITE
, 1 );
2278 ImplWriteRasterOpAction( rOStm
, 0 );
2285 case MetaActionType::Transparent
:
2287 const tools::PolyPolygon
& rPolyPoly
= static_cast<const MetaTransparentAction
*>(pAction
)->GetPolyPolygon();
2288 const sal_Int16 nTrans
= static_cast<const MetaTransparentAction
*>(pAction
)->GetTransparence();
2289 const sal_Int16 nBrushStyle
= ( nTrans
< 38 ) ? 8 : ( nTrans
< 63 ) ? 9 : 10;
2290 sal_uLong nOldPos
, nNewPos
;
2292 // write transparence comment
2293 rOStm
.WriteInt16( GDI_TRANSPARENT_COMMENT
);
2295 // we'll write the ActionSize later
2296 nOldPos
= rOStm
.Tell();
2299 // write comment data
2300 WritePolyPolygon( rOStm
, rPolyPoly
);
2301 rOStm
.WriteInt16( nTrans
);
2302 rOStm
.WriteInt32( 15 ); // number of actions that follow this comment
2304 // calculate and write ActionSize of comment
2305 nNewPos
= rOStm
.Tell();
2306 rOStm
.Seek( nOldPos
);
2307 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2308 rOStm
.Seek( nNewPos
);
2311 // write actions for transparence
2312 ImplWritePushAction( rOStm
);
2314 ImplWriteRasterOpAction( rOStm
, 4 );
2315 ImplWritePolyPolyAction( rOStm
, rPolyPoly
);
2317 ImplWritePushAction( rOStm
);
2319 ImplWriteRasterOpAction( rOStm
, 2 );
2320 ImplWriteFillColor( rOStm
, COL_BLACK
, nBrushStyle
);
2321 ImplWritePolyPolyAction( rOStm
, rPolyPoly
);
2323 ImplWritePopAction( rOStm
);
2325 ImplWriteRasterOpAction( rOStm
, 4 );
2326 ImplWritePolyPolyAction( rOStm
, rPolyPoly
);
2328 ImplWritePopAction( rOStm
);
2330 ImplWritePushAction( rOStm
);
2332 ImplWriteFillColor( rOStm
, Color(), 0 );
2333 ImplWritePolyPolyAction( rOStm
, rPolyPoly
);
2335 ImplWritePopAction( rOStm
);
2344 case MetaActionType::FLOATTRANSPARENT
:
2346 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pAction
);
2347 const GDIMetaFile
& rTransMtf
= pA
->GetGDIMetaFile();
2348 const Point
& rPos
= pA
->GetPoint();
2349 const Size
& rSize
= pA
->GetSize();
2350 const Gradient
& rGradient
= pA
->GetGradient();
2351 sal_uLong nOldPos
, nNewPos
;
2353 // write RefPoint comment
2354 rOStm
.WriteInt16( GDI_FLOATTRANSPARENT_COMMENT
);
2356 // we'll write the ActionSize later
2357 nOldPos
= rOStm
.Tell();
2360 // write comment data
2361 WriteGDIMetaFile( rOStm
, rTransMtf
);
2362 WritePair( rOStm
, rPos
);
2363 WritePair( rOStm
, rSize
);
2364 WriteGradient( rOStm
, rGradient
);
2366 // calculate and write ActionSize of comment
2367 nNewPos
= rOStm
.Tell();
2368 rOStm
.Seek( nOldPos
);
2369 rOStm
.WriteInt32( nNewPos
- nOldPos
+ 4 );
2370 rOStm
.Seek( ( nOldPos
= nNewPos
) + 4 );
2373 // write actions for float transparence
2374 sal_uLong nAddCount
;
2375 GDIMetaFile
aMtf( rTransMtf
);
2376 const Size
aSrcSize( rTransMtf
.GetPrefSize() );
2377 Point
aSrcPt( rTransMtf
.GetPrefMapMode().GetOrigin() );
2378 const double fScaleX
= aSrcSize
.Width() ? (double) rSize
.Width() / aSrcSize
.Width() : 1.0;
2379 const double fScaleY
= aSrcSize
.Height() ? (double) rSize
.Height() / aSrcSize
.Height() : 1.0;
2380 long nMoveX
, nMoveY
;
2382 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
2384 aMtf
.Scale( fScaleX
, fScaleY
);
2385 aSrcPt
.X() = FRound( aSrcPt
.X() * fScaleX
);
2386 aSrcPt
.Y() = FRound( aSrcPt
.Y() * fScaleY
);
2389 nMoveX
= rPos
.X() - aSrcPt
.X();
2390 nMoveY
= rPos
.Y() - aSrcPt
.Y();
2392 if( nMoveX
|| nMoveY
)
2393 aMtf
.Move( nMoveX
, nMoveY
);
2395 nAddCount
= ImplWriteActions( rOStm
, aMtf
, rSaveVDev
, rRop_0_1
, rLineCol
, rLineColStack
, rActualCharSet
);
2396 nNewPos
= rOStm
.Tell();
2397 rOStm
.Seek( nOldPos
);
2398 rOStm
.WriteInt32( nAddCount
);
2399 rOStm
.Seek( nNewPos
);
2401 nCount
+= nAddCount
;
2408 case MetaActionType::HATCH
:
2410 const MetaHatchAction
* pA
= static_cast<const MetaHatchAction
*>(pAction
);
2411 const tools::PolyPolygon
& rPolyPoly
= pA
->GetPolyPolygon();
2412 const Hatch
& rHatch
= pA
->GetHatch();
2413 sal_uLong nOldPos
, nNewPos
, nAddCount
;
2415 // write hatch comment
2416 rOStm
.WriteInt16( GDI_HATCH_COMMENT
);
2418 // we'll write the ActionSize later
2419 nOldPos
= rOStm
.Tell();
2422 // write comment data
2423 WritePolyPolygon( rOStm
, rPolyPoly
);
2424 WriteHatch( rOStm
, rHatch
);
2426 // calculate and write ActionSize of comment
2427 nNewPos
= rOStm
.Tell();
2428 rOStm
.Seek( nOldPos
);
2429 rOStm
.WriteInt32( nNewPos
- nOldPos
+ 4 );
2430 rOStm
.Seek( ( nOldPos
= nNewPos
) + 4 );
2433 // write actions for hatch
2434 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2435 GDIMetaFile aTmpMtf
;
2437 aVDev
->AddHatchActions( rPolyPoly
, rHatch
, aTmpMtf
);
2438 nAddCount
= ImplWriteActions( rOStm
, aTmpMtf
, rSaveVDev
, rRop_0_1
, rLineCol
, rLineColStack
, rActualCharSet
);
2439 nNewPos
= rOStm
.Tell();
2440 rOStm
.Seek( nOldPos
);
2441 rOStm
.WriteInt32( nAddCount
);
2442 rOStm
.Seek( nNewPos
);
2444 nCount
+= nAddCount
;
2451 case MetaActionType::REFPOINT
:
2453 const MetaRefPointAction
* pA
= static_cast<const MetaRefPointAction
*>(pAction
);
2454 const Point
& rRefPoint
= pA
->GetRefPoint();
2455 const bool bSet
= pA
->IsSetting();
2456 sal_uLong nOldPos
, nNewPos
;
2458 // write RefPoint comment
2459 rOStm
.WriteInt16( GDI_REFPOINT_COMMENT
);
2461 // we'll write the ActionSize later
2462 nOldPos
= rOStm
.Tell();
2466 WritePair( rOStm
, rRefPoint
);
2467 rOStm
.WriteBool( bSet
);
2468 rOStm
.WriteInt32( 0 ); // number of actions that follow this comment
2470 // calculate and write ActionSize of comment
2471 nNewPos
= rOStm
.Tell();
2472 rOStm
.Seek( nOldPos
);
2473 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2474 rOStm
.Seek( nNewPos
);
2480 case MetaActionType::TEXTLINECOLOR
:
2482 const MetaTextLineColorAction
* pA
= static_cast<const MetaTextLineColorAction
*>(pAction
);
2483 const Color
& rColor
= pA
->GetColor();
2484 const bool bSet
= pA
->IsSetting();
2485 sal_uLong nOldPos
, nNewPos
;
2487 // write RefPoint comment
2488 rOStm
.WriteInt16( GDI_TEXTLINECOLOR_COMMENT
);
2490 // we'll write the ActionSize later
2491 nOldPos
= rOStm
.Tell();
2495 WriteColor( rOStm
, rColor
);
2496 rOStm
.WriteBool( bSet
);
2497 rOStm
.WriteInt32( 0 ); // number of actions that follow this comment
2499 // calculate and write ActionSize of comment
2500 nNewPos
= rOStm
.Tell();
2501 rOStm
.Seek( nOldPos
);
2502 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2503 rOStm
.Seek( nNewPos
);
2509 case MetaActionType::TEXTLINE
:
2511 const MetaTextLineAction
* pA
= static_cast<const MetaTextLineAction
*>(pAction
);
2512 const Point
& rStartPt
= pA
->GetStartPoint();
2513 const sal_Int32 nWidth
= (sal_Int32
) pA
->GetWidth();
2514 const FontStrikeout eStrikeout
= pA
->GetStrikeout();
2515 const FontLineStyle eUnderline
= pA
->GetUnderline();
2516 sal_uLong nOldPos
, nNewPos
;
2518 // write RefPoint comment
2519 rOStm
.WriteInt16( GDI_TEXTLINE_COMMENT
);
2521 // we'll write the ActionSize later
2522 nOldPos
= rOStm
.Tell();
2526 WritePair( rOStm
, rStartPt
);
2527 rOStm
.WriteInt32( nWidth
).WriteUInt32( eStrikeout
).WriteUInt32( eUnderline
);
2528 rOStm
.WriteInt32( 0 ); // number of actions that follow this comment
2530 // calculate and write ActionSize of comment
2531 nNewPos
= rOStm
.Tell();
2532 rOStm
.Seek( nOldPos
);
2533 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2534 rOStm
.Seek( nNewPos
);
2540 case MetaActionType::EPS
:
2543 case MetaActionType::COMMENT
:
2545 const MetaCommentAction
* pA
= static_cast<const MetaCommentAction
*>(pAction
);
2546 const sal_uInt32 nDataSize
= pA
->GetDataSize();
2547 sal_uLong nOldPos
, nNewPos
;
2549 // write RefPoint comment
2550 rOStm
.WriteInt16( GDI_COMMENT_COMMENT
);
2552 // we'll write the ActionSize later
2553 nOldPos
= rOStm
.Tell();
2557 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm
, pA
->GetComment());
2558 rOStm
.WriteInt32( pA
->GetValue() ).WriteUInt32( nDataSize
);
2561 rOStm
.WriteBytes( pA
->GetData(), nDataSize
);
2563 rOStm
.WriteInt32( 0 ); // number of actions that follow this comment
2565 // calculate and write ActionSize of comment
2566 nNewPos
= rOStm
.Tell();
2567 rOStm
.Seek( nOldPos
);
2568 rOStm
.WriteInt32( nNewPos
- nOldPos
);
2569 rOStm
.Seek( nNewPos
);
2578 OStringBuffer
aStr("Missing implementation for Action#: ");
2579 aStr
.append(static_cast<sal_Int32
>(pAction
->GetType()));
2581 OSL_FAIL(aStr
.getStr());
2591 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */