24 #include <osl/thread.h>
32 #include <osl/diagnose.h>
58 sal_uInt16 nSize = nSize32;
60 const size_t nMaxPossiblePoints = rIStm.
remainingSize() / 2 *
sizeof(sal_Int32);
61 if (nSize > nMaxPossiblePoints)
63 SAL_WARN(
"vcl.gdi",
"svm record claims to have: " << nSize <<
" points, but only " << nMaxPossiblePoints <<
" possible");
69 for (sal_uInt16
i = 0;
i < nSize && rIStm.
good(); ++
i)
81 sal_Int32 nPolyCount32(0);
83 sal_uInt16 nPolyCount =
static_cast<sal_uInt16
>(nPolyCount32);
85 for (sal_uInt16
i = 0;
i < nPolyCount && rIStm.
good(); ++
i)
95 return bSuccess && rIStm.
good();
102 rIStm.
ReadInt16( nVal ); rColor.
SetRed( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
103 rIStm.
ReadInt16( nVal ); rColor.
SetGreen( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
104 rIStm.
ReadInt16( nVal ); rColor.
SetBlue( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
116 sal_Int32 nXNum(0), nXDenom(0), nYNum(0), nYDenom(0);
119 if (!rIStm.
good() || nXDenom <= 0 || nYDenom <= 0 || nXNum <= 0 || nYNum <= 0)
121 SAL_WARN(
"vcl.gdi",
"Parsing error: invalid mapmode fraction");
125 if (nUnit < sal_Int16(MapUnit::Map100thMM) || nUnit > sal_Int16(MapUnit::LAST))
127 SAL_WARN(
"vcl.gdi",
"Parsing error: invalid mapmode");
138 sal_uInt32 nOld = rIStm.
Tell();
142 sal_uInt32 nActionSize;
143 std::size_t nStringLen;
145 rIStm.
Seek( nStrmPos );
149 nStringLen = (nActionSize - 4) >> 1;
159 sal_Int32 nActionSize;
164 if (!rIStm.
good() || nActionSize < 4)
166 rIStm.
SeekRel(nActionSize - 4);
175 sal_uInt16 nPolygonCount(0);
181 const size_t nMinRecordSize =
sizeof(sal_uInt16);
182 const size_t nMaxRecords = rIStm.
remainingSize() / nMinRecordSize;
183 if (nPolygonCount > nMaxRecords)
185 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxRecords <<
186 " max possible entries, but " << nPolygonCount <<
" claimed, truncating");
187 nPolygonCount = nMaxRecords;
190 for(sal_uInt16
a(0);
a < nPolygonCount;
a++)
192 sal_uInt16 nPointCount(0);
195 const size_t nMinPolygonSize =
sizeof(sal_Int32) * 2;
196 const size_t nMaxPolygons = rIStm.
remainingSize() / nMinPolygonSize;
197 if (nPointCount > nMaxPolygons)
199 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxPolygons <<
200 " max possible entries, but " << nPointCount <<
" claimed, truncating");
201 nPointCount = nMaxPolygons;
208 for(sal_uInt16 b(0); b < nPointCount; b++)
220 for(sal_uInt16 c(0); c < nPointCount; c++)
223 aCandidate.
SetFlags(c, static_cast<PolyFlags>(aPolyFlags));
228 rPolyPoly.
Insert(aCandidate);
242 sal_Int32 SkipActions(sal_Int32 i, sal_Int32 nFollowingActionCount, sal_Int32 nActions)
244 sal_Int32 remainingActions = nActions - i;
245 if (nFollowingActionCount < 0)
246 nFollowingActionCount = remainingActions;
247 return std::min(remainingActions, nFollowingActionCount);
251 #define LF_FACESIZE 32
265 rIStm.
SetEndian( SvStreamEndian::LITTLE );
280 SAL_WARN(
"vcl.gdi",
"svm: value for width should be positive");
288 SAL_WARN(
"vcl.gdi",
"svm: value for height should be positive");
296 || ( memcmp( aCode,
"SVGDI",
sizeof( aCode ) ) != 0 )
297 || ( nVersion != 200 ) )
299 SAL_WARN(
"vcl.gdi",
"svm: wrong check for header-magic and version");
305 std::stack<std::unique_ptr<LineInfo>> aLIStack;
307 rtl_TextEncoding eActualCharSet = osl_getThreadTextEncoding();
308 bool bFatLine =
false;
316 sal_uInt32 nUnicodeCommentStreamPos = 0;
317 sal_Int32 nUnicodeCommentActionNumber = 0;
325 sal_Int32 nActions(0);
329 SAL_WARN(
"vcl.gdi",
"svm claims negative action count (" << nActions <<
")");
333 const size_t nMinActionSize =
sizeof(sal_uInt16) +
sizeof(sal_Int32);
334 const size_t nMaxPossibleActions = rIStm.
remainingSize() / nMinActionSize;
337 SAL_WARN(
"vcl.gdi",
"svm claims more actions (" << nActions <<
") than stream could provide, truncating");
338 nActions = nMaxPossibleActions;
341 size_t nLastPolygonAction(0);
345 for (sal_Int32
i = 0;
i < nActions && rIStm.
good(); ++
i)
349 sal_Int32 nActBegin = rIStm.
Tell();
350 sal_Int32 nActionSize(0);
353 SAL_WARN_IF( ( nType > 33 ) && ( nType < 1024 ),
"vcl.gdi",
"Unknown GDIMetaAction while converting!" );
361 rMtf.
AddAction(
new MetaPixelAction( aPt, aActionColor ) );
382 sal_Int16 nLineJoin(0);
384 aLineInfo.SetLineJoin(static_cast<basegfx::B2DLineJoin>(nLineJoin));
390 sal_Int16 nLineCap(0);
392 aLineInfo.SetLineCap(static_cast<css::drawing::LineCap>(nLineCap));
401 rIStm.
ReadInt16( a ); aLineInfo.SetDashCount(a);
402 rIStm.
ReadInt32( b ); aLineInfo.SetDashLen(b);
403 rIStm.
ReadInt16( a ); aLineInfo.SetDotCount(a);
404 rIStm.
ReadInt32( b ); aLineInfo.SetDotLen(b);
405 rIStm.
ReadInt32( b ); aLineInfo.SetDistance(b);
407 if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
408 || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
409 && aLineInfo.GetDistance())
425 MetaPolyLineAction* pPolyLineAction =
dynamic_cast< MetaPolyLineAction*
>(rMtf.
GetAction(nLastPolygonAction));
432 if(1 == aInputPolyPolygon.
Count())
435 new MetaPolyLineAction(
437 pPolyLineAction->GetLineInfo()),
443 MetaPolyPolygonAction* pPolyPolygonAction =
dynamic_cast< MetaPolyPolygonAction*
>(rMtf.
GetAction(nLastPolygonAction));
445 if(pPolyPolygonAction)
449 if(pPolyPolygonAction->GetPolyPolygon().Count() == aInputPolyPolygon.
Count())
452 new MetaPolyPolygonAction(
459 MetaPolygonAction* pPolygonAction =
dynamic_cast< MetaPolygonAction*
>(rMtf.
GetAction(nLastPolygonAction));
464 if(1 == aInputPolyPolygon.
Count())
467 new MetaPolygonAction(
481 sal_Int32 nTmp(0), nTmp1(0);
485 rMtf.
AddAction(
new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
491 rMtf.
AddAction(
new MetaPolyLineAction( aRect, aLineInfo ) );
506 rMtf.
AddAction(
new MetaPolygonAction( aPoly ) );
508 rMtf.
AddAction(
new MetaPolyLineAction( aPoly, aLineInfo ) );
511 rMtf.
AddAction(
new MetaEllipseAction( aRect ) );
527 rMtf.
AddAction(
new MetaPolygonAction( aPoly ) );
529 rMtf.
AddAction(
new MetaPolyLineAction( aPoly, aLineInfo ) );
532 rMtf.
AddAction(
new MetaArcAction( aRect, aPt, aPt1 ) );
548 rMtf.
AddAction(
new MetaPolygonAction( aPoly ) );
550 rMtf.
AddAction(
new MetaPolyLineAction( aPoly, aLineInfo ) );
553 rMtf.
AddAction(
new MetaPieAction( aRect, aPt, aPt1 ) );
575 rMtf.
AddAction(
new MetaPolyLineAction( aActionPoly, aLineInfo ) );
577 rMtf.
AddAction(
new MetaPolyLineAction( aActionPoly ) );
590 rMtf.
AddAction(
new MetaPolygonAction( aActionPoly ) );
592 rMtf.
AddAction(
new MetaPolyLineAction( aActionPoly, aLineInfo ) );
597 rMtf.
AddAction(
new MetaPolygonAction( aActionPoly ) );
613 rMtf.
AddAction(
new MetaPolyPolygonAction( aPolyPoly ) );
617 rMtf.
AddAction(
new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
622 rMtf.
AddAction(
new MetaPolyPolygonAction( aPolyPoly ) );
639 sal_Int32 nWidth(0), nHeight(0);
641 sal_Int16 nCharOrient(0), nLineOrient(0);
643 sal_Int16 nCharSet(0), nFamily(0), nPitch(0), nAlign(0), nWeight(0), nUnderline(0), nStrikeout(0);
645 bool bItalic(
false), bOutline(
false), bShadow(
false), bTransparent(
false);
649 aFont.
SetCharSet( static_cast<rtl_TextEncoding>(nCharSet) );
650 aFont.
SetFamily( static_cast<FontFamily>(nFamily) );
651 aFont.
SetPitch( static_cast<FontPitch>(nPitch) );
655 aFont.
SetUnderline( static_cast<FontLineStyle>(nUnderline) );
656 aFont.
SetStrikeout( static_cast<FontStrikeout>(nStrikeout) );
664 if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
665 eActualCharSet = osl_getThreadTextEncoding();
667 rMtf.
AddAction(
new MetaFontAction( aFont ) );
673 aFontVDev->SetFont( aFont );
679 sal_Int32
nIndex(0), nLen(0), nTmp(0);
687 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
689 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
690 if ( nUnicodeCommentActionNumber ==
i )
695 if (nActionSize < 24)
698 rIStm.
Seek(nActBegin + nActionSize);
704 sal_Int32
nIndex(0), nLen(0), nAryLen(0), nTmp(0);
712 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
714 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
716 std::unique_ptr<tools::Long[]> pDXAry;
719 const size_t nMinRecordSize =
sizeof(sal_Int32);
720 const size_t nMaxRecords = rIStm.
remainingSize() / nMinRecordSize;
723 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxRecords <<
724 " max possible entries, but " << nAryLen <<
" claimed, truncating");
725 nAryLen = nMaxRecords;
728 sal_Int32 nStrLen( aStr.getLength() );
730 sal_Int32 nDXAryLen = std::max(nAryLen, nStrLen);
732 if (nDXAryLen < nLen)
736 SAL_WARN(
"vcl.gdi",
"dxary too short, discarding completely");
737 rIStm.
SeekRel(
sizeof(sal_Int32) * nDXAryLen);
745 for (sal_Int32 j = 0; j < nAryLen; ++j)
752 if( nAryLen != nStrLen )
754 if (nAryLen+1 == nStrLen &&
nIndex >= 0)
756 std::unique_ptr<tools::Long[]> pTmpAry(
new tools::Long[nStrLen]);
758 aFontVDev->GetTextArray( aStr, pTmpAry.get(),
nIndex, nLen );
768 pDXAry[ nStrLen-1 ] = pDXAry[ nStrLen-2 ] + pTmpAry[ nStrLen-1 ] - pTmpAry[ nStrLen-2 ];
770 pDXAry[ nStrLen-1 ] = pTmpAry[ nStrLen-1 ];
774 OSL_FAIL(
"More than one DX array element missing on SVM import");
779 if ( nUnicodeCommentActionNumber ==
i )
781 rMtf.
AddAction(
new MetaTextArrayAction( aPt, aStr, pDXAry.get(),
nIndex, nLen ) );
784 if (nActionSize < 24)
787 rIStm.
Seek(nActBegin + nActionSize);
793 sal_Int32
nIndex(0), nLen(0), nWidth(0), nTmp(0);
802 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
804 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
805 if ( nUnicodeCommentActionNumber ==
i )
810 if (nActionSize < 28)
813 rIStm.
Seek(nActBegin + nActionSize);
848 rMtf.
AddAction(
new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
861 aLineInfo.SetWidth( nPenWidth );
862 bFatLine = nPenStyle && !aLineInfo.IsDefault();
870 sal_Int16 nBrushStyle;
884 rMtf.
AddAction(
new MetaMapModeAction(aMapMode));
887 aFontVDev->SetMapMode(aMapMode);
896 sal_Int16 bIntersect;
929 bool bSuccess =
true;
931 sal_Int32 nPolyCount32(0);
933 sal_uInt16 nPolyCount(nPolyCount32);
935 for (sal_uInt16 j = 0; j < nPolyCount && rIStm.
good(); ++j)
942 aPolyPoly.
Insert(aActionPoly);
957 rMtf.
AddAction(
new MetaClipRegionAction( aRegion, bClip ) );
963 sal_Int32 nTmp(0), nTmp1(0);
965 rMtf.
AddAction(
new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
972 rMtf.
AddAction(
new MetaISectRectClipRegionAction( aRect ) );
999 rMtf.
AddAction(
new MetaRasterOpAction( eRasterOp ) );
1005 aLIStack.push(std::make_unique<LineInfo>(aLineInfo));
1016 std::unique_ptr<LineInfo> xLineInfo;
1017 if (!aLIStack.empty())
1019 xLineInfo = std::move(aLIStack.top());
1026 aLineInfo = *xLineInfo;
1028 bFatLine = (
LineStyle::NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
1047 sal_Int16 nIntensityStart;
1048 sal_Int16 nIntensityEnd;
1056 Gradient aGrad( static_cast<GradientStyle>(nStyle), aStartCol, aEndCol );
1071 sal_Int32 nFollowingActionCount(0);
1072 sal_Int16 nTrans(0);
1079 i = SkipActions(
i, nFollowingActionCount, nActions);
1089 sal_Int32 nFollowingActionCount(0);
1095 rIStm.
ReadInt32( nFollowingActionCount );
1099 i = SkipActions(
i, nFollowingActionCount, nActions);
1107 sal_Int32 nFollowingActionCount(0);
1111 rIStm.
ReadInt32( nFollowingActionCount );
1115 i = SkipActions(
i, nFollowingActionCount, nActions);
1123 sal_Int32 nFollowingActionCount(0);
1128 rMtf.
AddAction(
new MetaRefPointAction( aRefPoint, bSet ) );
1130 i = SkipActions(
i, nFollowingActionCount, nActions);
1134 aFontVDev->SetRefPoint( aRefPoint );
1136 aFontVDev->SetRefPoint();
1144 sal_Int32 nFollowingActionCount(0);
1149 rMtf.
AddAction(
new MetaTextLineColorAction( aColor, bSet ) );
1151 i = SkipActions(
i, nFollowingActionCount, nActions);
1158 sal_Int32 nWidth(0);
1159 sal_uInt32 nStrikeout(0);
1160 sal_uInt32 nUnderline(0);
1161 sal_Int32 nFollowingActionCount(0);
1167 static_cast<FontStrikeout>(nStrikeout),
1168 static_cast<FontLineStyle>(nUnderline),
1171 i = SkipActions(
i, nFollowingActionCount, nActions);
1179 sal_Int32 nFollowingActionCount(0);
1183 rIStm.
ReadInt32( nFollowingActionCount );
1185 rMtf.
AddAction(
new MetaGradientExAction( aPolyPoly, aGradient ) );
1187 i = SkipActions(
i, nFollowingActionCount, nActions);
1193 std::vector<sal_uInt8>
aData;
1197 sal_uInt32 nDataSize(0);
1203 if (nDataSize > nMaxPossibleActions)
1205 SAL_WARN(
"vcl.gdi",
"svm record claims to have: " << nDataSize <<
" data, but only " << nMaxPossibleData <<
" possible");
1206 nDataSize = nMaxPossibleActions;
1208 aData.resize(nDataSize);
1209 nDataSize = rIStm.
ReadBytes(aData.data(), nDataSize);
1212 sal_Int32 nFollowingActionCount(0);
1217 i = SkipActions(
i, nFollowingActionCount, nActions);
1223 nUnicodeCommentActionNumber =
i + 1;
1224 nUnicodeCommentStreamPos = rIStm.
Tell() - 6;
1225 if (nActionSize < 4)
1228 rIStm.
SeekRel(nActionSize - 4);
1233 if (nActionSize < 4)
1236 rIStm.
SeekRel(nActionSize - 4);
void SetFamily(FontFamily)
SvStream & ReadInt16(sal_Int16 &rInt16)
static void ImplReadRect(SvStream &rIStm, tools::Rectangle &rRect)
void SetStrikeout(FontStrikeout)
static bool ImplReadMapMode(SvStream &rIStm, MapMode &rMapMode)
void SetFillColor(const Color &)
#define GDI_LINEDASHDOT_ACTION
void SetFontSize(const Size &)
void SetBlue(sal_uInt8 nBlue)
void setWidth(tools::Long nWidth)
OUString read_uInt16s_ToOUString(SvStream &rStrm, std::size_t nLen)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
static void ImplSkipActions(SvStream &rIStm, sal_uLong nSkipCount)
static void lcl_error(SvStream &rIStm, const SvStreamEndian &nOldFormat, sal_uLong nPos)
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
#define GDI_TEXTARRAY_ACTION
#define GDI_FILLBRUSH_ACTION
SvStream & ReadCharAsBool(bool &rBool)
void SetWeight(FontWeight)
#define GDI_ELLIPSE_ACTION
void SetOutline(bool bOutline)
sal_uInt64 Seek(sal_uInt64 nPos)
#define GDI_UNICODE_COMMENT
#define GDI_GRADIENTEX_COMMENT
void SetBorder(sal_uInt16 nBorder)
void SetCharSet(rtl_TextEncoding)
void SetEndIntensity(sal_uInt16 nIntens)
#define GDI_CLIPREGION_ACTION
sal_uInt64 SeekRel(sal_Int64 nPos)
FontAlign GetAlignment() const
#define GDI_TEXTLINE_COMMENT
static void ImplReadExtendedPolyPolygonAction(SvStream &rIStm, tools::PolyPolygon &rPolyPoly)
OString read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream &rStrm)
void SetOfsY(sal_uInt16 nOfsY)
#define GDI_BITMAPSCALE_ACTION
#define GDI_REFPOINT_COMMENT
#define GDI_LINECAP_ACTION
void SetUnderline(FontLineStyle)
#define GDI_POLYPOLYGON_ACTION
sal_uInt64 remainingSize()
#define GDI_BITMAPSCALEPART_ACTION
void SetShadow(bool bShadow)
void SetPitch(FontPitch ePitch)
constexpr OUStringLiteral aData
#define GDI_MOVECLIPREGION_ACTION
static void ImplReadUnicodeComment(sal_uInt32 nStrmPos, SvStream &rIStm, OUString &rString)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
#define GDI_POLYGON_ACTION
void SetAlignment(FontAlign)
void SetFamilyName(const OUString &rFamilyName)
void SetOrientation(Degree10 nLineOrientation)
#define GDI_RASTEROP_ACTION
#define GDI_EXTENDEDPOLYGON_ACTION
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
void SetRed(sal_uInt8 nRed)
static void ImplConvertFromSVM1(SvStream &rIStm, GDIMetaFile &rMtf)
void SetError(ErrCode nErrorCode)
void Intersect(const tools::Rectangle &rRegion)
SvStream & ReadUChar(unsigned char &rChar)
const Color & GetFillColor() const
#define GDI_INVERTRECT_ACTION
void SetOfsX(sal_uInt16 nOfsX)
static bool ImplReadPolyPoly(SvStream &rIStm, tools::PolyPolygon &rPolyPoly)
#define GDI_ISECTCLIPREGION_ACTION
SvStream & ReadHatch(SvStream &rIStm, Hatch &rHatch)
void SetColor(const Color &)
SvStream & ReadInt32(sal_Int32 &rInt32)
#define GDI_COMMENT_COMMENT
std::size_t ReadBytes(void *pData, std::size_t nSize)
tools::Long const nBorder
void SetAngle(Degree10 nAngle)
#define GDI_HATCH_COMMENT
SvStreamEndian GetEndian() const
const Color & GetColor() const
SVMConverter(SvStream &rIStm, GDIMetaFile &rMtf)
#define SAL_WARN_IF(condition, area, stream)
void SetGreen(sal_uInt8 nGreen)
void SetTransparent(bool bTransparent)
SvStream & ReadGDIMetaFile(SvStream &rIStm, GDIMetaFile &rGDIMetaFile, ImplMetaReadData *pData)
void SetEndian(SvStreamEndian SvStreamEndian)
bool IsTransparent() const
#define SVSTREAM_FILEFORMAT_ERROR
rtl_TextEncoding GetStreamCharSet() const
#define GDI_LINEJOIN_ACTION
static bool ImplReadPoly(SvStream &rIStm, tools::Polygon &rPoly)
#define GDI_MAPMODE_ACTION
#define GDI_TRANSPARENT_COMMENT
void SetItalic(FontItalic)
void setHeight(tools::Long nHeight)
#define GDI_POLYLINE_ACTION
#define SAL_WARN(area, stream)
#define GDI_HIGHLIGHTRECT_ACTION
#define GDI_STRETCHTEXT_ACTION
void readGradient(Gradient &rGradient)
static void ImplReadColor(SvStream &rIStm, Color &rColor)
#define GDI_FLOATTRANSPARENT_COMMENT
#define GDI_GRADIENT_ACTION
OString read_uInt8s_ToOString(SvStream &rStrm, std::size_t nLen)
void SetStartIntensity(sal_uInt16 nIntens)
rtl_TextEncoding GetCharSet() const
#define GDI_BITMAP_ACTION
#define GDI_TEXTLINECOLOR_COMMENT