21#include <osl/diagnose.h>
22#include <osl/thread.h>
36#include <boost/rational.hpp>
61 sal_uInt16 nSize = nSize32;
63 const size_t nMaxPossiblePoints = rIStm.
remainingSize() / 2 *
sizeof(sal_Int32);
64 if (nSize > nMaxPossiblePoints)
66 SAL_WARN(
"vcl.gdi",
"svm record claims to have: " << nSize <<
" points, but only " << nMaxPossiblePoints <<
" possible");
72 for (sal_uInt16
i = 0;
i < nSize && rIStm.
good(); ++
i)
84 sal_Int32 nPolyCount32(0);
86 sal_uInt16 nPolyCount =
static_cast<sal_uInt16
>(nPolyCount32);
88 for (sal_uInt16
i = 0;
i < nPolyCount && rIStm.
good(); ++
i)
98 return bSuccess && rIStm.
good();
105 rIStm.
ReadInt16( nVal ); rColor.
SetRed( sal::static_int_cast<sal_uInt8>(
static_cast<sal_uInt16
>(nVal) >> 8) );
106 rIStm.
ReadInt16( nVal ); rColor.
SetGreen( sal::static_int_cast<sal_uInt8>(
static_cast<sal_uInt16
>(nVal) >> 8) );
107 rIStm.
ReadInt16( nVal ); rColor.
SetBlue( sal::static_int_cast<sal_uInt8>(
static_cast<sal_uInt16
>(nVal) >> 8) );
119 sal_Int32 nXNum(0), nXDenom(0), nYNum(0), nYDenom(0);
122 if (!rIStm.
good() || nXDenom <= 0 || nYDenom <= 0 || nXNum <= 0 || nYNum <= 0)
124 SAL_WARN(
"vcl.gdi",
"Parsing error: invalid mapmode fraction");
128 if (nUnit < sal_Int16(MapUnit::Map100thMM) || nUnit > sal_Int16(MapUnit::LAST))
130 SAL_WARN(
"vcl.gdi",
"Parsing error: invalid mapmode");
141 sal_uInt64 nOld = rIStm.
Tell();
145 sal_uInt32 nActionSize;
146 std::size_t nStringLen;
148 rIStm.
Seek( nStrmPos );
152 nStringLen = (nActionSize - 4) >> 1;
162 sal_Int32 nActionSize;
167 if (!rIStm.
good() || nActionSize < 4)
169 rIStm.
SeekRel(nActionSize - 4);
178 sal_uInt16 nPolygonCount(0);
184 const size_t nMinRecordSize =
sizeof(sal_uInt16);
185 const size_t nMaxRecords = rIStm.
remainingSize() / nMinRecordSize;
186 if (nPolygonCount > nMaxRecords)
188 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxRecords <<
189 " max possible entries, but " << nPolygonCount <<
" claimed, truncating");
190 nPolygonCount = nMaxRecords;
193 for(sal_uInt16
a(0);
a < nPolygonCount;
a++)
195 sal_uInt16 nPointCount(0);
198 const size_t nMinPolygonSize =
sizeof(sal_Int32) * 2;
199 const size_t nMaxPolygons = rIStm.
remainingSize() / nMinPolygonSize;
200 if (nPointCount > nMaxPolygons)
202 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxPolygons <<
203 " max possible entries, but " << nPointCount <<
" claimed, truncating");
204 nPointCount = nMaxPolygons;
211 for(sal_uInt16 b(0); b < nPointCount; b++)
223 for(sal_uInt16 c(0); c < nPointCount; c++)
231 rPolyPoly.
Insert(aCandidate);
245 sal_Int32 SkipActions(sal_Int32 i, sal_Int32 nFollowingActionCount, sal_Int32 nActions)
247 sal_Int32 remainingActions = nActions -
i;
248 if (nFollowingActionCount < 0)
249 nFollowingActionCount = remainingActions;
250 return std::min(remainingActions, nFollowingActionCount);
253 void ClampRange(std::u16string_view rStr, sal_Int32& rIndex, sal_Int32& rLength,
256 const sal_Int32 nStrLength = rStr.size();
258 if (rIndex < 0 || rIndex > nStrLength)
260 SAL_WARN(
"vcl.gdi",
"inconsistent offset");
264 if (rLength < 0 || rLength > nStrLength - rIndex)
266 SAL_WARN(
"vcl.gdi",
"inconsistent len");
267 rLength = nStrLength - rIndex;
271 pDXAry->resize(rLength);
275#define LF_FACESIZE 32
286 const sal_uInt64
nPos = rIStm.
Tell();
289 rIStm.
SetEndian( SvStreamEndian::LITTLE );
304 SAL_WARN(
"vcl.gdi",
"svm: value for width should be positive");
312 SAL_WARN(
"vcl.gdi",
"svm: value for height should be positive");
321 || ( memcmp( aCode,
"SVGDI",
sizeof( aCode ) ) != 0 ) )
323 SAL_WARN(
"vcl.gdi",
"svm: wrong check for header-magic and version");
329 std::stack<LineInfo, std::vector<LineInfo>> aLIStack;
331 rtl_TextEncoding eActualCharSet = osl_getThreadTextEncoding();
332 bool bFatLine =
false;
340 sal_uInt32 nUnicodeCommentStreamPos = 0;
341 sal_Int32 nUnicodeCommentActionNumber = 0;
349 sal_Int32 nActions(0);
353 SAL_WARN(
"vcl.gdi",
"svm claims negative action count (" << nActions <<
")");
357 const size_t nMinActionSize =
sizeof(sal_uInt16) +
sizeof(sal_Int32);
358 const size_t nMaxPossibleActions = rIStm.
remainingSize() / nMinActionSize;
361 SAL_WARN(
"vcl.gdi",
"svm claims more actions (" << nActions <<
") than stream could provide, truncating");
362 nActions = nMaxPossibleActions;
365 size_t nLastPolygonAction(0);
369 for (sal_Int32
i = 0;
i < nActions && rIStm.
good(); ++
i)
373 sal_Int32 nActBegin = rIStm.
Tell();
374 sal_Int32 nActionSize(0);
377 SAL_WARN_IF( (
nType > 33 ) && (
nType < 1024 ),
"vcl.gdi",
"Unknown GDIMetaAction while converting!" );
406 sal_Int16 nLineJoin(0);
414 sal_Int16 nLineCap(0);
416 aLineInfo.SetLineCap(
static_cast<css::drawing::LineCap
>(nLineCap));
426 rIStm.
ReadInt32( b ); aLineInfo.SetDashLen(b);
428 rIStm.
ReadInt32( b ); aLineInfo.SetDotLen(b);
429 rIStm.
ReadInt32( b ); aLineInfo.SetDistance(b);
431 if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
432 || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
433 && aLineInfo.GetDistance())
456 if(1 == aInputPolyPolygon.
Count())
469 if(pPolyPolygonAction)
488 if(1 == aInputPolyPolygon.
Count())
505 sal_Int32 nTmp(0), nTmp1(0);
663 sal_Int32 nWidth(0), nHeight(0);
665 sal_Int16 nCharOrient(0), nLineOrient(0);
667 sal_Int16 nCharSet(0), nFamily(0), nPitch(0), nAlign(0), nWeight(0), nUnderline(0), nStrikeout(0);
669 bool bItalic(
false), bOutline(
false), bShadow(
false), bTransparent(
false);
673 aFont.
SetCharSet(
static_cast<rtl_TextEncoding
>(nCharSet) );
688 if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
689 eActualCharSet = osl_getThreadTextEncoding();
697 aFontVDev->SetFont( aFont );
703 sal_Int32
nIndex(0), nLen(0), nTmp(0);
711 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
713 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
714 if ( nUnicodeCommentActionNumber ==
i )
720 if (nActionSize < 24)
723 rIStm.
Seek(nActBegin + nActionSize);
729 sal_Int32
nIndex(0), nLen(0), nAryLen(0), nTmp(0);
737 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
739 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
744 const size_t nMinRecordSize =
sizeof(sal_Int32);
745 const size_t nMaxRecords = rIStm.
remainingSize() / nMinRecordSize;
748 SAL_WARN(
"vcl.gdi",
"Parsing error: " << nMaxRecords <<
749 " max possible entries, but " << nAryLen <<
" claimed, truncating");
750 nAryLen = nMaxRecords;
753 sal_Int32 nStrLen(
aStr.getLength() );
755 sal_Int32 nDXAryLen = std::max(nAryLen, nStrLen);
757 if (nDXAryLen < nLen)
761 SAL_WARN(
"vcl.gdi",
"dxary too short, discarding completely");
762 rIStm.
SeekRel(
sizeof(sal_Int32) * nDXAryLen);
770 for (sal_Int32 j = 0; j < nAryLen; ++j)
777 if( nAryLen != nStrLen )
779 if (nAryLen+1 == nStrLen &&
nIndex >= 0)
783 aFontVDev->GetTextArray(
aStr, &aTmpAry,
nIndex, nLen );
786 SAL_WARN(
"vcl.gdi",
"TextArray too short to recover missing element");
797 aDXAry.
set(nStrLen-1, aDXAry[ nStrLen-2 ] + aTmpAry[ nStrLen-1 ] - aTmpAry[ nStrLen-2 ]);
799 aDXAry.
set(nStrLen-1, aTmpAry[ nStrLen-1 ]);
804 OSL_FAIL(
"More than one DX array element missing on SVM import");
809 if ( nUnicodeCommentActionNumber ==
i )
815 if (nActionSize < 24)
818 rIStm.
Seek(nActBegin + nActionSize);
824 sal_Int32
nIndex(0), nLen(0), nWidth(0), nTmp(0);
833 SAL_WARN_IF( nTerminator != 0,
"vcl.gdi",
"expected string to be NULL terminated" );
835 OUString
aStr(OStringToOUString(aByteStr, eActualCharSet));
836 if ( nUnicodeCommentActionNumber ==
i )
842 if (nActionSize < 28)
845 rIStm.
Seek(nActBegin + nActionSize);
888 sal_Int32 nPenWidth(0);
889 sal_Int16 nPenStyle(0);
893 aLineInfo.SetWidth( nPenWidth );
894 bFatLine = nPenStyle && !aLineInfo.IsDefault();
904 sal_Int16 nBrushStyle(0);
918 aFontVDev->SetMapMode(aMapMode);
928 sal_Int16 nRegType(0);
929 sal_Int16 bIntersect(0);
960 bool bSuccess =
true;
962 sal_Int32 nPolyCount32(0);
964 sal_uInt16 nPolyCount(nPolyCount32);
966 for (sal_uInt16 j = 0; j < nPolyCount && rIStm.
good(); ++j)
973 aPolyPoly.
Insert(aActionPoly);
994 sal_Int32 nTmp(0), nTmp1(0);
1011 sal_Int16 nRasterOp(0);
1036 aLIStack.push(aLineInfo);
1047 std::optional<LineInfo> xLineInfo;
1048 if (!aLIStack.empty())
1050 xLineInfo = std::move(aLIStack.top());
1057 aLineInfo = *xLineInfo;
1059 bFatLine = (
LineStyle::NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
1073 sal_Int16 nStyle(0);
1076 Color aStartCol, aEndCol;
1080 sal_Int16 nAngle(0),
nBorder(0), nOfsX(0), nOfsY(0), nIntensityStart(0), nIntensityEnd(0);
1083 Gradient aGrad(
static_cast<css::awt::GradientStyle
>(nStyle), aStartCol, aEndCol );
1098 sal_Int32 nFollowingActionCount(0);
1099 sal_Int16 nTrans(0);
1106 i = SkipActions(
i, nFollowingActionCount, nActions);
1116 sal_Int32 nFollowingActionCount(0);
1119 aReader.
Read( aMtf );
1123 rIStm.
ReadInt32( nFollowingActionCount );
1127 i = SkipActions(
i, nFollowingActionCount, nActions);
1135 sal_Int32 nFollowingActionCount(0);
1139 rIStm.
ReadInt32( nFollowingActionCount );
1143 i = SkipActions(
i, nFollowingActionCount, nActions);
1151 sal_Int32 nFollowingActionCount(0);
1158 i = SkipActions(
i, nFollowingActionCount, nActions);
1162 aFontVDev->SetRefPoint( aRefPoint );
1164 aFontVDev->SetRefPoint();
1172 sal_Int32 nFollowingActionCount(0);
1179 i = SkipActions(
i, nFollowingActionCount, nActions);
1186 sal_Int32 nWidth(0);
1187 sal_uInt32 nStrikeout(0);
1188 sal_uInt32 nUnderline(0);
1189 sal_Int32 nFollowingActionCount(0);
1199 i = SkipActions(
i, nFollowingActionCount, nActions);
1207 sal_Int32 nFollowingActionCount(0);
1211 rIStm.
ReadInt32( nFollowingActionCount );
1215 i = SkipActions(
i, nFollowingActionCount, nActions);
1221 std::vector<sal_uInt8>
aData;
1225 sal_uInt32 nDataSize(0);
1231 if (nDataSize > nMaxPossibleActions)
1233 SAL_WARN(
"vcl.gdi",
"svm record claims to have: " << nDataSize <<
" data, but only " << nMaxPossibleData <<
" possible");
1234 nDataSize = nMaxPossibleActions;
1236 aData.resize(nDataSize);
1240 sal_Int32 nFollowingActionCount(0);
1245 i = SkipActions(
i, nFollowingActionCount, nActions);
1251 nUnicodeCommentActionNumber =
i + 1;
1252 nUnicodeCommentStreamPos = rIStm.
Tell() - 6;
1253 if (nActionSize < 4)
1256 rIStm.
SeekRel(nActionSize - 4);
1261 if (nActionSize < 4)
1264 rIStm.
SeekRel(nActionSize - 4);
1276 aReader.
Read(aGDIMetaFile);
1280 aGDIMetaFile.
Play(*aVDev);
1282 catch (
const boost::bad_rational&)
static void ImplReadRect(SvStream &rIStm, tools::Rectangle &rRect)
static void ImplReadColor(SvStream &rIStm, Color &rColor)
static void ImplReadUnicodeComment(sal_uInt32 nStrmPos, SvStream &rIStm, OUString &rString)
static bool ImplReadPoly(SvStream &rIStm, tools::Polygon &rPoly)
static void lcl_error(SvStream &rIStm, const SvStreamEndian &nOldFormat, sal_uInt64 nPos)
static void ImplReadExtendedPolyPolygonAction(SvStream &rIStm, tools::PolyPolygon &rPolyPoly)
bool TestImportSVM(SvStream &rStream)
static bool ImplReadMapMode(SvStream &rIStm, MapMode &rMapMode)
static bool ImplReadPolyPoly(SvStream &rIStm, tools::PolyPolygon &rPolyPoly)
static void ImplSkipActions(SvStream &rIStm, sal_uLong nSkipCount)
#define GDI_EXTENDEDPOLYGON_ACTION
#define GDI_CLIPREGION_ACTION
#define GDI_POLYPOLYGON_ACTION
#define GDI_POLYLINE_ACTION
#define GDI_MAPMODE_ACTION
#define GDI_TEXTLINE_COMMENT
#define GDI_TRANSPARENT_COMMENT
#define GDI_BITMAPSCALE_ACTION
#define GDI_ELLIPSE_ACTION
#define GDI_FLOATTRANSPARENT_COMMENT
#define GDI_ISECTCLIPREGION_ACTION
#define GDI_MOVECLIPREGION_ACTION
#define GDI_STRETCHTEXT_ACTION
#define GDI_POLYGON_ACTION
#define GDI_HATCH_COMMENT
#define GDI_LINEJOIN_ACTION
#define GDI_HIGHLIGHTRECT_ACTION
#define GDI_COMMENT_COMMENT
#define GDI_BITMAP_ACTION
#define GDI_FILLBRUSH_ACTION
#define GDI_UNICODE_COMMENT
#define GDI_GRADIENTEX_COMMENT
#define GDI_REFPOINT_COMMENT
#define GDI_TEXTARRAY_ACTION
#define GDI_LINEDASHDOT_ACTION
#define GDI_BITMAPSCALEPART_ACTION
#define GDI_INVERTRECT_ACTION
#define GDI_RASTEROP_ACTION
#define GDI_LINECAP_ACTION
#define GDI_GRADIENT_ACTION
#define GDI_TEXTLINECOLOR_COMMENT
void SetGreen(sal_uInt8 nGreen)
void SetRed(sal_uInt8 nRed)
void SetBlue(sal_uInt8 nBlue)
void SetOfsX(sal_uInt16 nOfsX)
void SetStartIntensity(sal_uInt16 nIntens)
void SetBorder(sal_uInt16 nBorder)
void SetOfsY(sal_uInt16 nOfsY)
void SetAngle(Degree10 nAngle)
void SetEndIntensity(sal_uInt16 nIntens)
void resize(size_t nSize)
void set(size_t nIndex, sal_Int32 nValue)
SVMConverter(SvStream &rIStm, GDIMetaFile &rMtf)
static void ImplConvertFromSVM1(SvStream &rIStm, GDIMetaFile &rMtf)
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
SvStream & ReadCharAsBool(bool &rBool)
void SetEndian(SvStreamEndian SvStreamEndian)
SvStream & ReadInt16(sal_Int16 &rInt16)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvStreamEndian GetEndian() const
void SetError(ErrCode nErrorCode)
sal_uInt64 Seek(sal_uInt64 nPos)
SvStream & ReadInt32(sal_Int32 &rInt32)
std::size_t ReadBytes(void *pData, std::size_t nSize)
rtl_TextEncoding GetStreamCharSet() const
sal_uInt64 SeekRel(sal_Int64 nPos)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
sal_uInt64 remainingSize()
SvStream & ReadUChar(unsigned char &rChar)
SvStream & Read(GDIMetaFile &rMetaFile, ImplMetaReadData *pData=nullptr)
void readGradient(Gradient &rGradient)
void SetFontSize(const Size &)
void SetOrientation(Degree10 nLineOrientation)
void SetOutline(bool bOutline)
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
void SetFillColor(const Color &)
void SetColor(const Color &)
void SetItalic(FontItalic)
void SetWeight(FontWeight)
bool IsTransparent() const
void SetFamily(FontFamily)
void SetUnderline(FontLineStyle)
TextAlign GetAlignment() const
void SetCharSet(rtl_TextEncoding)
const Color & GetColor() const
void SetAlignment(TextAlign)
void SetFamilyName(const OUString &rFamilyName)
rtl_TextEncoding GetCharSet() const
void SetShadow(bool bShadow)
const Color & GetFillColor() const
void SetStrikeout(FontStrikeout)
void Intersect(const tools::Rectangle &rRegion)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
#define SVSTREAM_FILEFORMAT_ERROR
SvStream & ReadHatch(SvStream &rIStm, Hatch &rHatch)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
constexpr OUStringLiteral aData
tools::Long const nBorder
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
TOOLS_DLLPUBLIC OString read_uInt8s_ToOString(SvStream &rStrm, std::size_t nUnits)
OString read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream &rStrm)
TOOLS_DLLPUBLIC OUString read_uInt16s_ToOUString(SvStream &rStrm, std::size_t nUnits)