tdf#142566 EMF Add support for EMR_POLYTEXTOUT records
With this implementation the support for EMF records:
EMR_POLYTEXTOUTA and EMR_POLYTEXTOUTW were added.
Change-Id: I39580d051ae73bed88e04a34d97b797b6d468dc5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116556
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 79ff9cf..106b9a5 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1790,14 +1790,17 @@ namespace emfio
}
break;
case EMR_POLYTEXTOUTA :
case EMR_EXTTEXTOUTA :
bFlag = true;
[[fallthrough]];
case EMR_POLYTEXTOUTW :
case EMR_EXTTEXTOUTW :
{
sal_Int32 nLeft, nTop, nRight, nBottom;
sal_uInt32 nGfxMode;
float nXScale, nYScale;
sal_uInt32 ncStrings( 1 );
sal_Int32 ptlReferenceX, ptlReferenceY;
sal_uInt32 nLen, nOffString, nOptions, offDx;
sal_Int32 nLeftRect, nTopRect, nRightRect, nBottomRect;
@@ -1805,112 +1808,118 @@ namespace emfio
nCurPos = mpInputStream->Tell() - 8;
mpInputStream->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom )
.ReadUInt32( nGfxMode ).ReadFloat( nXScale ).ReadFloat( nYScale )
.ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadUInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
.ReadUInt32( nGfxMode ).ReadFloat( nXScale ).ReadFloat( nYScale );
SAL_INFO("emfio", "\t\tBounds: " << nLeft << ", " << nTop << ", " << nRight << ", " << nBottom);
SAL_INFO("emfio", "\t\tiGraphicsMode: 0x" << std::hex << nGfxMode << std::dec);
SAL_INFO("emfio", "\t\texScale: " << nXScale);
SAL_INFO("emfio", "\t\teyScale: " << nYScale);
SAL_INFO("emfio", "\t\tReference: (" << ptlReferenceX << ", " << ptlReferenceY << ")");
mpInputStream->ReadInt32( nLeftRect ).ReadInt32( nTopRect ).ReadInt32( nRightRect ).ReadInt32( nBottomRect );
const tools::Rectangle aRect( nLeftRect, nTopRect, nRightRect, nBottomRect );
BkMode mnBkModeBackup = mnBkMode;
if ( nOptions & ETO_NO_RECT ) // Don't draw the background rectangle and text background
mnBkMode = BkMode::Transparent;
else if ( nOptions & ETO_OPAQUE )
DrawRectWithBGColor( aRect );
mpInputStream->ReadUInt32( offDx );
ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
if ( nOptions & ETO_RTLREADING )
nTextLayoutMode = ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
SetTextLayoutMode( nTextLayoutMode );
SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "emfio", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
Point aPos( ptlReferenceX, ptlReferenceY );
bool bOffStringSane = nOffString <= mnEndPos - nCurPos;
if ( bOffStringSane )
SAL_INFO("emfio", "\t\t Scale: " << nXScale << " x " << nYScale);
if ( ( nRecType == EMR_POLYTEXTOUTA ) || ( nRecType == EMR_POLYTEXTOUTW ) )
{
mpInputStream->Seek( nCurPos + nOffString );
OUString aText;
if ( bFlag )
mpInputStream->ReadUInt32( ncStrings );
SAL_INFO("emfio", "\t\t Number of Text objects: " << ncStrings);
}
for ( sal_uInt32 nStringNo = 0; nStringNo < ncStrings; nStringNo++ )
{
mpInputStream->ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadUInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
SAL_INFO("emfio", "\t\tReference: (" << ptlReferenceX << ", " << ptlReferenceY << ")");
mpInputStream->ReadInt32( nLeftRect ).ReadInt32( nTopRect ).ReadInt32( nRightRect ).ReadInt32( nBottomRect );
const tools::Rectangle aRect( nLeftRect, nTopRect, nRightRect, nBottomRect );
const BkMode mnBkModeBackup = mnBkMode;
if ( nOptions & ETO_NO_RECT ) // Don't draw the background rectangle and text background
mnBkMode = BkMode::Transparent;
else if ( nOptions & ETO_OPAQUE )
DrawRectWithBGColor( aRect );
mpInputStream->ReadUInt32( offDx );
ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
if ( nOptions & ETO_RTLREADING )
nTextLayoutMode = ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
SetTextLayoutMode( nTextLayoutMode );
SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "emfio", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
Point aPos( ptlReferenceX, ptlReferenceY );
bool bOffStringSane = nOffString <= mnEndPos - nCurPos;
if ( bOffStringSane )
{
if ( nLen <= ( mnEndPos - mpInputStream->Tell() ) )
mpInputStream->Seek( nCurPos + nOffString );
OUString aText;
if ( bFlag )
{
std::unique_ptr<char[]> pBuf(new char[ nLen ]);
mpInputStream->ReadBytes(pBuf.get(), nLen);
aText = OUString(pBuf.get(), nLen, GetCharSet());
}
}
else
{
if ( ( nLen * sizeof(sal_Unicode) ) <= ( mnEndPos - mpInputStream->Tell() ) )
{
aText = read_uInt16s_ToOUString(*mpInputStream, nLen);
}
}
SAL_INFO("emfio", "\t\tText: " << aText);
SAL_INFO("emfio", "\t\tDxBuffer:");
std::unique_ptr<tools::Long[]> pDXAry, pDYAry;
sal_Int32 nDxSize;
bool bOverflow = o3tl::checked_multiply<sal_Int32>(nLen, (nOptions & ETO_PDY) ? 8 : 4, nDxSize);
if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos)
{
mpInputStream->Seek( nCurPos + offDx );
pDXAry.reset( new tools::Long[aText.getLength()] );
if (nOptions & ETO_PDY)
{
pDYAry.reset( new tools::Long[aText.getLength()] );
}
for (sal_Int32 i = 0; i < aText.getLength(); ++i)
{
sal_Int32 nDxCount = 1;
if (aText.getLength() != static_cast<sal_Int32>( nLen ) )
if ( nLen <= ( mnEndPos - mpInputStream->Tell() ) )
{
sal_Unicode cUniChar = aText[i];
OString aTmp(&cUniChar, 1, GetCharSet());
if (aTmp.getLength() > 1)
{
nDxCount = aTmp.getLength();
}
std::unique_ptr<char[]> pBuf(new char[ nLen ]);
mpInputStream->ReadBytes(pBuf.get(), nLen);
aText = OUString(pBuf.get(), nLen, GetCharSet());
}
sal_Int32 nDx = 0, nDy = 0;
while (nDxCount--)
}
else
{
if ( ( nLen * sizeof(sal_Unicode) ) <= ( mnEndPos - mpInputStream->Tell() ) )
{
sal_Int32 nDxTmp = 0;
mpInputStream->ReadInt32(nDxTmp);
nDx += nDxTmp;
if (nOptions & ETO_PDY)
{
sal_Int32 nDyTmp = 0;
mpInputStream->ReadInt32(nDyTmp);
nDy += nDyTmp;
}
aText = read_uInt16s_ToOUString(*mpInputStream, nLen);
}
}
SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << nDx);
pDXAry[i] = nDx;
SAL_INFO("emfio", "\t\tText: " << aText);
SAL_INFO("emfio", "\t\tDxBuffer:");
std::unique_ptr<tools::Long[]> pDXAry, pDYAry;
sal_Int32 nDxSize;
bool bOverflow = o3tl::checked_multiply<sal_Int32>(nLen, (nOptions & ETO_PDY) ? 8 : 4, nDxSize);
if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos)
{
mpInputStream->Seek( nCurPos + offDx );
pDXAry.reset( new tools::Long[aText.getLength()] );
if (nOptions & ETO_PDY)
{
pDYAry[i] = nDy;
pDYAry.reset( new tools::Long[aText.getLength()] );
}
for (sal_Int32 i = 0; i < aText.getLength(); ++i)
{
sal_Int32 nDxCount = 1;
if ( static_cast<sal_uInt32>( aText.getLength() ) != nLen )
{
sal_Unicode cUniChar = aText[i];
OString aTmp(&cUniChar, 1, GetCharSet());
if (aTmp.getLength() > 1)
{
nDxCount = aTmp.getLength();
}
}
sal_Int32 nDx = 0, nDy = 0;
while (nDxCount--)
{
sal_Int32 nDxTmp = 0;
mpInputStream->ReadInt32(nDxTmp);
nDx += nDxTmp;
if (nOptions & ETO_PDY)
{
sal_Int32 nDyTmp = 0;
mpInputStream->ReadInt32(nDyTmp);
nDy += nDyTmp;
}
}
SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << nDx);
pDXAry[i] = nDx;
if (nOptions & ETO_PDY)
{
pDYAry[i] = nDy;
}
}
}
if ( nOptions & ETO_CLIPPED )
{
Push(); // Save the current clip. It will be restored after text drawing
IntersectClipRect( aRect );
}
DrawText(aPos, aText, pDXAry.get(), pDYAry.get(), mbRecordPath, nGfxMode);
if ( nOptions & ETO_CLIPPED )
Pop();
}
if ( nOptions & ETO_CLIPPED )
{
Push(); // Save the current clip. It will be restored after text drawing
IntersectClipRect( aRect );
}
DrawText(aPos, aText, pDXAry.get(), pDYAry.get(), mbRecordPath, nGfxMode);
if ( nOptions & ETO_CLIPPED )
Pop();
mnBkMode = mnBkModeBackup;
}
}
@@ -2050,8 +2059,6 @@ namespace emfio
case EMR_ANGLEARC :
case EMR_SETCOLORADJUSTMENT :
case EMR_POLYDRAW16 :
case EMR_POLYTEXTOUTA :
case EMR_POLYTEXTOUTW :
case EMR_CREATECOLORSPACE :
case EMR_SETCOLORSPACE :
case EMR_DELETECOLORSPACE :